What is the logic to use bitwise operation in generating subsequences? [duplicate] - c++

This question already has answers here:
What does the statement if (counter & (1<<j)) mean and how does it work?
(2 answers)
Closed last year.
I have an array, A=[1,2,3,4] (where n=4). I want to generate sub-sequences from this array.
Number of subsequences is (2^n -1)
Run from counter 0001 to 1111
for (int counter = 1; counter < 2^n; counter++)
{
for (int j = 0; j < n; j++)
{
Check if the jth bit in the counter is set. If set then print jth element from arr[]
if (counter & (1<<j))
cout << arr[j] << " ";
}
cout << endl;
}
}
can anyone explain me? How it works " counter & (1<

The logic goes like this. Say, like you put in the example, you have n = 4, and, to avoid confusion, let's say the array is A = [5, 7, 8, 9], for example. Then you want all the possible sequences containing some elements (at least one) from the original array. So you want a sequence containing only the first one, a sequence containing the first and the second, the first and the third, etc. Each printed sequence may or may not contain each of the elements in the array. So you could see it as something like this:
| 5 | 7 | 8 | 9 | Sequence
----------------- --------
| 1 | 0 | 0 | 0 | -> 5
| 1 | 1 | 0 | 0 | -> 5 7
| 1 | 0 | 1 | 0 | -> 5 8
...
That is, each sequence can be expressed as a list of bits, each indicating whether each member of the array is included.
In this loop:
for (int counter = 1; counter < 2^n; counter++)
The program iterates from 1 to 2^n - 1, that is 15 in this case. So the values that you get for counter are:
Dec Binary
--- ------
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
10 1010
11 1011
12 1100
13 1101
14 1110
15 1111
If you look closely, you will see that we have all the possible sequences of four elements composed of 0 and 1 in binary (except 0000, which would be the empty sequence and does not interest us). In this loop:
for (int j = 0; j < n; j++)
The program just goes through each bit of counter, from 0 (the rightmost) to n - 1 and whenever it finds a 1 it outputs the corresponding array element. The condition:
if (counter & (1<<j))
Simply computes the number 1<<j which is 1 plus j number of zeros at its right (so, for example, for j = 0 it would be 1 and for j = 2 it would be 100) and then a bitwise and operation, so it basically "filters" the j-th bit only (e.g. 1101 & 100 = 0100), and if the result is not zero then it means there was a one, and so arr[j] must be printed.
Obviously, the problem with the function is that it is limited to the number of bits that the variable counter can hold. That depends on its declared type and your architecture/compiler, but typically it will be either 32 or 64.

Related

How many palindromes can you create from array

