How does using XOR to find a single element with odd number of occurrences in an array work? - c

Consider this problem:
You are given an array containing positive integers. All the integers occur even number of times except one. Find this special integer.
Solution:
The integer with the odd number of occurrences will have 0 or more pairs and one single number. So, if we could some how get rid of all the pairs then all we'd be left with is the single number. Now, what gets rid of pairs? Hint: think of an operator.
XOR will do the trick. Its gives you O(n) solution with no extra memory.
int GetSpecialOne(int[] array, int length)
{
int specialOne = array[0];
for (int i=1; i < length; i++)
{
specialOne ^= array[i];
}
return specialOne;
}
I don't understand how reducing the array by accumulating the XOR on each element produces the special integer. How does it work?

It works because (N xor Q) xor Q = N.
Exactly one integer is present an odd number of times, so it will be the only number not to "disappear" from the list. All other numbers are present an even number of times so they all appear in groups of 2's (conceivably), so they all "disappear". Also, the "distance" between the XORs don't matter: (((N xor Z) xor Q) xor Z) xor Q = N. The Z's and the Q's "cancel out" even though there are intermediate XORs between the pairs.

The XOR operator has the property that (a ^ a) == 0, and (by extension) that (a ^ b ^ a) == b. Therefore, any value that occurs an even number of times will "cancel" out to zero in the XOR "accumulation", leaving just the odd one out.

Fact one: x XOR x is zero.
This follows from the fact that 0 XOR 0 is zero and 1 XOR 1 is zero.
Fact two: x XOR x XOR x ... x is zero where x appears an even number of times.
This follows from fact one by induction.
Fact three: x XOR x XOR x ... x is x where x appears an odd number if times.
This follows from fact two by writing the expression as
(x XOR x XOR x ... x) XOR x = 0 XOR x = x
where there are 2n terms in the parentheses if there were 2n + 1 terms in the original.
Fact four: XOR is associative and commutative.
This is trivial to verify.
Now it is clear how this code works. The numbers that appear an even number of times are reduced to zero by this code. The sole number that appears an odd number of times is reduced to itself by this code.

^ is an exclusive or operator. Both operands to the bitwise exclusive OR operator must be of integral types. The bitwise exclusive OR operator compares each bit of its first operand to the corresponding bit of its second operand. If one bit is 0 and the other bit is 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0.
If both are either high or low, output is 0 and in all other cases output is 1.
Ex: a^b^a^a^b^c^c => ( c^c =0; b^b = 0; a^a = 0; Finally left with 0^0^0^a = a ) . So, the number which is odd times repeated among the even times repetition in the sequence is the output. You can work with the same example, taking the array elements.

Related

Find Minimum Operand to Maximize sum of bitwise AND operator

Given an array of integers Arr and an integer K, bitwise AND is to be performed on each element A[i] with an integer X
Let Final sum be defined as follows:
Sum of ( A[i] AND X ) for all values of i ( 0 to length of array-1 )
Return the integer X subject to following constraints:
Final sum should be maximum
X should contain exactly K bits as 1 in its binary representation
If multiple values of X satisfy the above conditions, return the minimum possible X
Input:
Arr : [8,4,2]
K = 2
Output: X=12
12 Contains exactly 2 bits in its binary and is the smallest number that gives maximum possible answer for summation of all (A[i] AND X)
Approach Tried :
Took bitwise OR for all numbers in the array in binary and retained the first K bits of the binary that had 1 , made remaining bits 0, convert back to int
Passed 7/12 Test Cases
Can someone help me out with what mistake am I making with regards to the approach or suggest a better approach ? Thanks in advance.
Consider an input like [ 8, 4, 4, 4 ], K = 1. Your algorithm will give 8 but the correct answer is 4. Just because a given bit is more significant doesn't mean that it will automatically contribute more to the sum, as there might be more than twice as many elements of the array that use a smaller bit.
My suggestion would be to compute a weight for each bit of your potential X -- the number of elements of the array that have that bit set times the value of that bit (2i for bit i). Then find the K bits with the largest weight.
To do this, you need to know how big your integers are -- if they are 32 bits, you need to compute just 32 weights. If they might be bigger you need more. Depending on your programming language you may also need to worry about overflow with your weight calculations (or with the sum calculation -- is this a true sum, or a sum mod 2n for some n?). If some elements of the array might be negative, how are negatives represented (2s complement?) and how does that interact with AND?
Let dp[k][i] represent the maximum sum(a & X), a ∈ array, where i is the highest bit index in X and k is the number of bits in X. Then:
dp[1][i]:
sum(a & 2^i)
dp[k][i]:
sum(a & 2^i) + max(dp[k-1][j])
for j < i
sum(a & 2^i) can be precalculated for all values of i in O(n * m), where m is the word size. max(dp[k-1][j]) is monotonically increasing over j and we want to store the earliest instance of each max to minimise the resulting X.
For each k, therefore, we iterate over m is. Overall time complexity O(k * m + n * m), where m is the word size.

Working of bitwise XOR on int operands of arrays

I am just a beginner.So, the problem that I am facing is :-
How does the logic of bitwise XOR works in case of arrays?
For example in the code below:-
// Function to return the only odd occurring element
int findOdd(int arr[], int n) {
int res = 0, i;
for (i = 0; i < n; i++)
res ^= arr[i];
return res;
}
int main(void) {
int arr[] = {12, 12, 14, 90, 14, 14, 14};
int n = sizeof(arr)/sizeof(arr[0]);
printf ("The odd occurring element is %d ", findOdd(arr, n));
return 0;
}
How, exactly, is the whole findOdd function working?
Can someone please explain the basic logic behind the use of xor in the above code example?
You have used bitwise XOR , so it deals with binary bytes. It is not directly applied on array but on binary representation of data stored in it .
And what function does is to find number with odd occurrence in an array.
And using property of XOR operations -
XOR of any number with itself gives us 0,
XOR of any number with 0 gives us number itself.
We can understand the operations in each iteration-
1 iteration- res=0(0000)^12(1100) -> res= 12(1100) // just writing in decimal for clarity
2 iteration- res=12(1100)^12(1100) -> res=0(0000) //operation is done on its binary representation
3 iteration- res=0^14 -> res=14
4 iteration- res=14 (00001110) ^ 90 (01011010) -> res=84 (01010100)
5 iteration- res=84^14-> res=90
6 iteration- res=90^14 -> res=84
7 iteration- res=84^14-> res=90
Therefore , res return 90 as result.
When do we use the bitwise XOR in arrays?
It perform operations on bits , not on a whole array.And is used in similar way as we use it on two numbers.
Working of xor on arrays is not different from normal xor or bitwise xor. To understand the logic better, following are the properties of xor.
xor of same bits returns 0
xor of different bits returns 1
Now, The array contains only one element that occurs odd number of times. So, When xor is applied on two same numbers, result is 0 and xor of 0 and any number gives the number itself.
Hence, when we xor all the elements in the array, even occurrences cancel out by returning 0 and final result remains as the only odd occurring element.
HTH.
The findOdd function uses the ^ or bitwise xor operator.
You already know about arithmetic operators like +, or -, etc.
The xor operator has some properties in common with addition and multiplication. It is:
Commutative (ie. A xor B is the same as B xor A)
Associative (ie. A xor (B xor C) is the same as (A xor B) xor C).
The bitwise xor simply does the xor operation on each bit of the operands in parallel. Given these two properties, we can xor the array elements in any order without altering the result.
Now, consider the bitwise xor of 2 numbers. It is always 0:
A^A == 0
For every evenly occurring number, we can pair them up, and the bitwise xor of these pairs are 0.
Therefore, the bitwise xor of the array, is the bitwise xor of the oddly occurring elements of the array.
If there is only one element which occurs an odd number of times, findOdd will return this number.
However, be warned, that if there are more than one set of oddly occurring numbers, the function will not do what you might expect.
Eg. taking the xor of {5, 2, 2, 7}, the 2's cancel out, but we are left with, which is 5^7 = 0b101 ^ 0b111 = 0b010 = 2.

Fixed point code division understanding

