Skip to content

Commit 75537f8

Browse files
committed
Day 18 Python solutions
1 parent 8cddf8a commit 75537f8

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed

18-1.py

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
#!/usr/bin/env python
2+
3+
from math import ceil, floor
4+
5+
class Snailfish:
6+
def __init__(self, pair):
7+
if isinstance(pair, str):
8+
pair = eval(pair)
9+
self.pair = pair
10+
11+
def __add__(self, other):
12+
p = Snailfish([self.pair, other.pair])
13+
return p.reduce()
14+
15+
def reduce(self):
16+
while True:
17+
did_explode, new_pair = self.explode(self.pair)
18+
self.pair = new_pair
19+
if did_explode:
20+
continue
21+
22+
did_split, new_pair = self.split(self.pair)
23+
self.pair = new_pair
24+
if did_split:
25+
continue
26+
27+
break
28+
return self
29+
30+
def increase_rightmost(self, element, increase):
31+
if isinstance(element, int):
32+
return element + increase
33+
34+
return [element[0], self.increase_rightmost(element[1], increase)]
35+
36+
def increase_leftmost(self, element, increase):
37+
if isinstance(element, int):
38+
return element + increase
39+
40+
return [self.increase_leftmost(element[0], increase), element[1]]
41+
42+
def inner_explode(self, element, level):
43+
if level == 5 and isinstance(element, list):
44+
return (True, 0, element[0], element[1])
45+
elif isinstance(element, int):
46+
return (False, element, None, None)
47+
else:
48+
new_right = element[1]
49+
50+
did_explode_left, new_left, propagate_left, propagate_right = self.inner_explode(element[0], level + 1)
51+
52+
if did_explode_left and propagate_right is not None and propagate_right > 0:
53+
new_right = self.increase_leftmost(element[1], propagate_right)
54+
propagate_right = 0
55+
56+
did_explode_right = False
57+
if not did_explode_left:
58+
did_explode_right, new_right, propagate_left, propagate_right = self.inner_explode(element[1], level + 1)
59+
60+
if did_explode_right and propagate_left is not None and propagate_left > 0:
61+
new_left = self.increase_rightmost(element[0], propagate_left)
62+
propagate_left = 0
63+
64+
return (
65+
did_explode_left or did_explode_right,
66+
[new_left, new_right],
67+
propagate_left,
68+
propagate_right
69+
)
70+
71+
def explode(self, pair):
72+
did_explode, new_pair, _, _ = self.inner_explode(pair, 1)
73+
return (did_explode, new_pair)
74+
75+
def split(self, element):
76+
if isinstance(element, int) and element >= 10:
77+
return (True, [floor(element / 2), ceil(element / 2)])
78+
elif isinstance(element, int):
79+
return (False, element)
80+
else:
81+
did_split_left, new_left = self.split(element[0])
82+
did_split_right = False
83+
new_right = element[1]
84+
if not did_split_left:
85+
did_split_right, new_right = self.split(element[1])
86+
87+
return (
88+
did_split_left or did_split_right,
89+
[new_left, new_right]
90+
)
91+
92+
def magnitude(self, element):
93+
if isinstance(element, int):
94+
return element
95+
else:
96+
return 3 * self.magnitude(element[0]) + 2 * self.magnitude(element[1])
97+
98+
def score(self):
99+
return self.magnitude(self.pair)
100+
101+
def __str__(self):
102+
return f"<{self.__class__.__name__}: {self.pair}>"
103+
104+
105+
numbers = [Snailfish(line.strip()) for line in open('18.input').readlines()]
106+
107+
collect = numbers[0]
108+
109+
for number in numbers[1:]:
110+
collect += number
111+
112+
print(collect.score())

18-2.py

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#!/usr/bin/env python
2+
3+
from itertools import product
4+
from math import ceil, floor
5+
6+
class Snailfish:
7+
def __init__(self, pair):
8+
if isinstance(pair, str):
9+
pair = eval(pair)
10+
self.pair = pair
11+
12+
def __add__(self, other):
13+
p = Snailfish([self.pair, other.pair])
14+
return p.reduce()
15+
16+
def reduce(self):
17+
while True:
18+
did_explode, new_pair = self.explode(self.pair)
19+
self.pair = new_pair
20+
if did_explode:
21+
continue
22+
23+
did_split, new_pair = self.split(self.pair)
24+
self.pair = new_pair
25+
if did_split:
26+
continue
27+
28+
break
29+
return self
30+
31+
def increase_rightmost(self, element, increase):
32+
if isinstance(element, int):
33+
return element + increase
34+
35+
return [element[0], self.increase_rightmost(element[1], increase)]
36+
37+
def increase_leftmost(self, element, increase):
38+
if isinstance(element, int):
39+
return element + increase
40+
41+
return [self.increase_leftmost(element[0], increase), element[1]]
42+
43+
def inner_explode(self, element, level):
44+
if level == 5 and isinstance(element, list):
45+
return (True, 0, element[0], element[1])
46+
elif isinstance(element, int):
47+
return (False, element, None, None)
48+
else:
49+
new_right = element[1]
50+
51+
did_explode_left, new_left, propagate_left, propagate_right = self.inner_explode(element[0], level + 1)
52+
53+
if did_explode_left and propagate_right is not None and propagate_right > 0:
54+
new_right = self.increase_leftmost(element[1], propagate_right)
55+
propagate_right = 0
56+
57+
did_explode_right = False
58+
if not did_explode_left:
59+
did_explode_right, new_right, propagate_left, propagate_right = self.inner_explode(element[1], level + 1)
60+
61+
if did_explode_right and propagate_left is not None and propagate_left > 0:
62+
new_left = self.increase_rightmost(element[0], propagate_left)
63+
propagate_left = 0
64+
65+
return (
66+
did_explode_left or did_explode_right,
67+
[new_left, new_right],
68+
propagate_left,
69+
propagate_right
70+
)
71+
72+
def explode(self, pair):
73+
did_explode, new_pair, _, _ = self.inner_explode(pair, 1)
74+
return (did_explode, new_pair)
75+
76+
def split(self, element):
77+
if isinstance(element, int) and element >= 10:
78+
return (True, [floor(element / 2), ceil(element / 2)])
79+
elif isinstance(element, int):
80+
return (False, element)
81+
else:
82+
did_split_left, new_left = self.split(element[0])
83+
did_split_right = False
84+
new_right = element[1]
85+
if not did_split_left:
86+
did_split_right, new_right = self.split(element[1])
87+
88+
return (
89+
did_split_left or did_split_right,
90+
[new_left, new_right]
91+
)
92+
93+
def magnitude(self, element):
94+
if isinstance(element, int):
95+
return element
96+
else:
97+
return 3 * self.magnitude(element[0]) + 2 * self.magnitude(element[1])
98+
99+
def score(self):
100+
return self.magnitude(self.pair)
101+
102+
def __str__(self):
103+
return f"<{self.__class__.__name__}: {self.pair}>"
104+
105+
106+
lines = [line.strip() for line in open('18.input').readlines()]
107+
additions = [a for a in list(product(lines, lines)) if a[0] != a[1]]
108+
sums = [(Snailfish(a) + Snailfish(b)).score() for a, b in additions]
109+
print(max(sums))

0 commit comments

Comments
 (0)