day 17-19
This commit is contained in:
113
2021/18.py
Normal file
113
2021/18.py
Normal file
@@ -0,0 +1,113 @@
|
||||
|
||||
def add(a, b):
|
||||
return [a, b]
|
||||
|
||||
DIGITS = '0123456789'
|
||||
|
||||
def try_explode(num):
|
||||
num_str = str(num).replace(' ', '')
|
||||
depth = 0
|
||||
for idx, c in enumerate(num_str):
|
||||
if c == '[':
|
||||
depth += 1
|
||||
if depth == 5:
|
||||
# Explode!
|
||||
end_idx = num_str.find(']', idx)
|
||||
a, b = list(map(int, num_str[idx+1:end_idx].split(',')))
|
||||
left = num_str[:idx]
|
||||
for lidx in range(len(left)-1, -1, -1):
|
||||
c = left[lidx]
|
||||
if c in DIGITS:
|
||||
term = max(i for i in range(lidx)
|
||||
if left[i] not in DIGITS)
|
||||
val = int(left[term+1:lidx+1])
|
||||
val += a
|
||||
left = left[:term+1] + str(val) + left[lidx+1:]
|
||||
break
|
||||
mid = '0'
|
||||
right = num_str[end_idx+1:]
|
||||
for ridx, c in enumerate(right):
|
||||
if c in DIGITS:
|
||||
term = min(i for i in range(ridx+1, len(right))
|
||||
if right[i] not in DIGITS)
|
||||
val = int(right[ridx:term])
|
||||
val += b
|
||||
right = right[:ridx] + str(val) + right[term:]
|
||||
break
|
||||
return eval(left + mid + right)
|
||||
elif c == ']':
|
||||
depth -= 1
|
||||
return None
|
||||
|
||||
def try_split(num):
|
||||
if isinstance(num, list):
|
||||
a, b = num
|
||||
new_a = try_split(a)
|
||||
if new_a is not None:
|
||||
return [new_a, b]
|
||||
new_b = try_split(b)
|
||||
if new_b is not None:
|
||||
return [a, new_b]
|
||||
return None
|
||||
if num > 9:
|
||||
d, m = divmod(num, 2)
|
||||
return [d, d + m]
|
||||
return None
|
||||
|
||||
def reduce(num):
|
||||
while True:
|
||||
new_num = try_explode(num)
|
||||
if new_num is not None:
|
||||
num = new_num
|
||||
continue
|
||||
new_num = try_split(num)
|
||||
if new_num is not None:
|
||||
num = new_num
|
||||
continue
|
||||
return num
|
||||
|
||||
def magnitude(num):
|
||||
if isinstance(num, list):
|
||||
a, b = num
|
||||
a = magnitude(a)
|
||||
b = magnitude(b)
|
||||
return 3*a + 2*b
|
||||
return num
|
||||
|
||||
def part1(s):
|
||||
lines = s.splitlines()
|
||||
fake_nums = list(map(eval, lines))
|
||||
|
||||
num = fake_nums[0]
|
||||
|
||||
for item in fake_nums[1:]:
|
||||
item = reduce(item)
|
||||
num = reduce(add(num, item))
|
||||
|
||||
answer = magnitude(num)
|
||||
|
||||
print(f'The answer to part one is {answer}')
|
||||
|
||||
def part2(s):
|
||||
lines = s.splitlines()
|
||||
fake_nums = list(map(eval, lines))
|
||||
|
||||
fake_nums = list(map(reduce, fake_nums))
|
||||
|
||||
best = 0
|
||||
for ia, a in enumerate(fake_nums):
|
||||
for ib, b in enumerate(fake_nums):
|
||||
if ia == ib:
|
||||
continue
|
||||
|
||||
mag = magnitude(reduce(add(a, b)))
|
||||
best = max(best, mag)
|
||||
|
||||
answer = best
|
||||
|
||||
print(f'The answer to part two is {answer}')
|
||||
|
||||
with open('./2021/18.input') as input_file:
|
||||
INPUT = input_file.read()
|
||||
part1(INPUT)
|
||||
part2(INPUT)
|
||||
Reference in New Issue
Block a user