new to java - trying to understand: checker |= (1 << val) - java

the following code will check to see if you have any duplicate characters in the string, but i don't understand the if clause:
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;
}
I tried to look up some references, I am new to bit shifting, all i understand is that << shifts the binary number left or right. Can you explain to me how checker |= (1 << val) works ? and that 'if' statement as well.

I was also going through this book Cracking the Code Interview and ended up googling for a clear explanations. Finally I understood the concept.
Here is the approach.
Note :
We will assume, in the below code, that the string is only lower case ‘a’ through ‘z’. This will allow us to use just a single int.
Java integer is of size 32
Number of lower case alphabets is 26
So we can clearly set 0/1 (true or false) value inside one integer in
decimal notation.
It is similar to bool visited[32] .
bool uses 1 byte. Hence you need 32 bytes for storing bool visited[32].
Bit masking is a space optimization to this.
Lets start :
You are looping through all the characters in the string.
Suppose on i'th iteration you found character 'b' .
You calculate its 0 based index.
int val = str.charAt(i) - 'a';
For 'b' it is 1. ie 98-97 .
Now using left shift operator, we find the value of 2^1 => 2.
(1 << val) // 1<<1 => 10(binary)
Now let us see how bitwise & works
0 & 0 -> 0
0 & 1 -> 0
1 & 0 -> 0
1 & 1 -> 1
So by the below code :
(checker & (1 << val))
We check if the checker[val] == 0 .
Suppose we had already encountered 'b'.
check = 0000 0000 0000 0000 0000 1000 1000 0010 &
'b' = 0000 0000 0000 0000 0000 0000 0000 0010
----------------------------------------------
result= 0000 0000 0000 0000 0000 0000 0000 0010
ie decimal value = 2 which is >0
So you finally we understood this part.
if ((checker & (1 << val)) > 0)
return false;
Now if 'b' was not encountered, then we set the second bit of checker using bitwise OR.
( This part is called as bit masking. )
OR's Truth table
0 | 0 -> 0
0 | 1 -> 1
1 | 0 -> 1
1 | 1 -> 1
So
check = 0000 0000 0000 0000 0000 1000 1000 0000 |
'b' = 0000 0000 0000 0000 0000 0000 0000 0010
----------------------------------------------
result= 0000 0000 0000 0000 0000 1000 1000 0010
So that simplifies this part:
checker |= (1 << val); // checker = checker | (1 << val);
I hope this helped someone !

Seems like I am late to the party, but let me take a stab at the explanation.
First of all the AND i.e & operation:
0 & 0 = 0
1 & 0 = 0
0 & 1 = 0
1 & 1 = 1
So basically, if you are given a bit, and you want to find out if its 1 or 0, you just & it with a 1. If the result is 1 then you had a 1, else you had 0. We will use this property of the & below.
The OR i.e | operation
0 | 0 = 0
1 | 0 = 1
0 | 1 = 1
1 | 1 = 1
So basically, if you are given a bit, and you want to do something to it so that the output is always 1, then you do an | 1 with it.
Now, In Java the type int is 4 bytes i.e. 32 bits. Thus we can use an int itself as a data-structure to store 32 states or booleans in simpler terms, since a bit can either be 0 or 1 i.e false or true. Since we assume that our string is composed of only lower case characters, we have enough space inside our int to store a boolean for each of the 26 chars!
So first we initialize our data-structure that we call checker to 0 which is nothing but 32 zeros: 0000000000000000000000.
So far so good?
Now we go through our string, for each character, first we get an integer representation of the character.
int val = str.charAt(i) - 'a';
We subtract a from it because we want our integer to be 0 based. So if vals:
a = 0 i.e. `0000000000000000000000`
b = 1 i.e. `0000000000000000000001`
c = 2 i.e. `0000000000000000000010`
d = 4 i.e. `0000000000000000000100`
Now as seen above, a is 32 zeros, but rest of the characters have a single 1 and 31 zeros. So when we use these characters, we left shift each of them by 1, i.e. (1 << val), so each of them have a single 1 bit, and 31 zero bits:
a = 1 i.e. `0000000000000000000001`
b = 2 i.e. `0000000000000000000010`
c = 4 i.e. `0000000000000000000100`
d = 8 i.e. `0000000000000000001000`
We are done with the setup. Now we do 2 things:
First assume all characters are different. For every char we encounter, we want our datastructure i.e. checker to have 1 for that char. So we use our OR property descrived above to generate a 1 in our datastructure, and hence we do:
checker = checker | (1 << val);
Thus checker stores 1 for every character we encounter.
Now we come to the part where characters can repeate. So before we do step 1, we want to make sure that the checker already does not have a 1 at the position corresponding to the current character. So we check the value of
checker & (1 << val)
So with help of the AND property described above, if we get a 1 from this operation, then checker already had a 1 at that position, which means we must have encountered this character before. So we immediately return false.
That's it. If all our & checks return 0, we finally return true, meaning there were no character repititions.

