在Python中检查唯一输出

时间:2011-09-21 20:33:09

标签: python puzzle

我昨天遇到了一个有趣的数学问题并且已经解决了,但是根据我写的代码,我不得不做一个键盘中断或它会永远运行,哈哈。因此我将其更改为具有结束条件,但现在它只打印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')

此代码打印遇到的第一个解决方案并停止。任何人都可以告诉我如何在停止之前打印两种解决方案吗?

5 个答案:

答案 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 answeryi_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')

当然,这种方法假设有两种解决方案。如果您有一个未知数量的解决方案,您将不知道何时停止,因此我建议采用另一种方法来寻找解决方案。