aboutsummaryrefslogtreecommitdiff
path: root/justify.cc
blob: 495dd8166ac8bcce6f5c0e5a7655e179ca56f758 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <iostream>
#include <string>
#include <vector>
#include <random>
#include <algorithm>
#include <cassert>

class LineAccumulator {
	static const std::size_t MAX_LENGTH = 60;

	public:
		LineAccumulator():
			device_(),
			length_(0),
			tokens_(),
			spaces_() { }

		~LineAccumulator() {
			this->discharge(false);
		}

		void operator()(const std::string& word) {
			if ( ( this->length_ + word.length() + 1 ) > MAX_LENGTH ) {
				this->pop_trailing_token();
				this->discharge(true);
			}

			this->add_token(word);
			this->add_space();
		}

	private:
		std::random_device       device_;
		std::size_t              length_;
		std::vector<std::string> tokens_;
		std::vector<std::size_t> spaces_;

		void add_token(const std::string& token) {
			this->length_ += token.length();
			this->tokens_.emplace_back(token);
		}

		void add_space() {
			this->add_token(" ");
			this->spaces_.emplace_back(this->tokens_.size() - 1);
		}

		void increase_space_at(const std::size_t index) {
			this->tokens_.at(this->spaces_[index]).append(" ");
			++this->length_;
		}

		void pop_trailing_token() {
			this->length_ -= this->tokens_.back().length();
			this->tokens_.pop_back();
			this->spaces_.pop_back();
		}

		void discharge(const bool full) {
			if ( full ) {
				std::mt19937 generator(this->device_());
				std::uniform_int_distribution<> random(0, this->spaces_.size()-1);

				while ( this->length_ < MAX_LENGTH ) {
					this->increase_space_at(random(generator));
				}
			}

			for ( const auto& token : this->tokens_ ) {
				std::cout << token;
			}

			std::cout << '\n';

			this->length_ = 0;
			this->tokens_.clear();
			this->spaces_.clear();
		}

};

int main() {
	std::cout.sync_with_stdio(false);
	std::cin.sync_with_stdio(false);

	LineAccumulator acc;
	std::string     word;

	while ( std::cin >> word ) {
		acc(word);
	}
}