-
Notifications
You must be signed in to change notification settings - Fork 0
/
day18_2.py
110 lines (85 loc) · 2.34 KB
/
day18_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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import ast
import itertools
import re
import sys
from math import ceil, floor
from pathlib import Path
inputs = Path(sys.argv[1]).read_text().strip()
inputs = [s for s in inputs.split('\n') if s]
def find_pair_to_explode(s: str):
nested = 0
start = 0
for i, ch in enumerate(s):
if ch == '[':
nested += 1
start = i
if ch == ']':
nested -= 1
if nested >= 4:
return start, i
return None
def add(s, n):
def _add(m):
value = m.group(0)
return str(int(value) + int(n))
return re.sub(r'\d+', _add, s, 1)
def add_left(s, n):
end = 0
for i in range(len(s) - 1, 0, -1):
if s[i].isdigit() and not end:
end = i
if not s[i].isdigit() and end:
return s[:i] + add(s[i:end + 1], n) + s[end + 1:]
return s
def explode(s):
indexes = find_pair_to_explode(s)
if indexes:
value = s[indexes[0] + 1:indexes[1]]
pair = value.split(',')
left = add_left(s[:indexes[0]], pair[0])
right = add(s[indexes[1] + 1:], pair[1])
return left + '0' + right
return s
def split(s):
def _split(m):
value = m.group(0)
i = int(value)
if i > 9:
first = floor(i / 2)
second = ceil(i / 2)
return f'[{first},{second}]'
return value
return re.sub(r'\d{2,}', _split, s, 1)
def reduce(s):
while True:
exploded = explode(s)
if exploded != s:
s = exploded
continue
splitted = split(s)
if splitted != s:
s = splitted
continue
break
return s
def magnitude(s):
def _magnitude(value, i):
if isinstance(value, list):
value = sum(_magnitude(item, i) for i, item in enumerate(value))
if i is None:
return value
return value * 2 if i else value * 3
a = ast.literal_eval(s)
return _magnitude(a, None)
def calculate_sum_magnitude(a):
result = None
for sn in a:
result = f'[{result},{sn}]' if result else sn
result = reduce(result)
return magnitude(result)
max_magnitude = 0
for combination in itertools.permutations(inputs, 2):
m = calculate_sum_magnitude(combination)
if m > max_magnitude:
max_magnitude = m
print(max_magnitude)