I'm trying to build a basic code that is taking an int array and outputing all of its optional palindromes.
Example: {1, 2, 2, 2, 3}
Output: {2 2}, {2 1 2}, {2 3 2}, {2 2 2}
I was thinking of reorganizing the array in every way possible and checking if it's an array by each time. But, I think I'm heading to it wrongly.
The code I made for now is:
#include <iostream>
using namespace std;
int main()
{
int arr[] = { 1, 2, 3, 2, 1 };// 7 int //56
bool check = true;
for(int i=0; i< sizeof(arr)/sizeof(int)/2;i++)
{
if(arr[i] != arr[sizeof(arr)/sizeof(int)-1-i])
check = false;
}
if(check)
{
for(int i=0; i< sizeof(arr)/sizeof(int);i++)
{
cout<<arr[i]<< " ";
}
cout<<endl;
}
return 0;
}
I will appreciate help if possible. Thank you all and have an amazing day!
We have to implement 2 major mathematical concepts here
Create a power set
Get all permutations from powerset.
Then, of course check for the palindrome property.
Let's start with the power set.
We will first make a simplification for an easier understanding of the task. We will use lower case letters in this example. Then we will take 4 elements {A,B,C,D} for demo purposes.
What we need to generate is a power set from this. There are 2 main standard approaches.
Counting with checking of set bits via it mask
Setting more and more bits in a field and do permutations.
Let us look at solution 1. Counting. Based on "abcd" we will get
Count Binary Selection (sub set)
DCBA Cardinality
0 0000 {----} 0 Empty set
1 0001 {---A} 1
2 0010 {--B-} 1
3 0011 {--BA} 2
4 0100 {-C--} 1
5 0101 {-C-A} 2
6 0110 {-CB-} 2
7 0111 {-CBA} 3
8 1000 {D---} 4
9 1001 {D--A} 2
10 1010 {D-B-} 2
11 1011 {D-BA} 3
12 1100 {DC--} 3
13 1101 {DC-A} 3
14 1110 {DCB-} 3
15 1111 {DCBA} 4
As a result we will get the powerset:
{{A},{B},{AB},{C},{AC},{BC},{ABC},{D},{AD},{BD},{ABD},{CD},{ACD},{BCD},{ABCD}}
If you look at the output, we see that the elements are not sorted according to their cardinality. Therefore we will choose a different approach. We will set more and more bits in a field an do permutations on them. Also with a selector. Then, we will get something like this:
Binary Selection
0000 {----} Empty set. Ignored
0001 {---A} Set bit 0
0010 {--B-} Permutation
0101 {-C--} Permutation
1000 {D---} Permutation
0011 {--BA} Set next bit number 1
0101 {-C-A} Permutation
1001 {D--A} Permutation
0110 {-CB-} Permutation
1010 {D-B-} Permutation
1100 {D--A} Permutation
0111 {-CBA} Set next bit number 2
1011 {D-BA} Permutation
1101 {DC-A} Permutation
1110 {DCB-} Permutation
1111 {DCBA} Set next bit number 3
As a result we will get the "more reasonable/expected" powerset:
{{A},{B},{C},{D},{AB},{AC},{AD},{BC},{BD},{AD},{ABC},{ABD},{ACD},{BCD},{ABCD}}
By the way. The overall number of sub sets is of course 2^n and the size of the cardinality group is equal to the corresponding binomial coeeficient.
Cardinality
0 4 choose 0 --> 1
1 4 choose 1 --> 4
2 4 choose 1 --> 6
3 4 choose 1 --> 4
4 4 choose 1 --> 1
Sum: 16
The corresponding algorithm is easy to implement, which can also be seen later in the code example.
Next, after having calculated one subset, we will create all permutations of data in this subset with the existing C++ function std::next_permutation.
After a successful check for a Palindrome, we will add this subset to a resulting std::set . We will use the std::set to avoid duplicates.
At the end, we can show the result.
The below example is brute force and hence very very slow for big input arrays.
Anyway, please see the example code below:
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
int main() {
std::vector testData{ 1,2,2,2,3 };
// Here we will store the result
std::set<std::vector<int>> result{};
// Selectors for creating the subsets of the power set
std::vector<bool> selector(testData.size());
// For all number of elements in the original test data
for (size_t k{0}; k < testData.size(); ++k) {
// Set selector bits. In each loop one more bit. So, 1 then 11, then 111 and so on
selector[k] = true;
// Do all permutations of the above set selector bits
do {
// Build the subset
std::vector<int> subset{};
for (std::size_t n{}; n < testData.size(); ++n)
if (selector[n]) subset.push_back(testData[n]);
do {
// Check, if palindrome
if (subset == std::vector<int>(subset.rbegin(), subset.rend()))
result.insert(subset);
} while (std::next_permutation(subset.begin(), subset.end()));
} while (std::prev_permutation(selector.begin(), selector.end()));
}
// Show all resulting palindromes
std::cout << "\n\nNumber of palindromes: " << result.size() << "\n\n";
int counter{ 1 };
for (const std::vector<int>& v : result) {
std::cout << "Palindrome " << counter++ << ":\t";
for (const int i : v) std::cout << ' ' << i;
std::cout << '\n';
}
}

What do "Non-Power-Of-Two Textures" mean?

