aboutsummaryrefslogtreecommitdiff
path: root/justify.cc
blob: 8480231df5f9a9d4314af032aafdc85852a9022b (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
#include <iostream>
#include <string>
#include <vector>

#include "random.h"

class LineAccumulator {
	public:
		LineAccumulator(const std::size_t max_length):
			max_length_{max_length},
			random_{},
			length_{0},
			tokens_{},
			spaces_{} { }

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

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

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

	private:
		const std::size_t max_length_;

		utility::Random          random_;
		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 ) {
				auto range = this->random_.makeRange(0, this->spaces_.size()-1);

				while ( this->length_ < this->max_length_ ) {
					this->increase_space_at(range.get());
				}
			}

			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{60};
	std::string     word;

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