Skip to main content
Source Link
Sciborg
  • 3.4k
  • 6
  • 8

Arithmetic operations puzzle solver

Solves 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)))
Post Made Community Wiki by Sciborg