算术运算中的强力搜索算法

时间:2016-08-28 01:36:28

标签: python algorithm math

由于我是Python初学者,我试图从一些网站学习一些代码。我在GitHub中找到了一个为算术表达式执行Bruteforce search的算法。代码是:

#!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 = 5
    solutions = solve(target, numbers)
    for solution in solutions:
        print("{0}={1}".format(target, solution))

它只是使用我的numbers结束尝试任何算术表达式,然后打印得到target的结果(我得到的结果)。

我想知道,当表达式没有target我设置的结果时,如何打印脚本尝试的任何解决方案?

编辑:

这是我尝试过的代码:

#!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:
        num = numbers[0]
        yield str(num), num == 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, truth in solve_inner(target, subnumbers):
                yield solution.replace(str(product),
                    "{0}=({1}{2}{3})".format(product, a, symbol, b), 1), truth


if __name__ == "__main__":
    numbers = [1, 5, 6, 7]
    target = 5
    solutions = solve(target, numbers)
    for solution, truth in solutions:
        print("{0}? {1}".format(solution,
              'True' if truth else ''))

我得到了实际的产品,但我得到了表达式中小操作的结果:

42=(7*6)/5=(42/5)=(1*42/5)

虽然我实际上只想在字符串的开头只获得42个。

1 个答案:

答案 0 :(得分:2)

如果num [0]等于target,则递归通过产生str(num [0])而终止,否则无效。如果产生了某些东西,则字符串表达式建立在连续的产量上。要获得所有表达式,必须始终产生一些东西。我还选择是否达到目标。相反,可以在打印之前评估表达式。

#!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:
        num = numbers[0]
        yield str(num), num == 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, truth in solve_inner(target, subnumbers):
                # expand product (but only once)
                yield solution.replace(str(product),
                    "({0}{1}{2})".format(a, symbol, b), 1), truth

if __name__ == "__main__":
    numbers = [1, 5, 6, 7]
    target = 5
    solutions = solve(target, numbers)
    for solution, truth in solutions:
        print("{0}={1}? {2}".format(target, solution,
              'True' if truth else ''))

原版中有一个小故障。产品附加到最后,但替换了与前面产品匹配的第一个数字。我相信结果可能是表达式的遗漏,在这种情况下算法并不完整。由于无法在最后开始更换,因此应将产品放在前面(subnumbers.insert(0, product)),以便更换产品。我会让你试验一下它的不同之处。但我相信如果写得正确,代码会更容易理解。