// Generate successive k-length permutations from sequence. (1.00)
// (algorithm adapted from python/itertools page)
#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_index;
std::vector<int> m_cycle;
};
template<typename T>
template<typename InputIt>
Permutation<T>::Permutation(InputIt first, InputIt last, int k)
: m_pool(first, last)
{
int n = m_pool.size();
for (int i = 0; i < n; i++)
m_index.push_back(i);
k = std::min(k, n);
for (int i = 0; i < k; i++)
m_cycle.push_back(n-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])
{
std::swap(m_index[i], m_index[n - m_cycle[i]]);
return true;
}
m_cycle[i] = n - i;
auto first = m_index.begin();
std::rotate(std::next(first, i), std::next(first, i+1), m_index.end());
}
return false;
}
template<typename T>
std::vector<T> Permutation<T>::get() const
{
std::vector<T> out;
for (int k = m_cycle.size(), i = 0; i < k; i++)
out.push_back(m_pool[m_index[i]]);
return out;
}
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()));
}
Ly8gR2VuZXJhdGUgc3VjY2Vzc2l2ZSBrLWxlbmd0aCBwZXJtdXRhdGlvbnMgZnJvbSBzZXF1ZW5jZS4gKDEuMDApCi8vIChhbGdvcml0aG0gYWRhcHRlZCBmcm9tIHB5dGhvbi9pdGVydG9vbHMgcGFnZSkKCiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0cnVjdCBQZXJtdXRhdGlvbiB7CiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBJbnB1dEl0PgogICAgUGVybXV0YXRpb24oSW5wdXRJdCwgSW5wdXRJdCwgaW50IGspOwogICAgYm9vbCBuZXh0KCk7CiAgICBzdGQ6OnZlY3RvcjxUPiBnZXQoKSBjb25zdDsKCnByaXZhdGU6CiAgICBzdGQ6OnZlY3RvcjxUPiAgIG1fcG9vbDsKICAgIHN0ZDo6dmVjdG9yPGludD4gbV9pbmRleDsKICAgIHN0ZDo6dmVjdG9yPGludD4gbV9jeWNsZTsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnRlbXBsYXRlPHR5cGVuYW1lIElucHV0SXQ+ClBlcm11dGF0aW9uPFQ+OjpQZXJtdXRhdGlvbihJbnB1dEl0IGZpcnN0LCBJbnB1dEl0IGxhc3QsIGludCBrKQo6IG1fcG9vbChmaXJzdCwgbGFzdCkKewogICAgaW50IG4gPSBtX3Bvb2wuc2l6ZSgpOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCiAgICAgICAgbV9pbmRleC5wdXNoX2JhY2soaSk7CiAgICBrID0gc3RkOjptaW4oaywgbik7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IGs7IGkrKykKICAgICAgICBtX2N5Y2xlLnB1c2hfYmFjayhuLWkpOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpib29sIFBlcm11dGF0aW9uPFQ+OjpuZXh0KCkKewogICAgaW50IG4gPSBtX3Bvb2wuc2l6ZSgpOwogICAgZm9yIChpbnQgayA9IG1fY3ljbGUuc2l6ZSgpLCBpID0gay0xOyBpID49IDA7IGktLSkKICAgIHsKICAgICAgICBpZiAoLS1tX2N5Y2xlW2ldKQogICAgICAgIHsKICAgICAgICAgICAgc3RkOjpzd2FwKG1faW5kZXhbaV0sIG1faW5kZXhbbiAtIG1fY3ljbGVbaV1dKTsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIG1fY3ljbGVbaV0gPSBuIC0gaTsKICAgICAgICBhdXRvIGZpcnN0ID0gbV9pbmRleC5iZWdpbigpOwogICAgICAgIHN0ZDo6cm90YXRlKHN0ZDo6bmV4dChmaXJzdCwgaSksIHN0ZDo6bmV4dChmaXJzdCwgaSsxKSwgbV9pbmRleC5lbmQoKSk7CiAgICB9CiAgICByZXR1cm4gZmFsc2U7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0ZDo6dmVjdG9yPFQ+IFBlcm11dGF0aW9uPFQ+OjpnZXQoKSBjb25zdAp7CiAgICBzdGQ6OnZlY3RvcjxUPiBvdXQ7CiAgICBmb3IgKGludCBrID0gbV9jeWNsZS5zaXplKCksIGkgPSAwOyBpIDwgazsgaSsrKQogICAgICAgIG91dC5wdXNoX2JhY2sobV9wb29sW21faW5kZXhbaV1dKTsKICAgIHJldHVybiBvdXQ7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIElucHV0SXQ+CmF1dG8gbWFrZV9wZXJtdXRhdGlvbihJbnB1dEl0IGZpcnN0LCBJbnB1dEl0IGxhc3QsIGludCBrKQp7CiAgICB0eXBlZGVmIHR5cGVuYW1lIHN0ZDo6aXRlcmF0b3JfdHJhaXRzPElucHV0SXQ+Ojp2YWx1ZV90eXBlIHZhbHVlX3R5cGU7CiAgICByZXR1cm4gUGVybXV0YXRpb248dmFsdWVfdHlwZT4oZmlyc3QsIGxhc3QsIGspOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBJbnB1dEl0PgphdXRvIG1ha2VfcGVybXV0YXRpb24oSW5wdXRJdCBmaXJzdCwgSW5wdXRJdCBsYXN0KQp7CiAgICByZXR1cm4gbWFrZV9wZXJtdXRhdGlvbihmaXJzdCwgbGFzdCwgc3RkOjpkaXN0YW5jZShmaXJzdCwgbGFzdCkpOwp9CgovLwovLyBNYWluLgovLwoKdGVtcGxhdGU8dHlwZW5hbWUgVD4Kdm9pZCBzaG93KFBlcm11dGF0aW9uPFQ+JiYgcGVybXV0YXRpb24pCnsKICAgIGRvCiAgICB7CiAgICAgICAgZm9yIChhdXRvIHggOiBwZXJtdXRhdGlvbi5nZXQoKSkKICAgICAgICAgICAgc3RkOjpjb3V0IDw8IHg7CiAgICAgICAgc3RkOjpjb3V0IDw8ICcgJzsKICAgIH0KICAgIHdoaWxlIChwZXJtdXRhdGlvbi5uZXh0KCkpOwogICAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbDsKfQoKaW50IG1haW4oKQp7CiAgICAvLyBFeHBlY3Q6IEFCIEFDIEFEIEJBIEJDIEJEIENBIENCIENEIERBIERCIERDCiAgICBzdGQ6OnN0cmluZyBzeyJBQkNEIn07CiAgICBzaG93KG1ha2VfcGVybXV0YXRpb24ocy5iZWdpbigpLCBzLmVuZCgpLCAyKSk7CgogICAgLy8gRXhwZWN0OiAwMTIgMDIxIDEwMiAxMjAgMjAxIDIxMAogICAgc3RkOjp2ZWN0b3I8aW50PiB2ezAsIDEsIDJ9OwogICAgc2hvdyhtYWtlX3Blcm11dGF0aW9uKHYuYmVnaW4oKSwgdi5lbmQoKSkpOwp9