Thought I’d share my solution to one of the problems in a well-rated competitive programming contest today, which as per the problem given is not that complicated, but I quite like my approach with which I solved the thing in a short amount of time, via the power and efficacy of bitwise operations.
As per the problem statement, I take as input an integer number in the decimal form and I need to toggle (0
->1
and 1
->0
) the middle bit of that number in the binary form, and print it to the console. There is a condition though, which is that if the number of bits in the binary form is even, then I have to toggle both the middle bits (for instance, 10101010
would become 101100101
), as opposed to the straightforward case when the number is odd, as then there is only one middle bit, and hence I only need to toggle that (for instance, 000
would become 010
).
Possibly, there are quite a few ways to achieve this, but for an optimized approach, this problem could do with the use of bitwise operators, which involves the concept of left shift to set a desired bit and XOR to handle the toggling. To set any B
th binary bit, one can left shift <<
from the right bit of the binary form of the concerned decimal number by using 1 << (B - 1)
. Toggling is as simple as using the XOR operator ^
for the bit required to toggle.
Going by the problem statement, the requirement is to toggle the middle bit(s), so I must find them first. I begin by obtaining the bit count in my number in order to determine whether it falls in the first or second condition based on parity (odd/even). For this, I implemented a function that takes as input a decimal number and returns the count of digits in its binary equivalent: (using unsigned
to avoid overflow)
unsigned bitCount(unsigned int n)
{
return (int)log2(n)+1;
}
Using the above function, I determine the number of bits, which if found to be an odd number, I toggle the middle bit at (c/2) + 1
position, else I set the middle bits at (c/2) + 1
and c/2
positions, considering said bit count that is obtained to be some value c
. Thereafter, I implemented a function for handling the case with odd count of bits by taking the number and bit position (say b
) as input, wherein I toggle my number using ^
at set position b
:
int toggle(int n, int b)
{
return (n ^ (1 << (b - 1)));
}
Similarly, I implemented another function for handling the even bit count case by taking two bit positions as input parameters (apart from the number itself) and toggling both of them at their set positions (via left shifts) with respect to the concerned number:
int toggleTwo(int n, int bitOne, int bitTwo)
{
return ((n ^ (1 << (bitOne - 1))) ^ (1 << (bitTwo - 1)));
}
Note that toggle
can be used twice to handle this case as well.
Here’s the rest of my solution:
int main()
{
unsigned int n;
std::cin >> n;
int c = bitCount(n);
int result = (c & 1) ? toggle(n, (c / 2) + 1) : toggleTwo(n, (c / 2) + 1, c / 2);
// Alternatively, one can use (c % 2 != 0) for the condition to rule out parity (odd if true), but given my love for bitwise operators, I prefer the above :)
std::cout << result << "\n";
return 0;
}
Anirban | 04/18/2020 |