I'm currently learning about bitset, and in one paragraph it says this about their interactions with strings:
"The numbering conventions of strings and bitsets are inversely related: the rightmost character in the string--the one with the highest subscript--is used to initialize the low order bit in the bitset--the bit with subscript 0."
however later on they give an example + diagram which shows something like this:
string str("1111111000000011001101");
bitset<32> bitvec5(str, 5, 4); // 4 bits starting at str[5], 1100
value of str:
1 1 1 1 1 (1 1 0 0) 0 0 0 ...
value of bitvec5:
...0 0 0 0 0 0 0 (1 1 0 0)
This example shows it taking the rightmost bit and putting it so the last element from the string is the last in the bitset, not the first.
Which is right?(or are both wrong?)
They are both right.
Traditionally the bits in a machine word are numbered from right to left, so the lowest bit (bit 0) is to the right, just like it is in the string.
The bitset looks like this
...1100 value
...3210 bit numbers
and the string that looks the same
"1100"
will have string[0] == '1' and string[3] == '0', the exact opposite!
string strval("1100"); //1100, so from rightmost to leftmost : 0 0 1 1
bitset<32> bitvec4(strval); //bitvec4 is 0 0 1 1
So whatever you are reading is correct(both text and example) :
the rightmost character in the string--the one with the highest
subscript--is used to initialize the low order bit in the bitset--the
bit with subscript 0.
Related
This question is a follow-up of another one I had asked quite a while ago:
We have been given an array of integers and another number k and we need to find the total number of continuous subarrays whose sum equals to k. For e.g., for the input: [1,1,1] and k=2, the expected output is 2.
In the accepted answer, #talex says:
PS: BTW if all values are non-negative there is better algorithm. it doesn't require extra memory.
While I didn't think much about it then, I am curious about it now. IMHO, we will require extra memory. In the event that all the input values are non-negative, our running (prefix) sum will go on increasing, and as such, sure, we don't need an unordered_map to store the frequency of a particular sum. But, we will still need extra memory (perhaps an unordered_set) to store the running (prefix) sums that we get along the way. This obviously contradicts what #talex said.
Could someone please confirm if we absolutely do need extra memory or if it could be avoided?
Thanks!
Let's start with a slightly simpler problem: all values are positive (no zeros). In this case the sub arrays can overlap, but they cannot contain one another.
I.e.: arr = 2 1 5 1 1 5 1 2, Sum = 8
2 1 5 1 1 5 1 2
|---|
|-----|
|-----|
|---|
But this situation can never occur:
* * * * * * *
|-------|
|---|
With this in mind there is algorithm that doesn't require extra space (well.. O(1) space) and has O(n) time complexity. The ideea is to have left and right indexes indicating the current sequence and the sum of the current sequence.
if the sum is k increment the counter, advance left and right
if the sum is less than k then advance right
else advance left
Now if there are zeros the intervals can contain one another, but only if the zeros are on the margins of the interval.
To adapt to non-negative numbers:
Do as above, except:
skip zeros when advancing left
if sum is k:
count consecutive zeros to the right of right, lets say zeroes_right_count
count consecutive zeros to the left of left. lets say zeroes_left_count
instead of incrementing the count as before, increase the counter by: (zeroes_left_count + 1) * (zeroes_right_count + 1)
Example:
... 7 0 0 5 1 2 0 0 0 9 ...
^ ^
left right
Here we have 2 zeroes to the left and 3 zeros to the right. This makes (2 + 1) * (3 + 1) = 12 sequences with sum 8 here:
5 1 2
5 1 2 0
5 1 2 0 0
5 1 2 0 0 0
0 5 1 2
0 5 1 2 0
0 5 1 2 0 0
0 5 1 2 0 0 0
0 0 5 1 2
0 0 5 1 2 0
0 0 5 1 2 0 0
0 0 5 1 2 0 0 0
I think this algorithm would work, using O(1) space.
We maintain two pointers to the beginning and end of the current subsequence, as well as the sum of the current subsequence. Initially, both pointers point to array[0], and the sum is obviously set to array[0].
Advance the end pointer (thus extending the subsequence to the right), and increase the sum by the value it points to, until that sum exceeds k. Then advance the start pointer (thus shrinking the subsequence from the left), and decrease the sum, until that sum gets below k. Keep doing this until the end pointer reaches the end of the array. Keep track of the number of times the sum was exactly k.
I took part in a coding contest wherein I encountered the following question:
On the first row, we write a 0. Now in every subsequent row, we look at the previous row and replace each occurrence of 0 with 01, and each occurrence of 1 with 10. Given row N and index K, return the K-th indexed symbol in row N. (The values of K are 1-indexed.)
While solving the question, I solved it like a level-order traversal of a tree, trying to form the new string at each level. Unfortunately, it timed-out. I then tried to think along the terms of caching the results, etc. with no luck.
One of the highly upvoted solutions is like this:
class Solution {
public:
int kthGrammar(int N, int K) {
if (N == 1) return 0;
if (K % 2 == 0) return (kthGrammar(N - 1, K / 2) == 0) ? 1 : 0;
else return (kthGrammar(N - 1, (K + 1) / 2) == 0) ? 0 : 1;
}
};
My question is simple - what is the intuition behind working with the value of K (especially, the parities of K)? (I hope to be able to identify such questions when I encounter them in future).
Thanks.
Look at the sequence recursively. In generating a new row, the first half is identical to the process you used to get the previous row, so that part of the expansion is already done. The second half is merely the same sequence inverted (0 for 1, 1 for 0). This is one classic way to generate a parity map: flip all the bits and append, representing adding a 1 to the start of each binary number. Thinking of expanding the sequence 0-3 to 0-7, we start with
00 => 0
01 => 1
10 => 1
11 => 0
We now replicate the 2-digit sequence twice: first with a leading 0, which preserves the original parity; second with a leading 1, which inverts the parity.
000 => 0
001 => 1
010 => 1
011 => 0
100 => 1
101 => 0
110 => 0
111 => 1
Is that an intuition that works for you?
Just for fun, as a different way to solve this, consider that the nth row (0-indexed) has 2^n elements in it, and a determination as to the value of the kth (0-indexed) element can be made soley according to the parity of how many bits are set in k.
The check for parity in the code you posted is just to make the division by two correct, there's no advanced math or mystery hiding here :) Since the pattern is akin to a tree, where the pattern size multiplies by two for each added row, correctly dividing points to the element's parent. The indexes in this question are said to be "1-indexed;" if the index is 2, dividing by two yields the parent index (1) in the row before; and if the index is 1, dividing (1+1) by two yields that same parent index. I'll leave it to the reader to generalize that to ks parity. After finding the parent, the code follows the rule stated in the question: if the parent is 0, the left-child must be 0 and right-child 1, and vice versa.
0
0 1
0 1 1 0
0 1 1 0 1 0 0 1
0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0
a a b a b b a
0 01 0110 01101001 0110100110010110
a b b a b a a b
0110100110010110 1001011001101001
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm struggling with the piece of code below, it's used to convert an integer into a binary. Can someone explain it more cearly? especially the '0'+
for (;d>0;d--){
buffer[index++] = '0'+ (x & 1);
x >>= 1;
}
First of all, "index" is initialized to 0. But what is the definition of "d"?
We have an array of characters named "buffer" and "x" is an integer to be converted.
Now, in "x & 1", "&" is Bitwise AND operator. If we operate "x & n", it changes the last n least significant bits as,
1 & 1 = 1,
1 & 0 = 0,
0 & 1 = 0,
0 & 0 = 0.
if we execute 4 & 1,
100
001
---
000
then, it returns 0.
if we execute 9 & 1,
1001
0001
----
0001
then, it returns 1.
Basically, if x is a even number x&1 returns 0, or returns 1 if x is odd.
Now, after that, this 0 or 1 is added to '0' (ascii 48), which is-
if x is even, '0' + (x & 1) stays '0', otherwise it becomes '1' as x&1 returns 1 and '0'+1 is '1'.
After that in "x >>= 1", ">>" is Bitwise right shift operator, which is equivalent to x = x / 2 or x /= 2. But there is little bit difference if we consider integers.
Consider x = 12, that is 1100 in binary.
if we execute x >>= 1, then x becomes 6, if shifts away last 0 of 1100, becomes 110.
again if we execute x >>= 1, then x becomes 3, if shifts away last 0 of 110, becomes 11.
again if we execute x >>= 1, then x becomes 1, if shifts away last 1 of 11, becomes 1.
again if we execute x >>= 1, then x becomes 0, if shifts away last 1 of 1, becomes 0.
Finally, if x is even it stores '0' in buffer[index], otherwise stores '1', until x is not 0.
This is a loop that starts with a variable containing some value and then creates a string of character digits of ones and zeros.
The '0' + (x & 1) takes the character for a digit zero '0' and then adds to that character the value of the right most bit of x which have either a value of zero or of one. If the bit is zero then the result of the addition is '0' and if the bit is one then the result of the addition is '1'.
This character is then put into the buffer, the variable x is right shifted by one bit to move the next binary digit to the right most place.
The addition is then repeated.
The result is that you have a text string of zeros and ones as character digits.
Are you sure this is the correct source code? Looks to me like the text string result would need to be reversed in order to correctly represent the binary value.
buffer[index++] = '0'+ (x & 1);
This line progresses through what is presumably a char array, setting each character to the character '0' PLUS a value that will be equal to either 0 or 1. '0' + 0 is ''0'. '0' + 1 is '1'. The reason x & 1 will be either 0 or 1 is because this code is essentially checking if the low bit is on in x. The reason this works is because the line below then right shifts x by 1, then sets x equal to that value, which basically is knocking off the low bit, and shifting all other bits over by 1. In this way, x is traversed, and each bit is checked.
Please note, however. It appears that it will be written BACKWARDS!
In ASCII 0 has the ASCII value 48 and 1 has the ASCII value 49. IOW if you write putchar(48); you see a 0 on the screen
The buffer presumably being a char 2-dimensional array is assigned
either 48 or 49 because x & 1 evaluates to either 1 or 0.
so say you have a value x = 225 and want to convert it to readable text containing 0's and 1's
225 looks like this in binary
1110 0001
when you do 1110 0001 & 0x1 you mask out the last 1 left is 0000 0001
so adding 1 to 48 and converting the sum ito a character is 1
next the bits are shifted one step right x >>= 1
0111 0000
masking that with 0x1 is 0000 0000
so adding 0 to 48 and converting the sum to a character becomes 0
and so on until x is 0
I'm writing a program that exchanges the values of the bits on positions 3, 4 and 5 with bits on positions 24, 25 and 26 of a given 32-bit unsigned integer.
So lets say I use the number 15 and I want to turn the 4th bit into a 0, I'd use...
int number = 15
int newnumber = number & (~(1 << 3));
// output is 7
This makes sense because I'm exchanging the 4th bit from 1 to 0 so 15(1111) becomes 7(0111).
However this wont work the other way round (change a 0 to a 1), Now I know how to achieve exchanging a 0 to a 1 via a different method, but I really want to understand the code in this method.
So why wont it work?
The truth table for x AND y is:
x y Output
-----------
0 0 0
0 1 0
1 0 0
1 1 1
In other words, the output/result will only be 1 if both inputs are 1, which means that you cannot change a bit from 0 to 1 through a bitwise AND. Use a bitwise OR for that (e.g. int newnumber = number | (1 << 3);)
To summarize:
Use & ~(1 << n) to clear bit n.
Use | (1 << n) to set bit n.
To set the fourth bit to 0, you AND it with ~(1 << 3) which is the negation of 1000, or 0111.
By the same reasoning, you can set it to 1 by ORing with 1000.
To toggle it, XOR with 1000.
I'm not good in English, I can't ask it better, but please below:
if byte in binary is 1 0 0 0 0 0 0 0 then result is 1
if byte in binary is 1 1 0 0 0 0 0 0 then result is 2
if byte in binary is 1 1 1 0 0 0 0 0 then result is 3
if byte in binary is 1 1 1 1 0 0 0 0 then result is 4
if byte in binary is 1 1 1 1 1 0 0 0 then result is 5
if byte in binary is 1 1 1 1 1 1 0 0 then result is 6
if byte in binary is 1 1 1 1 1 1 1 0 then result is 7
if byte in binary is 1 1 1 1 1 1 1 1 then result is 8
But if for example the byte in binary is 1 1 1 0 * * * * then result is 3.
I would determine how many bit is set contiguous from left to right with one operation.
The results are not necessary numbers from 1-8, just something to distinguish.
I think it's possible in one or two operations, but I don't know how.
If you don't know a solution as short as 2 operations, please write that too, and I won't try it anymore.
Easiest non-branching solution I can think of:
y=~x
y|=y>>4
y|=y>>2
y|=y>>1
Invert x, and extend the lefttmost 1-bit (which corresponds to the leftmost 0-bit in the non-inverted value) to the right. Will give distinct values (not 1-8 though, but it's pretty easy to do a mapping).
110* ****
turns into
001* ****
001* **1*
001* 1*1*
0011 1111
EDIT:
As pointed out in a different answer, using a precomputed lookup table is probably the fastets. Given only 8 bits, it's probably even feasible in terms of memory consumption.
EDIT:
Heh, woops, my bad.. You can skip the invert, and do ands instead.
x&=x>>4
x&=x>>2
x&=x>>1
here
110* ****
gives
110* **0*
110* 0*0*
1100 0000
As you can see all values beginning with 110 will result in the same output (1100 0000).
EDIT:
Actually, the 'and' version is based on undefined behavior (shifting negative numbers), and will usually do the right thing if using signed 8-bit (i.e. char, rather than unsigned char in C), but as I said the behavaior is undefined and might not always work.
I'd second a lookup table... otherwise you can also do something like:
unsigned long inverse_bitscan_reverse(unsigned long value)
{
unsigned long bsr = 0;
_BitScanReverse(&bsr, ~value); // x86 bsr instruction
return bsr;
}
EDIT: Not that you have to be careful of the special case where "value" has no zeroed bits. See the documentation for _BitScanReverse.