Python 2.7 挑战:创建具有不同值的不同组合的元组列表';选项';在元组的每个位置。
这就是挑战。如果你能解决这个问题,你就比我强。 假设a can=1或0,b can=1或0,c can=0,1或2,d can=0,1,2或4,e仅为0,f=0或1 列出一个元组列表,其中所有组合的总和为特定数字,小于5,用于选择字母 例如a、b、c、d和数字4(无特定顺序) 或者f,f,e,d,c和3会给出Python 2.7 挑战:创建具有不同值的不同组合的元组列表';选项';在元组的每个位置。,python-2.7,combinations,Python 2.7,Combinations,这就是挑战。如果你能解决这个问题,你就比我强。 假设a can=1或0,b can=1或0,c can=0,1或2,d can=0,1,2或4,e仅为0,f=0或1 列出一个元组列表,其中所有组合的总和为特定数字,小于5,用于选择字母 例如a、b、c、d和数字4(无特定顺序) 或者f,f,e,d,c和3会给出 [(1,1,0,1,0),(1,1,0,0,1)(1,0,0,1,1),(1,0,0,2,0),(1,0,0,0,2),(0,1,0,2,0),(0,1,0,0,2)] 创建所有的组合,
[(1,1,0,1,0),(1,1,0,0,1)(1,0,0,1,1),(1,0,0,2,0),(1,0,0,0,2),(0,1,0,2,0),(0,1,0,0,2)]
创建所有的组合,然后删除那些不符合数字的组合,这是欺骗,效率太低
我试过使用
list(itertools.product(*a))
但就像我说的那样,它创造了所有的组合,所以使用它可以减少它是欺骗。你可以使用:
这将查找所有解决方案,而无需枚举整个笛卡尔函数集
产品。只要部分和大于最大值,它就会短路
目标金额
将其推广到可以接受任意 我们可以使用它来形成笛卡尔积
def constrained_product(target, *args):
pools = map(tuple, args)
if len(pools) == 1:
for y in pools[0]:
if y == target:
yield (y,)
else:
for y in pools[-1]:
for x in constrained_product(target-y, *pools[:-1]):
yield x + (y,)
这是这个纯Python实现的一个稍加修改的版本
itertools.product
:
def iterproduct(*args):
"""
list(iterproduct('ABCD', 'xy')) --> Ax Ay Bx By Cx Cy Dx Dy
"""
pools = map(tuple, args)
if len(pools) == 1:
for y in pools[0]:
yield (y,)
else:
for x in iterproduct(*pools[:-1]):
for y in pools[-1]:
yield x + (y,)
主要区别在于,如果y==target
将生成的项目约束为总和等于target
的项目
它与类似,只是在生成项目之前不会生成所有产品
例如,
constrated\u product
可以这样使用:
A = range(2)
B = range(2)
C = range(3)
D = [0,1,2,4]
E = [0]
F = range(2)
def constrained_product(target, *args):
pools = map(tuple, args)
if len(pools) == 1:
for y in pools[0]:
if y == target:
yield (y,)
else:
for y in pools[-1]:
for x in constrained_product(target-y, *pools[:-1]):
yield x + (y,)
for item in constrained_product(4, A, B, C, D):
print(item)
# (1, 1, 2, 0)
# (1, 1, 1, 1)
# (1, 0, 2, 1)
# (0, 1, 2, 1)
# (1, 1, 0, 2)
# (1, 0, 1, 2)
# (0, 1, 1, 2)
# (0, 0, 2, 2)
# (0, 0, 0, 4)
for item in constrained_product(3, F, F, E, D, C):
print(item)
# (1, 1, 0, 1, 0)
# (1, 0, 0, 2, 0)
# (0, 1, 0, 2, 0)
# (1, 1, 0, 0, 1)
# (1, 0, 0, 1, 1)
# (0, 1, 0, 1, 1)
# (0, 0, 0, 2, 1)
# (1, 0, 0, 0, 2)
# (0, 1, 0, 0, 2)
# (0, 0, 0, 1, 2)
如果我们可以还假设
args
中的值都是非负的
然后,我们可以通过添加if语句
,来加快代码的速度:
for y in pools[-1]:
if target-y >= 0:
for x in constrained_product(target-y, *pools[:-1]):
yield x + (y,)
如果target-y<0
则调用约束的_产品(target-y,
*池[:-1])
因为根据假设,池[:-1]
中的所有值都是
非负。我们知道没有可以和为负数的元组,所以
我们可以去掉这根树枝来节省时间
使用此修改版本的受约束的\u产品
def constrained_product_nonneg(target, *args):
pools = map(tuple, args)
if len(pools) == 1:
for y in pools[0]:
if y == target:
yield (y,)
else:
for y in pools[-1]:
if target-y >= 0:
for x in constrained_product_nonneg(target-y, *pools[:-1]):
yield x + (y,)
现在
快速找到解决方案:
In [35]: %timeit list(constrained_product_nonneg(0, *[A]*53))
10000 loops, best of 3: 170 µs per loop
这是一个基于树的解决方案。它为系统提供了所有有效的答案(这可能是作弊),但它不必重复计算
class tree_node:
def __init__(self, v, s, p):
self.value = v
self.sum = s
self.parent = p
self.branchList = []
if __name__ == "__main__":
# Initialize the tree. The sums will be in the leaves once it's built
root = tree_node(None, 0, None)
leaf_list = [root]
# Define the rules of the problem
a = [0, 1]
b = [0, 1]
c = [0, 1, 2]
d = [0, 1, 4]
e = [0]
f = [0, 1]
rules = [a, b, c, d, e, f]
# Build the tree, one layer of nodes at a time
for rule in rules:
new_leaves = []
for leaf in leaf_list:
for r in rule:
tn = tree_node(r, r + leaf.sum, leaf)
new_leaves.append(tn)
leaf_list = new_leaves
# Traverse the tree starting from each matching leaf
target = 4
for n in leaf_list:
if n.sum == target:
sequence = [n.value]
parent = n.parent
while parent.value != None:
sequence = sequence + [parent.value]
parent = parent.parent
sequence.reverse()
print sequence
如果我错了,请告诉我这真的很接近,但是当我运行它时,输出给我len()=7的列表,因为规则中只有6个字母,我不确定它是否正确。你是对的。它考虑的是根节点,这不是规则的一部分。现在应该修好了。你排在倒数第二,这真是太棒了。我将约束_产品(4,A,B,C,D)中的“for item:”部分更改为约束_产品(4,A,B,C,D)中的项的x=[]:x.append(item),以便将其输出到列表中。你认为这样做有什么问题吗?然而,像“0、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A”这样的东西,似乎需要很长时间,因为它只需要(0、0、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A、A,
C
s是否只包含非负数?如果是这样的话,代码可以进一步加速。@HappyleAppSecond yes,A,B,C将只包含0,1,2,3,4。此外,如果您将“目标”设置为4,并计算目标0,1,2,3,4,则更容易/更快。关于第一条注释中的Q:您可以使用x=list(受约束产品(4,A,B,C,D))
而不是x=[]。。。;x、 附加(项目)
。
def constrained_product_nonneg(target, *args):
pools = map(tuple, args)
if len(pools) == 1:
for y in pools[0]:
if y == target:
yield (y,)
else:
for y in pools[-1]:
if target-y >= 0:
for x in constrained_product_nonneg(target-y, *pools[:-1]):
yield x + (y,)
list(constrained_product_nonneg(0, *[A]*53))
In [35]: %timeit list(constrained_product_nonneg(0, *[A]*53))
10000 loops, best of 3: 170 µs per loop
class tree_node:
def __init__(self, v, s, p):
self.value = v
self.sum = s
self.parent = p
self.branchList = []
if __name__ == "__main__":
# Initialize the tree. The sums will be in the leaves once it's built
root = tree_node(None, 0, None)
leaf_list = [root]
# Define the rules of the problem
a = [0, 1]
b = [0, 1]
c = [0, 1, 2]
d = [0, 1, 4]
e = [0]
f = [0, 1]
rules = [a, b, c, d, e, f]
# Build the tree, one layer of nodes at a time
for rule in rules:
new_leaves = []
for leaf in leaf_list:
for r in rule:
tn = tree_node(r, r + leaf.sum, leaf)
new_leaves.append(tn)
leaf_list = new_leaves
# Traverse the tree starting from each matching leaf
target = 4
for n in leaf_list:
if n.sum == target:
sequence = [n.value]
parent = n.parent
while parent.value != None:
sequence = sequence + [parent.value]
parent = parent.parent
sequence.reverse()
print sequence