Reputation: 4603
I have a vector of N objects, and I would like to iterate through all neighbor permutations of this vector. What I call a neighbor permutation is a permutation where only two elements of the original vector would be changed :
if I have a vector with 'a','b','c','d'
then :
'b','a','c','d' //is good
'a','c','b','d' //is good
'b','a','d','c' //is not good (2 permutations)
If I use std::next_permutation(myVector.begin(), myVector.end()
then I will get all the possible permutations, not only the "neighbor" ones...
Do you have any idea how that could be achieved ?
Upvotes: 1
Views: 1211
Reputation: 15844
Another way to get it, just a try.
int main()
{
std::vector<char> vec={'b','a','c','d'};
std::vector<int> vec_in={1,1,0,0};
do{
auto it =std::find(vec_in.begin(),vec_in.end(),1);
if( *(it++) ==1)
{
for(auto &x : vec)
{
std::cout<<x<<" ";
}
std::cout<<"\n";
}
} while(std::next_permutation(vec_in.begin(),vec_in.end()),
std::next_permutation(vec.begin(),vec.end()) );
}
Upvotes: 0
Reputation: 18950
Initially, I thought I would filter the permutations that have a hamming distance greater than 2.
However, if you really only need to generate all the vectors resulting by swapping one pair, it would be more efficient if you do like this:
for(int i = 0; i < n; i++)
for(int j = i + 1; j < n; j++)
// swap i and j
Depending on whether you need to collect all the results or not, you should make a copy or the vector before the swap, or swap again i and j after you processed the current permutation.
Collect all the results:
std::vector< std::vector<T> > neighbor_permutations;
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
std::vector<T> perm(v);
std::swap(perm[i], perm[j]);
neighbor_permutations.push_back(perm);
}
}
Faster version - do not collect results:
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
std::swap(v[i], v[j]);
process_permutation(v);
std::swap(v[i], v[j]);
}
}
Upvotes: 2
Reputation: 76406
Perhaps it's a good idea to divide this into two parts:
How to generate the "neighbor permutations"
How to iterate over them
Regarding the first, it's easy to write a function:
std::vector<T> make_neighbor_permutation(
const std::vector<T> &orig, std::size_t i, std::size_t j);
which swaps i and j. I did not understand from your question if there's an additional constraint that j = i + 1, in which case you could drop a parameter.
Armed with this function, you now need an iterator that iterates over all legal combinations of i and j (again, I'm not sure of the interpretation of your question. It might be that there are n - 1 values).
This is very easy to do using boost::iterator_facade
. You simply need to define an iterator that takes in the constructor your original iterator, and sets i (and possibly j) to initial values. As it is incremented, it needs to update the index (or indices). The dereference method needs to call the above function.
Upvotes: 1