I'm going through "Elements of Programming Interviews" and the very first question is about computing the parity of a number ( whether the number of 1's in the binary representation is even or odd). The final solution provided does this:
short Parity(unsigned long x) {
x ^= x >> 32;
x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
x &= 0xf;
...
I understand that with that final value of x you can lookup the answer in a lookup table = 0x6996. But my question is why does the above code work? I've worked a 16 bit example out by hand and it does give the correct parity, I just don't understand it conceptually.
The lookup table is confusing. Let's drop it and keep going:
...
x ^= x >> 2;
x ^= x >> 1;
p = x&1;
To figure it out, let's start with the 1-bit case. In the 1-bit case, p=x, so if x is 1 the parity is odd, and if x is 0 the parity is even. Trivial.
Now the two bit case. You look at b0^b1 (bit 0 XOR bit 1) and that's the parity. If they're equal, the parity is even, otherwise it's odd. Simple, too.
Now let's add more bits. In the four bit example - b3 b2 b1 b0, we calculate x ^ (x>>2), which gives us a two bit number: b3^b1 b2^b0 . These are actual two parities - one for the odd bits of the original number, and one for the even bits of the original number. XOR the two parities and we get the original parity.
And now this goes on and on for us many bits as you want.
It works because,
the parity of a single bit is itself (base case)
the parity of the concatenation of bitstrings x and y is the xor of the parity of x and the parity of y
That gives a recursive algorithm by splitting every string down the middle until it's a base case, which you can then group by layer and flip upside down to get the code shown in the question .. sort of, because it ends early and apparently does the last step by lookup.
For an n bit number x, the answer is always in the rightmost n/(2 to the power z) bits of x after z iterations.
Let's take an example where n=8 and x=10110001 (b7, b6, b5, b4, b3, b2, b1, b0).
It's actual/correct answer is even_parity.
After 1 iteration
10110001
00001011
___________
x = 10111010
Rightmost 8/(2 to the power 1) = 4 digits of x = 1010(even parity)
After 2 iterations
10111010
00101110
___________
x = 10010100
Rightmost 8/(2 to the power 2) = 2 digits of x = 00(even parity)
After 3 iterations
10010100
01001010
___________
x = 11011110
Rightmost 8/(2 to the power 3) = 1 digit of x = 0(even parity)
Now we can extract any dth digit of a number b by ANDING it with a
number q in which only the dth digit is 1(one) and all other digits are 0(zero).
Here we want to extract the (0th digit)/(rightmost digit) of final value of x.
So let's AND it(i.e, ( final_value_of_x
(i.e, 11011110)
)
after (
2 to the power(
log n to the base 2
)
) iterations
) with 00000001 to get the answer.
11011110
00000001
_________________
00000000
Related
I have a bitwise equation of the form
X = (A & X) + (B & X)
where A and B are known integers and X is unknown, How do I find X?
Here, & is Bitwise AND and + is Arithmetic addition, A, B, and X are integers.
One of the trivial solutions is zero but I have to return that if no other solution is possible.
My approach: I know the range of X so I could iterate over it in O(n) to check for the condition but the range could be very large so it might not be efficient.
Also, I tried doing AND operations on both sides to shorten the equation but cannot come to a meaningful solution.
Let's begin by focusing on just one bit of X, the very last bit. It can be either 0 or 1, and depending on how A and B are structured, we may be able to rule certain options out. There are four combinations of the last bits of A and B, but there's really only three cases to consider because of symmetry:
Case 1: A and B end in zero. In that case, A & X ends in 0 and B & X ends in 0. Therefore, since X = A & X + B & X, the last bit of X must be 0.
Case 2: One of A and B ends in 1 and the other ends in 0. Assume, without loss of generality, that A ends in 1 and B ends in 0. Then A & X + B & X = 0 + X = X, so either choice of bit for the last bit of X works.
Case 3: A and B end in 1. In that case, A & X ends with the last bit of X and B & X ends with the last bit of X. Then the last bit of X is given by A & X + B & X = X + X = 2X = 0, since multiplying any bit by two and looking at the lowest resulting bit gives 0.
Stated differently, in each case for the combination of A and B bits, we can determine what bit(s) are possible for X by consulting a table and then move one position to the right to process the next bit. The table, specifically, is shown here
A | B | X
---+---+---
0 | 0 | 0
0 | 1 | any
1 | 0 | any
1 | 1 | 0
Note that this matches your intuition that zero is always a solution, since these rules allow you to pick 0 for any bit that you'd like. But if you'd like to find a solution that isn't 0 everywhere, just fill in 1s any time you have a choice.
As an example, suppose A in binary is 011101001 and B in binary is 001101010. Then, using this table, we have these options:
A 011101001
B 001101010
X 0*00000*0
That gives four possibilities:
010000010
010000000
000000010
000000000
And we can check that, indeed, each of these is a solution to X = A & X + B & X.
This solution runs in time O(b), where b is the number of bits in the numbers A and B. That's O(log A + log B), if you're given A and B numerically, which means that this is way faster than a brute-force search.
Hope this helps!
I encountered a problem recently I have a hard time finding the answer.
This is the question:
Consider a set of numbers.There are tree kinds of input:
1 x
2 x
3
The first command adds integer x to the set.
The second one means for every element y in list, put:
y = y xor x
and The last command prints the biggest number in the set. for instance:
10
3
1 7
3
2 4
2 8
2 3
1 10
1 3
3
2 1
results:
0
7
15
if n is the number of commands in input:
and:
also there is a 1 second execution time limit!
My solution so far:
lets call the set S and have an integer m which initially is 0.as you know:
number = number xor x xor x
meaning that if we apply xor twice on something then the its effect is reversed and the original number doesn't change. That being said if we every time we insert a number(command 1) we do the following:
y = y xor m
add y to S
and every time we want to get a number from the set:
find y
y = y xor m
return y
and if command two comes to the following:
m = m xor x
then the problem is almost solved, since initially save the XORed version of the numbers and when needed we do the revers!
But the problem here is to find the largest number in the set( pay attention that the numbers in the set are different from original numbers) so command 3 works right. I don't know how to do this in an efficient time.but I have an idea here:
if we save the binary representation of the numbers in the set in a trie data structure at first the maybe we can quickly find the biggest number. I don't really know how but this idea occurred to me.
so to sum up these are my issues:
problem 1:
how to find the biggest number in the revised list
problem 2:
is this trie idea good?
problem 3:
how can I implement it in code(the language is not very important here) so that it works time find?
also what is the time complexity needed to solve this problem in the first place?
Thanks for reading my question.
Yes your idea is correct, it can be solved in O(N log 10^9) using binary trie data structure.
The idea is to store numbers in binary notation yet putting biggest bits first, so while traversing the trie we can choose a branch that leads to greatest answer.
For determining which branch to choose we can determine this bit by bit, if from some trie node we have 2 branches with values 0 and 1 we choose the one which gives better result after xoring with m
Sample code (C++):
#include <bits/stdc++.h>
using namespace std;
int Trie[4000005][2];
int nxt = 2;
void Add(int x)
{
bitset<32>b(x);
int c = 1;
for(int j=31; j>=0; j--)
if(Trie[c][b[j]])c=Trie[c][b[j]];
else c = Trie[c][b[j]] = nxt++;
}
int Get(int x)
{
bitset<32>b(x),res(0);
int c = 1;
for(int j=31; j>=0; j--)
if(Trie[c][!b[j]])c=Trie[c][!b[j]],res[j]=!b[j];
else c = Trie[c][b[j]], res[j]=b[j];
return res.to_ullong()^x;
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int q,m=0;
cin>>q;
Add(0);
while(q--)
{
int type;
cin>>type;
if(type==1)
{
int x;
cin>>x;
Add(x^m);
}
else if(type==2)
{
int x;
cin>>x;
m^=x;
}
else cout<<Get(m)<<"\n";
}
}
This is very similar to this problem and should be solvable in O(n), because the number of bits for x is constant (for 10^9 you will have to look at the 30 lowest bits).
At start m = 0, each time you encounter the 2nd command you do m ^= x (m = m xor x).
Use a binary tree. Unlike for the linked question the amount of numbers in a bucket doesn't matter, you just need to be able to tell if there is a number that has a certain bit which is one or zero. E.g. for 3-bit numbers 1, 4 and 5 the tree could look like this (left means bit is 0, right means bit is 1):
*
/ \
1 1 there are numbers with highest bit 0 and 1
/ /
1 1 of the numbers with 1st bit 0, there is a number with 2nd bit 0 and ...
\ / \
1 1 1 of the numbers with 1st and 2nd bit 0, there is a number with 3rd bit 1,...
1 4 5 (the numbers just to clarify)
So adding a number just means adding some edges and nodes.
To get the highest number in the set you go down the tree and through the bits of m and calculate the max x as follows:
Initialize node n as the root of the tree, i = 29 the bit of m we are looking at and the solution x = 0.
mi = (m & (1 << i)) >> i (1 if the bit in m is 1, 0 otherwise).
If we look at n and there is only an edge denoting a 0 or if mi == 1 and we have a 0-edge: n becomes the node connected by that edge, x = 2 * x + mi (or more fancy: x = (x << 1) | mi).
Otherwise n becomes the node connected by the 1-edge and x = 2 * x + 1 - mi
If i > 0: decrease i by 1 and continue with step 2.
An example for 3-bit numbers m = 6 (110) and the numbers 1 (001), 4 (100) and 5 (101) in the set, the answer should be 7 (111), i.e. 1 xor 6: First step we go left and x = 1, then we can only go left and x = 3, then we can only go right and x = 7.
Is there a name for this algorithm? (I've been calling it changeBinary)
DESCRIPTION:
You take a binary string as input.
The first bit of the output is the same as the first bit of the input.
Every bit after that is 0 if the bit at that index of the input string is the same as the bit at the previous index in the input string. Otherwise, it's 1.
For example,
Input: 00011000001010100001001000010011
Output: 00010100001111110001101100011010
Here is a simple javascript implementation:
var changeBinary = function(binaryString){
var output = binaryString[0] === '0' ? '0' : 1;
for (var i = 1; i < binaryString.length; i++){
var nextBit = binaryString[i] === binaryString[i - 1] ? '0' : '1';
output += nextBit;
}
return output;
}
OBSERVATIONS:
First, it seems that if you keep applying the algorithm to a string, it eventually returns to its original value. Second, it the number of iterations it takes to do so seems to always be a power of 2 (including 2^0 = 1). For example, if you apply the changeBinary function above 32 times to the string above, it will return to the original value.
Has anyone ever encountered this before, and if so, do you know of any other information about it?
It just seems to me like this is something so simple and basic that someone must have studied it more in depth.
Any feedback would be greatly appreciated.
It may be interesting to know that this is x ^ (x << 1) on a BigInteger (or, if you limit the length of the strings, the same thing but on a fixed-size integer), also describable as clmul(x, 3).
Carryless multiplication, which is essentially just like normal multiplication, but instead of adding the partial products you XOR them, has some fairly nice properties, such as being commutative and associative. The associative property is especially of interest since it allows you to reason easily about what composing your algorithm with itself a couple of times does: for example
changeBinary o changeBinary is clmul(clmul(x, 3), 3) = clmul(x, clmul(3, 3)) = clmul(x, 5)
That it's a carryless multiplication by 3 also explains why it "undoes" itself when applied often enough, as the carryless multiplicative inverse of 3 is the number with all bits set, which with 32 bits is 0xffffffff, which can be formed as 331 (with carryless exponentiation). This also follows from the equivalence of a carryless square to a "bit-spread", so it takes a bit string abcd to a0b0c0d, and thus clpow(3, 32) = 1 - 5 spreads have spread the bits so far apart that only the original lsb is left over, the rest does not fit in a 32bit number.
And that also gives a faster inversion, because the number with all bits set can be decomposed into small number of (carryless) factors:
3 x 5 x 17 x 257 x 65537 ...
With a number of factors that is the base two logarithm of the number of bits (rounded up).
Since x ^ (x >> 1) converts a number to Gray Code, I suppose you might call this a "mirrored" Gray Code. The same trick with the factors is used "in the mirror image" to convert a Gray Code back to binary:
x ^= x >> 1 // this is like a "mirror" of x = clmul(x, 3)
x ^= x >> 2 // 5
x ^= x >> 4 // 17
x ^= x >> 8
x ^= x >> 16
Here we just flip the direction of the shift to get:
x ^= x << 1
x ^= x << 2
x ^= x << 4
x ^= x << 8
x ^= x << 16
Which is clmul(x, 0xffffffff) and has also been called PS-XOR(x)
The algorithm you described is an example of Delta Encoding.
Does anyone know the steps for dividing unsigned binary integers using non-restoring division?
It's hard to find any good sources online.
i.e if A = 101110 and B = 010111
how do we find A divided by B in non-restoring division? What do the registers look like in each step?
Thanks!
(My answer is a little late-reply. But I hope it will be useful for future visitors)
Algorithm for Non-restoring division is given in below image :
In this problem, Dividend (A) = 101110, ie 46, and Divisor (B) = 010111, ie 23.
Initialization :
Set Register A = Dividend = 000000
Set Register Q = Dividend = 101110
( So AQ = 000000 101110 , Q0 = LSB of Q = 0 )
Set M = Divisor = 010111, M' = 2's complement of M = 101001
Set Count = 6, since 6 digits operation is being done here.
After this we start the algorithm, which I have shown in a table below :
In table, SHL(AQ) denotes shift left AQ by one position leaving Q0 blank.
Similarly, a square symbol in Q0 position denote, it is to be calculated later
Hope all the steps are clear from the table !!!
1) Set the value of register A as 0 (N bits)
2) Set the value of register M as Divisor (N bits)
3) Set the value of register Q as Dividend (N bits)
4) Concatenate A with Q {A,Q}
5) Repeat the following “N” number of times (here N is no. of bits in divisor):
If the sign bit of A equals 0,
shift A and Q combined left by 1 bit and
subtract M from A,
else shift A and Q combined left by 1 bit and add M to A
Now if sign bit of A equals 0, then set Q[0] as 1, else set Q[0] as 0
6) Finally if the sign bit of A equals 1 then add M to A.
7) Assign A as remainder and Q as quotient.
We know that for example modulo of power of two can be expressed like this:
x % 2 inpower n == x & (2 inpower n - 1).
Examples:
x % 2 == x & 1
x % 4 == x & 3
x % 8 == x & 7
What about general nonpower of two numbers?
Let's say:
x % 7==?
First of all, it's actually not accurate to say that
x % 2 == x & 1
Simple counterexample: x = -1. In many languages, including Java, -1 % 2 == -1. That is, % is not necessarily the traditional mathematical definition of modulo. Java calls it the "remainder operator", for example.
With regards to bitwise optimization, only modulo powers of two can "easily" be done in bitwise arithmetics. Generally speaking, only modulo powers of base b can "easily" be done with base b representation of numbers.
In base 10, for example, for non-negative N, N mod 10^k is just taking the least significant k digits.
References
JLS 15.17.3 Remainder Operator %
Wikipedia/Modulo Operation
There is only a simple way to find modulo of 2^i numbers using bitwise.
There is an ingenious way to solve Mersenne cases as per the link such as n % 3, n % 7...
There are special cases for n % 5, n % 255, and composite cases such as n % 6.
For cases 2^i, ( 2, 4, 8, 16 ...)
n % 2^i = n & (2^i - 1)
More complicated ones are hard to explain. Read up only if you are very curious.
This only works for powers of two (and frequently only positive ones) because they have the unique property of having only one bit set to '1' in their binary representation. Because no other class of numbers shares this property, you can't create bitwise-and expressions for most modulus expressions.
This is specifically a special case because computers represent numbers in base 2. This is generalizable:
(number)base % basex
is equivilent to the last x digits of (number)base.
There are moduli other than powers of 2 for which efficient algorithms exist.
For example, if x is 32 bits unsigned int then
x % 3 =
popcnt (x & 0x55555555) - popcnt (x & 0xaaaaaaaa)
Not using the bitwise-and (&) operator in binary, there is not. Sketch of proof:
Suppose there were a value k such that x & k == x % (k + 1), but k != 2^n - 1. Then if x == k, the expression x & k seems to "operate correctly" and the result is k. Now, consider x == k-i: if there were any "0" bits in k, there is some i greater than 0 which k-i may only be expressed with 1-bits in those positions. (E.g., 1011 (11) must become 0111 (7) when 100 (4) has been subtracted from it, in this case the 000 bit becomes 100 when i=4.) If a bit from the expression of k must change from zero to one to represent k-i, then it cannot correctly calculate x % (k+1), which in this case should be k-i, but there is no way for bitwise boolean and to produce that value given the mask.
Modulo "7" without "%" operator
int a = x % 7;
int a = (x + x / 7) & 7;
In this specific case (mod 7), we still can replace %7 with bitwise operators:
// Return X%7 for X >= 0.
int mod7(int x)
{
while (x > 7) x = (x&7) + (x>>3);
return (x == 7)?0:x;
}
It works because 8%7 = 1. Obviously, this code is probably less efficient than a simple x%7, and certainly less readable.
Using bitwise_and, bitwise_or, and bitwise_not you can modify any bit configurations to another bit configurations (i.e. these set of operators are "functionally complete"). However, for operations like modulus, the general formula would be necessarily be quite complicated, I wouldn't even bother trying to recreate it.