Number Expression Solver: 4, 31
By Charlie and Logan
31 = ((4!+sqrt(4))+(sqrt(4)/.4))
31 = (4!+((4+4!)/4))
31 = (((4!-sqrt(4))/.4)-4!)
31 = (sqrt(4)+(4!+(sqrt(4)/.4)))
31 = ((sqrt(4)+(4!/.4))/sqrt(4))
class NumWithExplanation:
def __init__(self, value, count, op, left, right, value_str = None):
self.value = value
self.count = count
self.op = op
self.left = left
self.right = right
self.value_str = value_str
def equals(self, other):
if self.value != other.value:
return False
if self.count !=other.count:
return False
if self.op !=other.op:
return False
if self.left and self.right and other.left and other.right and (
(self.left.value != other.left.value and self.right.value != other.right.value)
and
(self.left.value != other.right.value and self.right.value != other.left.value)):
return False
return True
def to_string(self):
if self.count == 1:
if self.value_str:
return self.value_str
else:
return '4'
else:
s = "(%s%s%s)" % (self.left.to_string(), self.op, self.right.to_string())
if self.value_str =="sqrt":
s = 'sqrt(%s)' % (s)
return s
def to_full_string(self):
s = '%d = %s'% (self.value, self.to_string())
return s
def add_to_dict(d,value, num_with_explanation, n_sqrts = 0):
if value!=int(value):
return
value=int(value)
if value not in d:
d [value] = []
for elem in d [value]:
if elem.equals(num_with_explanation):
return
d[value].append(num_with_explanation)
if value>0 and n_sqrts == 0:
if math.sqrt(value) == int(math.sqrt(value)):
add_to_dict(d, math.sqrt(value),
NumWithExplanation(
math.sqrt(value),
num_with_explanation.count,
num_with_explanation.op,
num_with_explanation.left,
num_with_explanation.right,
'sqrt'), 1)
def combine(d, d1, d2):
for v1 in d1:
solutions1=d1[v1]
for solution1 in solutions1:
for v2 in d2:
solutions2 = d2 [v2]
for solution2 in solutions2:
count=solution1.count + solution2.count
value=solution1.value+solution2.value
add_to_dict(d, value,
NumWithExplanation(value, count, "+", solution1, solution2))
value=solution1.value - solution2.value
add_to_dict(d, value,
NumWithExplanation(value, count, "-", solution1, solution2))
value=solution2.value - solution1.value
add_to_dict(d, value,
NumWithExplanation(value, count, "-", solution2, solution1))
value=solution1.value * solution2.value
add_to_dict(d, value,
NumWithExplanation(value, count, "*", solution1, solution2))
if solution2.value != 0:
value=solution1.value / solution2.value
add_to_dict(d, value,
NumWithExplanation(value, count, "/", solution1,
solution2))
if solution1.value != 0:
value=solution2.value / solution1.value
add_to_dict(d, value,
NumWithExplanation(value, count, "/", solution2,
solution1))
base = NumWithExplanation(BASE_VALUE, 1, 'identity', None, None)
base_value_factorial = NumWithExplanation(math.factorial(BASE_VALUE),
1, 'identity', None, None, '%d!' % BASE_VALUE)
base_value_decimal = NumWithExplanation(BASE_VALUE/10,
1, 'decimal', None, None, '.%d' % BASE_VALUE)
dicts = {}
dicts[1] = {BASE_VALUE: [base],
math.factorial(BASE_VALUE): [base_value_factorial],
BASE_VALUE/10: [base_value_decimal]
}
if int(math.sqrt(BASE_VALUE)) == math.sqrt(BASE_VALUE):
dicts[1][math.sqrt(BASE_VALUE)] = [NumWithExplanation(math.sqrt(BASE_VALUE),
1, 'sqrt', None, None, 'sqrt(%d)' % BASE_VALUE)]
dicts[2] = {}
combine(dicts[2], dicts[1], dicts[1]);
if DOUBLE not in dicts[2]:
dicts[2][DOUBLE] = []
dicts[2][DOUBLE].append(NumWithExplanation(DOUBLE, 2, ' ', base, base, '%d' % (DOUBLE)))
dicts[3] = {}
combine(dicts[3], dicts[1], dicts[2]);
dicts[4] = {}
combine(dicts[4], dicts[2], dicts[2]);
combine(dicts[4], dicts[1], dicts[3]);
if TARGET in dicts[4]:
for solution in dicts[4][TARGET]:
print(solution.to_full_string())