1 << val is the same as 2 to the degree of val. So it's a number which has
just one one in its binary representation (the one is at position val+1, if you count from
the right side of the number to the left one).
a |= b means basically this: set in a all binary flags/ones from the
binary representation of b (and keep those in a which were already set).

The other answers explain the coding operator usages but i don't think they touch the logic behind this code.
Basically the code 1 << val is shifting 1 in a binary number to a unique place for each character for example
a-0001
b-0010
c-0100
d-1000
As you can notice for different characters the place of 1 is different
checker = checker | (1 << val)
checker here is Oring (basically storing 1 at the same place as it was in 1<<val)
So checker knows what characters have already ocurred
Let's say after the occurence of a,b,c,d checker would look like this
0000 1111
finally
if ((checker & (1 << val)) > 0)
checks if that character has already been occured before if yes return false.To explain you should know a little about AND(&) operation.
1&1->1
0&0->0
1&0->0
So checker currently have 1 in places whose corresponding characters have already occured the only way the expression inside if statement is true
if a character occurs twice which leads 1&1->1 > 0

This sets the 'val'th bit from the right to 1.
1 << val is a 1 shifted left val times. The rest of the value is 0.
The line is equivalent to checker = checker | (1 << val). Or-ing with a 0 bit does nothing, since x | 0 == x. But or-ing with 1 always results in 1. So this turns (only) that bit on.
The if statement is similar, in that it is checking to see if the bit is already on. The mask value 1 << val is all 0s except for a single 1. And-ing with 0 always produces 0, so most bits in the result are 0. x & 1 == x, so this will be non-zero only if that bit at val is not 0.

checker |= (1 << val) is the same as checker = checker | (1 << val).
<< is left bit shift as you said. 1 << val means it's a 1 shifted val digits left.
Example: 1 << 4 is 1000. A left bit shift is the same as multiply by 2. 4 left bit shifts are 4 times 1 multiplied by 2.
1 * 2 = 2 (1)
2 * 2 = 4 (2)
4 * 2 = 8 (3)
8 * 2 = 16 = (4)
| operator is bitwise or. It's like normal or for one bit. If we have more than one bit you do the or operation for every bit.
Example:
110 | 011 = 111
You can use that for setting flags (make a bit 1).
The if condition is similar to that, but has the & operator, which is bitwise and. It is mainly used to mask a binary number.
Example:
110 | 100 = 100
So your code just checks if the bit at place val is 1, then return false, otherwise set the bit at place val to 1.

It means do a binary OR on the values checker and (1 << val) (which is 1, left shifted val times) and save the newly created value in checker.
Left Shift (<<)
Shift all the binary digits left one space. Effectively raise the number to 2 to the power of val or multiply the number by 2 val times.
Bitwise OR (|)
In each binary character of both left and right values, if there is a 1 in the place of either of the two numbers then keep it.
Augmented Assignment (|=)
Do the operation (in this case bitwise OR) and assign the value to the left hand variable. This works with many operators such as:-
a += b, add a to b and save the new value in a.
a *= b, multiply a by b and save the new value in a.

Bitwise shift works as follows:
Example: a=15 (bit representation : 0000 1111)
For operation: a<<2
It will rotate bit representation by 2 positions in left direction.
So a<<2 is 0011 1100 = 0*2^7+0*2^6+1*2^5+1*2^4+1*2^3+1*2^2+0*2^1+0*2^0 = 1*2^5+1*2^4+1*2^3+1*2^2 = 32+18+8+4=60
hence a<<2 = 60
Now:
checker & (1<<val),
will always be greater then 0, if 1 is already present at 1<<val position.
Hence we can return false.
Else we will assign checker value of 1 at 1

I've been working on the algorithm and here's what I noticed that would also work. It makes the algorithm easier to understand when you exercise it by hand:
public static boolean isUniqueChars(String str) {
if (str.length() > 26) { // Only 26 characters
return false;
}
int checker = 0;
for (int i = 0; i < str.length(); i++) {
int val = str.charAt(i) - 'a';
int newValue = Math.pow(2, val) // int newValue = 1 << val
if ((checker & newValue) > 0) return false;
checker += newValue // checker |= newValue
}
return true;
When we get the value of val (0-25), we could either shift 1 to the right by the value of val, or we could use the power of 2s.
Also, for as long as the ((checker & newValue) > 0) is false, the new checker value is generated when we sum up the old checker value and the newValue.

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;
}
1 << val uses right shift operator. Let us say we have character z. ASCII code of z is 122. a-z is 97- 122 = 25. If we multiply 1*(2)^25 = 33554432. Binary of that is 10000000000000000000000000
if checker has 1 on its 26th bit then this statement if ((checker & (1 << val)) > 0) would be true and isUniqueChar would return false.
otherwise checker would turn it's 26th bit on. |= operator(bitwise or and assignment operator) does checker bitwise OR 10000000000000000000000000. Assigns the result to checker.

