In competitive programming or in general, some problems seem difficult but can be solved very easily with little concepts of bit magic. We have discussed some tricks below in the previous post.
Bitwise Hacks for Competitive Programming
Evaluates to 1 if the number is odd else evaluates to 0
Clears the lowest set bit of x
Extracts the lowest set bit of x (all others are cleared)
Clears all bits of x from LSB to ith bit
Clears all bits of x from MSB to ith bit
Divides x by 2
Multiplies x by 2
Upper case English alphabet ch to lower case
Lower case English alphabet ch to upper case
Checking if given 32-bit integer is power of 2
Find the last set bit
1) Check Whether Number is Even or Oddx & 1
Logic:
Even numbers have 0 as their LSB and Odd numbers have 1 as their LSB, so Bitwise AND with even numbers results in 0 and with odd numbers results in 1.
Example:
x = 29 (00011101), (x & 1) = 1, therefore x is an odd number
x= 16(10000), (x & 1) = 0, therefore x is an even number
lear the Lowest Set bit of x
x & (x-1)
Logic:
When you subtract 1 from x, all the bits to the right of the lowest set bit become 1, and the lowest set bit becomes 0 and performing a bitwise AND operation between x and (x-1) sets each bit to 0 except for the bits that are common in both x and (x-1).
Example:
x = 10101010
x-1 = 10101001
x & (x-1) = 10101000
the Lowest Set bit of x
x & ~(x-1);
Logic:
When you subtract 1 from x, all the bits to the right of the lowest set bit become 1, and the lowest set bit becomes 0 and performing a bitwise AND operation between x and ~(x-1) sets each bit to 0 except for the lowest set bit of x.
Example:
x = 10101010
~(x-1) = 01010110
x & ~(x-1) = 00000010
mask = ~((1 << i+1 ) - 1); x &= mask;
Logic:
To clear all bits from LSB to i-th bit, we have to AND x with mask having LSB to i-th bit 0. To obtain such mask, first left shift 1 i times. Now if we minus 1 from that, all the bits from 0 to i-1 become 1 and remaining bits become 0. Now we can simply take the complement of mask to get all first i bits to 0 and remaining to 1.
Example:-
x = 29 (00011101) and we want to clear LSB to 3rd bit, total 4 bits
mask -> 1 << 4 -> 16(00010000)
mask -> 16 – 1 -> 15(00001111)
mask -> ~mask -> 11110000
x & mask -> 16 (00010000)
mask = (1 << i) - 1; x &= mask;
Logic:
To clear all bits from MSB to i-th bit, we have to AND x with mask having MSB to i-th bit 0. To obtain such mask, first left shift 1 i times. Now if we minus 1 from that, all the bits from 0 to i-1 become 1 and the remaining bits become 0.
Example:
x = 215 (11010111) and we want to clear MSB to 4th bit, total 4 bits
mask -> 1 << 4 -> 16(00010000)
mask -> 16 – 1 -> 15(00001111)
x & mask -> 7(00000111)
x >>= 1;
Logic:
When we do arithmetic right shift, every bit is shifted to right and blank position is substituted with sign bit of number, 0 in case of positive and 1 in case of negative number. Since every bit is a power of 2, with each shift we are reducing the value of each bit by factor of 2 which is equivalent to division of x by 2.
Example:
x = 18(00010010)
x >> 1 = 9 (00001001)
x <<= 1;
Logic:
When we do arithmetic left shift, every bit is shifted to left and blank position is substituted with 0 . Since every bit is a power of 2, with each shift we are increasing the value of each bit by a factor of 2 which is equivalent to multiplication of x by 2.
Example:
x = 18(00010010)
x << 1 = 36 (00100100)
ch |= ' ';
Logic: The bit representation of upper case and lower case English alphabets are -
A -> 01000001 a -> 01100001 B -> 01000010 b -> 01100010 C -> 01000011 c -> 01100011 . . . . Z -> 01011010 z -> 01111010
As we can see if we set 5th bit of upper case characters, it will be converted into lower case character. We have to prepare a mask having 5th bit 1 and other 0 (00100000). This mask is bit representation of space character (‘ ‘). The character ‘ch’ then OR with mask.
Example:
ch = ‘A’ (01000001)
mask = ‘ ‘ (00100000)
ch | mask = ‘a’ (01100001)
Please refer Case conversion (Lower to Upper and Vice Versa) for details.
ch &= '_’ ;
Logic: The bit representation of upper case and lower case English alphabets are -
A -> 01000001 a -> 01100001 B -> 01000010 b -> 01100010 C -> 01000011 c -> 01100011 . . . . Z -> 01011010 z -> 01111010
As we can see if we clear 5th bit of lower-case characters, it will be converted into upper case character. We have to prepare a mask having 5th bit 0 and other 1 (11011111). This mask is bit representation of underscore character (‘_‘). The character ‘ch’ then AND with mask.
Example:
ch = ‘a’ (01100001)
mask = ‘_ ‘ (11011111)
ch & mask = ‘A’ (01000001)
Please refer Case conversion (Lower to Upper and Vice Versa) for details.
int countSetBits(int x) { int count = 0; while (x) { x &= (x-1); count++; } return count; }
Logic: This is Brian Kernighan’s algorithm.
int log2(int x) { int res = 0; while (x >>= 1) res++; return res; }
Logic: We right shift x repeatedly until it becomes 0, meanwhile we keep count on the shift operation. This count value is the log2(x).
int isPowerof2(int x) { return (x && !(x & x-1)); }
Logic:
All the power of 2 have only single bit set e.g. 16 (00010000). If we minus 1 from this, all the bits from LSB to set bit get toggled, i.e., 16-1 = 15 (00001111). Now if we AND x with (x-1) and the result is 0 then we can say that x is power of 2 otherwise not. We have to take extra care when x = 0.
Example :
x = 16(00010000)
x – 1 = 15(00001111)
x & (x-1) = 0
so, 16 is power of 2
int lastSetBit(int n){ return log2(n & -n)+1; }
The logarithmic value of AND of x and -x to the base 2 gives the index of the last set bit(for 0-based indexing).
2) Turn On kth bit in a numberint turnOffKthBit(int n, int k) {
return n & ~(1 << (k - 1));
}
3) Check if kth bit is set for a numberint turnOnKthBit(int n, int k) {
return n | (1 << (k - 1));
}
4) Toggle the kth bitbool isKthBitSet(int n, int k) {
return (n & (1 << (k - 1))) != 0;
}
int toggleKthBit(int n, int k) {
return n ^ (1 << (k - 1));
}
Please refer this article for more bit hacks.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4