diff options
-rw-r--r-- | CMakeLists.txt | 12 | ||||
-rw-r--r-- | justify.cc | 92 |
2 files changed, 104 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..deddd48 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 2.8) +project(justify) + +set( + CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -std=c++14 -W -Wall -Wextra -Winline -pedantic" +) + +add_executable( + justify + justify.cc +) diff --git a/justify.cc b/justify.cc new file mode 100644 index 0000000..495dd81 --- /dev/null +++ b/justify.cc @@ -0,0 +1,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); + } +} |