Related

Programming: Minimum steps required to convert a binary number to zero

I was working on a programming exercise and was stuck on figuring out the correct algorithm. Here is the problem:
Given a decimal number, how many minimum possible steps are required to convert this to zero provided:
Change the bit i if the next bit i+1 is '1' and all the other bits i+2 and later are 0
Change the last bit without restriction
For example:
if input is (8)Base10 = (1000)Base2, then the steps taken are:
1000→1001→1011→1010→1110→1111→1101→1100→0100→0101→0111→0110→0010→0011→0001→0000
total 15 steps are required.
Complete the following definition:
int minStepsRequired(long number)
It's ok to get a pseudo code or just the algorithm. This is not a homework or assignment.
This is a wonderful problem for a recursive algorithm.
If the length of the binary representation is 0, you can already tell the answer. Or if length 0 is not allowed, then if the length is 1 you tell the answer depending on whether that one bit is 0 or 1.
If the length is longer than 1:
If the first bit is 0, the answer is the same as it would be without that 0 bit. Remove it and call recursively to get the answer.
If the first bit is 1, divide into three subproblems and find the step count for each:
Establish a situation where you are allowed to change the leading 1 to 0. This means it should be followed by a 1 and then all 0s. Write a recursive auxiliary algorithm for this. It is going to be quite similar to the main algorithm, and likely they can share some logic.
Flip the 1 to 0 (1 step)
Convert the remaining bits bits to 0. Another recursive call.
The algorithm may take a long time. It is actually counting the steps, so takes time proportional to the number of steps, which I think is roughly proportional to the input number. Your method takes a long argument, but with my algorithm for large long values it may not terminate witin the lifetime of the computer it is running on. Also the number of steps may overflow an int and even a long (if the input is a negative long value).
The fast way
The following solution doesn’t require recursion and runs in constant time. I can’t explain properly how it works, which is a serious problem if we want to use it for something. I played with some examples, saw a pattern and generalized it. By contrast IMHO some of the beauty of the recursive solution above is that it is straightforward to understand (if you understand recursion).
Example: Input 8 or 1000 binary. Result 15 or 1111 binary. The pattern is: each bit of the result is the XOR of the previous bit of the result and the bit in the same position in the input. So from 1000 just copy the front bit, 1. The following bit is 1 XOR 0 = 1, where 1 is the front bit of the result and 0 is taken from the input. The remaining two bits are calculated the same way.
A longer example so you can check if you understood:
Input: 115 = 1110011
Result: 1011101 = 93
Or in code:
static BigInteger calculateStepsRequired(long number) {
// Take sign bit
int bit = number < 0 ? 1 : 0;
BigInteger result = BigInteger.valueOf(bit);
for (int i = 0; i < 63; i++) {
number = number << 1;
int sign = number < 0 ? 1 : 0;
bit = (bit + sign) % 2;
result = result.shiftLeft(1).add(BigInteger.valueOf(bit));
}
return result;
}
I have checked this method against my own implementation of the first algorithm above using various inputs up to 100 000 000, and they always agree, so I believe that the fast method is correct too. I still suggest that you should code, run and test it to verify that I got it right.
At first, I tried to solve it with a recursive depth-first function (in NodeJS) but it just worked for small numbers - an input value such as 10^5 would generate a runtime error due to the number of recursive calls in the stack.
So then I tried to see how I could reduce the problem to the sum of smaller problems and found out that the number of steps for N, being N a power of 2, was
Rule #1
N * 2 - 1
(e.g.: number of steps for 2 is 3, for 32 is 63, for 256 is 511, and so on).
Then I had find what to do with any other number (that is not a power of 2) and since any integer is the sum of different powers of 2 (hence the binary representation), I only had to see if the number of steps would add up as well ... but it was not the case. However, I did find that I had to not just add the number of steps from every power of two, but to
Rule #2
subtract and add the steps in an alternate fashion, starting from the highest order digit
Demonstration
Given number 42 (101010 in binary)
Let's first apply Rule #1
1 0 1 0 1 0
^ ^ ^ ^ ^ ^
| | | | | |_ 0 steps
| | | | |___ 2*2-1 = 3 steps
| | | |_____ 0 steps
| | |_______ 2*8-1 = 15 steps
| |_________ 0 steps
|___________ 2*32-1 = 63 steps
And secondly, applying Rule #2:
63 - 15 + 3 = 51
The total number of steps is 51
Implementation (JavaScript)
function minOperations(n) {
const bin = n.toString(2);
const digitCount = bin.length;
let accumulator = 0;
let sign = 1;
for (let i = 0; i < digitCount; ++i) {
const digit = Number.parseInt(bin.charAt(i));
const power = digit > 0 ? Math.pow(2, digitCount - (i + 1)) : 0;
const steps = digit * (power * 2 - 1);
accumulator += steps * sign;
sign = sign * (digit == 0 ? 1 : -1);
}
return accumulator;
}
Here is a recursive PHP function for computing the number of steps required. It operates by noting there are two possible requirements:
convert a string to 0s (the overall requirement); and
convert a string to a 1 followed by a string of 0s (to allow flipping the preceding digit)
The second requirement is obviously an extension of the first, and so it's possible to write a recursive function which does both. It has a special case for the single digit length string, just checking if it needs to be flipped or not.
function reduce($bits, $value = '0') {
if (strlen($bits) == 1) {
// a single bit can be flipped as needed
return ($bits[0] == $value) ? 0 : 1;
}
if ($bits[0] == $value) {
// nothing to do with this bit, flip the remainder
return reduce(substr($bits, 1));
}
// need to convert balance of string to 1 followed by 0's
// then we can flip this bit, and then reduce the new string to 0
return reduce(substr($bits, 1), '1') + 1 + reduce(str_pad('1', strlen($bits) - 1, '0'));
}
Demo on 3v4l.org
This function can be adapted to store the actual steps taken, then the number of steps is just the count of that array (-1, since we put the original value in the array too). To store the steps we need to keep track of the first part of the string ($prefix in the below code) as well as the part we are reducing:
function reduce($bits, $prefix, $value = '0') {
if (strlen($bits) == 1) {
// a single bit can be flipped as needed
return array($prefix . ($bits[0] == '0' ? '1' : '0'));
}
if ($bits[0] == $value) {
// nothing to do with this bit, flip the remainder
$prefix .= $bits[0];
return reduce(substr($bits, 1), $prefix);
}
// need to convert balance of string to 1 followed by 0's
$prefix .= $bits[0];
$steps = reduce(substr($bits, 1), $prefix, '1');
// now we can flip this bit
$prefix = substr($prefix, 0, -1) . ($bits[0] == '0' ? '1' : '0');
$steps[] = $prefix . str_pad('1', strlen($bits) - 1, '0');
// now reduce the new string to 0
$steps = array_merge($steps, reduce(str_pad('1', strlen($bits) - 1, '0'), $prefix));
return $steps;
}
You can run this like so:
$bin = decbin($i);
$steps = array_merge(array($bin), reduce($bin, ''));
echo "$i ($bin) takes " . (count($steps) - 1) . " steps\n";
print_r($steps);
Output for an input of 8:
8 (1000) takes 15 steps
Array
(
[0] => 1000
[1] => 1001
[2] => 1011
[3] => 1010
[4] => 1110
[5] => 1111
[6] => 1101
[7] => 1100
[8] => 0100
[9] => 0101
[10] => 0111
[11] => 0110
[12] => 0010
[13] => 0011
[14] => 0001
[15] => 0000
)
Demo on 3v4l.org
Gray code
Looking at the steps we can see that this is actually a Gray code (Reflected Binary Code) counting from the original value down to 0. So if we generate a list of sufficient codes to cover the starting value, we can simply look for the binary representation of the starting value in that list, and that will give us the number of steps required to get back to 0:
function gray_code($bits) {
if ($bits == 1) {
return array('0', '1');
}
else {
$codes = gray_code($bits - 1);
return array_merge(array_map(function ($v) { return '0' . $v; }, $codes),
array_map(function ($v) { return '1' . $v; }, array_reverse($codes))
);
}
}
$value = 8;
$bin = decbin($value);
// get sufficient gray codes to cover the input
$gray_codes = gray_code(strlen($bin));
$codes = array_flip($gray_codes);
echo "$bin takes {$codes[$bin]} steps to reduce to 0\n";
// echo the steps
for ($i = $codes[$bin]; $i >= 0; $i--) {
echo $gray_codes[$i] . PHP_EOL;
}
Demo on 3v4l.org
If you don't need the individual steps you can just use a Gray code to binary converter to find the number of steps. This is super fast:
function gray_to_binary($value) {
$dec = $value;
for ($i = 1; $i < strlen($value); $i++) {
$dec[$i] = (int)$dec[$i-1] ^ (int)$value[$i];
}
return $dec;
}
echo bindec(gray_to_binary(decbin(115)));
Output:
93
Demo on 3v4l.org
A Gray Code Generator
We can use an iterative Gray code generator to count down the steps from our original code. The advantage of this is that it doesn't consume any memory to store the codes so it can work for very large numbers. This version uses a Gray code to binary converter that works with integers rather than strings as did the one above:
function gray_to_binary($value) {
$dec = 0;
$bits = floor(log($value, 2));
for ($i = $bits; $i >= 0; $i--) {
$dec = $dec | (((($dec >> ($i + 1)) ^ ($value >> $i)) & 1) << $i);
}
return $dec;
}
function iterate_gray($value) {
// get the equivalent starting binary value
$code = decbin($value);
yield $code;
$len = strlen($code);
$count = gray_to_binary($value);
while ($count > 0) {
// flip the bit which corresponds to the least significant 1 bit in $count
$xor = 1;
while (($count & $xor) == 0) $xor <<= 1;
$value ^= $xor;
yield sprintf("%0{$len}b", $value);
$count--;
}
}
foreach (iterate_gray(8) as $code) {
echo $code . PHP_EOL;
}
Output:
1000
1001
1011
1010
1110
1111
1101
1100
0100
0101
0111
0110
0010
0011
0001
0000
Demo on 3v4l.org
Here is a PHP implementation of Ole's "fast way" algorithm. The idea is the same:
Initialize the result with the first bit of the number (starting from the left)
For every following bit of the number, XOR it with the previous bit of the result, which gives a new bit for the result
function getBit($number, $i)
{
// Extracts bit i from number
return ($number & (1<<$i)) == 0 ? 0 : 1;
}
function minStepsRequired($number)
{
$i = 30; // Enough to handle all positive 32-bit integers
$bit = getBit($number, $i); // First bit
$res = $bit;
do
{
$i--;
$bit ^= getBit($number, $i); // Computes XOR between previous bit of the result and current bit of the number
$res = ($res<<1) + $bit; // Shifts the result to the left by 1 position and adds the new bit
}
while($i>0);
return $res;
}
var_dump(minStepsRequired(8)); // Outputs 15
var_dump(minStepsRequired(115)); // Outputs 93
It is important to notice that the first k bits, which are zeroes can be left as they are and you only start with the (k + 1)'th bit and we ignore all the starting bits, having a value of zero and always aim to increase their number. This is our primary goal and thus, we always reduce the problem-space to a similar, but smaller problem-space. Now, assuming that your number looks like
1b1b2b3...bn
you need to make sure that b1 is 1 and b2, b3, ..., bn is 0 in order to be able to modify the bit prior to b1 to 0. After that happened, you know that b2 is 1 and all the subsequent bits are 0, then the new goal is to change b2 to 0, knowing that all the subsequent bits are 0.
You can keep track of your progress with a stack which can have as much elements as many bits you are working with, always its top will represent your current goal.
So, when you want to zero your first bit, then achieving the right sequence of subsequent bits represent subtasks for you before you can change your bit and once you succeeded doing so, you need to proceed similarly, but ignoring the first bit. You can number the steps.
Assuming that a number of
1...0000000
can be zeroed in 2^n - 1 steps, the total number of steps to do equals with 2^n - 1 + the number of steps needed to achieve the combination we see above. I didn't check whether it's 2^n - 1 though
private static int reduce(String s) {
int count = 0;
char[] ch = s.toCharArray();
for (int i = ch.length - 1; i >= 0; i--) {
if (i == 0 && ch[i] == '0') {
return count - 1;
}
if (i == 0 && ch[i] == '1') {
return count + 1;
}
if (ch[i] == '0') {
count++;
} else {
count++;
ch[i] = '0';
i++;
}
}
return count;
}
def minOperations(n):
number = []
while n>0:
number.append(n%2)
n = n // 2
ans = 0
sign = 1
for i in range(len(number)):
if number[i] == 1:
ans = (2**(i+1) - 1) - ans
return ans

