// Generate successive k-length permutations from sequence. (2.01)
// (eliminates indirect indexing; revised indexing)
// @see hHkYMq, pdPHbN
#include <algorithm>
#include <vector>
#include <iostream>
template<typename T>
struct Permutation {
template<typename InputIt>
Permutation(InputIt, InputIt, int k);
bool next();
std::vector<T> get() const;
private:
std::vector<T> m_pool;
std::vector<int> m_cycle;
};
template<typename T>
template<typename InputIt>
Permutation<T>::Permutation(InputIt first, InputIt last, int k)
: m_pool(first, last)
{
k = std::min(k, static_cast<int>(m_pool.size()));
for (int i = 0; i < k; i++)
m_cycle.push_back(i);
}
template<typename T>
bool Permutation<T>::next()
{
int n = m_pool.size();
for (int k = m_cycle.size(), i = k-1; i >= 0; i--)
{
if (++m_cycle[i] < n)
{
std::swap(m_pool[i], m_pool[m_cycle[i]]);
return true;
}
m_cycle[i] = i;
auto first = m_pool.begin();
std::rotate(std::next(first, i), std::next(first, i+1), m_pool.end());
}
return false;
}
template<typename T>
std::vector<T> Permutation<T>::get() const
{
auto first = m_pool.begin();
return std::vector<T>(first, std::next(first, m_cycle.size()));
}
template<typename InputIt>
auto make_permutation(InputIt first, InputIt last, int k)
{
typedef typename std::iterator_traits<InputIt>::value_type value_type;
return Permutation<value_type>(first, last, k);
}
template<typename InputIt>
auto make_permutation(InputIt first, InputIt last)
{
return make_permutation(first, last, std::distance(first, last));
}
//
// Main.
//
template<typename T>
void show(Permutation<T>&& permutation)
{
do
{
for (auto x : permutation.get())
std::cout << x;
std::cout << ' ';
}
while (permutation.next());
std::cout << std::endl;
}
int main()
{
// Expect: AB AC AD BA BC BD CA CB CD DA DB DC
std::string s{"ABCD"};
show(make_permutation(s.begin(), s.end(), 2));
// Expect: 012 021 102 120 201 210
std::vector<int> v{0, 1, 2};
show(make_permutation(v.begin(), v.end()));
}
Ly8gR2VuZXJhdGUgc3VjY2Vzc2l2ZSBrLWxlbmd0aCBwZXJtdXRhdGlvbnMgZnJvbSBzZXF1ZW5jZS4gKDIuMDEpCi8vIChlbGltaW5hdGVzIGluZGlyZWN0IGluZGV4aW5nOyByZXZpc2VkIGluZGV4aW5nKQovLyBAc2VlIGhIa1lNcSwgcGRQSGJOCgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8aW9zdHJlYW0+Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpzdHJ1Y3QgUGVybXV0YXRpb24gewogICAgdGVtcGxhdGU8dHlwZW5hbWUgSW5wdXRJdD4KICAgIFBlcm11dGF0aW9uKElucHV0SXQsIElucHV0SXQsIGludCBrKTsKICAgIGJvb2wgbmV4dCgpOwogICAgc3RkOjp2ZWN0b3I8VD4gZ2V0KCkgY29uc3Q7Cgpwcml2YXRlOgogICAgc3RkOjp2ZWN0b3I8VD4gbV9wb29sOwogICAgc3RkOjp2ZWN0b3I8aW50PiBtX2N5Y2xlOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVD4KdGVtcGxhdGU8dHlwZW5hbWUgSW5wdXRJdD4KUGVybXV0YXRpb248VD46OlBlcm11dGF0aW9uKElucHV0SXQgZmlyc3QsIElucHV0SXQgbGFzdCwgaW50IGspCjogbV9wb29sKGZpcnN0LCBsYXN0KQp7CiAgICBrID0gc3RkOjptaW4oaywgc3RhdGljX2Nhc3Q8aW50PihtX3Bvb2wuc2l6ZSgpKSk7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IGs7IGkrKykKICAgICAgICBtX2N5Y2xlLnB1c2hfYmFjayhpKTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgVD4KYm9vbCBQZXJtdXRhdGlvbjxUPjo6bmV4dCgpCnsKICAgIGludCBuID0gbV9wb29sLnNpemUoKTsKICAgIGZvciAoaW50IGsgPSBtX2N5Y2xlLnNpemUoKSwgaSA9IGstMTsgaSA+PSAwOyBpLS0pCiAgICB7CiAgICAgICAgaWYgKCsrbV9jeWNsZVtpXSA8IG4pCiAgICAgICAgewogICAgICAgICAgICBzdGQ6OnN3YXAobV9wb29sW2ldLCBtX3Bvb2xbbV9jeWNsZVtpXV0pOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgbV9jeWNsZVtpXSA9IGk7CiAgICAgICAgYXV0byBmaXJzdCA9IG1fcG9vbC5iZWdpbigpOwogICAgICAgIHN0ZDo6cm90YXRlKHN0ZDo6bmV4dChmaXJzdCwgaSksIHN0ZDo6bmV4dChmaXJzdCwgaSsxKSwgbV9wb29sLmVuZCgpKTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgVD4Kc3RkOjp2ZWN0b3I8VD4gUGVybXV0YXRpb248VD46OmdldCgpIGNvbnN0CnsKICAgIGF1dG8gZmlyc3QgPSBtX3Bvb2wuYmVnaW4oKTsKICAgIHJldHVybiBzdGQ6OnZlY3RvcjxUPihmaXJzdCwgc3RkOjpuZXh0KGZpcnN0LCBtX2N5Y2xlLnNpemUoKSkpOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBJbnB1dEl0PgphdXRvIG1ha2VfcGVybXV0YXRpb24oSW5wdXRJdCBmaXJzdCwgSW5wdXRJdCBsYXN0LCBpbnQgaykKewogICAgdHlwZWRlZiB0eXBlbmFtZSBzdGQ6Oml0ZXJhdG9yX3RyYWl0czxJbnB1dEl0Pjo6dmFsdWVfdHlwZSB2YWx1ZV90eXBlOwogICAgcmV0dXJuIFBlcm11dGF0aW9uPHZhbHVlX3R5cGU+KGZpcnN0LCBsYXN0LCBrKTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgSW5wdXRJdD4KYXV0byBtYWtlX3Blcm11dGF0aW9uKElucHV0SXQgZmlyc3QsIElucHV0SXQgbGFzdCkKewogICAgcmV0dXJuIG1ha2VfcGVybXV0YXRpb24oZmlyc3QsIGxhc3QsIHN0ZDo6ZGlzdGFuY2UoZmlyc3QsIGxhc3QpKTsKfQoKLy8KLy8gTWFpbi4KLy8KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnZvaWQgc2hvdyhQZXJtdXRhdGlvbjxUPiYmIHBlcm11dGF0aW9uKQp7CiAgICBkbwogICAgewogICAgICAgIGZvciAoYXV0byB4IDogcGVybXV0YXRpb24uZ2V0KCkpCiAgICAgICAgICAgIHN0ZDo6Y291dCA8PCB4OwogICAgICAgIHN0ZDo6Y291dCA8PCAnICc7CiAgICB9CiAgICB3aGlsZSAocGVybXV0YXRpb24ubmV4dCgpKTsKICAgIHN0ZDo6Y291dCA8PCBzdGQ6OmVuZGw7Cn0KCmludCBtYWluKCkKewogICAgLy8gRXhwZWN0OiBBQiBBQyBBRCBCQSBCQyBCRCBDQSBDQiBDRCBEQSBEQiBEQwogICAgc3RkOjpzdHJpbmcgc3siQUJDRCJ9OwogICAgc2hvdyhtYWtlX3Blcm11dGF0aW9uKHMuYmVnaW4oKSwgcy5lbmQoKSwgMikpOwoKICAgIC8vIEV4cGVjdDogMDEyIDAyMSAxMDIgMTIwIDIwMSAyMTAKICAgIHN0ZDo6dmVjdG9yPGludD4gdnswLCAxLCAyfTsKICAgIHNob3cobWFrZV9wZXJtdXRhdGlvbih2LmJlZ2luKCksIHYuZW5kKCkpKTsKfQ==