[英]All posible combinations of numbers on a list
我需要找到具有已定义长度和已定义大小数字的列表的所有可能组合,但受制于不允许在列表中具有相同重复数字(0 除外)的限制。 目前我有一个生成所有组合的递归代码,但是在尝试创建约束时,我失去了很多选项。 我已经尝试了出现评论的选项来解决它,但它仍然对我不起作用。 预先感谢您的帮助。
size=3
l=[0 for x in range(size)]
def recursive(l, index, num, final):
if index == len(l) or num == final:
return
# if num!=0 and num in l:
# return
l[index]=num
print(l)
recursive(l, index+1, 0, final)
recursive(l, index, num+1, final)
recursive(l, 0, 0, 4)
对于大小为 3 和最终数字为 3 的列表,预期的 output 将是这样的
[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
[0, 0, 3]
[0, 1, 0]
[0, 1, 2]
[0, 1, 3]
[0, 2, 0]
[0, 2, 1]
[0, 2, 3]
[0, 3, 0]
[0, 3, 1]
[0, 3, 2]
[1, 0, 0]
[1, 0, 2]
[1, 0, 3]
[1, 2, 0]
[1, 2, 3]
[1, 3, 0]
[1, 3, 2]
[2, 0, 0]
[2, 0, 1]
[2, 0, 3]
[2, 1, 0]
[2, 1, 3]
[2, 3, 0]
[2, 3, 1]
[3, 0, 0]
[3, 0, 1]
[3, 0, 2]
[3, 1, 0]
[3, 1, 2]
[3, 2, 0]
[3, 2, 1]
从非零值的幂集开始(可以在itertools
文档中找到用于计算列表的幂集的 function。)
def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
>>> list(powerset([1,2,3]))
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
(您可以计算包括 0 的幂集,但您仍然需要对较短的元素进行零填充,并丢弃(0,1,2,3)
)。
幂集的每个元素接下来应该用零填充,以使它们的长度都相同。
最后,您需要原始输入的每个 0 填充排列的排列列表(使用itertools.permutations
)。
使用itertools.combinations_with_replacement()
,然后过滤掉重复的元素。
def has_duplicates(l):
'''Return True if list has duplicate elements other than 0'''
l = [x in l if x != 0]
return len(l) != len(set(l))
result = [comb for comb in itertools.combinations_with_replacement(l, 3) if not has_duplicates(comb)]
你可以通过使用itertools.filterfalse()
使它变得懒惰; 这样你就不会用一个大列表的所有组合来填充 memory 。
result = itertools.filterfalse(has_duplicates, itertools.combinations_with_replacement(l, 3))
这是一个基于计数器的解决方案,我使用的是 4 进制计数器:
def charcnt(s, a):
ctr = [1 if x == a else 0 for x in s ]
return sum(ctr)
def my_range(start,end,base,step=1):
def Convert(n,base):
string = "0123"
if n < base:
return string[n]
else:
return Convert(n//base,base) + string[n%base]
return (Convert(i,base) for i in range(start,end,step))
# base-10 58 will produce base-4 321
counter = [x.zfill(3) for x in my_range(0, 58, 4)]
result = []
for s in counter:
if charcnt(s, '1') > 1 or charcnt(s, '2') > 1 or charcnt(s, '3') > 1:
continue
else:
result.append(s)
result = [[int(n) for n in list(s)] for s in result]
#print(len(result))
for i in result:
print(i)
将产生:
[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
[0, 0, 3]
[0, 1, 0]
[0, 1, 2]
[0, 1, 3]
[0, 2, 0]
[0, 2, 1]
[0, 2, 3]
[0, 3, 0]
[0, 3, 1]
[0, 3, 2]
[1, 0, 0]
[1, 0, 2]
[1, 0, 3]
[1, 2, 0]
[1, 2, 3]
[1, 3, 0]
[1, 3, 2]
[2, 0, 0]
[2, 0, 1]
[2, 0, 3]
[2, 1, 0]
[2, 1, 3]
[2, 3, 0]
[2, 3, 1]
[3, 0, 0]
[3, 0, 1]
[3, 0, 2]
[3, 1, 0]
[3, 1, 2]
[3, 2, 0]
[3, 2, 1]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.