问题
I have to write a programm that shows some numbers coding in Gray Code. I already found an algorithm written in C++ in this page ( https://www.geeksforgeeks.org/given-a-number-n-generate-bit-patterns-from-0-to-2n-1-so-that-successive-patterns-differ-by-one-bit/ ).
But I want to create a new method to delete the numbers that have two "1" consecutively and have "1" in their extremity (left and right).
Example : for n = 3 we get this numbers :
000
001
011
010
110
111
101
100
Now I want to delete this numbers : 011 , 110 , 111 , 101 and show the other numbers remiding in the list.
My idea is to create a vector of vectors. Something like that for example when n = 3 : {{000},{001},{011},{010},{110},{111},{101},{100}}.
For the size it will be like this :
int m = pow(2,n);
int vector[m][n];
For example : vector[0][1] = {0} and vector[1][2] = {1} if I'm correct with the sizes.
Now to delete the numbers that have two "1" consecutively and have "1" in their extremity I can use this code :
while (i < m){
for (j=0; j<n-1; j++){
if (vector[i][j]==vector[i][j+1]==1 && vector[i][0]==vector[i][n-1]==1 )
i=i+1; //Don't show this number
else { cout <<vector[i][j] << endl; i=i+1; }
}
}
Now the problem is that I don't know how to store the result in the Gray Code written in C++ in my vectors, or maybe there is a way to compare between two numbers from this code without using vectors.
回答1:
This is going to be extra work when you get to larger strings, and the code is not trivial to read. How about creating a simple mask? Shift a pair of contiguous 1 bits the length of the number (num).
mask = 0b11000 // fill in the correct quantity of 0s
end_mask = 0b10001
while mask > 1
if (num && mask) == mask
remove num from array
mask = mask >> 1
if num && end_mask == end_mask
remove num from array
回答2:
Without using bit manipulation, which admittedly would be faster, since you have a vector of vectors, one way to perform the removal is to use std::adjacent_find using a predicate to find the adjacent 1's, and to use std::remove_if to remove those vectors matching the criteria of having adjacent 1's.
Here is an example:
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>
bool findOnes(const std::vector<int>& v)
{
// less than 2 digits, so can't do anything
if ( v.size() < 2 )
return false;
// test extremes
if ( v.front() == 1 && v.back() == 1 )
return true;
// check if there are adjacent 1's
return std::adjacent_find(v.begin(), v.end(), [&](int n1, int n2)
{ return n1 == 1 && n2 == 1; }) != v.end();
}
int main()
{
//test
std::vector<std::vector<int>> vect = {{0,0,0},{0,0,1},{0,1,1},{0,1,0},{1,1,0},{1,1,1},{1,0,1},{1,0,0}};
// erase the vectors that match the criteria
vect.erase(std::remove_if(vect.begin(), vect.end(), findOnes), vect.end());
// show the final results
for ( auto& i : vect )
{
std::copy(i.begin(), i.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n";
}
}
Live Example
Basically, if the adjacent_find
does not find adjacent 1's, the iterator returned will be end()
. Thus in the findOne
predicate function, after doing the easy tests for size and the extreme values, adjacent_find
takes over and does the rest.
来源:https://stackoverflow.com/questions/48000038/choose-some-numbers-coding-in-gray-code