Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from ast import literal_eval
- from collections import deque
- from itertools import combinations
- from math import ceil
- def parse_input(filepath):
- with open(filepath, "r") as f:
- snailfish_numbers = [line.strip() for line in f.readlines()]
- return snailfish_numbers
- def explode(num):
- new_num: deque[str] = deque()
- depth = -1
- num_len = len(num)
- ptr = 0
- exploded = False
- right_applied = False
- right = None
- while ptr < num_len:
- if num[ptr] == "[":
- new_num.append(num[ptr])
- depth += 1
- ptr += 1
- elif num[ptr] == "]":
- if depth >= 4 and not exploded:
- exploded = True
- temp = deque()
- while new_num[-1] != "[":
- temp.appendleft(new_num.pop())
- new_num.pop()
- temp = ''.join(temp).split(",")
- left, right = int(temp[0]), int(temp[1])
- # Iterate left and find a number to add left to??
- new_num_left = deque()
- while new_num:
- left_val = new_num.pop()
- if left_val.isnumeric():
- left_val = str(int(left) + int(left_val))
- new_num.append(left_val)
- break
- else:
- new_num_left.appendleft(left_val)
- new_num.extend(new_num_left)
- new_num.append("0")
- else:
- new_num.append(num[ptr])
- ptr += 1
- depth -= 1
- elif num[ptr] == ",":
- new_num.append(num[ptr])
- ptr += 1
- else:
- inner_num = []
- while num[ptr].isnumeric():
- inner_num.append(num[ptr])
- ptr += 1
- next_num = "".join(inner_num)
- if right and not right_applied:
- next_num = str(int(next_num) + int(right))
- right_applied = True
- new_num.append(next_num)
- return "".join(new_num)
- def split(num) -> str:
- new_num: deque[str] = deque()
- num_len = len(num)
- ptr = 0
- num_split = False
- while ptr < num_len:
- if num[ptr] in "[,]":
- new_num.append(num[ptr])
- ptr += 1
- else:
- inner_num = []
- while num[ptr].isnumeric():
- inner_num.append(num[ptr])
- ptr += 1
- next_num = "".join(inner_num)
- if not num_split and int(next_num) >= 10:
- next_num = int(next_num)
- left = next_num // 2
- right = ceil(next_num / 2)
- new_num.append(f"[{str(left)},{str(right)}]")
- num_split = True
- else:
- new_num.append(next_num)
- return "".join(new_num)
- def reduce(num):
- while True:
- exploded_num = explode(num)
- if exploded_num != num:
- num = exploded_num
- continue
- split_num = split(num)
- if split_num != num:
- num = split_num
- continue
- return num
- def add(num1, num2):
- new_num = f"[{num1},{num2}]"
- reduced_num = reduce(new_num)
- return reduced_num
- def calculate_magnitude(num):
- if isinstance(num,str):
- num = literal_eval(num)
- match (isinstance(num[0], int), isinstance(num[1], int)):
- case (True, True):
- return num[0] * 3 + num[1] * 2
- case (True, False):
- return 3 * num[0] + 2 * calculate_magnitude(num[1])
- case (False, True):
- return 3 * calculate_magnitude(num[0]) + 2 * num[1]
- case (False, False):
- return 3 * calculate_magnitude(num[0]) + 2 * calculate_magnitude(num[1])
- def part_a():
- fp = r"data/day18.txt"
- data = parse_input(fp)
- l, *r = data
- for n in r:
- l = add(l, n)
- m = calculate_magnitude(l)
- return m
- def part_b():
- fp = r"data/day18.txt"
- data = parse_input(fp)
- data = parse_input(fp)
- max_magnitude = float("-inf")
- for a, b in combinations(data, 2):
- c = calculate_magnitude(add(a, b))
- d = calculate_magnitude(add(b, a))
- max_magnitude = max(max_magnitude, c, d)
- return max_magnitude
- if __name__ == '__main__':
- print(part_a())
- print(part_b())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement