假设我有一些二进制掩码mask
。 (例如0b101011011101)
是否有一种有效的方法来计算所有整数k
,以便k & mask == k
? (其中&
是按位AND运算符)(或者,k& ~mask == 0)
如果mask
有m
个,那么正好有2个 m 数字满足这个属性,所以看起来应该有某种过程就是O (2 米)。枚举小于掩码的整数是浪费的(虽然很容易消除不适用的值)。
答案 0 :(得分:0)
我想通了......你可以识别所有单个位模式,如下所示,因为在计算k
时,任何整数k & (k-1)
的最低有效位被清除:
def onebits(x):
while x > 0:
# find least significant 1 bit
xprev = x
x &= x-1
yield x ^ xprev
然后我可以使用ruler function以1位的各种组合进行异或,以模拟每次切换计数器的哪些位:
def maskcount(mask):
maskbits = []
m = 0
for ls1 in onebits(mask):
m ^= ls1
maskbits.append(m)
# ruler function modified from
# http://lua-users.org/wiki/LuaCoroutinesVersusPythonGenerators
def ruler(k):
for i in range(k):
yield i
for x in ruler(i): yield x
x = 0
yield x
for k in ruler(len(maskbits)):
x ^= maskbits[k]
yield x
看起来像这样:
>>> for x in maskcount(0xc05):
... print format(x, '#016b')
0b00000000000000
0b00000000000001
0b00000000000100
0b00000000000101
0b00010000000000
0b00010000000001
0b00010000000100
0b00010000000101
0b00100000000000
0b00100000000001
0b00100000000100
0b00100000000101
0b00110000000000
0b00110000000001
0b00110000000100
0b00110000000101
答案 1 :(得分:0)
解决问题的一种简单方法是找到在掩码中设置的位,然后简单地用i计数,然后用掩码中的相应位替换i的位。
def codes(mask):
bits = filter(None, (mask & (1 << i) for i in xrange(mask.bit_length())))
for i in xrange(1 << len(bits)):
yield sum(b for j, b in enumerate(bits) if (i >> j) & 1)
print list(codes(39))
它为每次迭代提供O(log(N))工作(其中N是mask
中设置的位数)。
可以提高效率,并通过使用gray codes进行计数,每次迭代执行O(1)工作。使用格雷码计数,每次迭代只改变一个位,因此可以有效地更新当前值v
。显然,这比上面的简单解决方案更难理解。
def codes(mask):
bits = filter(None, (mask & (1 << i) for i in xrange(mask.bit_length())))
blt = dict((1 << i, b) for i, b in enumerate(bits))
p, v = 0, 0
for i in xrange(1 << len(bits)):
n = i ^ (i >> 1)
v ^= blt.get(p^n, 0)
p = n
yield v
print list(codes(39))
使用格雷码的一个缺点是结果不是按数字顺序返回的。但幸运的是,这不是问题的一个条件!