Reputation: 109
So I have a list containing some values e.g. [230, 67, 34, 60, 2, 10]
and a list of operations [operations.add, operations.sub, operations.mul, operations.div]
and a result number
, which I know beforehand.
What would be the best way to find all possible mathematical expressions which give me the result.
For example, if the result is 154
, one possible solution would be 60*2+34
.
The problem I have in designing this algorithm, is because I don't know beforehand which values and operations will be used for the expression, and which won't, or maybe all will be used.
Would appreciate it if you could provide some python code.
Thanks in advance
Upvotes: 0
Views: 275
Reputation: 3134
You could create a tree that represents all possible combinations, where a Node represents either a number or an operator. Then by performing DFS or BFS on the resulting tree, you can find all Nodes such that the expression represented by the path from the root to the Node calculates to the desired value. Here's the code in 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()
Which gives the output:
[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]
The code is quite rough and can probably be improved. Note that Integer division will be occurring in the code. Also note that the program will get exponentially slower as you add more numbers to the original list.
Upvotes: 1