Code for division by 9 in fixed point.
1. q = 0; // quotient
2. y = (x << 3) - x; // y = x * 7
3. while(y) { // until nothing significant
4. q += y; // add (effectively) binary 0.000111
5. y >>= 6; // realign
6. }
7. q >>= 6; // align
Line 2 through 5 in the FIRST execution of while loop is effectively doing
x*.000111 (in decimal representation x*0.1), what it is trying to achieve in subsequent while loops?
Should it not be again multiplying that with 7 and again shifting instead
of doing only shifting to take care of recurrence?
Explanation with respect to plain decimal number multiplication as to what is being achieved with only shifting would be nice.
Detailed code explanation here:
Divide by 9 without using division or multiplication operator
Lets denote 7/64 by the letter F. 7/64 is represented in binary as 0.000111 and is very close to 1/9. But very close is not enough. We want to use F to get exactly to 1/9.
It is done in the following way
F+ (F/64) + (F/64^2) + (F/64^3) + (F/64^4)+ (F/64^5) + ...
As we add more elements to this sequence the results gets closer to 1/9
Note each element in the sequence is exactly 1/64 from previous element.
A fast way to divide by 64 is >>6
So effectively you want to build a loop which sums this sequence. You start from F and in each iteration do F>>6 and add it to the sum.
Eventually (after enough iterations) the sum will be exactly 1/9.
Ok now, you are ready to understand the code.
Instead of using F (which is a fraction and cannot be represented in fixed points) the code multiplies F by x.
So the sum of the sequence will be X/9 instead of 1/9
Moreover in order to work with fixed points it is better to store 64*X*F and the result would by 64*X/9.
Later after the summation we can divide by 64 to get the X/9
The code stores in the variable y the value of F*x*64
variable q stores the sum of the sequence. In each loop iteration we generate the next element in the sequence by dividing the previous element by 64 (y>>=6)
Finally after the loop we divide the sum by 64 (q>>=6) and get the result X/9.
Regarding you question. We should not multiply by 7 each time or else we will get a sum of the sequence of
F+ (F^2) + (F^3) + (F^4) + (F^5)...
This would yield a result of ~X/(8+1/7) instead of X/9.
Shifting by one to the left multiplies by two, shifting by one to the right divides by two. Why?
Shifting is the action of taking all the bits from your number and moving them n bits to the left/right. For example:
00101010 is 42 in Binary
42 << 2 means "shift 42 2 bits to the left" the result is
10101000 which is 168 in Binary
we multiplied 42 by 4.
42 >> 2 means "shift 42 2 bits to the right" the result is
00001010 which is 10 in binary (Notice the rightmost bits have been discarded)
we divided 42 by 4.
Similarly : (x << 3) is x * 8, so (x << 3) - x is (x * 8) - x => x * 7

CRC (cyclic redundancy check) Understanding an Optimization

