From 05c4ee3665445eadf094ccab395518e992c337d4 Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Sat, 30 Apr 2016 20:06:48 +0200 Subject: Implement `--seed` argument Enables users to customize the seed used for the pseudorandom number generator. --- README.md | 2 ++ justify.cc | 16 +++++++++++++--- src/line_accumulator.cc | 49 +++++++++++++++++++++++-------------------------- src/line_accumulator.h | 11 ++++++++--- 4 files changed, 46 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 9b6ab36..214e2b8 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ i.e. `echo "$the_paragraph_above" | justify --length 40 --offset 2` results in: leading spaces may be defined using `--offset`. +The seed used to pseudorandomly distribute missing spaces may be customized via the `--seed` argument. + ## Requirements * CMake diff --git a/justify.cc b/justify.cc index c417dfd..9115d83 100644 --- a/justify.cc +++ b/justify.cc @@ -23,6 +23,11 @@ boost::optional input( boost::program_options::value(), "Number of spaces to be prepended on each line" ) + ( + "seed", + boost::program_options::value(), + "Seed for pseudorandomly distributing missing spaces" + ) ; boost::program_options::variables_map variables; @@ -51,8 +56,9 @@ bool process(const boost::program_options::variables_map& variables) { std::cout.sync_with_stdio(false); std::cin.sync_with_stdio(false); - std::uint8_t line_length = 60; - std::uint8_t line_offset = 0; + std::uint8_t line_length = 60; + std::uint8_t line_offset = 0; + std::uint32_t seed = 3473018784; if ( variables.count("length") ) { const int user_length = variables["length"].as(); @@ -78,7 +84,11 @@ bool process(const boost::program_options::variables_map& variables) { } } - justify::LineAccumulator acc{line_length, line_offset}; + if ( variables.count("seed") ) { + seed = variables["seed"].as(); + } + + justify::LineAccumulator acc{line_length, line_offset, seed}; std::string token; while ( std::cin.good() ) { diff --git a/src/line_accumulator.cc b/src/line_accumulator.cc index 9ce389b..a203fac 100644 --- a/src/line_accumulator.cc +++ b/src/line_accumulator.cc @@ -6,23 +6,17 @@ namespace { -static std::mt19937 generator; - std::uint8_t getRandomIndex( - const int seed, + std::mt19937& generator, const std::uint8_t n ) { - generator.seed(seed); - return std::uniform_int_distribution{0, n}(generator); } std::vector getRandomIndizes( - const int seed, - const std::uint8_t n + std::mt19937& generator, + const std::uint8_t n ) { - generator.seed(seed); - std::vector indizes(n); std::iota(indizes.begin(), indizes.end(), 0); std::shuffle( @@ -55,11 +49,13 @@ std::size_t getCharacterLength(const std::string& token) { namespace justify { LineAccumulator::LineAccumulator( - const std::uint8_t max_length, - const std::uint8_t offset + const std::uint8_t max_length, + const std::uint8_t offset, + const std::uint32_t seed ): max_length_{max_length}, offset_{offset}, + generator_{seed}, length_{0}, tokens_{} { } @@ -67,14 +63,6 @@ LineAccumulator::~LineAccumulator() { this->discharge(false); } -std::uint8_t LineAccumulator::getMissing() const { - if ( this->length_ < this->max_length_ ) { - return this->max_length_ - this->length_; - } else { - return 0; - } -} - void LineAccumulator::operator()(const std::string& token) { const std::size_t tokenLength = getCharacterLength(token); @@ -91,10 +79,15 @@ void LineAccumulator::operator()(const std::string& token) { } } -void LineAccumulator::justify() { - const int seed = this->tokens_.size() - + this->getMissing(); +std::uint8_t LineAccumulator::getMissing() const { + if ( this->length_ < this->max_length_ ) { + return this->max_length_ - this->length_; + } else { + return 0; + } +} +void LineAccumulator::justify() { switch ( this->tokens_.size() ) { // There is no sensible block justification of null or any single token case 0: @@ -137,14 +130,18 @@ void LineAccumulator::justify() { } // randomly distribute missing spaces case 1: { - this->tokens_[ - getRandomIndex(seed, this->tokens_.size() - 2) - ].second += 1; + this->tokens_[getRandomIndex( + this->generator_, + this->tokens_.size() - 2 + )].second += 1; break; } default: { - const auto indizes = getRandomIndizes(seed, this->tokens_.size() - 2); + const auto indizes = getRandomIndizes( + this->generator_, + this->tokens_.size() - 2 + ); std::for_each( indizes.begin(), diff --git a/src/line_accumulator.h b/src/line_accumulator.h index 69b4c74..db75c8c 100644 --- a/src/line_accumulator.h +++ b/src/line_accumulator.h @@ -9,23 +9,28 @@ namespace justify { class LineAccumulator { public: - LineAccumulator(const std::uint8_t max_length, const std::uint8_t offset); + LineAccumulator( + const std::uint8_t max_length, + const std::uint8_t offset, + const std::uint32_t seed + ); ~LineAccumulator(); - std::uint8_t getMissing() const; - void operator()(const std::string& token); private: const std::uint8_t max_length_; const std::uint8_t offset_; + std::mt19937 generator_; std::uint8_t length_; std::vector< std::pair > tokens_; + std::uint8_t getMissing() const; + void justify(); void discharge(const bool full); -- cgit v1.2.3