一位朋友分享了这个难题:
如何从数字1,5,6,7中制作21?
您可以使用加法,减法,乘法和除法以及括号的操作。您必须使用每个号码一次。
两天后我终于在纸上解决了这个问题。毫无疑问,计算机可以在一秒钟内强制执行所有解决方案。
怎么样?我尝试生成所有字符串a.b.c.d
插入字母的数字和点的操作,但它错过了我的解决方案。
奖金谜题:
答案 0 :(得分:9)
一个明显的方法是:
S
矢量开始:S = ( 1, 5, 6, 7 )
a
中挑选任意两个号码b
和S
,将其从S
a
和b
应用任意算术运算,从而获得一个新的数字c
(如果问题需要,请注意避免除零并验证精确除法) c
加入S
,从而获得S'
S'
代替S
在步骤2(选择两个数字)和步骤3(选择操作)执行强力分支。应该重复该循环,直到S
减少到只有1个元素,这是这个特定的强力分支的结果。
未明确使用括号,但它们是隐式存在的。
如果一个分支以21
中的S
结尾,则您有一个解决方案,此时您可以终止或继续分支以搜索其他解决方案。
答案 1 :(得分:2)
在这里"弹出两个,结合,递归" AnT建议的算法,用Python编码。最难的部分是在递归后组装表达式。我使用了find-and-replace。
#!python
import operator
import itertools
from fractions import Fraction
operations = dict()
operations['+'] = operator.add
operations['-'] = operator.sub
operations['/'] = operator.truediv
operations['*'] = operator.mul
def solve(target, numbers):
"""List ways to make target from numbers."""
numbers = [Fraction(x) for x in numbers]
return solve_inner(target, numbers)
def solve_inner(target, numbers):
if len(numbers) == 1:
if numbers[0] == target:
yield str(target)
return
# combine a pair of numbers with an operation, then recurse
for a,b in itertools.permutations(numbers, 2):
for symbol, operation in operations.items():
try:
product = operation(a,b)
except ZeroDivisionError:
continue
subnumbers = list(numbers)
subnumbers.remove(a)
subnumbers.remove(b)
subnumbers.append(product)
for solution in solve_inner(target, subnumbers):
# expand product (but only once)
yield solution.replace(str(product), "({0}{1}{2})".format(a, symbol, b), 1)
if __name__ == "__main__":
numbers = [1, 5, 6, 7]
target = 21
solutions = solve(target, numbers)
for solution in solutions:
print("{0}={1}".format(target, solution))
三个谜题的解决方案:
>>> solve(21,[1,5,6,7])
6/(1-(5/7))
>>> solve(11,[1,5,6,7])
(6*(7-5))-1
((7-5)*6)-1
>>> solve(16,[1,5,6,7])
[]
(第三个难题是不可能的)