我昨天遇到了一个有趣的数学问题并且已经解决了,但是根据我写的代码,我不得不做一个键盘中断或它会永远运行,哈哈。因此我将其更改为具有结束条件,但现在它只打印1个解决方案并停止。
问题是这样的:“你有数字123456789,按顺序排列。在每个数字之间,你必须插入任何内容,加号或乘法符号,以便结果表达式等于2002.编写一个程序打印所有解决方案。(有两个。)“
import random
def try1(param):
global solved
opers = ['+', '*', '']
hotpotato = ('%s'.join(param) % (random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
)
)
if eval(hotpotato) == 2002:
solved += 1
print "Solution:", hotpotato, "= 2002 :-)"
else:
pass
solved = 0
while solved == 0:
try1('123456789')
此代码打印遇到的第一个解决方案并停止。任何人都可以告诉我如何在停止之前打印两种解决方案吗?
答案 0 :(得分:8)
不要使用随机,枚举所有可能的运算符组合(好吧,你可以稍微削减搜索空间,如果结果大于2002的前几个数字,则结果不会变小)。 itertools
是你的朋友。
如果你这样做,你的程序将很快完成。
如果您知道完全两个解决方案,您可以从try1
返回解决方案并进行循环,直到您收集了两个不同的解决方案,但这不是很优雅,是吗?
答案 1 :(得分:5)
解决问题的方法是,解决时破解== 2.
但是你的代码真正的问题是随机使用。在算法中使用随机通常是个坏主意。您的代码有可能持续一个多世纪。
使用itertools有更简单快捷的方法:
import itertools
for s in itertools.product(("+", "*", ""), repeat=8):
z = itertools.izip_longest("123456789", s, fillvalue="")
e = "".join(itertools.chain.from_iterable(z))
if eval(e) == 2002:
print(e)
找到两个解决方案时无需中断,因为代码已在0.2秒内完成:)。
答案 2 :(得分:3)
将您的解决方案存储在一个集合中:
solutions = set([])
每次找到解决方案时,请更新集:
solutions.append(solution)
设置很好,因为不存储重复项:
>>> len(set([1, 1, 1, 1, 1, 1, 1]))
1
所以只需循环直到集合的大小大于1:
while len(solved) < 2:
try1('123456789')
此外,您可以缩短此代码:
hotpotato = ('%s'.join(param) % (random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
)
)
对此:
hotpotato = ('%s'.join(param) % (random.choice(opers) for i in range(8))))
答案 3 :(得分:3)
要获得两个(所有)解决方案,您需要完全不同的方法来解决此问题。检查插入操作的所有排列。如何计算排列如下所示:http://www.bearcave.com/random_hacks/permute.html
修改强>
示例:
ops = ['+', '*']
def gen(ver, i):
if i == len(ver):
return
for op in ops:
ver = ver[:i] + op + ver[i:]
if eval(ver) == 2002:
yield ver
for j in range(i + 2, len(ver)):
for sol in gen(ver, j):
yield sol
ver = ver[:i] + ver[i+1:]
for sol in gen("123456789", 1):
print "solution:", sol
输出:
solution: 1*2+34*56+7+89
solution: 1*23+45*6*7+89
答案 4 :(得分:2)
为了记录,我鼓励采用不同的方法来搜索解决方案,例如Andy T's answer或yi_H's answer中建议的方法。也就是说,这个答案解决了问题中提出的问题。
您提供的代码将一直运行,直到找到一个答案并停止,因为找到第一个答案将使solved
不等于0.因为您知道有2个解决方案,您可以更改您的while循环条件:< / p>
while solved < 2:
try1('123456789')
回应Mark的评论,这可能会导致重复的答案,这里的代码将确保您获得不同的解决方案:
import random
def try1(param):
global solved
try1.prev_soln = []
opers = ['+', '*', '']
hotpotato = ('%s'.join(param) % (random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
random.choice(opers),
)
)
if eval(hotpotato) == 2002:
if hotpotato not in try1.prev_soln:
solved += 1
try1.prev_soln.append(hotpotato)
print "Solution:", hotpotato, "= 2002 :-)"
else:
pass
solved = 0
while solved < 2:
try1('123456789')
当然,这种方法假设有两种解决方案。如果您有一个未知数量的解决方案,您将不知道何时停止,因此我建议采用另一种方法来寻找解决方案。