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
|
from __future__ import annotations
from copy import deepcopy
from dataclasses import dataclass
from functools import reduce
from itertools import combinations
from math import floor, ceil
from utils import open_day
@dataclass
class Pair:
car: int | Pair
cdr: int | Pair
def __repr__(self) -> str:
return f'[{self.car},{self.cdr}]'
def car(p, assign=None):
if assign is not None:
p.car = assign
return p.car
def cdr(p, assign=None):
if assign is not None:
p.cdr = assign
return p.cdr
def is_pair(p): return isinstance(p, Pair)
def parse(s): return eval(s.replace('[', 'Pair(').replace(']', ')'))
with open_day(18) as f:
homework = [parse(l) for l in f]
def try_explode(n, depth=0):
def try_add(n, val, access, primary, secondary):
if val == 0: return 0
content = access(n)
if not is_pair(content):
access(n, content + val)
return 0
val = try_add(content, val, primary, primary, secondary)
val = try_add(content, val, secondary, primary, secondary)
return val
if not is_pair(n): return None
if depth == 4: return n
for access in (car, cdr):
val = try_explode(access(n), depth + 1)
if val is None: continue
if depth == 3: access(n, 0)
if access == car:
return Pair(val.car, try_add(n, val.cdr, cdr, car, cdr))
else:
return Pair(try_add(n, val.car, car, cdr, car), val.cdr)
def try_split(n, access=lambda n: n):
content = access(n)
if is_pair(content):
return try_split(content, car) or try_split(content, cdr)
if content < 10: return False
content /= 2
access(n, Pair(floor(content), ceil(content)))
return True
def reduce_num(n):
n = deepcopy(n)
while True:
if try_explode(n): continue
if try_split(n): continue
break
return n
def magnitude(n):
if is_pair(n):
return 3 * magnitude(n.car) + 2 * magnitude(n.cdr)
return n
print(magnitude(reduce(lambda a, b: reduce_num(Pair(a, b)), homework)))
print(max(max(magnitude(reduce_num(Pair(a, b))), magnitude(reduce_num(Pair(b, a)))) for a, b in combinations(homework, 2)))
|