What do "Non-Power-Of-Two Textures" mean? I read this tutorial and I meet some binaries operations("<<", ">>", "^", "~"), but I don't understand what they are doing.
For example following code:
GLuint LTexture::powerOfTwo(GLuint num)
{
if (num != 0)
{
num--;
num |= (num >> 1); //Or first 2 bits
num |= (num >> 2); //Or next 2 bits
num |= (num >> 4); //Or next 4 bits
num |= (num >> 8); //Or next 8 bits
num |= (num >> 16); //Or next 16 bits
num++;
}
return num;
}
I very want to understand this operations. As well, I read this. Very short article. I want to see examples of using, but I not found. I did the test:
int a = 5;
a <<= 1; //a = 10
a = 5;
a <<= 2; //a = 20
a = 5;
a <<= 3; //a = 40
Okay, this like multiply on two, but
int a = 5;
a >>= 1; // a = 2 Whaat??
In C++, the <<= is the "left binary shift" assignment operator; the operand on the left is treated as a binary number, the bits are moved to the left, and zero bits are inserted on the right.
The >>= is the right binary shift; bits are moved to the right and "fall off" the right end, so it's like a division by 2 (for each bit) but with truncation. For negative signed integers, by the way, additional 1 bits are shifted in at the left end ("arithmetic right shift"), which may be surprising; for positive signed integers, or unsigned integers, 0 bits are shifted in at the left ("logical right shift").
"Powers of two" are the numbers created by successive doublings of 1: 2, 4, 8, 16, 32… Most graphics hardware prefers to work with texture maps which are powers of two in size.
As said in http://lazyfoo.net/tutorials/OpenGL/08_non_power_of_2_textures/index.php
powerOfTwo will take the argument and find nearest number that is power of two.
GLuint powerOfTwo( GLuint num );
/*
Pre Condition:
-None
Post Condition:
-Returns nearest power of two integer that is greater
Side Effects:
-None
*/
Let's test:
num=60 (decimal) and its binary is 111100
num--; .. 59 111011
num |= (num >> 1); //Or first 2 bits 011101 | 111011 = 111111
num |= (num >> 2); //Or next 2 bits 001111 | 111111 = 111111
num |= (num >> 4); //Or next 4 bits 000011 | 111111 = 111111
num |= (num >> 8); //Or next 8 bits 000000 | 111111 = 111111
num |= (num >> 16); //Or next 16 bits 000000 | 111111 = 111111
num++; ..63+1 = 64
output 64.
For num=5: num-1 =4 (binary 0100), after all num |= (num >> N) it will be 0111 or 7 decimal). Then num+1 is equal to 8.
As you should know the data in our computers is represented in the binary system, in which digits are either a 1 or a 0.
So for example number 10 decimal = 1010 binary. (1*2^3 + 0*2^2 + 1*2^1 + 0*2^0).
Let's go to the operations now.
Binary | OR means that wherever you have at least one 1 the output will be 1.
1010
| 0100
------
1110
~ NOT means negation i.e. all 0s become 1s and all 1s become 0s.
~ 1010
------
0101
^ XOR means you turn a pair of 1 and 0 into a 1. All other combinations leave a 0 as output.
1010
^ 0110
------
1100
Bit shift.
N >> x means we "slide" our number N, x bits to the right.
1010 >> 1 = 0101(0) // zero in the brackets is dropped,
since it goes out of the representation = 0101
1001 >> 1 = 0100(1) // (1) is dropped = 0100
<< behaves the same way, just the opposite direction.
1000 << 1 = 0001
Since in binary system numbers are represented as powers of 2, shifting a bit one or the other direction will result in multiplying or dividing by 2.
Let num = 36. First subtract 1, giving 35. In binary, this is 100011.
Right shift by 1 position gives 10001 (the rightmost digit disappears). Bitwise Or'ed with num gives:
100011
10001
-------
110011
Note that this ensures two 1's on the left.
Now right shift by 2 positions, giving 1100. Bitwise Or:
110011
1100
-------
111111
This ensures four 1's on the left.
And so on, until the value is completely filled with 1's from the leftmost.
Add 1 and you get 1000000, a power of 2.
This procedure always generates a power of two, and you can check that it is just above the initial value of num.

C++ using AND operator in integer expression

