【问题标题】:How to brute force arithmetic puzzle?如何蛮力算术难题?
【发布时间】:2015-03-31 18:18:34
【问题描述】:

一位朋友分享了这个谜题:

如何将数字 1、5、6、7 变成 21?

您可以使用加法、减法、乘法和除法运算以及括号。每个数字必须使用一次。

两天后,我最终在纸上解决了这个问题。毫无疑问,计算机可以在一秒钟内暴力破解所有解决方案。

怎么办?我尝试生成所有字符串a.b.c.d,为字母插入数字,为点插入运算,但它错过了我的解决方案。


奖励谜题:

  • 如何将 1,5,6,7 变成 11?
  • 如何将 1,5,6,7 变成 16?

【问题讨论】:

  • 21 的答案是什么? (我好像找不到)
  • 我很确定this python code 实现了AnT 的算法。我找不到1621 的结果。
  • @BillLynch 总是把value 放在左边,它就不见了,例如1-(5+6)
  • 如果有人感兴趣,6/(1 - 5/7) = 21
  • 11 = 6*(7-5)-116 = 67 - 51

标签: algorithm math


【解决方案1】:

一个明显的方法是:

  1. 您从四个数字的向量S 开始:S = ( 1, 5, 6, 7 )
  2. S中选择任意两个数字ab,从S中删除它们
  3. ab 应用任意算术运算,从而获得一个新数c(注意避免除以零并验证精确除法,如果问题需要)
  4. c包含到S中,从而得到S'
  5. 从步骤 1 继续,现在使用 S' 代替 S

在第 2 步(选择两个数字)和第 3 步(选择操作)执行蛮力分支。应重复该循环,直到 S 减少到仅 1 个元素,这是此特定蛮力分支的结果。

括号没有显式使用,但它们隐式存在。

如果一个分支在S 中以21 结尾,则您有一个解决方案,此时您可以终止或继续分支以搜索其他解决方案。

【讨论】:

【解决方案2】:

这是 AnT 建议的“pop two, combine, recurse”算法,用 Python 编码。最困难的部分是在递归之后组装表达式。我使用了查找和替换。

#!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])
[]

(第三个谜题是不可能的)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-24
    • 1970-01-01
    • 2016-04-05
    • 2015-06-22
    • 1970-01-01
    • 2015-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多