【问题标题】:Finding (or brute-forcing) mathematical expression for a list of values and math operations查找(或暴力破解)值列表和数学运算的数学表达式
【发布时间】:2017-05-12 03:00:59
【问题描述】:

所以我有一个包含一些值的列表,例如[230, 67, 34, 60, 2, 10]
以及我事先知道的[operations.add, operations.sub, operations.mul, operations.div]result number 的操作列表。

找到所有可能给我结果的数学表达式的最佳方法是什么。

例如,如果结果是154,则一种可能的解决方案是60*2+34

我在设计这个算法时遇到的问题是因为我事先不知道哪些值和操作将用于表达式,哪些不会,或者可能全部使用。
如果您能提供一些 python 代码将不胜感激。
提前致谢

【问题讨论】:

    标签: python algorithm math brute-force


    【解决方案1】:

    您可以创建表示所有可能组合的树,其中节点表示数字或运算符。然后通过对结果树执行 DFS 或 BFS,您可以找到所有节点,使得从根到节点的路径表示的表达式计算为所需的值。这是 Python 中的代码:

    class Node():
        def __init__(self, type, val, parent, children):
            self.type = type
            self.value = val
            self.parent = parent
            self.children = children
            self.total = None
    
    
    def expandBranch(node, numList, opList):
    
        if len(numList) == 0:
            return
    
        if node.type == "Operator" or node.type is None:
            for i in range(len(numList)):
                newList = numList[:]
                num = newList.pop(i)
                newNode = Node("Number", num, node, [])
                node.children.append(newNode)
                expandBranch(newNode, newList, opList)
        else:
            for op in opList:
                newNode = Node("Operator", op, node, [])
                node.children.append(newNode)
                expandBranch(newNode, numList, opList)
    
    
    def dfs(node, result):
    
        if len(node.children) == 0:
            return
    
        if node.type == "Number":
            if node.parent.type == None:
                node.total = node.value
            elif node.parent.value == "+":
                node.total = node.parent.total + node.value
            elif node.parent.value == "-":
                node.total = node.parent.total - node.value
            elif node.parent.value == "*":
                node.total = node.parent.total * node.value
            elif node.parent.value == "/":
                node.total = node.parent.total / node.value
            else:
                pass # should never come here
            if node.total == result:
                output = []
                while node.parent is not None:
                    output.insert(0, node.value)
                    node = node.parent
                print(output)
                return
        elif node.type == "Operator":
            node.total = node.parent.total
        else:
            pass # root node, nothing to do
    
        for child in node.children:
            dfs(child, result)
    
    
    def main():
        nums = [230, 67, 34, 60, 2, 10]
        ops = ["+", "-", "*", "/"]
        root = Node(None, None, None, [])
        expandBranch(root, nums, ops)
        dfs(root, 154)
    
    if __name__ == "__main__":
        main()
    

    它给出了输出:

    [230, '+', 10, '/', 2, '+', 34]
    [67, '+', 10, '*', 2]
    [67, '*', 10, '/', 230, '*', 60, '+', 34]
    [67, '/', 230, '+', 60, '*', 2, '+', 34]
    [67, '/', 230, '+', 2, '*', 60, '+', 34]
    [34, '-', 67, '*', 2, '+', 230, '-', 10]
    [34, '-', 67, '*', 2, '-', 10, '+', 230]
    [34, '-', 2, '*', 67, '/', 10, '-', 60]
    [34, '/', 230, '+', 67, '+', 10, '*', 2]
    [34, '/', 230, '+', 10, '+', 67, '*', 2]
    [34, '/', 60, '+', 67, '+', 10, '*', 2]
    [34, '/', 60, '+', 10, '+', 67, '*', 2]
    [34, '/', 2, '+', 67, '+', 60, '+', 10]
    [34, '/', 2, '+', 67, '+', 10, '+', 60]
    [34, '/', 2, '+', 60, '+', 67, '+', 10]
    [34, '/', 2, '+', 60, '+', 10, '+', 67]
    [34, '/', 2, '+', 10, '+', 67, '+', 60]
    [34, '/', 2, '+', 10, '+', 60, '+', 67]
    [60, '*', 2, '+', 34]
    [60, '/', 230, '+', 67, '+', 10, '*', 2]
    [60, '/', 230, '+', 10, '+', 67, '*', 2]
    [60, '/', 34, '+', 230, '-', 67, '-', 10]
    [60, '/', 34, '+', 230, '-', 10, '-', 67]
    [60, '/', 34, '-', 67, '+', 230, '-', 10]
    [60, '/', 34, '-', 67, '-', 10, '+', 230]
    [60, '/', 34, '-', 10, '+', 230, '-', 67]
    [60, '/', 34, '-', 10, '-', 67, '+', 230]
    [60, '/', 34, '*', 67, '+', 10, '*', 2]
    [60, '/', 34, '*', 10, '+', 67, '*', 2]
    [2, '*', 60, '+', 34]
    [10, '+', 230, '/', 2, '+', 34]
    [10, '+', 67, '*', 2]
    [10, '*', 67, '/', 230, '*', 60, '+', 34]
    [10, '/', 230, '+', 60, '*', 2, '+', 34]
    [10, '/', 230, '+', 2, '*', 60, '+', 34]
    [10, '/', 67, '+', 60, '*', 2, '+', 34]
    [10, '/', 67, '+', 2, '*', 60, '+', 34]
    

    代码相当粗糙,可能还可以改进。请注意,代码中将发生整数除法。另请注意,当您在原始列表中添加更多数字时,程序会以指数方式变慢。

    【讨论】:

    • 我喜欢这种基于树的方法并回答了问题。
    猜你喜欢
    • 2013-10-23
    • 1970-01-01
    • 2011-02-25
    • 2017-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多