一个着名的难题如下。 发送+更多=钱币
用等号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())
但它不起作用。它没有输出。我该如何解决这个问题?
答案 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 -> 0
或M -> 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
解释您是如何遇到您尝试解决的问题的,以及 任何阻碍你自己解决的困难。该 你问题的第一段是大多数读者的第二句话 看,所以尽量使它具有吸引力和信息量。
答案 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]
send
和more
都是4位数字money
是5位数字send
和more
具有e
作为公用数字money
中的前4位数字必须与send
和more
中的相应数字相匹配