方程构建器使用循环

时间:2013-05-19 23:15:13

标签: python loops

我正在尝试编写一个程序,它遍历所有可能的简单方程式以找到24的值。我设法完成了循环但是有些东西我没有抓住。

这个想法是一个3级循环(我猜是theta(n ^ 3)?,时间复杂度很差),这用于构建一个4个数字的方程式(在程序的早期随机生成)到我的名单。

numList = [x2, x3, x4]

这是我的代码:

for i in range(4):
    for j in range(4):
        for k in range(4):
            for l in range(len(numList)):
                n += 1
                print(i, j, k, " i, j, k")
                print(x2, x3, x4, "x2, x3, x4")
                print(x, "x supposed to be reset")
                print(l, "val of l")
                print(n, "val of n")
                if i == 0 or j == 0 or k == 0:
                    x += "+"
                    x += str(numList[n])
                    print(x, "add")
                if i == 1 or j == 1 or k == 1:
                    x += "-"
                    x += str(numList[n])
                    print(x, "sub")
                if i == 2 or j == 2 or k == 2:
                    x += "*"
                    x += str(numList[n])
                    print(x, "mult")
                if i == 3 or j == 3 or k == 3:
                    x += "/"
                    x += str(numList[n])
                    print(x, "div")

                if n == 2:        
                    print()
                    print("----")
                    print(x, "final")
                    print(eval(x), "evald")
                    if eval(x) is not 24:
                        x = x1
                        print(x, "x reset")
                    else:
                        print(eval(x), "= 24")
                    n = -1
                    print("----")

当由于某种原因,我正在构建和评估(x)的字符串没有重置时,错误进来,而是添加到在最后一个循环迭代中生成的相同字符串(它应该是默认值) 。 x的默认值是随机生成的:

x = str(randrange(1, 9))

这对我来说很奇怪,我不确定出了什么问题,循环就像一个没有中断的switch条件语句。这是我的控制台输出:Pasted to pastebin

有人可以告诉我我做错了吗?或者我的代码中发生了什么我没看到 为什么x没有被重置,好像它是一个正在构建的新字符串(这是我想要的)?

编辑:这是完整的来源:equation.py

2 个答案:

答案 0 :(得分:1)

问题不在于'x未被重置'。问题是你的代码并没有设计成在每次传递时只使用三个运算符。例如,如果i为0,j为1且k为2则由于i为0而使用+, - 由于j为1而*由于k为2,因此对于等式中的每个数字,所以你' d看到1+5-5*5+6-6*6+4-4*4之类的内容,所有操作符重复三次。

你想要更像这样的逻辑,你明确地使用三个运算符并迭代三个运算符的所有组合:

from random import randrange

def brute_force():
    x1 = randrange(1, 9)
    x2 = randrange(1, 9)
    x3 = randrange(1, 9)
    x4 = randrange(1, 9)
    numList = [x1, x2, x3, x4]
    operatorList = ["+", "-", "/", "*"]
    equation = ""

    for i in range(4):
        for j in range(4):
            for k in range(4):
                equation = str(numList[0]) + operatorList[i] + str(numList[1]) + operatorList[j] + str(numList[2]) + operatorList[k] + str(numList[3])
                print("equation: " + equation)
                print("evaluation: " + str(eval(equation)))

if __name__ == "__main__":
    brute_force()

输出看起来像

>>> brute_force()
equation: 4+6+4+6
evaluation: 20
equation: 4+6+4-6
evaluation: 8
equation: 4+6+4/6
evaluation: 10
equation: 4+6+4*6
evaluation: 34
equation: 4+6-4+6
evaluation: 12
equation: 4+6-4-6
evaluation: 0
equation: 4+6-4/6
evaluation: 10
...

答案 1 :(得分:1)

这是另一种不依赖于eval的方程式构建器的方法,并且还可以让您轻松使用任何二进制(2个参数)函数以及任何操作顺序:

class Operation():
    def __init__(self, func, precedence):
        self.func = func
        self.precedence = precedence
    def __call__(self, *args):
        return self.func(*args)
    def __repr__(self):
        return self.func.__name__

class Equation():
    def __init__(self, numbers, operations):
        self.nums = list(numbers)
        self.ops = list(operations)
    def eval(self):
        while self.ops:
            min_op_precedence = min([x.precedence for x in self.ops])
            #get all pairs of numbers in the list [1,2,3] -> [(1,2), (2,3)]
            for index, pair in enumerate(zip(self.nums, self.nums[1:])):
                if self.ops[index].precedence == min_op_precedence:
                    #evaluate pair of numbers if the precedence for their op is highest
                    #ie "1 * 2 - 3" -> "2 - 3"
                    val = self.ops[index](*pair) 
                    self.nums.pop(index) 
                    self.nums[index] = val 
                    self.ops.pop(index)
                    break
        return self.nums.pop()

以下是如何使用它来查找操作的排列给出某种结果,如果存在这样的排列(使用暴力):

from operator import add, sub, mul, floordiv
from itertools import permutations

numbers = [ 1, 2, 3, 4 ]
#operations with order of operations:
ops = [ Operation(*x) for x in [(mul, 1), (floordiv, 2), (sub, 3), (add, 4)] ] 

def findequation( numbers, ops, answer ):
    for p in permutations(ops, (len(numbers)-1)):
        if Equation( numbers, list(p) ).eval() == answer:
            return p
    return None

print findequation(numbers, ops, 0)
#>>> (sub, mul, floordiv)
#this means "1 - 2 * 3 / 4" = 0