请问,我怎样才能获得所有这些二进制排列,但不会在Python中重复?
a = list(itertools.permutations([1, 1, 0, 0]))
for i in range(len(a)):
print a[i]
(1, 1, 0, 0)
(1, 1, 0, 0)
(1, 0, 1, 0)
...
如果它大致有效,那就太好了,因为我必须用这样的30个元素列表做到这一点。
答案 0 :(得分:11)
正如@Antti在评论中所说,这相当于查找输入列表的combinations
个位置,这些位置确定输出中的哪些位为1.
from itertools import combinations
def binary_permutations(lst):
for comb in combinations(range(len(lst)), lst.count(1)):
result = [0] * len(lst)
for i in comb:
result[i] = 1
yield result
for perm in binary_permutations([1, 1, 0, 0]):
print(perm)
输出:
[1, 1, 0, 0]
[1, 0, 1, 0]
[1, 0, 0, 1]
[0, 1, 1, 0]
[0, 1, 0, 1]
[0, 0, 1, 1]
答案 1 :(得分:2)
这里是来自the accepted answer to the generic algorithm question的算法,适用于Python 3(应该在Python 2.7+中工作)。函数generate(start, n_bits)
将按字典顺序从start
开始生成所有 n位整数。
def generate(start, n_bits):
# no ones to permute...
if start == 0:
yield 0
return
# fastest count of 1s in the input value!!
n_ones = bin(start).count('1')
# the minimum value to wrap to when maxv is reached;
# all ones in LSB positions
minv = 2 ** n_ones - 1
# this one is just min value shifted left by number of zeroes
maxv = minv << (n_bits - n_ones)
# initialize the iteration value
v = start
while True:
yield v
# the bit permutation doesn't wrap after maxv by itself, so,
if v == maxv:
v = minv
else:
t = ((v | ((v - 1))) + 1)
v = t | (((((t & -t)) // ((v & -v))) >> 1) - 1)
# full circle yet?
if v == start:
break
for i in generate(12, 4):
print('{:04b}'.format(i))
打印
1100
0011
0101
0110
1001
1010
如果生成了列表输出,则可以对其进行修饰:
def generate_list(start):
n_bits = len(start)
start_int = int(''.join(map(str, start)), 2)
# old and new-style formatting in one
binarifier = ('{:0%db}' % n_bits).format
for i in generate(start_int, n_bits):
yield [int(j) for j in binarifier(i)]
for i in generate_list([1, 1, 0, 0]):
print(i)
打印
[1, 1, 0, 0]
[0, 0, 1, 1]
[0, 1, 0, 1]
[0, 1, 1, 0]
[1, 0, 0, 1]
[1, 0, 1, 0]
这个算法有什么好处,你可以随时恢复它。如果您找到计算好起点的方法,也可以并行化。 数字应该比列表更紧凑,所以如果可能的话你可以使用它们。
答案 2 :(得分:1)
您要做的是选择元素为1
的两个位置。
from itertools import combinations
def bit_patterns(size, ones):
for pos in map(set, combinations(range(size), ones)):
yield [int(i in pos) for i in range(size)]
>>> print(*bit_patterns(4, 2), sep='\n')
[1, 1, 0, 0]
[1, 0, 1, 0]
[1, 0, 0, 1]
[0, 1, 1, 0]
[0, 1, 0, 1]
[0, 0, 1, 1]
一个有趣的替代方案是将所需的输出视为仅具有两个的二进制表示。我们可以使用这个定义来获得你想要的输出。
from itertools import combinations
def bit_patterns(size, ones):
for t in combinations([1 << i for i in range(size)], ones):
yield [int(n) for n in f'{sum(t):0{size}b}']
答案 3 :(得分:1)
这是一个递归解决方案:
def bin_combs_iter(ones, zeros):
if not zeros:
yield [1] * ones
elif not ones:
yield [0] * zeros
else:
for x in bin_combs_iter(ones - 1, zeros):
x.append(1)
yield x
for x in bin_combs_iter(ones, zeros - 1):
x.append(0)
yield x
def bin_combs(ones, zeros):
return list(bin_combs_iter(ones, zeros))