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