I'm reading some source code for designing an Octree and found this in the code. I have removed some elements for simplication, but can anyone explain what i&4 is supposed to evaluate to?
for (int i = 0; i < 8; i++)
{
float j = i&4 ? .5f : -.5f;
}
& is the bitwise AND Operator.
It just does a bitwise operation of the value stored in i AND 0x4.
It exactly just isolates the third bit as 2^2 = 4.
Your expression in the loop checks if third bit is set in i and assigns to j (which must be a float!) 0.5 or if not set -0.5
I am not sure, but it may evaluate the bitwise and operation of i and 4 (100), so any number which has a '1' in its third bit will be evaluted to true, otherwise false.
Ex:
5 (101) & 4 (100) = 100 (4) which is different from 0 so its true
8 (1000) & 4 (100) = 0000 (0) which is false
The & operator in this case is a bitwise AND. Since the second operand is 4, a power of 2, it evaluates to 4 when i has its second least-significant bit set, and to 0 otherwise.
The for loop takes i from 0 to 7, inclusive. Consider bit representations of i in this range:
0000 - 0
0001 - 1
0010 - 2
0011 - 3
0100 - 4
0101 - 5
0110 - 6
0111 - 7
^
|
This bit determines the result of i & 4
Therefore, the end result of the conditional is as follows: if the second bit is set (i.e. when i is 4, 5, 6, or 7), the result is 0.5f; otherwise, it is -0.5f.
For the given range of values, this expression can be rewritten as
float j = (i >= 4) ? .5f : -.5f;
i & 4 just evaluate to true when the value-4 bit is set. In your case this only happens in the second half of the loop. So the code could actually be rewritten:
for (int i = 0; i < 4; i++)
{
float j = -.5f;
}
for (int i = 4; i < 8; i++)
{
float j = .5f;
}

Why does "number & (~(1 << 3))" not work for 0's?

I'm writing a program that exchanges the values of the bits on positions 3, 4 and 5 with bits on positions 24, 25 and 26 of a given 32-bit unsigned integer.
So lets say I use the number 15 and I want to turn the 4th bit into a 0, I'd use...
int number = 15
int newnumber = number & (~(1 << 3));
// output is 7
This makes sense because I'm exchanging the 4th bit from 1 to 0 so 15(1111) becomes 7(0111).
However this wont work the other way round (change a 0 to a 1), Now I know how to achieve exchanging a 0 to a 1 via a different method, but I really want to understand the code in this method.
So why wont it work?
The truth table for x AND y is:
x y Output
-----------
0 0 0
0 1 0
1 0 0
1 1 1
In other words, the output/result will only be 1 if both inputs are 1, which means that you cannot change a bit from 0 to 1 through a bitwise AND. Use a bitwise OR for that (e.g. int newnumber = number | (1 << 3);)
To summarize:
Use & ~(1 << n) to clear bit n.
Use | (1 << n) to set bit n.
To set the fourth bit to 0, you AND it with ~(1 << 3) which is the negation of 1000, or 0111.
By the same reasoning, you can set it to 1 by ORing with 1000.
To toggle it, XOR with 1000.

How does this implementation of bitset::count() work?

Here's the implementation of std::bitset::count with MSVC 2010:
size_t count() const
{ // count number of set bits
static char _Bitsperhex[] = "\0\1\1\2\1\2\2\3\1\2\2\3\2\3\3\4";
size_t _Val = 0;
for (int _Wpos = _Words; 0 <= _Wpos; --_Wpos)
for (_Ty _Wordval = _Array[_Wpos]; _Wordval != 0; _Wordval >>= 4)
_Val += _Bitsperhex[_Wordval & 0xF];
return (_Val);
}
Can someone explain to me how this is working? what's the trick with _Bitsperhex?
_Bitsperhex contains the number of set bits in a hexadecimal digit, indexed by the digit.
digit: 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
value: 0 1 1 2 1 2 2 3 1 2 2 3 2 3 3 4
index: 0 1 2 3 4 5 6 7 8 9 A B C D E F
The function retrieves one digit at a time from the value it's working with by ANDing with 0xF (binary 1111), looks up the number of set bits in that digit, and sums them.
_Bitsperhex is a 16 element integer array that maps a number in [0..15] range to the number of 1 bits in the binary representation of that number. For example, _Bitsperhex[3] is equal to 2, which is the number of 1 bits in the binary representation of 3.
The rest is easy: each multi-bit word in internal array _Array is interpreted as a sequence of 4-bit values. Each 4-bit value is fed through the above _Bitsperhex table to count the bits.
It is a slightly different implementation of the lookup table-based method described here: http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetTable. At the link they use a table of 256 elements and split 32-bit words into four 8-bit values.