This commit is contained in:
164
day-18/day-18.py
Normal file
164
day-18/day-18.py
Normal file
@@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env python3
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def parse(line):
|
||||
if ',' not in line:
|
||||
return int(line)
|
||||
line = line[1:-1]
|
||||
level = 0
|
||||
split_idx = 0
|
||||
for i, c in enumerate(line):
|
||||
if '[' == c:
|
||||
level += 1
|
||||
elif ']' == c:
|
||||
level -= 1
|
||||
elif 0 == level and ',' == c:
|
||||
split_idx = i
|
||||
break
|
||||
left = parse(line[:split_idx])
|
||||
right = parse(line[split_idx + 1:])
|
||||
return (left, right)
|
||||
|
||||
|
||||
def explode_to_left(n, l):
|
||||
(left, right) = n
|
||||
res = True
|
||||
if type(right) == int:
|
||||
right = right + l
|
||||
else:
|
||||
res, right = explode_to_left(right, l)
|
||||
if not res:
|
||||
if type(left) == int:
|
||||
left = left + l
|
||||
res = True
|
||||
else:
|
||||
res, left = explode_to_left(left, l)
|
||||
if not res:
|
||||
res = False
|
||||
return res, (left, right)
|
||||
|
||||
|
||||
def explode_to_right(n, r):
|
||||
(left, right) = n
|
||||
res = True
|
||||
if type(left) == int:
|
||||
left = left + r
|
||||
else:
|
||||
res, left = explode_to_right(left, r)
|
||||
if not res:
|
||||
if type(right) == int:
|
||||
right = right + r
|
||||
res = True
|
||||
else:
|
||||
res, right = explode_to_right(right, r)
|
||||
if not res:
|
||||
res = False
|
||||
return res, (left, right)
|
||||
|
||||
|
||||
def explode(n, lvl=0):
|
||||
if type(n) is int:
|
||||
return False, n, None, None
|
||||
(left, right) = n
|
||||
if lvl == 4 and type(left) is int and type(right) is int:
|
||||
return True, 0, left, right
|
||||
else:
|
||||
res, left, l, r = explode(left, lvl+1)
|
||||
if not res:
|
||||
res, right, l, r = explode(right, lvl+1)
|
||||
if not res:
|
||||
return False, n, None, None
|
||||
else:
|
||||
if l:
|
||||
if type(left) is int:
|
||||
left = left + l
|
||||
l = None
|
||||
else:
|
||||
res, left = explode_to_left(left, l)
|
||||
if res:
|
||||
l = None
|
||||
return True, (left, right), l, r
|
||||
else:
|
||||
if r:
|
||||
if type(right) is int:
|
||||
right = right + r
|
||||
r = None
|
||||
else:
|
||||
res, right = explode_to_right(right, r)
|
||||
if res:
|
||||
r = None
|
||||
return True, (left, right), l, r
|
||||
|
||||
|
||||
def split(n):
|
||||
if type(n) is int:
|
||||
if 10 <= n:
|
||||
return True, (n // 2, (n + 1) // 2)
|
||||
else:
|
||||
return False, n
|
||||
(left, right) = n
|
||||
res, left = split(left)
|
||||
if not res:
|
||||
res, right = split(right)
|
||||
return res, (left, right)
|
||||
|
||||
|
||||
def magnitude(n):
|
||||
m = 0
|
||||
(left, right) = n
|
||||
if type(left) is int:
|
||||
m += 3 * left
|
||||
else:
|
||||
m += 3 * magnitude(left)
|
||||
if type(right) is int:
|
||||
m += 2 * right
|
||||
else:
|
||||
m += 2 * magnitude(right)
|
||||
return m
|
||||
|
||||
|
||||
def part_1(input):
|
||||
result = 0
|
||||
n = None
|
||||
for line in input:
|
||||
line = line.rstrip()
|
||||
if not n:
|
||||
n = parse(line)
|
||||
continue
|
||||
n = (n, parse(line))
|
||||
res = True
|
||||
while res:
|
||||
while res:
|
||||
res, n, _, _ = explode(n)
|
||||
res, n = split(n)
|
||||
result = magnitude(n)
|
||||
print("Part 1 result:", result)
|
||||
|
||||
|
||||
def part_2(input):
|
||||
result = 0
|
||||
nbrs = []
|
||||
for line in input:
|
||||
line = line.rstrip()
|
||||
nbrs.append(parse(line))
|
||||
for n1 in nbrs:
|
||||
for n2 in nbrs:
|
||||
if n1 == n2:
|
||||
continue
|
||||
n = (n1, n2)
|
||||
res = True
|
||||
while res:
|
||||
while res:
|
||||
res, n, _, _ = explode(n)
|
||||
res, n = split(n)
|
||||
result = max(result, magnitude(n))
|
||||
print("Part 2 result:", result)
|
||||
|
||||
|
||||
input = list()
|
||||
p = Path(__file__).with_name('input.txt')
|
||||
with open(p) as f:
|
||||
input = f.readlines()
|
||||
part_1(input)
|
||||
part_2(input)
|
||||
Reference in New Issue
Block a user