day18: regexp power!

This commit is contained in:
Stefan Harmuth 2021-12-18 10:15:31 +01:00
parent 537abb62bd
commit 081eb3302a

View File

@ -1,9 +1,16 @@
import re
from itertools import combinations from itertools import combinations
from math import ceil from math import ceil
from tools.aoc import AOCDay from tools.aoc import AOCDay
from typing import Any from typing import Any
re_pair = re.compile(r"\[(\d+),(\d+)\]")
re_lnum = re.compile(r".*[^\d](\d+)")
re_rnum = re.compile(r"(\d+)")
re_bignum = re.compile(r"(\d\d+)")
class Snailfish: class Snailfish:
def __init__(self, fish_str: str): def __init__(self, fish_str: str):
self.pairs = fish_str self.pairs = fish_str
@ -21,72 +28,46 @@ class Snailfish:
elif c == "[": elif c == "[":
open_count += 1 open_count += 1
if open_count == 5: if open_count == 5:
index_explode = i explode_pair_match = re_pair.search(self.pairs, i)
while self.pairs[index_explode + 1] == "[" or self.pairs[index_explode + 3] == "[": index_l, index_r = explode_pair_match.span()
if self.pairs[index_explode + 1] == "[": explode_left, explode_right = map(int, explode_pair_match.groups())
index_explode += 1 lnum_old = rnum_old = lnum_new = rnum_new = ""
if self.pairs[index_explode + 3] == "[": lnum_index = index_l
index_explode += 3 rnum_index = index_r
explode_pair = self.pairs[index_explode:self.pairs.index("]", index_explode) + 1]
explode_left, explode_right = map(int, explode_pair[1:-1].split(",")) if left_num := re_lnum.search(self.pairs[:index_l]):
old_number_left = "" lnum_old = left_num.groups()[0]
old_number_right = "" lnum_new = str(int(lnum_old) + explode_left)
new_number_left = "" lnum_index = left_num.span()[1] - len(lnum_old)
new_number_right = ""
index_left = index_explode if right_num := re_rnum.search(self.pairs, index_r):
index_right = index_explode + len(explode_pair) rnum_old = right_num.groups()[0]
for i_left in range(index_explode, 0, -1): rnum_new = str(int(rnum_old) + explode_right)
if self.pairs[i_left] not in ['[', ']', ',']: rnum_index = right_num.span()[0]
il_add = 0
while self.pairs[i_left - il_add - 1] in "0123456789": self.pairs = "".join([
il_add += 1 self.pairs[:lnum_index],
index_left = i_left - il_add lnum_new,
old_number_left = self.pairs[i_left - il_add:i_left + 1] self.pairs[lnum_index + len(lnum_old):index_l],
new_number_left = str(int(old_number_left) + explode_left) "0",
break self.pairs[index_r:rnum_index],
for i_right in range(index_explode + len(explode_pair), len(self.pairs)): rnum_new,
if self.pairs[i_right] not in ['[', ']', ',']: self.pairs[rnum_index + len(rnum_old):]
ir_add = 0 ])
while self.pairs[i_right + ir_add + 1] in "0123456789":
ir_add += 1
index_right = i_right
old_number_right = self.pairs[i_right:i_right + ir_add + 1]
new_number_right = str(int(old_number_right) + explode_right)
break
new_pairs = ""
if index_left != index_explode:
new_pairs += self.pairs[:index_left] + new_number_left + self.pairs[index_left + len(old_number_left):index_explode]
else:
new_pairs = self.pairs[:index_explode]
new_pairs += "0"
if index_right != index_explode + len(explode_pair):
new_pairs += self.pairs[index_explode + len(explode_pair):index_right] + new_number_right + self.pairs[index_right + len(old_number_right):]
else:
new_pairs += self.pairs[index_explode + len(explode_pair):]
self.pairs = new_pairs
return True return True
for i in range(1, len(self.pairs)): if big_num_match := re_bignum.search(self.pairs):
if self.pairs[i - 1] not in ["[", "]", ","] and self.pairs[i] not in ["[", "]", ","]: num = int(big_num_match.group())
number = int(self.pairs[i-1:i+1]) self.pairs = self.pairs.replace(big_num_match.group(), "[%d,%d]" % (num // 2, int(ceil(num / 2))), 1)
self.pairs = self.pairs.replace(str(number), "[%d,%d]" % (number // 2, int(ceil(number / 2))), 1) return True
return True
return False return False
def getMagnitude(self) -> int: def getMagnitude(self) -> int:
pairs = self.pairs pairs = self.pairs
while "[" in pairs: while re_pair.search(pairs):
for i in range(len(pairs)): for num1, num2 in re_pair.findall(pairs):
if pairs[i] == "]": pairs = pairs.replace("[%s,%s]" % (num1, num2), str(int(num1) * 3 + int(num2) * 2))
r = i + 1
l = i - 1
while pairs[l] != "[":
l -= 1
replace_pair = pairs[l:r]
num1, num2 = map(int, replace_pair[1:-1].split(","))
pairs = pairs.replace(replace_pair, str(num1 * 3 + num2 * 2))
break
return int(pairs) return int(pairs)