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)
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)