Python 如何按1';索引的二进制值是多少?(最好是蟒蛇)

Python 如何按1';索引的二进制值是多少?(最好是蟒蛇),python,recursion,dynamic,binary,superset,Python,Recursion,Dynamic,Binary,Superset,如果我有一个巨大的列表(比如2^50个元素),我如何迭代这个列表,但是按照索引二进制值中1的数量的顺序,以Python中最快的方式迭代 例如,首先是11111111,然后是11111110,11111111101,111110011,11110111,11101111,11011111,10111111,01111111,然后是11111100等等 我之所以需要这样做,是因为我在做动态规划,为给定集合V的每个子集找到一个值,用值(子集)表示,并且因为有太多可能的子集,我决定用二进制表示这些子集,

如果我有一个巨大的列表(比如2^50个元素),我如何迭代这个列表,但是按照索引二进制值中1的数量的顺序,以Python中最快的方式迭代

例如,首先是11111111,然后是11111110,11111111101,111110011,11110111,11101111,11011111,10111111,01111111,然后是11111100等等

我之所以需要这样做,是因为我在做动态规划,为给定集合V的每个子集找到一个值,用值(子集)表示,并且因为有太多可能的子集,我决定用二进制表示这些子集,例如,子集{v1,v2,v5}是000010011。我必须按上述顺序迭代,因为我必须使用的递归函数的基本情况值(V)=0,即值(1111)=0,并且随着子集大小的减小而进一步构建,即二进制值中1的数量

如果有完全不同的方法根本不使用二进制,请让我知道!谢谢你读了这篇文章, 约斯特

编辑:这是递归函数: ,其中N(v)是顶点v的邻域。(这是一个图表问题)。 对于集合V和子集X,伪代码如下所示:

value(V)=0
Forloop in described order:
    pick a vertex v from V that is not in X and denote it in binary
    subset, so that for example  v = 001000000, where X = 010111101
    #Use bitwise operator '|' to get intersections of binary values: 
    value(X) = value(X|v) + value(X|N(v)) + 1
    

PS:您可以在python中使用普通整数,按位运算符仍然有效:8 | 4将返回12:100 | 010=110

下面提出了两种不同的方法

方法1:基于组合的发电机 实现这一点的一种方法是在on位的数量上使用外循环,在on位的位置上使用内循环。对于内部循环,可以使用a来迭代on位的位置。相应的序列将以所有on位的数字开始,然后是除一个on位之外的所有on位的数字,然后是除两个on位之外的所有on位的数字,…,最后以0(无on位)结束。位上位置的组合可以通过对位上的位置求和
2^position
转换为数字

对于问题的用例,序列的元素将被用作遍历相关列表的索引

旋转门组合生成器在每次访问时对要在组合中交换的小项目集进行迭代。这种算法可能用于减少上述方法的计算需求,方法是根据打开和关闭的比特修改每次迭代的当前数目

这里有一个Python实现,它不使用旋转门方法,基于Python内置的
itertools.compositions
。函数下面的示例用法总共使用八位。对于生成序列中的每个数字,输出显示1)十进制表示,2)二进制表示,以及3)on位计数

来自itertools导入组合的

def发生器(数字位):
幂=[2**范围内指数的指数(num_位-1,-1,-1)]
对于范围内的num_on(num_位,-1,-1):
对于组合中的位置(范围(num_位),num_开):
收益总额(头寸中头寸的幂[头寸])
对于发电机(8)中的x:
二进制=f'{x:#010b}'
比特计数=二进制计数('1')
打印(f'{x:03}{binary}{bit_count}')
输出:

