我想知道如何生成给定长度的每个偶数为0‘S和1’S的二进制数的最好方法.我目前正在用一种强力方法来生成字符串,我认为这是一种垃圾的方法:

def max_bits(b):
    return (1 << b) - 1


def binary_options(digits):
    target = digits / 2
    return [f"{i:b}" for i in range(max_bits(digits - 1), 2 ** digits) if f"{i:b}".count("0") == target]

我使用二进制数作为索引,对拆分为两个偶数部分的数组的所有可能组合求和,所以我实际上不需要存储这些组合,我可以边走边求和,我也不需要将二进制数作为字符串.请参见下面的示例.

arr = [1,2,3,4]

comb1 = 1001 # 1 + 4 and 2 + 3
comb2 = 1010 # 1 + 3 and 2 + 4
comb3 = 1100 # 1 + 2 and 3 + 4

非常感谢.

编辑:

很抱歉之前没有提到这一点,但我不需要生成解的逆,所以我只需要潜在排列的一半.例如,在上面的示例中,我有100110101100,但没有011001010011.

发帖主题:Re:Kolibrios

马克提供了最好的解决方案.为了只生成一半的二进制数(因为我不需要倒数),我使用下面的函数.我还将二进制数存储为整数,而不是字符串,并使用this answer中提供的方法将整数的位用作索引.

def binary_options(digits):
    target = digits / 2
    return [i for i in range(int('1' * (digits - 1), 2)) if i.bit_count() == target]

推荐答案

如果使用的是Python3.10+,则可使用int.bit_count():

>>> for i in range(16):
...   print(f'{i:04b}, count={i.bit_count()}')
...
0000, count=0
0001, count=1
0010, count=1
0011, count=2
0100, count=1
0101, count=2
0110, count=2
0111, count=3
1000, count=1
1001, count=2
1010, count=2
1011, count=3
1100, count=2
1101, count=3
1110, count=3
1111, count=4

因此,对于4位数字中的偶数个0和1:

>>> for i in range(16):
...   if i.bit_count() == 2:
...     print(f'{i:04b}')
...
0011
0101
0110
1001
1010
1100

或者简单地数一数:

>>> sum(1 for i in range(2**4) if i.bit_count() == 2)
6
>>> sum(1 for i in range(2**24) if i.bit_count() == 12)
2704156

一种更快的计数 Select 是一次生成N位的组合,每次取N/2,这比以上24位数字的.bit_count()求和快约4倍:

>>> from itertools import combinations as C
>>> numbits = 24
>>> target = numbits // 2
>>> sum(1 for c in C(range(numbits), target))
2704156

时序比较:

C:\>py -m timeit -s "from itertools import combinations as C" "sum(1 for c in C(range(24), 12))"
1 loop, best of 5: 383 msec per loop

C:\>py -m timeit "sum(1 for i in range(2**24) if i.bit_count() == 12)"
1 loop, best of 5: 1.53 sec per loop

itertools生成位模式和值的解决方案.例如,下面迭代20次,而不是try 所有64(26)个数字:

from itertools import combinations as C
numbits = 6
target = numbits // 2
for c in C([1<<n for n in range(numbits)], target):
    value = sum(c)
    print(f'{value:0{numbits}b} {value}')

输出:

000111 7
001011 11
010011 19
100011 35
001101 13
010101 21
100101 37
011001 25
101001 41
110001 49
001110 14
010110 22
100110 38
011010 26
101010 42
110010 50
011100 28
101100 44
110100 52
111000 56

Python-3.x相关问答推荐

这是重命名极地df列的最好方式吗?

是否有必要使用Threads()中的args显式地将共享变量传递给Python中的线程函数或直接访问它?

在Pandas 数据帧中为小于5位的邮政编码添加前导零

没有这样的命令';角色';-可靠分子

如何使用正则表达式通过反向搜索从链接中获取特定文本

GEKKO 在没有不等式的模型中抛出不等式定义错误

在 groupby 之后,Pandas 在特定类别中获得最常见和最后的值

在 pytest 中,如何测试 sys.exit('some error message')?

获取字符串中的两个工作日之间的差异

Pandas 按值和索引对 DF 进行排序

列表中的重复数字与列表理解

使用一周的特定第一天将每日日期转换为每周

'~'(波浪号)运算符在 Python 中的应用

ValueError:预期的 2D 数组,得到 1D 数组:

AttributeError:LinearRegression 对象没有属性coef_

登录csv文件的正确方法是什么?

清除 PyCharm 运行窗口

如何将文档字符串放在 Enums 上?

三个参数的reduce函数

如何修复:cx_Oracle.DatabaseError:DPI-1047:找不到 64 位 Oracle 客户端库 - Python