Home > Net >  Understanding bitwise binary combination algorithm
Understanding bitwise binary combination algorithm

Time:10-29

I've been looking at algorithms that list all the possible combinations of an array of boolean values.

For example, an array of two booleans can have these combinations: [true, true], [true, false], [false, true], [false, false]

I've found several examples that use bitwise operators and whilst I've looked up the definitions of the operators used, I still don't understand their contextual use in the algorithms.

I've listed an example algorithm (source: http://zacg.github.io/blog/2013/08/02/binary-combinations-in-javascript/) below with annotations to describe what I'm seeing when I look at them:

function binaryCombos(n){
    var result = [];
    for(y=0; y<Math.pow(2,n); y  ){         // This cycles through the maximum number of combinations 
                                               (power of 2 because it's binary)
        
    var combo = [];                         // combo for particular iteration, eventually pushed to result
        for(x=0; x<n; x  ){                 // iterate over number of booleans in array
            //shift bit and and it with 1
            if((y >> x) & 1)                // right shifts and then masks for 1? i.e. tests if it's odd??
                combo.push(true);           // I don't see how this ensures all combiantions are covered
             else 
                combo.push(false);          // I don't understand the criteria for pushing false or true :(        
        }
        result.push(combo);
    }
    return result;
}

//Usage
combos = binaryCombos(3);


for(x=0; x<combos.length; x  ){               // This looks like driver code so have been ignoring this
    console.log(combos[x].join(','));
}

Here's an example working with n = 2:

y = 0 x = 0

0 >> 0 is still 0 so will evaluate to false when 'anded' with 1 as:

0000 0000 & 0000 0001 --> 0

'false' pushed to combo array

y=0 x=1

0 >> 1 still 0 and will push 'false' to combo array

pushed to results: [false, false]

y=1 x=0

1 >> 0 equates to 0000 0001 with no shift(?) so 'anding' with 1 will evaluate to true, 'true' pushed to combo array

y=1 x=1

1 >> 1 is the same as halving but would eval to 0 so false is pushed to combo array

pushed to results: [true, false]

y=2 x=0

2 >> 0 equates to false being pushed to combo array as 0000 0010 & 0000 0001 = 0

y=2 x=1

2 >> 1 equates to true being pushed as 0000 0001 & 0000 0001 = 1

pushed to results: [false, true]

y=3 x=0

3 >> 0 equates to true being pushed to combo array since 0000 0011 & 0000 0001 = 1

y=3 x=1

3 >> 1 equates to true being pushed to combo array

pushed to results: [true, true]

result returned: [[false, false], [true, false], [false, true], [true, true]]

I can intuitively see that nested loops will help solve permutations and I can recognize that this has arrived at the correct answer but can't see the relationship between shifting y by x and then 'anding' with comprehensively covering all combinations.

Any help appreciated!

CodePudding user response:

x is a (zero-based) bit number. That bit number refers to a bit in the binary representation of y: the least significant bit has number 0 (at the right of the binary representation), and the most significant bit has number n-1. As a combination has n boolean values, the bit representation (of y) has n bits. A zero-bit translates to false and a 1-bit to true.

Now, to extract the xth bit from the binary representation of y, we can use the shift operator:

y >> x

After this operation, the bit we are interested in has moved all the way to the right. All the bits that were at the right of the xth bit have "fallen of" by this >> operation. What remains is to get rid of all the bits at the left of the bit we want to extract. For that we use & 1. That's all that is needed to isolate the xth bit of the binary representation of y.

Example

Let's say we have n=4 and the outer loop has iterated to the point where y=13. The binary representation of y is 1101.

The loop on x will start with x=0, so the shift operation will not do anything, but the & 1 operation will extract the right-most bit of 1101, i.e. 1.

The next inner iteration will have x=1. Now the shift operation will kick that right most bit out, and we are left with 110. The & 1 operation will now extract the 0. And so it continues for x=3 and x=4.

Here represented in a table (for n=4 and y=13):

y x y >> x (y >> x) & 1 boolean
1101 0 1101 1 true
1101 1 110 0 false
1101 2 11 1 true
1101 3 1 1 true
  • Related