Over the past few days I've been trying to understand how CRC works. I am stuck on a particular optimization that is recommended for its implementation.
What I understand:
*CRC is polynomial division where bits represent powers of x. I can do a division (using regular polynomial division or using bits) and correctly get the CRC.
*A shift register is used to hold the remainder. It is n bits (for a polynomial of degree n) because each subtraction affects at most n bits. Once the entire message is fed through the register, it contains the division remainder.
Where I'm stuck:
On this page:
http://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks
the Implementation section has some pseudocode. I'm fine with the first pseudocode and with its two problems (though the first is easily solved). I cannot understand the second, and how associativity/commutativity of xor helps. By hand, I see that the second pseudocode works, but why?
Other sources:
A few other articles give this same optimization (feeding the bits in at the left of the register rather than the right). In particular, this article:
http://www.ross.net/crc/download/crc_v3.txt
in section 10 does it (text-search the word mangled). Except that this does it with tables, and I'm not ready for tables yet! It does say that the final n iterations serve only to get the tail of the message to the left of the register, and I understand that, but again I can't understand the optimization here.
Edit: I found another reference (page 8):
http://www.hackersdelight.org/crc.pdf
but this one still doesn't help. It says that pre-multiplying is the same as post-multiplying, but I don't see how this is true given that this changes the bits that are in the register when 1 bits are found at the left of the register (to trigger a subtraction).
Thanks. I appreciate your help with my curiosity here!
Dan
In the first pseudo-code, the remainder is initialized with leading portion of the input bit string. Then during iterations, in each step the remainder is up-shifted, and the now-vacant bottom bit is filled with the next bit from the input bit string. To complete the operation, the input bit string needs to be appended with zero. These zeros will effectively flush out data through the remainder during computation.
In the second pseudo-code, the remainder starts clear (full of zeros). During iterations, the next bit from the input bit string is placed directly at the top position in the remainder. Therefore no initialization and no flushing are necessary to complete the computation. In addition, test of the top bit and up-shifting of the remainder operations are re-ordered.
You can convert the first pseudo-code algorithm to the second pseudo-code algorithm in few transformation steps as follows.
Starting with pseudo-code of the basic algorithm (code fragment 1):
function crc(bit array bitString[1..len], int len) {
remainderPolynomial := polynomialForm(bitString[1..n]) // First n bits of the message
for i from 1 to len {
remainderPolynomial := remainderPolynomial * x + bitString[i+n] * x0 // Define bitString[k]=0 for k>len
if coefficient of xn of remainderPolynomial = 1 {
remainderPolynomial := remainderPolynomial xor generatorPolynomial
}
}
return remainderPolynomial
}
First transformation is to swap the order of updating the remainder polynomial and testing the top bit i.e. we can test the second-top bit (before up-shifting), then in the if branch update the remainder before xor-ing with the generator polynomial, and add else branch that also updates the remainder (in case the top bit is zero). Further, note that update of the remainder is essentially up-shifting it and then setting the empty bottom bit to the next bit from the input bit string. So the + operation is basically doing 0 + ? and this is equivalent to 0 xor ?. By applying these principles we now get the following equivalent pseudocode:
function crc(bit array bitString[1..len], int len) {
remainderPolynomial := polynomialForm(bitString[1..n]) // First n bits of the message
for i from 1 to len {
if coefficient of xn-1 of remainderPolynomial = 1 {
remainderPolynomial := (remainderPolynomial * x xor bitString[i+n] * x0) xor generatorPolynomial
} else {
remainderPolynomial := remainderPolynomial * x xor bitString[i+n] * x0
}
}
return remainderPolynomial
}
Now, notice that in the loop we take bitString[i+n] and put it at x0 position. The bit then gets shifted up during subsequent computation. We can conceptually change bitString[i+n] * x0 to bitString[i] * xn. And if we take it out of the if/else branches and do it before up-shifting the remainder (... * x), we get ... xor bitString[i] * xn-1. And because we are now placing bits from the input bit string at the top of the remainder, we simply clear the remainder at the beginning and do not need to append zeros to flush out the data through the remainder register. Voila, we now have pseudo-code of the modified algorithm (code fragment 2):
function crc(bit array bitString[1..len], int len) {
remainderPolynomial := 0
for i from 1 to len {
remainderPolynomial := remainderPolynomial xor (bitstring[i] * xn-1)
if (coefficient of xn-1 of remainderPolynomial) = 1 {
remainderPolynomial := (remainderPolynomial * x) xor generatorPolynomial
} else {
remainderPolynomial := remainderPolynomial * x
}
}
return remainderPolynomial
}

Need to know if a number is divisible after an operation

I have a number on which I perform a specific operation
I want to make sure that the number is still divisible after the operation.
Let's say I have an integer x which is divisible by PAGE_S
does this produces an integer which is also divisible by PAGE_S ?
x^ ~(PAGE_S-1);
so (x % PAGE_S) == ( (x^ ~(PAGE_S-1)) % PAGE_S) ?
As far as I tested, it works, but I need to understand why...
p.s this is part of a code of translating virtual memory addresses to physical addresses
Yes, but only if PAGE_S is a power of two.
If PAGE_S is a power of two (say, 2k), then its binary representation is a 1 followed by k 0s. So, PAGE_S-1 will be k 1s in binary, so ~(PAGE_S-1) is all 1s followed by k 0s.
The xor operation (^) will flip any bits of the first operand for which the corresponding bit in the second operand is 1; for example, 101101 ^ 111000 is 010101 because the first three bits are flipped.
Since x is divisible by PAGE_S, the last k bits must be zero. Since the last k bits of ~(PAGE_S-1) are also zero, the last k bits of x^~(PAGE_S-1) are zero so it is divisible by PAGE_S. This also inverts all the other bits of x.

Resources