Arithmetic operations puzzle solver
Solves formation-of-numbers puzzles of the form:
3 [] 3 [] 8 [] 8 = 24
where the brackets are replaced by arithmetic operations.
How to use
Call the function:
solve(target, numbers)
where
- target is the final number.
- numbers is the list of constituent numbers, not necessarily in order. The code doesn't care about the ordering of the numbers - it solves for all combinations in any order.
The results, if any, are printed for you as output to the Python console. Duplicates are automatically removed. If no results are found, the program ends without printing anything.
How to customize
The part of the code where the operations are defined can be changed to include or exclude specific operations, depending on if the puzzle has limitations (i.e. only allows multiplication and addition, for example). To customize this, just comment out the operations you don't want to be tested.
The code
In Python 3:
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]
solutions = solve_inner(target, numbers)
# Remove duplicate solutions.
solutions = list(dict.fromkeys(solutions))
# Print the final solutions.
for solution in solutions:
print("{0} = {1}".format(target, solution))
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):
yield solution.replace(str(product), "({0}{1}{2})".format(a, symbol, b), 1)
If you want to run a quick demo to see how this works, add the following code:
if __name__ == "__main__":
numbers = [3, 3, 8, 8]
target = 24
solutions = solve(target, numbers)
In this demo case, we want to form 24 from 3, 3, 8 and 8. Our output is:
24 = (8/(3-(8/3)))