用Python发送更多钱拼图

时间:2016-05-26 01:52:51

标签: python

一个着名的难题如下。 发送+更多=钱币

用等号0-9(无重复)替换等式中的每个字母,以使加法正确。写一个程序来解决这个难题。提示:蛮力运作良好{尝试所有可能性}。

到目前为止,这是我的代码:

def solution():
    letters = ('s', 'e', 'n', 'd', 'm', 'o', 'r', 'y')
    for s in range(9, 0, -1):
        for e in range(9, -1, -1):
            for n in range(9, -1, -1):
                for d in range(9, -1, -1):
                    for m in range(9, 0, -1):
                        for o in range(9, -1, -1):
                            for r in range(9, -1, -1):
                                for y in range(9, -1, -1):
                                    if len(set((letters))) != len(letters):
                                        send = 1000 * s + 100 * e + 10 * n + d
                                        more = 1000 * m + 100 * o + 10 * r + e
                                        money = 10000 * m + 1000 * o + 100 * n + 10 * e + y

                                        if send + more == money:
                                            return send, more, money

print(solution())

但它不起作用。它没有输出。我该如何解决这个问题?

6 个答案:

答案 0 :(得分:4)

具有唯一性要求并搜索所有解决方案:

def solutions():
    # letters = ('s', 'e', 'n', 'd', 'm', 'o', 'r', 'y')
    all_solutions = list()
    for s in range(9, -1, -1):
        for e in range(9, -1, -1):
            for n in range(9, -1, -1):
                for d in range(9, -1, -1):
                    for m in range(9, 0, -1):
                        for o in range(9, -1, -1):
                            for r in range(9, -1, -1):
                                for y in range(9, -1, -1):
                                    if len(set([s, e, n, d, m, o, r, y])) == 8:
                                        send = 1000 * s + 100 * e + 10 * n + d
                                        more = 1000 * m + 100 * o + 10 * r + e
                                        money = 10000 * m + 1000 * o + 100 * n + 10 * e + y

                                        if send + more == money:
                                            all_solutions.append((send, more, money))
    return all_solutions

print(solutions())

答案 1 :(得分:1)

我忍不住写了一些更简洁的蛮力解决方案,因为我之前从未听过这个谜题。

from itertools import combinations, permutations

a, b, c = 'SEND', 'MORE', 'MONEY'

for comb in combinations(range(10), 8):
    for perm in permutations(comb):
        d = dict(zip('SENDMORY', perm))
        f = lambda x: sum(d[e] * 10**i for i, e in enumerate(x[::-1]))
        if f(a) + f(b) == f(c):
            print "{} + {} = {}".format(f(a), f(b), f(c))

请注意,我并未排除此处S -> 0M -> 0的可能性。

编辑:类似,但使用生成器并忽略会导致前导零的替换。

from itertools import combinations, permutations

def replacements(): 
    for comb in combinations(range(10), 8): 
        for perm in permutations(comb): 
            if perm[0] * perm[1] != 0: 
                yield dict(zip('SMENDORY', perm))

a, b, c = 'SEND', 'MORE', 'MONEY'

for replacement in replacements(): 
    f = lambda x: sum(replacement[e] * 10**i for i, e in enumerate(x[::-1])) 
    if f(a) + f(b) == f(c):
        print('{} + {} = {}'.format(f(a), f(b), f(c)))

答案 2 :(得分:0)

如果集合列表具有非唯一元素,则它们只会更改其长度。 检查集合的工作方式:https://docs.python.org/2/library/sets.html

来自community guidelines

  

解释您是如何遇到您尝试解决的问题的,以及   任何阻碍你自己解决的困难。该   你问题的第一段是大多数读者的第二句话   看,所以尽量使它具有吸引力和信息量。

答案 3 :(得分:0)

@ siwica:你的快速'解决方案提供了多个结果的列表,因此我建议对您的第二行进行更改:

    if (f(a) + f(b) == f(c)) & (len(a) == len(str(f(a)))) & (len(b) == len(str(f(b)))):

所以,我没有评论的权利,这就是为什么我写这个'回答'

答案 4 :(得分:0)

首先我们可以得到m = 1,使用排列来避免出现相同的数字

from itertools import permutations 

perm = permutations([0,2,3,4,5,6,7,8,9], 7)

for i in perm:

    if((i[0]*1000 + i[1]*100 + i[2]*10 + i[3] + 1000 + 100*i[4] + 10 * i[5] + i[1]) == (10000+1000*i[4]+i[2]*100+i[1]*10+i[6])):

        print(i[0]*1000 + i[1]*100 + i[2]*10 + i[3])
        print(1000 + 100*i[4] + 10 * i[5] + i[1])

答案 5 :(得分:0)

具有列表理解能力(约束编程)的解决方案:

[(send, more, money) for send in range(1023,9877) for more in range(1023,9877) for money in [send+more]
  if send + more > 9999
    and str(send)[1] == str(more)[3]
    and str(money)[:4] == str(more)[:2] + str(send)[2:0:-1]
    and len("".join(set(str(money) + str(send) + str(more)))) == 8]
  • sendmore都是4位数字
  • money是5位数字
  • sendmore具有e作为公用数字
  • money中的前4位数字必须与sendmore中的相应数字相匹配
  • 总共必须有8个不同的数字