From 53aeedbab51d25c06dc7c38d1ea44cb8b2034acf Mon Sep 17 00:00:00 2001 From: Miguel Raggi Date: Wed, 6 Dec 2017 12:35:12 -0600 Subject: [PATCH 1/3] Added a new iterator, based on combinations_iterator, that traverses combinations in a different order. This one is faster. Based on library discreture. --- combination_iterator.hpp | 74 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 7 deletions(-) diff --git a/combination_iterator.hpp b/combination_iterator.hpp index 347795c..eb3e93f 100644 --- a/combination_iterator.hpp +++ b/combination_iterator.hpp @@ -11,6 +11,8 @@ #ifndef COMBINATION_ITERATOR_HPP #define COMBINATION_ITERATOR_HPP +// This code was produced by Juho Lauri (euler314). + #include #include #include @@ -27,9 +29,9 @@ class combination_iterator > { public: - combination_iterator() : end_(true), n_(0), size_(0), comb_() { } + combination_iterator() : end_(true), n_(0), k_(0), comb_() { } - explicit combination_iterator(T n, T k) : end_(false), n_(n), size_(k), comb_(k) + explicit combination_iterator(T n, T k) : end_(false), n_(n), k_(k), comb_(k) { assert(k != 0 && n_ > k); std::iota(comb_.begin(), comb_.end(), 0); @@ -41,20 +43,20 @@ class combination_iterator void increment() { - std::int64_t j = size_ - 1; + std::int64_t j = k_ - 1; - for (const T end = n_ - size_; j >= 0 && comb_[j] >= end + j; --j) { } + for (const T end = n_ - k_; j >= 0 && comb_[j] >= end + j; --j) { } if (j < 0) { - assert(comb_.front() == n_ - size_); + assert(comb_.front() == n_ - k_); end_ = true; return; } ++comb_[j]; - for (const std::int64_t end = size_ - 1; j < end; ++j) + for (const std::int64_t end = k_ - 1; j < end; ++j) { comb_[j + 1] = comb_[j] + 1; } @@ -74,7 +76,65 @@ class combination_iterator bool end_; const int n_; - const int size_; + const int k_; + std::vector comb_; +}; + + +template +class combination_iterator_maximin_order + : public boost::iterator_facade< + combination_iterator_maximin_order, + const std::vector&, + boost::forward_traversal_tag + > +{ +public: + combination_iterator_maximin_order() : end_(true), n_(0), k_(0), comb_() { } + + explicit combination_iterator_maximin_order(T n, T k) : end_(false), n_(n), k_(k), comb_(k) + { + assert(k != 0 && n_ > k); + std::iota(comb_.begin(), comb_.end(), 0); + assert(!end_); + } + +private: + friend class boost::iterator_core_access; + + void increment() + { + //The following code was copied from the discreture library: http://github.com/mraggi/discreture + if (comb_.empty()) + return; + T last = comb_.size()-1; + for (T i = 0; i < last; ++i) + { + if (comb_[i]+1 != comb_[i+1]) + { + ++comb_[i]; + return; + } + comb_[i] = i; + } + if (comb_[last]+1 == n_) + end_ = true; + ++comb_[last]; + } + + bool equal(const combination_iterator_maximin_order& other) const + { + return end_ == other.end_; + } + + const std::vector& dereference() const + { + return comb_; + } + + bool end_; + const int n_; + const int k_; std::vector comb_; }; From 33138bf4ad227abd616f36541813383fc7fd542c Mon Sep 17 00:00:00 2001 From: Miguel Raggi Date: Wed, 6 Dec 2017 12:36:10 -0600 Subject: [PATCH 2/3] Added a new iterator, based on combinations_iterator, that traverses combinations in a different order. This one is faster. Based on library discreture. --- combination_iterator.hpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/combination_iterator.hpp b/combination_iterator.hpp index eb3e93f..719b240 100644 --- a/combination_iterator.hpp +++ b/combination_iterator.hpp @@ -29,9 +29,9 @@ class combination_iterator > { public: - combination_iterator() : end_(true), n_(0), k_(0), comb_() { } + combination_iterator() : end_(true), n_(0), size_(0), comb_() { } - explicit combination_iterator(T n, T k) : end_(false), n_(n), k_(k), comb_(k) + explicit combination_iterator(T n, T k) : end_(false), n_(n), size_(k), comb_(k) { assert(k != 0 && n_ > k); std::iota(comb_.begin(), comb_.end(), 0); @@ -43,20 +43,20 @@ class combination_iterator void increment() { - std::int64_t j = k_ - 1; + std::int64_t j = size_ - 1; - for (const T end = n_ - k_; j >= 0 && comb_[j] >= end + j; --j) { } + for (const T end = n_ - size_; j >= 0 && comb_[j] >= end + j; --j) { } if (j < 0) { - assert(comb_.front() == n_ - k_); + assert(comb_.front() == n_ - size_); end_ = true; return; } ++comb_[j]; - for (const std::int64_t end = k_ - 1; j < end; ++j) + for (const std::int64_t end = size_ - 1; j < end; ++j) { comb_[j + 1] = comb_[j] + 1; } @@ -76,7 +76,7 @@ class combination_iterator bool end_; const int n_; - const int k_; + const int size_; std::vector comb_; }; @@ -90,9 +90,9 @@ class combination_iterator_maximin_order > { public: - combination_iterator_maximin_order() : end_(true), n_(0), k_(0), comb_() { } + combination_iterator_maximin_order() : end_(true), n_(0), size_(0), comb_() { } - explicit combination_iterator_maximin_order(T n, T k) : end_(false), n_(n), k_(k), comb_(k) + explicit combination_iterator_maximin_order(T n, T k) : end_(false), n_(n), size_(k), comb_(k) { assert(k != 0 && n_ > k); std::iota(comb_.begin(), comb_.end(), 0); @@ -134,7 +134,7 @@ class combination_iterator_maximin_order bool end_; const int n_; - const int k_; + const int size_; std::vector comb_; }; From 0073689bd48db077ba4a53e936448a99c9ce3023 Mon Sep 17 00:00:00 2001 From: Miguel Raggi Date: Wed, 6 Dec 2017 12:36:51 -0600 Subject: [PATCH 3/3] Added a new iterator, based on combinations_iterator, that traverses combinations in a different order. This one is faster. Based on library discreture. --- combination_iterator.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/combination_iterator.hpp b/combination_iterator.hpp index 719b240..8a5f6a2 100644 --- a/combination_iterator.hpp +++ b/combination_iterator.hpp @@ -11,8 +11,6 @@ #ifndef COMBINATION_ITERATOR_HPP #define COMBINATION_ITERATOR_HPP -// This code was produced by Juho Lauri (euler314). - #include #include #include