-
Notifications
You must be signed in to change notification settings - Fork 0
/
18.2.py
89 lines (79 loc) · 2.19 KB
/
18.2.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
from math import prod
with open('input/18.txt') as f:
lines = [line.strip().replace(' ','') for line in f.readlines()]
equations = [[x for x in line] for line in lines]
def get_result(x, y, op):
if op == '+':
return int(x) + int(y)
if op == '*':
return int(x) * int(y)
def get_subterms(e):
# get the enclosed list
subterms = []
level = -1
for y in e:
if y == '(':
level -= 1
elif y == ')':
level += 1
if level == 0:
break
subterms.append(y)
return subterms
def group(e):
op_stack = []
term_stack = []
skip = 0
for i, term in enumerate(e):
if skip:
skip -= 1
continue
if term in ['+','*']:
op_stack.append(term)
elif term == '(':
subterms = get_subterms(e[i+1:])
term_stack.append(group(subterms))
skip = len(subterms)
elif term == ')':
pass
else:
term_stack.append(term)
# do additions
for i, op in filter(lambda x: x[1]=='+', enumerate(op_stack, 1)):
if '(' in term_stack[i-1]:
left = group(term_stack[i-1][1:-1])
else:
left = int(term_stack[i-1])
if '(' in term_stack[i]:
right = group(term_stack[i][1:-1])
else:
right = int(term_stack[i])
term_stack[i-1] = '.' # mark for removal
term_stack[i] = str(get_result(left, right, op))
# remove spare elements
term_stack = [term for term in term_stack if term != '.']
op_stack = [op for op in op_stack if op != '+']
# do multiplications
for i, op in enumerate(op_stack, 1):
if '(' in term_stack[i-1]:
left = group(term_stack[i-1][1:-1])
else:
left = int(term_stack[i-1])
if '(' in term_stack[i]:
right = group(term_stack[i][1:-1])
else:
right = int(term_stack[i])
term_stack[i-1] = '.' # mark for removal
term_stack[i] = str(get_result(left, right, op))
# remove spare elements
term_stack = [term for term in term_stack if term != '.']
op_stack = [op for op in op_stack if op != '+']
return term_stack[-1]
example_results = [
'(1+2)*(3+4)*(5+6)',
'2*(3+(4*5))',
'(5+(8*(3+9+3)*4*3))',
'5*9*(7*3*(3+9)*(3+((8+6)*4)))',
'(((((2+4)*9)*(((6+9)*(8+6))+6))+2)+4)*2',
]
print('Part Two:', sum([int(group(e)) for e in equations]))