-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Day-26: More Bit manipulation problems
- Loading branch information
Showing
4 changed files
with
235 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/** | ||
* Problem : Determine parity of a number. | ||
* Parity refers to whether number contains odd or even number of set bits | ||
* Approach: We loop till number becomes zero and invert parity while unsetting | ||
* right most set bit. | ||
*/ | ||
|
||
#include <iostream> | ||
|
||
bool getparity( int num ) | ||
{ | ||
bool parity = false; | ||
while( num ) { | ||
parity = !parity; | ||
num = (num & (num - 1)); | ||
} | ||
return parity; | ||
} | ||
|
||
int main() | ||
{ | ||
int num; | ||
std::cout << "Enter number:"; | ||
std::cin >> num; | ||
std::cout << "Parity of num is " | ||
<< (getparity(num) ? "odd" : "even") | ||
<< std::endl; | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* Problem : Muliply a number by 7 by using bit manipulation. | ||
* Approach : left shift n by 3 --> 8n | ||
* Therefore 7n = 8n - n; | ||
*/ | ||
#include <iostream> | ||
|
||
int multiply_by_7( int number ) | ||
{ | ||
return ((number << 3) - number); | ||
} | ||
|
||
int main() | ||
{ | ||
std::cout << "Enter a number:"; | ||
int num; | ||
std::cin >> num; | ||
std::cout << "7 x " << num << " = " | ||
<< multiply_by_7(num) << std::endl; | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
/** | ||
* Problem : Reverse bits of an unsigned integer | ||
*/ | ||
|
||
#include <iostream> | ||
#include <sstream> | ||
#include <cassert> | ||
#include <algorithm> | ||
|
||
/** | ||
* swapBits - utility function to swap bits at position i and j in unsigned int x | ||
* l represents bit at position i | ||
* r represents bit at position j | ||
* if l and r are same nothing needs to be done. | ||
* if l and r are different i.e. (l ^ r == 1), | ||
* we toggle bits at position i and j, and return new x. | ||
*/ | ||
unsigned int swapBits(unsigned int x, unsigned int i, unsigned int j) | ||
{ | ||
unsigned int l = ((x >> i) & 1); | ||
unsigned int r = ((x >> j) & 1); | ||
if ( l ^ r ) | ||
{ | ||
x ^= ((1U << i) | (1U << j)); | ||
} | ||
return x; | ||
} | ||
|
||
/* | ||
reverseBits1 : we swap first bit with last, | ||
second with one before last and so on. | ||
*/ | ||
|
||
unsigned int reverseBits1(int n) | ||
{ | ||
unsigned bitCount = sizeof(n) * 8; | ||
for( unsigned int i = 0; i < bitCount/2; ++i) { | ||
n = swapBits(n, i, bitCount-i-1); | ||
} | ||
return n; | ||
} | ||
|
||
|
||
/** | ||
* Now, approach 2, divide and conquer: | ||
* | ||
* 01101001 | ||
* / \ | ||
* 0110 1001 | ||
* / \ / \ | ||
* 01 10 10 01 | ||
* /\ /\ /\ /\ | ||
* 0 1 1 0 1 0 0 1 | ||
* | ||
* Just like merge sort, swap at each level and you are done. | ||
* First swap all odd and even bits, and then consecutive pair of bits | ||
* and so on. | ||
* This below approach will work on assumption that unsigned int size is 4bytes | ||
* or 32 bits. | ||
* Lets say a is 10 = 00000000 00000000 00000000 00001010 | ||
* Step 1: swap all odd and even positions. | ||
* a = (a & 0x55555555) << 1 | (a & 0xAAAAAAAA) >> 1 | ||
* 0x55555555 = 01010101 01010101 01010101 01010101 | ||
* a = 00000000 00000000 00000000 00001010 | ||
* --------------------------------------------------- and | ||
* a & (0x5..) = 00000000 00000000 00000000 00000000 | ||
* a & (0x5..) << 1 = 00000000 00000000 00000000 00000000 | ||
* | ||
* 0xAAAAAAAA = 10101010 10101010 10101010 10101010 | ||
* a = 00000000 00000000 00000000 00001010 | ||
* ------------------------------------------------- and | ||
* a & (0xA..) = 00000000 00000000 00000000 00001010 | ||
* a & (0xA..) >> 1 = 00000000 00000000 00000000 00000101 | ||
* | ||
* (a & (0x5..)) << 1 | (x & (0xA..)) >> 1 | ||
* = 00000000 00000000 00000000 00000101 | ||
* a = 00000000 00000000 00000000 00000101 | ||
* | ||
*********************************************************** | ||
* | ||
* Step2 : swap two consecutive bits with next consecutive two bits. | ||
* a = ((a & 0x33333333) << 2) | ((a & 0xCCCCCCCC) >> 2) | ||
* 0x33333333 = 00110011 00110011 00110011 00110011 | ||
* a = 00000000 00000000 00000000 00000101 | ||
* ------------------------------------------------- and | ||
* a & (0x33..)= 00000000 00000000 00000000 00000001 | ||
* | ||
* a & (0x33.) << 2 = 00000000 00000000 00000000 00000100 | ||
* | ||
* 0xCCCCCCCC = 11001100 11001100 11001100 11001100 | ||
* a = 00000000 00000000 00000000 00000101 | ||
* ------------------------------------------------- and | ||
* a & (0xcc..)= 00000000 00000000 00000000 00000100 | ||
* a & (0xcc..) >> 2 = 00000000 00000000 00000000 00000001 | ||
* (a & (0x33..) << 2) | (a & (0xcc) >> 2 ) | ||
* = 00000000 00000000 00000000 00000101 | ||
* a = 00000000 00000000 00000000 00000101 | ||
* | ||
* ********************************************************** | ||
* | ||
* Step3 : Swap 4 consecutive bits with next 4 | ||
* a = ((a & 0x0F0F0F0F) << 4) | ((a & 0xF0F0F0F0) >> 4); | ||
* 0x0F0F0F0F = 00001111 00001111 00001111 00001111 | ||
* a = 00000000 00000000 00000000 00000101 | ||
* ------------------------------------------------ and | ||
* a & (0x0F..)= 00000000 00000000 00000000 00000101 | ||
* a & (0x0F..) << 4 = 00000000 00000000 00000000 01010000 | ||
* | ||
* 0xF0F0F0F0 = 11110000 11110000 11110000 11110000 | ||
* a = 00000000 00000000 00000000 00000101 | ||
* --------------------------------------------------- | ||
* a & (0xF0..)= 00000000 00000000 00000000 00000000 | ||
* a & (0xF0..) >> 4 = 00000000 00000000 00000000 00000000 | ||
* therefore a = ((a & 0x0F0F0F0F) << 4) | ((a & 0xF0F0F0F0) >> 4) | ||
* a = 00000000 00000000 00000000 01010000 | ||
* | ||
* *********************************************************** | ||
* | ||
* Step4 : Swap consecutive bytes with each other | ||
* a = ((a & 0x00FF00FF) << 8) | ((a & 0xFF00FF00) >> 8); | ||
* 0x00FF00FF = 00000000 11111111 00000000 11111111 | ||
* 0xFF00FF00 = 11111111 00000000 11111111 00000000 | ||
* Clearly same as above operations, our a will become | ||
* a = 00000000 00000000 01010000 00000000 | ||
* | ||
* ************************************************************ | ||
* step5 : Finally swap two consecutive bytes with next two i.e. swapping left | ||
* 16 bits with right | ||
* | ||
* a = ((a & 0x0000FFFF) << 16) | ((a & 0xFFFF0000) >> 16); | ||
* So we will end up with | ||
* a = 01010000 00000000 00000000 00000000 | ||
* Clearly which is reverse of how we started | ||
*/ | ||
|
||
unsigned int reverseBits2( unsigned int num ) | ||
{ | ||
assert(sizeof(num) == 4); // this method will work only for 32 bits | ||
num = ((num & 0x55555555) << 1) | ((num & 0xAAAAAAAA) >> 1); | ||
num = ((num & 0x33333333) << 2) | ((num & 0xCCCCCCCC) >> 2); | ||
num = ((num & 0x0F0F0F0F) << 4) | ((num & 0xF0F0F0F0) >> 4); | ||
num = ((num & 0x00FF00FF) << 8) | ((num & 0xFF00FF00) >> 8); | ||
num = ((num & 0x0000FFFF) << 16) | ((num & 0xFFFF0000) >> 16); | ||
return num; | ||
} | ||
|
||
std::string printBinary(unsigned int n) | ||
{ | ||
std::stringstream ss; | ||
std::string bin; | ||
int count = 0; | ||
while(n) | ||
{ | ||
ss << (n % 2); | ||
n /= 2; | ||
++count; | ||
} | ||
bin = ss.str(); | ||
bin.append(32-count, '0'); | ||
std::reverse(bin.begin(), bin.end()); | ||
return bin; | ||
} | ||
|
||
int main() | ||
{ | ||
std::cout << "Enter an unsigned number:"; | ||
unsigned int n; | ||
std::cin >> n; | ||
std::cout << "Binary representation of entered number : " | ||
<< printBinary(n) << std::endl; | ||
std::cout << "Reversing bits of entered number\n"; | ||
n = reverseBits1(n); | ||
std::cout << "Binary representation of number when bits are reversed: " | ||
<< printBinary(n) << std::endl; | ||
std::cout << "Reversing bits again\n"; | ||
n = reverseBits2(n); | ||
std::cout << "Binary representation of number when bits are reversed: " | ||
<< printBinary(n) << std::endl; | ||
return 0; | ||
} |