Undoing bitwise operations

I have a Java function written by another programmer, which uses bitwise manipulation. I need a function that will undo the process (if possible). Perhaps some of you are more savvy than I with these operators. Here's what needs to be undone:
public void someFunc(int[] msg, int[] newMsg) {
int i = SOME_LENGTH_CONSTANT;
for (int j = 0; j < newMsg.length; j++) {
// msg[i] Shift left by 8 bits bitwise or with next msg[i+1]
// then bitwise not (~) and bitwise and with $FFF
newMsg[j] = (~(((msg[i] & 0x0f) << 8) | (msg[i + 1]))) & 0xfff;
i += 2;
}
}
I just wanted to try to do it, here is the results of my attempt.
In the beginning I split the expression into single operations:
int t1 = msg[i] & 0x0f;
Here is we lose all except for the last 4 bits.
int t2 = t1 << 8;
Clear low 8 bits by shifting t1.
int t3 = t2 | msg[i + 1];
Here we should understand if m[i + 1] is large than 255 (particularly m[i + 1] & 0xf00 > 0), we are not able to restore the low 4 bits of m[i] because they are irreversibly overwritten.
int t4 = ~t3;
Just a negation.
newMsg[j] = t4 & 0xfff;
Take low 12 bits.
Just did these steps in reverse order:
public static void someFuncRev(int[] msg, int[] newMsg) {
for (int i = 0; i < msg.length; ++i) {
newMsg[2 * i] = (~msg[i] >> 8) & 0xf; // take 11-8 bits
newMsg[2 * i + 1] = ~msg[i] & 0xff; // take 7-0 bits
}
}
I assumed SOME_LENGTH_CONSTANT == 0. It is easy to adjust the constant.
So, when the values inside msg are <=15, the function above recovers the initial sequence.
In case when the values are >15 and <=255, for msg[i] we can restore only 4 bits, msg[i + 1] are restored completely.
If the values are >255, we can't restore msg[i] because it was correpted by bits of msg[i + 1] (look above at the point no. 3); can restore 8 bits of msg[i + 1].
I hope this helps you.
My version, behold:
public void undoFunc(int[] newMsg, int[] original) {
int i = SOME_LENGTH_CONSTANT; // starting point
for (int j = 0; j < newMsg.length; j++) { // Iterate over newMsg
original[i] = ~((newMsg[j]&0xff00)>>8)&0x000f; // &0x000f to get rid of "mistakes" when NOT-ing
original[i+1] = (~(newMsg[j]&0x00ff)) & 0xff;
// i = initial value + 2 * j
i+=2;
}
}
What does your code do?
The input is an integer array. Every two values are used to create one value in the 'output' (newMsg) array.
First, it removes the left four bits of the first value in the input.
Then it "scrolls" that value 8 places to the left and puts zeroes in the empty spots.
It places the second value, msg[i+1], in the zeroes in the four rightmost bits.
It negates the value, all ones become zeroes and all zeroes become ones.
When 4) was done, the 4 leftmost bits (cleared in step 1)) become ones, so it undoes this with a &0x0FFF.
Example iteration:
msg[i] == 1010'1011
msg[i+1] == 0010'0100
1) 1010'1011 -> 0000'1011
2) 0000'1011 -> 0000'1011'0000'0000
3) 0000'1011'0000'0000 -> 0000'1011'0010'0100
4) 0000'1011'0010'0100 -> 1111'0100'1101'1011
5) 1111'0100'1101'1011 -> 0000'0100'1101'1011
newMsg[j] == 0000'0100'1101'1011 == 0x04DB (I think, from memory)
What my code does:
Getting the value of (what used to be) msg[i+1] is easy, it's the opposite/NOT of the rightmost 8 bits. Because negating it turns all leading zeroes into ones, I'll AND it with 0xff.
Getting the value of (what used to be) msg[i] was more difficult. First scrolled the leftmost 8 bits to the right. Then I negate the value. But the four unused/lost bits are now ones, and I expect that the OP wants these to be zeroes, so I &0x000f it.
NOTE: I used hexes with leading zeroes to make it more clear. These are not necessary.
NOTE: I divided the binary numbers into four bits for readability. So 0000'0100'1101'1011 is actually (0b)0000010011011011.
The values of msg[i+1] are recovered, but the leftmost four bits of msg[i] are lost.
Fwew.
Original Post:
In your code, you use &. What & does, is turn all 'agreeing bits' (when a bit from byte a and the equally significant bit from byte b are both 1) into 1s and the rest into 0s. This means that all bits that don't agree are, as #Mike Harris said, gone and destroyed.
Example & (and operation):
1010 & 0110 =
1 & 0 => 0
0 & 1 => 0
1 & 1 => 1
0 & 0 => 0
= 0010
As you see, only the second and third most significant bits (or zero-inclusive first and second least significant bit) of byte a are kept (bit #4/#0 is 'luck'), because they are 1s in byte b.
You can reverse all bits that are 1s in byte b in your code (one of which is fff, or 1111 1111 1111 in binary, though remember all bits more significant than the first one are removed, because 1111 1111 1111 == 000000000...00111111111111). But this won't reverse it, and only works depending on what the purpose of reversing it is.
More about the AND Bitwise operation on Wikipedia.

Could someone please explain how shifting is used in this code?

I'm solving sample problems while simultaneously trying to learn Python %\ ... but the problem book I got has problems and solutions in Java, so I'm trying to convert back and forth between the two languages. I just learned how bit shifting works and I've been staring at this code trying to figure out what exactly is going on here on line 5 (and 8) ... I tried writing down some examples just going through the code line by line but for some reason it's still not entirely obvious to me ...
Could someone please clarify?
Also, it's really strange to me that str.charAt(i) returns a character, as far as I understand, and you can then proceed to subtract it from another character like numbers ... Is applying int to a character the same as ord() in Python?
Problem: Implement an algorithm to determine is a string has all unique characters.
Solution (in the case with only characters a-z):
1 boolean isUniqueChars(String str){
2 int checker = 0
3 for (int i = 0; i < str.length(); i++){
4 int val = str.charAt(i) - 'a';
5 if ((checker & (1 << val)) > 0){
6 return false;
7 }
8 checker |= (1 << val);
9 }
10 return true;
11 }
Sure. This code will really only work if str has only lower case letters in it.
checker is a 32-bit integer, and you're using 26 of the 32 bits to record the presence of a particular letter in str. So bit 0 will be used to record the presence of a, bit 1 will be used to record the presence of b, and so on up to bit 25, which will be used to record the presence of z.
The basic algorithm is to work through str, character by character. For each character, find the corresponding bit in checker. If it's already been set, this character must be occurring for the second time - so we can stop processing and return false. Otherwise, set that bit.
If you get to the end of the string without finding any duplicate characters, then return true.
The magic is in the following steps.
Subtracting 'a' from each character converts it to a number from 0 to 25.
The symbol << is the "left shift" operator, which moves a bit pattern a number of bits to the left. The result of this is that 1 << val is the place value of a particular bit (1, 2, 4, 8 etc).
The symbol & does a binary AND, so the expression checker & (1 << val) will be 0 if bit val is cleared, or equal to 1 << val if it is set.
The symbol |= does a binary OR, and assigns the result to the variable on the left. So the expression checker |= (1 << val) sets bit val.
Let's try a simpler variation:
boolean isUniqueChars(String str) {
boolean[] seen = new boolean[26];
for (int i = 0; i < str.length(); i++) {
// convert char to 0-based offset
int index = str.charAt(i) - 'a';
if (seen[index]) {
// this char was seen already
return false;
}
seen[index] = true;
}
// no duplicates found
return true;
}
Pretty straighforward, right? We create a boolean array, using the character offset as an index, and check each character in the string to see if we've come across it yet. The code you posted uses the same logic, but with a more efficient bit set instead.
(1 << val) turns val into a bit index. checker & (1 << val) filters out other indexes so we can check just this one. (checker & (1 << val)) > 0 checks if there's any value at the index. checker |= (1 << val) turns the bit on at the index. All of the other logic is identical.
First, the code will only work reliably if the input string contains letters 'a' to 'z'.
The variable checker is a 32 bit int. Each bit in checker is used as a flag to indicate the presence of one of the 26 letters 'a' to 'z'.
The line
int val = str.charAt(i) - 'a';
converts the character stored at str index i into an integer stored in val, by subtracting the value of character 'a' so. Yes I think pascal has the Ord('') function which does the same.
a = 0
b = 1
c = 2
etc
etc
etc
z = 25
the code
(1 << val)
shifts val into the appropriate value for its bit position,
so
a = 0 = 1
b = 1 = 2
c = 2 = 4
d = 3 = 8
etc
etc
z = 25 = 33554432
if ((checker & (1 << val)) > 0)
determines if the bit is already set in checker, indicating a duplicate character. If so the function returns false.
else
checker |= (1 << val)
sets the bit in checker via a binary OR and then loops round again.

Getting value from MSB of 16 bit register

I have 16 bits register which contain some values in LSB and MSB:
LSB:
At bit 0...1 the value is 0
At bit 2 the values is 0
MBS:
At MSB I need to write value 20
So the value that should be written in register is 0 + 0 + 20 = 160
When I'm reading register the I'm doing it on this way:
for the 1st value in bit [0...1]:
firstVal = (valFromReg & (((1 << 2)-1) << 1) / 2)
secondVal = (valFromReg & 4) / 4
But how to read/convert the third value to get number 20?
In Java, a short is a (signed) 16-bit value. You want to split that into 3 values:
Value a is a 2-bit value in bits 0-1
Value b is a 1-bit value in bit 2
Value c is a 13-bit value in bits 3-15
Bit-wise, that can be represented like this: cccc cccc cccc cbaa
To extract the 3 values from the 16-bit reg value, you'd do this:
short reg = /*register value*/;
int a = reg & 0x0003;
int b = (reg >> 2) & 0x0001;
int c = (reg >> 3) & 0x1fff;
To go the other way, you'd do this:
short reg = (short)((c << 3) | (b << 2) | a);
This of course assumes that the values are within value range, i.e. a = 0-3, b = 0-1, and c = 0-8191.
Some things in the question are not quite clear for me...
like:
At MSB I need to write value 20
back in my times MSB was only 1 bit and was only possible to write true or false...
anyways...
A 16 bits signal fits pretty good in an integer...
so you could basically get that register and manipulate it as an integer, then representing that as a binary number AS STRING will lets you to get the MSB or even the bit at any wanted position...
Do this:
Example
int register = -128;
String foo = String.format("%16s", Integer.toBinaryString(register)).replace(' ', '0');
System.out.println(register);
System.out.println(foo);
System.out.println(foo.charAt(0)); //char at 0 is the MSB....

Bitshift - Need help to understand the code

I am just trying to learn bitwise / shift operations.
I came across the below program but don't understand the AND condition part (checker & (1 << val) in the below program. When will the final Value be greater than 0? Can someone please explain whats happening there?
Sample input:
xyzz
Sample output:
8388608Value
0checker
0final value
16777216Value
8388608checker
0final value
33554432Value
25165824checker
0final value
33554432Value
58720256checker
33554432final value
public static boolean isUniqueChars(String str) {
int checker = 0;
for (int i = 0; i < str.length(); i++) {
int val = str.charAt(i) - 'a';
System.out.println((1 << val) + "Value");
System.out.println((checker) + "checker");
System.out.println(((checker & (1 << val))) + "final value\n");
if ((checker & (1 << val)) > 0) {
return false;
} else {
checker = checker | (1 << val);
}
}
return true;
}
}
OK, just to make sure you know what's going on:
int val = str.charAt(i) - 'a';
Assuming the English alphabet, this is taking the char value for your (lowercase) letter and subtracting 97 (the char value for 'a') to produce a number between 0 and 25 inclusive. Don't try this function on uppercase characters, you'll get errors unless you add a .toLowerCase() after the .charAt(i)
1 << val is bit-shifting 1 val places to the left. For instance, for 'x' (120 - 97 = 23, so... 1 << 23), the binary representation would be 00000000010000000000000000000000
OK, with me so far?
At the start, checker has all 0 bits, so it's 00000000000000000000000000000000
So... lets put in our numbers instead of our variables. For our x check, checker & (1 << val) becomes 00000000000000000000000000000000 & 00000000010000000000000000000000 which equals 00000000000000000000000000000000 because bit 23 isn't set in checker.
So, once x is processed, we add bit 23 to checker and move on to the next letter: y This time, checker & (1 << val) becomes 00000000010000000000000000000000 & 00000000100000000000000000000000 which equals 00000000000000000000000000000000 because bit 24 isn't set in checker.
For the first z, checker & (1 << val) becomes 00000000110000000000000000000000 & 00000001000000000000000000000000 which equals 00000000000000000000000000000000 because bit 25 isn't set in checker.
For the second z, checker & (1 << val) becomes 00000001110000000000000000000000 & 00000001000000000000000000000000 which equals 00000001000000000000000000000000 (decimal 33554432 or 2^25) because bit 25 is set in checker, therefore the > 0 is now true and the function returns false.
I think what your function does is check if all characters in the input string are different. It returns false iff the same (lower case) character appears more than once.
The checker variable serves as a kind of bit map that accumulates which characters have appeared so far. Data type int consists of 32 bits which is enough to assign one bit per each character (26).
The function loops over all characters of str. The row int val = str.charAt(i) - 'a'; assigns some sort of ordinal value to val depending on the character ('a' => 0, 'b' => 1, 'c' => 2, etc.).
The expression 1 << val assigns each val in the range of (0..25) to its bit position. Therefore, character 'a' is mapped to 1 << 0 == 1 == 00000001, character 'd' is mapped 1 << 3 == 00001000, and so on. Each character is assigned its unique bit mask with exactly one bit set and all other bits cleared.
The expression (checker & (1 << val)) is > 0 exactly iff the bit that is set in 1 << val is also set in checker (note that checker might have more than one bit set). If so, the currently iterated character has appeared earlier, and the function returns false. Otherwise, the bit mask of the current character is added via bitwise OR operator | to the checker that acts as an accumulator. If all characters have been looped over and no character has been met twice, the function returns true. Note that the function might ignore upper-case and other characters.

Categories

Resources