I have answered the following kata: Lost number in number sequence. The description is:
"An ordered sequence of numbers from 1 to N is given. One number might have deleted from it, then the remaining numbers were mixed. Find the number that was deleted.
Example:
The starting array sequence is [1,2,3,4,5,6,7,8,9]
The mixed array with one deleted number is [3,2,4,6,7,8,1,9]
Your function should return the int 5.
If no number was deleted from the array and no difference with it, your function should return the int 0.
Note that N may be 1 or less (in the latter case, the first array will be [])."
I have written a simple answer:
import java.util.*;
public class Kata {
public static int findDeletedNumber (int[] arr, int[] mixedArr) {
Arrays.sort(mixedArr);
for(int i = 0; i < arr.length; i++){
try{
if(arr[i] != mixedArr[i]){
return arr[i];
}
}catch(ArrayIndexOutOfBoundsException e) {
return arr[i];
}
}
return 0;
}
}
I was reading other people's answers and I found one which I find very hard to understand deeply:
import java.util.Arrays;
public class Kata {
public static int findDeletedNumber(int[] arr, int[] mixedArr) {
return Arrays.stream(arr).reduce((a, b) -> a ^ b).orElse(0) ^ Arrays.stream(mixedArr).reduce((a, b) -> a ^ b).orElse(0);
}
}
The link to the answer: https://www.codewars.com/kata/reviews/595be553429e11365c00006f/groups/59bef3a1eda42eb0bc001612
I would like to have some help, if anyone cares and have the patience to write an explanation and/or a trace, would be helpful. Currently I can see the answer but I do not understand it. 🤯
In addition I have tried to understand it by myself reading:
What does the ^ operator do in Java?
https://www.geeksforgeeks.org/bitwise-operators-in-java/
Truth table of XOR (Exclusive-OR)
X Y result
0 0 0
0 1 1
1 0 1
1 1 0
What means X^Y? Let´s look at an example, 5^6
dec bin
5 = 101
6 = 110
------------------ xor
3 = 011
XOR-ing two numbers is just converting the two numbers to binary and apply the rules in the truth table.
Looking at the table above, it is obvious that X^X = 0 for any integer X
5 = 101
5 = 101
------------------ xor
0 = 000
and X^0 = X
5 = 101
0 = 000
------------------ xor
5 = 101
Given your two arrays XOR-ing each element in both arrays and XOR-ing the result means something like
(1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ 8 ^ 9) ^ (3 ^ 2 ^ 4 ^ 6 ^ 7 ^ 8 ^ 1 ^ 9)
and because X^Y = Y^X and X^Y^Z = (X^Y)^Z = X^(Y^Z) you can rearrange the above to
(1 ^ 1) ^ ( 2 ^ 2) ^ (3 ^ 3) ^ (4 ^ 4) ^ (5) ^ (6 ^ 6) ^ (7 ^ 7) ^ (8 ^ 8) ^ (9 ^ 9)
everything cancels each other out except for the missing number, i.e 5.
Related
I'm trying to solve the following problem from the section Bit Manipulation at the Hacker Rank site using new features of Java 8 such as Streams.
The problem description:
Given an integer, n, find each x such that:
0 <= x <= n
n + x = n ^ x
where ^ denotes the bitwise XOR operator. Then print an integer denoting the total number of x's satisfying the criteria above.
Constraints
0 <= n <= 1015
Sample Input: 5
Sample Output: 2
Explanation:
For n = 5, the x values 0 and 2 satisfy the conditions:
5 + 0 = 5 ^ 0 = 5
5 + 2 = 5 ^ 2 = 7
Thus, we print 2 as our answer.
Sample Input: 10
Sample Output: 4
Explanation:
For n = 10, the x values 0, 1, 4, and 5 satisfy the conditions:
10 + 0 = 10 ^ 0 = 10
10 + 1 = 10 ^ 1 = 11
10 + 4 = 10 ^ 4 = 14
10 + 5 = 10 ^ 5 = 15
Thus, we print 4 as our answer.
My code is as follows:
public class SumVsXor
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
long n = in.nextLong();
long count = LongStream.rangeClosed(0, n)
.filter(k -> k + n == (k ^ n))
.count();
System.out.println(count);
}
}
The problem is this code doesn't pass all the test cases.
It works for small values of n, but for large values such as 1000000000000000 it fails due to timeout.
I wonder whether LongStream can't handle Streams with that many elements.
The problem with your code is that it is very inefficient. For the case of n==1000000000000000, your Stream pipeline is performing 1,000,000,000,000,000 addition and XOR operations, which takes a long time. Testing for each number between 0 and n whether n + x == n ^ x would take a long time even if you use a for loop instead of Streams.
Instead of checking all the numbers between 0 and n, you should try to figure out a better way to calculate the required total number of x's. That fact that this problem appears under a "Bit Manipulation" section should give you a hint
to look into the bits of numbers that satisfy n + x == n ^ x.
Let's consider the case of n==1000000000000000. The binary representation of that large number is
0000000000000011100011010111111010100100110001101000000000000000
=== == = ====== = = = == == =
--- - - - - -- -- --- - ---------------
~~~~~~~~~~~~~~
In order for n + x to be equal to n ^ x, x must have a 0 value in all the bits corresponding with the 1 bits of n (marked with = above), and either 0 or 1 value in the bits corresponding with the 0 bits of n (marked with - above). This doesn't include the leading 0s (marked with ~ above), since x must be <= n, so any leading 0s in n must also have a 0 value in x.
This means that the total number of x's for which n + x == n ^ x is 2the number of 0s in n, not including leading 0s.
In the case of n = 1000000000000000, there are 30 such 0 bits, so the total number of x's that satisfy the requirement is 230.
Here's one way to compute the total number of x's :
long n = 1000000000000000L;
int zeroBitsCount = 0;
while (n > 0) {
if (n % 2 == 0) {
zeroBitsCount++; // counts the number of non-leading 0 bits
}
n = n >> 1; // divide n by 2 in order to examine the next bit in the next iteration
}
long total = 1L << zeroBitsCount; // the total is 2^(the 0 bits count)
I came to the same result, but via a different explanation, so thought I might post it here.
Eran's answer got to the same conclusion that I did : to modify the zeroes in the binary representation of the initial number - that is pretty straightforward.
Let's suppose our number is
101010100
so it has 5 zeroes.
you need all the possible combinations of:
a single zero
two zeroes
three zeroes
four zeroes
five zeroes
that is actually :
comb(1,5) + comb(2,5) + comb(3,5) + comb(4,5) + comb (5,5)
that is a well known formula being equal to:
pow(2,n) // where n is five in our case
from there the solution is obvious...
This is a simple question if you know little bit about XOR. I don't know much about java. But I can explain in python.
1.First convert the number to binary.
2.Count the number of zeros in that binary number.
3.print 2 ^ (number of zeros) and that's it.
Here is my python code.
n = int(input())
sum = 0
if n!=0:
n=str(bin(n))
for i in range(len(n)):
if n[i]=='0':
sum = sum + 1
print(2**(sum-1))
else: print(1)
The reason to decrement the sum by 1 is, in python it convert the number to the binary as this format. e.g: 0b'10101.
public static void main (String[] args) {
Scanner in = new Scanner (System.in);
long n = in.nextLong();
long count = 1L << (64-Long.bitCount(n)-Long.numberOfLeadingZeros(n));
System.out.println(count);
}
Following implementation finds subsets of a set, but could anyone please explain what if((i&(1<<j)) > 0) is doing and for what reason?
The comment don't seem to help out and tried console logging, yet it is still difficult to see what it is doing exactly.
//Print all subsets of given set[]
static void printSubsets(char set[]) {
int n = set.length;
//Run a loop for printing all 2^n subsets one by one
for(int i=0; i<(1<<n); i++) {
System.out.print("{ ");
//Print current subset
for(int j=0; j<n; j++) {
//(1<<j) is a number with jth bit 1
//so when we 'and' them with the
//subset number we get which numbers
//are present in the subset and which are not
if((i&(1<<j)) > 0) {
System.out.print(set[j] + " ");
}
}
System.out.println("}");
}
}
public static void main(String args[]) {
char set[] = {'a', 'b', 'c'};
printSubsets(set);
}
In a subset, each element may be either present, or not. So each element has only 2 possible states: in or out. 1 or 0. If we look at the binary representation of numbers from 0 to 2^n -1, where n is the number of elements, for example when n=3, we have:
cba
0 = 000
1 = 001
2 = 010
3 = 011
4 = 100
5 = 101
6 = 110
7 = 111
There are 8 possible subsets, and the bits represent whether an element is in the subset or not.
This is the idea used by the program:
The outer loop goes from 0 until 2^n-1.
The inner loop goes from 0 until n-1.
1<<j is 1 shifted to the left j times.
For example, when i=3, that corresponds to bits 011.
We loop from 0 until 2, comparing i against 001, 010, and 100.
For these values, the expression i & (1 << j) will be evaluated as
011 & 001 = 001, 011 & 010 = 010, and 011 & 100 = 000, respectively.
The first two are greater than 0, the last one is not.
So System.out.print(set[j] + " ") will print a and b.
Here is the original code:
public static String reverseString(String s){
if(s == null) return "";
char[] rev = s.toCharArray();
int i = 0, j = s.length() - 1;
while(i < j) {
rev[i] ^= rev[j];
rev[j] ^= rev[i];
rev[i++] ^= rev[j--];
}
return String.valueOf(rev);
}
My question is how does Xor work in swapping character values here, and why is rev[i++]^=rev[j--] needed here?
The code is equivalent to
rev[i] ^= rev[j];
rev[j] ^= rev[i];
rev[i] ^= rev[j];
i++; j--;
The last part is just needed to increment i and decrement j for the next loop iteration.
As to why x ^= y; y ^= x; x ^= y works to swap the values, I don't know why, but you can see that it works on 1-bit values by look at all four possibilities:
start after x^=y after y^=x after x^=y
x y x y x y x y
0 0 0 0 0 0 0 0
0 1 1 1 1 0 1 0
1 0 1 0 1 1 0 1
1 1 0 1 0 1 1 1
So you can see that in all cases, the x and y bits are swapped. When the statements are applied to larger integers, the ^ operator works on all bits in parallel, so the end result is that every pair of bits is swapped, i.e. the entire values are swapped.
XOR operator has this very unique operator that it acts as inequality detector meaning only when the two bits differ result will be 1 else result is 0.
Now take this for example say in A^B, ith bit 1, this means that ith bit of A and B differ. Meaning one of them is 1 and the other is 0.
Now when we do this (A^B)^B , if the ith bit in B was 0, what we will get is 1 since 1^0 = 1, which is equal to ith bit in A and (A^B)^A = 0, which is ith bit in B.
Similarly,When ith bit is B is 1 and in A is 0, again swapping occurs.
Same logic applies to when ith bit in A^B is 0. You can veryify it very easily.
Its easy to see how the swapping is occurring, When you xor the original number with A^B, you get the other number, because swapping happens for each of the respective bits
The below routine is expected to swap the values of a and b
a = a ^ b
b = b ^ a
a = a ^ b
Let's analyze to see how and why the swap works.
For that, let's not swap the values, but store them in separate variables, so we can see what exactly goes on.
a0 = a ^ b
b1 = b ^ a0
a1 = a0 ^ b1
Simplifying the equations using below properties of XOR. Check XOR Properties#Wikipedia for reference
commutative (a ^ b == b ^ a)
associative (a ^ (b ^ c) == (a ^ b) ^ c)
a ^ a == 0
0 ^ a == a
a0 = a ^ b // Equation #1
b1 = b ^ a0
a1 = a0 ^ b1
b1 = b ^ a0 // Equation #2
= b ^ (a ^ b) // Using Equation #1
= b ^ (b ^ a) // Property #1
= (b ^ b) ^ a // Property #2
= 0 ^ a // Property #3
= a // Property #4
a1 = a0 ^ b1
= a0 ^ (b ^ a0) // Using Equation #2
= (a ^ b) ^ (b ^ (a ^ b)) // Using Equation #1
= (b ^ a) ^ (b ^ (b ^ a)) // Using Property #1
= (b ^ a) ^ ((b ^ b) ^ a) // Using Property #2
= (b ^ a) ^ (0 ^ a) // Using Property #3
= (b ^ a) ^ a // Using Property #4
= b ^ (a ^ a) // Using Property #2
= b ^ 0 // Using Property #3
= b // Using Property #4
As you can see, b1 now contains the original value of a and a1 contains the original value of b, i.e. the values of b and a are swapped
In summary, a^=b;b^=a;a^=b is just an idiomatic expression, nothing magical in it :)
Plain English explanation for the same
XOR sets the bits when the operand bits are dissimilar and resets the bits otherwise
Let's walk through the transformations that take place with an example. For that let's say, we have the following numbers (in binary) assigned to the variables.
a = 1 1 0 0
b = 1 0 1 0
Step #1: a = a ^ b // CREATE A MASK
a = 0 1 1 0
b = 1 0 1 0
Imagine the new value of a is a mask for generating the old value of a given b or generating the old value of b given a.
Step #2: b = b ^ a // Recover original value of a using mask and original value of b
a = 0 1 1 0
b = 1 1 0 0
Since b is still preserved/untouched, we can recover original value of a with the mask - which is what we did in this step
Step #3: a = a ^ b // Recover original value of b using mask and original value of a
a = 1 0 1 0
b = 1 1 0 0
Now we have the original value of a in variable b, so we can use our same mask to recover the original value of b. We can overwrite the mask now, since we don't need the mask after this step.
If you will agree that y == (x^y)^x == x^(y^x), then you have the answer.
Consider an abstract version of the loop body in the code you gave:
a = a ^ b
b = b ^ a
a = a ^ b
Now rename one value to clarify what's happening:
a_xor_b = a ^ b
b = b ^ a_xor_b // Now b is the original a because b^(a^b) == a!
a = a_xor_b ^ b // Now a is the original b because (a^b)^a == b!
Now note the code works fine if a_xor_b is the same variable is a.
It may be easier to first consider a different (but closely related) way of swapping two number values a and b:
a = a + b;
b = a - b;
a = -b + a;
This works both with pure arbitrary-precision numbers, and with integers modulo N (integers that wrap around when they get too big or small, like they do in Java).
To analyze this mathematically, we should assign a new symbol each time a value would change so that = can represent mathematical equality instead of assignment. Then, it is just a matter of basic algebra.
a1 = a0 + b0
b2 = a1 - b0 = (a0 + b0) - b0 = a0
a2 = -b2 + a1 = -(a0) + (a0 + b0) = b0
What about XOR? One way to explain XOR is to think of it as binary addition without carrying. Performing a swap with XOR is then equivalent to performing the "addition swap" described above on each bit modulo 2. The expression can be simplified, though, since in addition modulo 2, each number is its own inverse (equivalently, addition and subtraction are the same). This (with commutativity) gives us the familiar:
a = a ^ b;
b = b ^ a;
a = a ^ b;
In general, the "addition swap" above can be performed in any mathematical group (even if it is non-commutative -- basically just associativity and inverses are needed). Another way of thinking of XOR is just that it induces a group structure on the n-bit integers, and so swapping works just as it does in any group.
I was trying to solve this question but the automated judge is returning "time limit exceeded" (TLE).
On the occasion of Valentine Day , Adam and Eve went on to take part in a competition.They cleared all rounds and got into the finals. In the final round, Adam is given a even number N and an integer K and he has to find the greatest odd number M less than N such that the sum of digits in binary representation of M is atmost K.
Input format:
For each test case you are given an even number N and an integer K
Output format:
For each test case, output the integer M if it exists, else print -1
Constraints:
1 ≤ T ≤ 104
2 ≤ N ≤ 109
0 ≤ K ≤ 30
Sample input:
2
10 2
6 1
Sample output:
9
1
This is what I have done so far.
static long play(long n, int k){
if(k==0) return -1;
if(k==1) return 1;
long m=n-1;
while(m>0){
long value=Long.bitCount(m); //built in function to count bits
if(value<=k ){
return m;
}
m=m-2;
}
return -1;
}
public void solve(InputReader in, OutputWriter out) {
long start=System.currentTimeMillis();
int t=in.readInt();
while(t-->0){
long n=in.readLong();
int k=in.readInt();
long result=play(n,k);
out.printLine(result);
}
long end=System.currentTimeMillis();
out.printLine((end-start)/1000d+"ms");
}
}
According to updated question N can be between 2 and 10^9. You're starting with N-1 and looping down by 2, so you get up to about 10^9 / 2 iterations of the loop. Not good.
Starting with M = N - 1 is good. And using bitCount(M) is good, to get started. If the initial bitcount is <= K you're done.
But if it's not, do not loop with step -2.
See the number in your mind as binary, e.g. 110101011. Bit count is 6. Let's say K is 4, that means you have to remove 2 bits. Right-most bit must stay on, and you want largest number, so clear the two second-last 1-bits. Result: 110100001.
Now, you figure out how to write that. And do it without converting to text.
Note: With N <= 10^9, it will fit in an int. No need for long.
You'll have to perform bitwise operations to compute the answer quickly. Let me give you a few hints.
The number 1 is the same in binary and decimal notation: 12 = 110
To make the number 102 = 210, shift 1 to the left by one position. In Java and many other languages, we can write this:
(1 << 1) == 2
To make the binary number 1002 = 410, shift 1 to the left by two positions:
(1 << 2) == 4
To make the binary number 10002 = 810 shift 1 to the left by three positions:
(1 << 3) == 8
You get the idea.
To see if a bit at a certain position is 1 or 0, use &, the bitwise AND operator. For example, we can determine that 510 = 1012 has a 1 at the third most significant bit, a 0 at the second most significant bit, and a 1 at the least significant bit:
5 & (1 << 2) != 0
5 & (1 << 1) == 0
5 & (1 << 0) != 0
To set a bit to 0, use ^, the bitwise XOR operator. For example, we can set the second most significant bit of 710 = 1112 to 0 and thus obtain 510 = 1012:
7 ^ (1 << 1) == 5
As the answer is odd,
let ans = 1, here we use 1 bit so k = k - 1;
Now binary representation of ans is
ans(binary) = 00000000000000000000000000000001
while(k > 0):
make 30th position set
ans(binary) = 01000000000000000000000000000001
if(ans(decimal) < N):
k -= 1
else:
reset 30th position
ans(binary) = 00000000000000000000000000000001
Do the same from 29th to 1st position
There is a question of implementing a code in Java where I have to find if the string has unique characters or not without having to create a new data structure.
The Java implementation was as follows:
public static boolean isUniqueChars(String str) {
int checker = 0;
for (int i = 0; i < str.length(); ++i) {
int val = str.charAt(i) - 'a';
if ((checker & (1 << val)) > 0) return false;
checker |= (1 << val);
}
return true;
}
In line 5-6, there's the << that I don't really get.
And in line 6, I don't get what the '|' symbol does.
Could someone give a brief explanation of how this code works?
Thanks.
1. For this symbol : <<
In your code : 1 << val means (int)Math.pow(2,val) = 2 ^ val
2. For this symbol : >>
>> is bit-shift operator
x >> N means (if you view it as a string of binary digits):
The rightmost N bits are discarded
The leftmost bit is replicated as many times as necessary to pad the result to the original size (32 or 64 bits),
e.g.
00000000000000000000000000101011 >> 2 -> 00000000000000000000000000001010
11111111111111111111111111010100 >> 2 -> 11111111111111111111111111110101
3. For this symbol : |=
it means bitwise inclusive OR and assignment operator
E.g:
checker |= (1<<val)
is same as checker |= (2^val)
is same as checker = checker | (2^val) (*)
then : A | B ( | means Binary OR Operator copies a bit if it exists in either operand)
Example
A = 00101010
B = 01101000
A | B = 01101010
with
0 OR 0 = 0 , 1 OR 0 = 1
1 OR 1 = 1 , 0 OR 1 = 1
Using Ziprox's helpful hint that (1 << val) is equivalent to 2^val or Math.pow(2,val). It becomes much easier to decipher what is happening.
I believe 'int' is 4 bytes long which is 32 bits. This method is converting each letter in the alphabet (undercase) to number 2 ^ val. Basically, each letter is represented by a unique bit of the variable checker. 26 letters, 32 bits gives you 6 extra bits that do nothing.
checker & (1<<val)
will only be true of it has seen the number previously.
checker |= (1<<val)
is equivalent to
checker = (checker | (1<<val))
which simply flips that letter's bit from 0 to 1 to indicate that it has been seen.