Вот полное и рабочее решение, которое я только что преобразовал в C ++ из документации по методу python itertools.permutations. http://docs.python.org/library/itertools.html#itertools.permutations. В исходной форме Python это генератор (просто подумайте итератор), но я не стал сейчас этим заниматься, хотя это имело бы большой смысл.
Метод перестановок - это шаблон, поэтому он работает с любым объектом, который вы можете сохранить в векторе, а не только с символом. С этим кодом:
vector<char> alphab={'a','b','c','d'};
auto perms=permutations(alphab,3);'
результатом является вектор 'vector', представляющий все неповторяющиеся 3-комбинации abcd:
abc abd acb acd adb adc bac bad bca bcd bda bdc
cab cad cba cbd cda cdb dab dac dba dbc dca dcb
Вот код (C ++ 11):
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
size_t nperms(size_t n,size_t k){
if(k<=0) return 1; // one empty set
if(k>n) return 0; // no possible ways
size_t out=1;
for (size_t i=n-k+1;i<=n;i++) out*=i;
return out;
}
template<class T>
vector<T > permutations(T & iterable, size_t r=-1){
vector<T> out;
T & pool = iterable;
size_t n = pool.size();
r = r>=0 ? r : n;
if (r > n)
return out;
vector<size_t> indices;
for (size_t i=0;i<n;++i) indices.push_back(i);
vector<size_t> cycles;
for (size_t i=n;i>(n-r);--i) cycles.push_back(i);
vector<typename T::value_type> line; //e.g. vector of char
line.reserve(r);
for (size_t i=0;i<r;++i)
line.push_back(pool[i]);
out.reserve(nperms(n,r));
// first permutation:
out.push_back(line);
while (1){
bool done=1;
for (size_t irev=0;irev<r;++irev){
size_t i=r-1-irev;
cycles[i] -= 1;
if(cycles[i] == 0){
// cycle upper part one step
rotate(begin(indices)+i,begin(indices)+i+1,end(indices));
cycles[i] = n-i;
}else{
int j = cycles[i];
swap(indices[n-j],indices[i]);
for (size_t k=0;k<r;++k)
line[k]=pool[indices[k]];
out.push_back(line);
done=0;
break ;
}
}
if(done) break;
}
return out;
}
int main(){
vector<char> alphab={'a','b','c','d'};
auto perms=permutations(alphab,3);
// print:
cout <<"perms of size " <<perms.size()<<endl;
for (auto &i : perms){
for (auto &j : i){
cout << j<<"";
}
cout <<" ";
}
cout <<endl;
return 0;
}
Как примечание:
Алфавит не проверяется на уникальность, вместо этого перестановки и выборки делаются по индексу, поэтому, если вы хотите разрешить использование более одного объекта, просто добавьте его в алфавит. Содержание также не должно быть сопоставимым.