在这个假设情景中,我有一个已知但随机长度的序列,我需要将序列中的每个数字设置为添加或减去以达到给定的输出并显示该过程。
有没有办法在不重新发明轮子的情况下做到这一点,比如模块?
编辑:更多信息:
我有一系列数字,如:5 4 3 2 1,我需要设置每个数字来添加(+)或减去( - )以得到7等结果。这种情况下的结果将是5+ 4-3 + 2-1。只要有可能的结果,它可以是任何数字的序列。如果有多个正确的答案,其中只有一个会做。
编辑:
让我们假设等式中的任何步骤都不会导致答案大于1000。
答案 0 :(得分:3)
最简单的方法是强制加强所有可能的加号和减号组合,并返回第一个具有正确总和的组合。您可以使用itertools.product
执行此操作。
import itertools
def find_correct_operators(seq, total):
signs = [-1,1]
for item_signs in itertools.product(*[signs]*len(seq)):
seq_with_signs_applied = [item*sign for item, sign in zip(seq, item_signs)]
sum(seq_with_signs_applied)
if sum(seq_with_signs_applied) == total:
return item_signs
a = [5,4,3,2,1]
b = 7
signs = find_correct_operators(a,b)
if signs is not None:
print "{} = {}".format(" ".join("{}{}".format("-" if sign == -1 else "+", item) for sign, item in zip(signs, a)), b)
else:
print "No solution found"
结果:
+5 -4 +3 +2 +1 = 7
这样做的缺点是它在O(2 ^ N)时间内运行,所以它非常不适合任何大于20个项目的数字序列。到那时,你正在迭代超过一百万种可能的组合。
编辑:如果你有一些限制 L 并且等式中没有中间步骤可以评估为大于L或小于-L,那么你可以在O(N * L)中找到答案)时间,这对L的小值是一个相当大的改进。
seq = [5,4,-3,2,1]
goal = 7
limit = 1000
d = {0: []}
for item in seq:
next_d ={}
for intermediary_total, path in d.iteritems():
for candidate in [-item, item]:
next_total = intermediary_total + candidate
if abs(next_total) <= limit:
next_d[next_total] = path + [candidate]
d = next_d
if goal in d:
print d[goal]
else:
print "no solution found"
结果:
[5, 4, -3, 2, -1]