You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
3.3 KiB
Python

4 years ago
import re
example1 = '1 + 2 * 3 + 4 * 5 + 6'
example2 = '1 + (2 * 3) + (4 * (5 + 6))'
example3 = '2 * 3 + (4 * 5)'
example4 = '5 + (8 * 3 + 9 + 3 * 4 * 3)'
example5 = '5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))'
example6 = '((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2'
with open('input') as f:
expressions = f.readlines()
def calc(op, a, b):
if op == '+':
return a + b
elif op == '*':
return a * b
else:
raise Exception(f'Operator "{op}" not known')
class Node:
leaf_value = None
def __init__(self, expression):
# print('Processing', expression)
while expression[0] == '(':
level = 0
split = None
closing_bracket = None
for idx, char in enumerate(expression):
if char == '(':
level += 1
elif char == ')':
level -= 1
if level == 0 and closing_bracket is None:
closing_bracket = idx
if level == 0 and char == '*' and split is None:
split = idx
# print(f'Found split at {i} within {expression}')
if closing_bracket + 1 == len(expression):
# print('stipping unneeded parens')
expression = expression[1:-1]
else:
if split is not None:
# self.split_at(expression, split)
self.split_at(expression, split)
else:
self.split_at(expression, closing_bracket + 2)
return
if '(' in expression:
level = 0
split = None
for idx, char in enumerate(expression):
if char == '(':
level += 1
elif char == ')':
level -= 1
if level == 0 and char == '*' and split is None:
split = idx
if split is not None:
self.split_at(expression, split)
else:
self.split_at(expression, expression.find('+'))
elif '*' in expression:
self.split_at(expression, expression.find('*'))
elif '+' in expression:
self.split_at(expression, expression.find('+'))
else:
self.leaf_value = int(expression.strip())
def split_at(self, expression, idx):
left = expression[:idx].strip()
right = expression[idx + 1:].strip()
op = expression[idx]
# print(f'Splitting "{left}" "{op}" "{right}"')
self.left = Node(left)
self.right = Node(right)
self.op = op
@ property
def value(self):
if self.leaf_value is not None:
return self.leaf_value
return calc(self.op, self.left.value, self.right.value)
def solve(line):
return Node(line.strip()).value
print(example1, '=', solve(example1))
print(example2, '=', solve(example2))
print(example3, '=', solve(example3))
print(example4, '=', solve(example4))
print(example5, '=', solve(example5))
print(example6, '=', solve(example6))
# should be 16530240
example7 = '3 + (8 * 2 * 4) * 8 * (2 + (8 * 5 + 3 * 4 + 4)) * (2 * (5 * 6))'
print(example7, '=', solve(example7), 'should be', '16530240')
print('Solution')
# for expr in expressions:
# print(expr.strip(), '=', solve(expr))
print(sum(map(solve, expressions)))