Reputation: 180391
I am struggling to understandwhat the "if (i >> j) % 2 ==1 " does in the following function or any function for that matter?
def powerSet(items):
N = len(items)
for i in xrange(2**N):
combo = []
for j in xrange(N):
if (i >> j) % 2 == 1:
combo.append(items[j])
yield combo
Upvotes: 2
Views: 1897
Reputation: 363537
It checks whether the j
'th bit of the binary number i
, counting from the end, is set. i >> j
right-shift, so the final j
bits are gone. n % 2 == 1
is the familiar check for odd numbers, which in binary have their last bit set.
EDIT: this is generating a power set as follows. The outer loop walks through all 2**N
subsets of items
, each represented as a binary integer. The inner loop then constructs the actual subset by checking which of the N
final bits of these integers are set, using the bits as indicators of subset membership.
E.g., suppose that N=5
. Then at some point, i
will be 0b10011
. From that, the set [items[0], items[1], items[4]]
can be constructed. First reverse the bits, because they're numbered right-to-left by j
:
1 1 0 0 1
items[0] items[1] (nothing) (nothing) items[4]
(Try printing i
and combo
inside the inner loop.)
Upvotes: 6
Reputation: 572
As an alternate flavour to larsmans already complete solution, here is how I understood it.
i >> j simply means i/pow(2,j), which mathematically means i/2^j [obviously we are in integer space]. lets set n=i/2^j. When you have n % 2 == 1 you ask if n mod 2 is 1? if it is then n must be odd, else n must be even.
Source: http://docs.python.org/2/reference/expressions.html
Upvotes: 0
Reputation: 77337
You can print the numbers in binary as the operation progresses to see how it works. Here's an example with i=1234 and j=4.
1234 in binary
>>> '{:b}'.format(1234)
'10011010010'
shifting right 4 places causes the rightmost bits (0010) to fall away
>>> '{:b}'.format(1234>>4)
'1001101'
the modulo operation divides by 2 and gives you the remainder
>>> '{:b}'.format((1234>>4)%2)
'1'
its also common to do this with the & operation
>>> '{:b}'.format((1234>>4)&1)
'1'
if you have a number where the 4th bit (from zero) is zero, you get a zero
>>> '{:b}'.format((1234+0b10000>>4)&1)
'0'
Upvotes: 3