c++ iterate through all neighbor permutations - c++

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 ?

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]);
}
}

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.

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()) );
}

Related

How to calculate a mismatch score between n number of strings more efficiently?

Suppose I have a vector that contains n strings, where the strings can be length 5...n. Each string must be compared with each string character by character. If there is a mismatch, the score is increased by one. If there is a match, the score does not increase. Then I will store the resulting scores in a matrix.
I have implemented this in the following way:
for (auto i = 0u; i < vector.size(); ++i)
{
// vector.size() x vector.size() matrix
std::string first = vector[i]; //horrible naming convention
for (auto j = 0u; j < vector.size(); ++j)
{
std::string next = vector[j];
int score = 0;
for (auto k = 0u; k < sizeOfStrings; ++k)
{
if(first[k] == second[k])
{
score += 0;
}
else
{
score += 1;
}
}
//store score into matrix
}
}
I am not happy with this solution because it is O(n^3). So I have been trying to think of other ways to make this more efficient. I have thought about writing another function that would replace the innards of our j for loop, however, that would still be O(n^3) since the function would still need a k loop.
I have also thought about a queue, since I only care about string[0] compared to string[1] to string[n]. String[1] compared to string[2] to string[n]. String[2] compared to string[3] to string[n], etc. So my solutions have unnecessary computations since each string is comparing to every other string. The problem with this, is I am not really sure how to build my matrix out of this.
I have finally, looked into the std template library, however std::mismatch doesn't seem to be what I am looking for, or std::find. What other ideas do you guys have?
I don't think you can easily get away from O(n^3) comparisons, but you can easily implement the change you talk about. Since the comparisons only need to be done one way (i.e. comparing string[1] to string[2] is the same as comparing string[2] to string[1]), as you point out, you don't need to iterate through the entire array each time and can change the start value of your inner loop to be the current index of your outer loop:
for (auto i = 0u; i < vector.size(); ++i) {
// vector.size() x vector.size() matrix
std::string first = vector[i]; //horrible naming convention
for (auto j = i; j < vector.size(); ++j) {
To store it in a matrix, setup your i x j matrix, initialize it to all zeroes and simply store each score in M[i][j]
for (auto k = 0u; k < sizeOfStrings; ++k) {
if (first[k] != second[k]) {
M[i][j]++;
}
}
If you have n strings each of length m, then no matter what (even with your queue idea), you have to do at least (n-1)+(n-2)+...+(1)=n(n-1)/2 string comparisons, so you'll have to do (n(n-1)/2)*m char comparisons. So no matter what, your algorithm is going to be O(mn^2).
General comment:
You don't have to compare the same strings with each other. And what is more important you starting from the begining each time in second loop while you already computed those diffs, so change the second loop to start from i+1.
By doing so your complexity will decrease as you won't check string that you already checked or are the same.
Improvement
Sort vector and remove duplicated entries, then instead wasting computation for checking the same strings you will only check those that are different.
The other answers that say this is at least O(mn^2) or O(n^3) are incorrect. This can be done in O(mn) time where m is string size and n is number of strings.
For simplicity we'll start with the assumption that all characters are ascii.
You have a data structure:
int counts[m][255]
where counts[x][y] is the number of strings that have ascii character y at index x in the string.
Now, if you did not restrict to ascii, then you would need to use a std::map
map counts[m]
But it works the same way, at index m in counts you have a map in which each entry in the map y,z tells you how many strings z use character y at index m. You would also want to choose a map with constant time lookups and constant time insertions to match the complexity.
Going back to ascii and the array
int counts[m][255] // start by initializing this array to all zeros
First initialize the data structure:
m is size of strings,
vec is a std::vector with the strings
for (int i = 0; i < vec.size(); i++) {
std::string str = vec[i];
for(int j = 0; j < m; j++) {
counts[j][str[j]]++;
}
}
Now that you have this structure, you can calculate the scores easily:
for (int i = 0; i < vec.size(); i++) {
std::string str = vec[i];
int score = 0;
for(int j = 0; j < m; j++) {
score += counts[j][str[j]] - 1; //subtracting 1 gives how many other strings have that same char at that index
}
std::cout << "string \"" << str << "\" has score " << score;
}
As you can see by this code, this is O(m * n)

sorting an array and maintaining element's old index

I have an array A:
A = [10 11 3 15 8 7]
index = 0 1 2 3 4 5
I want to sort this array.After sorting I want the information of old index.For this I can create a structure like this.
struct VnI{
int value;
int index;
};
sorting the array of structure with respect to value solve my problem.But I want to know that is it possible to solve this using sort or any other function in C++11.
I have tried this way:
struct VnI{
int V;
int I;
};
bool comparator(VnI x,VnI y){
if(x.V < y.V)
return true;
return false;
}
int maximumGap(const vector<int> &A) {
vector<VnI> B;
for(int i = 0;i < A.size();i++){
B[i].I = i;
B[i].V = A[i];
}
sort(B.begin(),B.end(),comparator);
for(int i = 0;i < B.size();i++){
cout<<B[i].I<<" "<<B[i].V<<endl;
}
}
But I got runtime error.
Please help.
This code is wrong:
vector<VnI> B;
for(int i = 0;i < A.size();i++){
B[i].I = i;
B[i].V = A[i];
}
When you write B[i], it assumes that B is at least of size i+1. Since the maximum value of i (which you used an index to B) is A.size()-1. The assumption in your code is that B is at least of size A.size(). This assumption is wrong — the fact is that B is of size 0.
Unfortunately operator[] of std::vector doesn't check for out of range index. If you use at(), the code will throw std::out_of_range exception:
vector<VnI> B;
for(int i = 0;i < A.size();i++){
B.at(i).I = i;
B.at(i).V = A[i];
}
Now this would throw std::out_of_range exception.
Anyway, one simple fix could be this:
vector<VnI> B (A.size()); //initialize B with the size of A.
for(int i = 0;i < A.size();i++){
B[i].I = i;
B[i].V = A[i];
}
However, I'd suggest this solution:
vector<VnI> B;
B.reserve(A.size());
for(int i = 0;i < A.size(); i++){
B.emplace_back(i, A[i]);
}
I'd also suggest you read more about std::vector, especially the following functions:
size()
capacity()
resize()
reserve()
push_back()
operator[]
at()
emplace_back()
and all the constructors.
Also, learn to naming your variables properly and be consistent with it.
Hope that helps.
do you pefer to use vector and pair?
each pair has "first" and "second", put "first"=value to sort,"second"=original index, create a pair for each element and put them into vector to sort:
int N[]={10,11,3,15,8,7};
std::vector<std::pair<int,int> > v;
//create pair for each element
for(int i=0;i<sizeof(N)/sizeof(int);i++){
//first is value of array,second is original index
v.push_back(std::make_pair(N[i],i));
}
//sort the vector of pair
sort(v.begin(),v.end());
//get original index from second of pair
for(std::pair<int,int>& p : v){
std::cout << p.first << ":" << p.second << std::endl;
}
output
3:2
7:5
8:4
10:0
11:1
15:3
Normally what is done is the opposite... i.e. given an array x of elements compute an array of integers ix so that x[ix[i]] appears to be sorted under a certain criteria.
This allows representing the container with different orderings without actually having to move/copy the elements.
With C++11 this can easily be done using lambdas:
// Build the index vector ix
std::vector<int> ix(x.size());
for (int i=0,n=x.size(); i<n; i++) ix[i] = i;
// Sort ix according to the corresponding values in x
// (without touching x)
std::sort(ix.begin(), ix.end(),
[&x](int a, int b) { return x[a] < x[b]; });
This ix index array is what you are asking for (i.e. the "old" position of an element: ix[i] is where the i-th element of the sorted list was in the original array) and there is no need to modify the input array.
You are trying to sort a list of custom objects, answerd here:
SO Link
Once you list the list of VnI objects you can then access there old index's through the I member that I presume is the index.

How to compute the complement of given vector Indices?

I have a 3D point vector, represented by class Point3D,
std::vector<Point3D> points;
I also have a size_t vector containing indices of the points vector,
std::vector<size_t> indices_true;
Now I want to build the inverse of indices_true, i.e. I want to build another index vector indices_false that contains all indices which are missing in indices_true. How can this be done in a faster way than the following:
for (size_t i = 0; i < points.size(); i++)
{
// TODO: The performance of the following is awful
if (std::find(indices_true.begin(), indices_true.end(), i) == indices_true.end())
indices_false.push_back(i);
}
Needs extra memory, but yields a linear algorithm:
Here is an attempt (neither compiled, nor tested):
indices_false.reserve(points.size() - indices_true.size());
std::vector<char> isTrue(points.size(), false); // avoided std::vector<bool> intentionally
for (const size_t i : indices_true)
{
isTrue[i] = true;
}
for (size_t i = 0; i < points.size(); ++i)
{
if (!isTrue[i])
indices_false.push_back(i);
}
Sort your indices_true vector first and use std::binary_search. To keep the orders within vector using std::stable_sort.
std::stable_sort(indices_true.begin(), indices_true.end());
for (size_t i = 0; i < points.size(); i++)
{
if (std::binary_search(indices_true.begin(), indices_true.end(), i))
indices_false.push_back(i);
}
Sort indices_true and gradually increase an index k within this sorted vector. Increase it when necessary. This yields (beside the initial sorting) a linear algorithm.
Here is an attempt (neither compiled, nor tested):
std::sort(begin(indices_true), end(indices_true));
indices_false.reserve(points.size() - indices_true.size());
size_t k = 0;
for (size_t i = 0; i < points.size(); ++i)
{
if (k < indices_true.size() && i > indices_true[k])
++k;
assert(k >= indices_true.size() || i <= indices_true[k]);
if (k >= indices_true.size() || i != indices_true[k])
indices_false.push_back(i);
}
}

c++ array can't get the right array

I have Array A[9]= {1,2,3,4,5,6,7,8,9} and I need to delete the numbers which are not dividing by 2. The code I tried to do:
int main()
{
int n;
ifstream fd(Cdf);
fd>>n; // read how many numbers are in the file.
int A[n];
for(int i = 0; i < n; i++)
{
fd >> A[i]; //read the numbers from file
}
for(int i = 0; i < n; i ++) // moving the numbers.
{
if(A[i] % 2 !=0)
{
for(int j = i; j < n; j++)
{
A[i] = A[i+1];
}
}
}
fd.close();
return 0;
}
But I get numbers like 224466888. what I need to do to get 2,4,6,8?
I need to delete numbers in the same array.
First you should use std::vector for dynamic size arrays.
Second, for removing numbers that are even in a vector, you can do :
std::vector<int> inf = {12,0,5,6,8};
auto func = [](int i){return i % 2 != 0;};
inf.erase(std::remove_if(inf.begin(),inf.end(),func), inf.end());
EDIT :
Ok, so you can still do this without std::vectors, but it will be uglier :
#include <algorithm>
int res[] = {2,5,9,8,6,7};
int size = 6;
auto func = [](int i){return i % 2 != 0;};
int new_size = std::remove_if(res,res + size, func) - res;
All the data you want is in [0, new_size[ range, the other part of your array is now garbage.
Your removal loop is indexing with the wrong variable:
for(int j = i; j < n; j++)
{
A[i] = A[i+1];
}
You're using i, which doesn't change in the loop.
Change it to j. You also need to subtract one from the upper limit, as you'd step outside of the array otherwise when accessing A[j + 1].
for(int j = i; j < n - 1; j++)
{
A[j] = A[j + 1];
}
An array can't be used for your purpose. It is allocated on stack and its size can't be changed dynamically (you can't change the size of an array in general, not only when it is allocated on stack).
You could allocate a second array and keep reallocating it with realloc everytime you add a new element but that's not the good way to do it. You are working with C++ so just use a std::vector<int> and your problems will be solved:
std::vector<int> evenArray;
evenArray.reserve(sizeof(A)/sizeof(A[0])/2);
if (number is even) {
evenArray.pushBack(number);
}
Mind that vector stores elements contiguously so this is legal:
int *evenA = &evenArray[0];
For your inner for loop you should be referencing j, not i.
for(int j = i; j < n - 1; j++)
{
A[j] = A[j+1];
}
Otherwise, what's the point of creating j?
Of course, this also means if you read the whole array back you will display all the characters that were shifted (which will just be equal to the last number). So, you should probably keep track of the new length of the array and just iterate to that instead of the end of the array.
EDIT:
In the inner for loop you need to loop to n - 1 otherwise when you have A[j + 1] it will go off the end of the array when you to change it, which may or may not give you a runtime error.

Correctly erasing an element from a vector

If I have a table of vectors declared as
vector<int> table[9][9]
and I want to compare and delete the element if it already exists, would the deletion be:
for(int row = 0; row < 9; row++)//erases the current choice from the whole row
{
for(int h = 0; h < (int)table[row][k].size();h++)
{
if(table[row][k][h] == table[i][k][0])
{
table[row][k].erase(table[row][k].begin() + h);
}
}
}
I thought this would work, but I'm not 100% because I tried to delete every element using this technique and it didn't work, for those of you who want to see the code I used to delete all the elements, then it is:
for(int i = 0; i < 9; i++)
for(int k = 0; k < 9; k++)
for(int n = 0; n < table[i][k].size();n++)
table[i][k].erase(table[i][k].begin + n);
this method did not work, so I used clear instead.
I don't know what choice and k are, but to erase all values from a vector v that are equal to a particular value val use the "erase-remove idiom":
v.erase(
std::remove(v.begin(), v.end(), val),
v.end()
);
Hence, to do this same thing for all vectors in table:
for (auto &row : table) {
for (auto &v : row) {
v.erase(
std::remove(v.begin(), v.end(), val),
v.end()
);
}
}
If you have a more complicated condition than equality, use remove_if in place of remove. But in your case, the extra condition involving puzzle doesn't use the loop variable h, so I think you can test that before looking in the vector:
if (puzzle[row][k] == 0) {
// stuff with erase
}
In C++03 you can't use "range-based for loops" for (auto &row : table). So if you don't have C++11, or if you need the index for use in the puzzle test, then stick with for(int i = 0; i < 9; i++).