Problem 92

Arithmetic expressions

Problem 94

Arithmetic expressions

Problem 93

By using each of the digits from the set, {1, 2, 3, 4}, exactly once, and making use of the four arithmetic operations (+, −, *, /) and brackets/parentheses, it is possible to form different positive integer targets.
For example,
8 = (4 * (1 + 3)) / 2
14 = 4 * (3 + 1 / 2)
19 = 4 * (2 + 3) − 1
36 = 3 * 4 * (2 + 1)
Note that concatenations of the digits, like 12 + 34, are not allowed.
Using the set, {1, 2, 3, 4}, it is possible to obtain thirty-one different target numbers of which 36 is the maximum, and each of the numbers 1 to 28 can be obtained before encountering the first non-expressible number.
Find the set of four distinct digits, a < b < c < d, for which the longest set of consecutive positive integers, 1 to n, can be obtained, giving your answer as a string: abcd.
from __future__ import division
import itertools


def plus(a, b):
    return a + b


def minus(a, b):
    return a - b


def times(a, b):
    return (a * b)


def divs(a, b):
    if b == 0:
        # random number, will get sorted out when checking for integers
        return 3.14159
    return a / b


# create all possible functions
def get_funcs():
    # all arithmetic operations
    operations = [plus, minus, times, divs]
    for f in operations:
        for g in operations:
            for h in operations:
                yield lambda a, b, c, d: f(a, g(b, h(c, d)))
                yield lambda a, b, c, d: f(g(b, h(c, d)), a)
                yield lambda a, b, c, d: f(a, g(b, h(c, d)))
                yield lambda a, b, c, d: f(g(h(c, d), b), a)
                yield lambda a, b, c, d: f(g(a, b), h(c, d))


# create all possible solutions
def get_candidates():
    return [(a, b, c, d) for a in range(10) for b in range(10) for c in range(10) for d in range(10)
            if (a < b) and (b < c) and (b < c) and (c < d)]


# evaluate a possible solution
def eval_candidate(candidate):
    return [f(*x) for f in get_funcs() for x in itertools.permutations(list(candidate))]


# get length of consecutive positive integer chain
def get_max_chain_length(candidate):
    res = eval_candidate(candidate)

    # Check if all consecutive positive integers are in the chain
    n = 0
    while True:
        n += 1
        if not n in res:
            break
    return n - 1


# python3 returns correct solution == 1258
# while python2 soution == 5689 without float division from the future
def run():
    return max([candidate for candidate in get_candidates()], key=get_max_chain_length)