255 0b11111111 8
254 0b11111110 7
253 0b11111101 7
251 0b11111011 7
247 0b11110111 7
239 0b11101111 7
223 0b11011111 7
191 0b10111111 7
127 0b01111111 7
252 0b11111100 6
250 0b11111010 6
249 0b11111001 6
...
006 0b00000110 2
005 0b00000101 2
003 0b00000011 2
128 0b10000000 1
064 0b01000000 1
032 0b00100000 1
016 0b00010000 1
008 0b00001000 1
004 0b00000100 1
002 0b00000010 1
001 0b00000001 1
000 0b00000000 0
p 15 0b01111 4
x 23 0b10111 4
h 07 0b00111 3
l 11 0b01011 3
n 13 0b01101 3
o 14 0b01110 3
t 19 0b10011 3
v 21 0b10101 3
w 22 0b10110 3
z 25 0b11001 3
d 03 0b00011 2
f 05 0b00101 2
g 06 0b00110 2
j 09 0b01001 2
k 10 0b01010 2
m 12 0b01100 2
r 17 0b10001 2
s 18 0b10010 2
u 20 0b10100 2
y 24 0b11000 2
b 01 0b00001 1
c 02 0b00010 1
e 04 0b00100 1
i 08 0b01000 1
q 16 0b10000 1
a 00 0b00000 0
方法2:有序索引列表 使用比先前方法更多内存的另一种方法是计算每个数字中的on位数(此处“number”是索引),然后按on位数的降序创建数字列表

下面是一个Python实现。对于从
a
z
的字母,输出显示按其索引中的位数排序的字符,以及每个字符的索引、二进制表示形式和位计数
bin(.)。count('1')
用于计算每个数字中its上的数量。on建议在Python 3.10中提供内置的
位计数
方法

letters = [
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
]

n = len(letters)
bit_counts = [bin(x).count('1') for x in range(n)]
indices_lookup = [[] for _ in range(len(bin(n)) - 2)]
for idx, bit_count in enumerate(bit_counts):
    indices_lookup[bit_count].append(idx)
ordered_indices = []
for idxs in reversed(indices_lookup):
    ordered_indices.extend(idxs)

for x in ordered_indices:
    print(f'{letters[x]} {x:02} {x:#07b}')
输出:

255 0b11111111 8
254 0b11111110 7
253 0b11111101 7
251 0b11111011 7
247 0b11110111 7
239 0b11101111 7
223 0b11011111 7
191 0b10111111 7
127 0b01111111 7
252 0b11111100 6
250 0b11111010 6
249 0b11111001 6
...
006 0b00000110 2
005 0b00000101 2
003 0b00000011 2
128 0b10000000 1
064 0b01000000 1
032 0b00100000 1
016 0b00010000 1
008 0b00001000 1
004 0b00000100 1
002 0b00000010 1
001 0b00000001 1
000 0b00000000 0
p 15 0b01111 4
x 23 0b10111 4
h 07 0b00111 3
l 11 0b01011 3
n 13 0b01101 3
o 14 0b01110 3
t 19 0b10011 3
v 21 0b10101 3
w 22 0b10110 3
z 25 0b11001 3
d 03 0b00011 2
f 05 0b00101 2
g 06 0b00110 2
j 09 0b01001 2
k 10 0b01010 2
m 12 0b01100 2
r 17 0b10001 2
s 18 0b10010 2
u 20 0b10100 2
y 24 0b11000 2
b 01 0b00001 1
c 02 0b00010 1
e 04 0b00100 1
i 08 0b01000 1
q 16 0b10000 1
a 00 0b00000 0

下文提出了两种不同的方法

方法1:基于组合的发电机 实现这一点的一种方法是在on位的数量上使用外循环,在on位的位置上使用内循环。对于内部循环,可以使用a来迭代on位的位置。相应的序列将以所有on位的数字开始,然后是除一个on位之外的所有on位的数字,然后是除两个on位之外的所有on位的数字,…,最后以0(无on位)结束。位上位置的组合可以通过对位上的位置求和
2^position
转换为数字

对于问题的用例,序列的元素将被用作遍历相关列表的索引

旋转门组合生成器在每次访问时对要在组合中交换的小项目集进行迭代。这种算法可能用于减少上述方法的计算需求,方法是根据打开和关闭的比特修改每次迭代的当前数目

这里有一个Python实现,它不使用旋转门方法,基于Python内置的
itertools.compositions
。函数下面的示例用法总共使用八位。对于生成序列中的每个数字,输出显示1)十进制表示,2)二进制表示,以及3)on位计数

来自itertools导入组合的

def发生器(数字位):
幂=[2**范围内指数的指数(num_位-1,-1,-1)]
对于范围内的num_on(num_位,-1,-1):
对于组合中的位置(范围(num_位),num_开):
收益总额(头寸中头寸的幂[头寸])
对于发电机(8)中的x: