day18: regexp power!
This commit is contained in:
parent
537abb62bd
commit
081eb3302a
99
day18.py
99
day18.py
@ -1,9 +1,16 @@
|
||||
import re
|
||||
from itertools import combinations
|
||||
from math import ceil
|
||||
from tools.aoc import AOCDay
|
||||
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:
|
||||
def __init__(self, fish_str: str):
|
||||
self.pairs = fish_str
|
||||
@ -21,72 +28,46 @@ class Snailfish:
|
||||
elif c == "[":
|
||||
open_count += 1
|
||||
if open_count == 5:
|
||||
index_explode = i
|
||||
while self.pairs[index_explode + 1] == "[" or self.pairs[index_explode + 3] == "[":
|
||||
if self.pairs[index_explode + 1] == "[":
|
||||
index_explode += 1
|
||||
if self.pairs[index_explode + 3] == "[":
|
||||
index_explode += 3
|
||||
explode_pair = self.pairs[index_explode:self.pairs.index("]", index_explode) + 1]
|
||||
explode_left, explode_right = map(int, explode_pair[1:-1].split(","))
|
||||
old_number_left = ""
|
||||
old_number_right = ""
|
||||
new_number_left = ""
|
||||
new_number_right = ""
|
||||
index_left = index_explode
|
||||
index_right = index_explode + len(explode_pair)
|
||||
for i_left in range(index_explode, 0, -1):
|
||||
if self.pairs[i_left] not in ['[', ']', ',']:
|
||||
il_add = 0
|
||||
while self.pairs[i_left - il_add - 1] in "0123456789":
|
||||
il_add += 1
|
||||
index_left = i_left - il_add
|
||||
old_number_left = self.pairs[i_left - il_add:i_left + 1]
|
||||
new_number_left = str(int(old_number_left) + explode_left)
|
||||
break
|
||||
for i_right in range(index_explode + len(explode_pair), len(self.pairs)):
|
||||
if self.pairs[i_right] not in ['[', ']', ',']:
|
||||
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
|
||||
explode_pair_match = re_pair.search(self.pairs, i)
|
||||
index_l, index_r = explode_pair_match.span()
|
||||
explode_left, explode_right = map(int, explode_pair_match.groups())
|
||||
lnum_old = rnum_old = lnum_new = rnum_new = ""
|
||||
lnum_index = index_l
|
||||
rnum_index = index_r
|
||||
|
||||
if left_num := re_lnum.search(self.pairs[:index_l]):
|
||||
lnum_old = left_num.groups()[0]
|
||||
lnum_new = str(int(lnum_old) + explode_left)
|
||||
lnum_index = left_num.span()[1] - len(lnum_old)
|
||||
|
||||
if right_num := re_rnum.search(self.pairs, index_r):
|
||||
rnum_old = right_num.groups()[0]
|
||||
rnum_new = str(int(rnum_old) + explode_right)
|
||||
rnum_index = right_num.span()[0]
|
||||
|
||||
self.pairs = "".join([
|
||||
self.pairs[:lnum_index],
|
||||
lnum_new,
|
||||
self.pairs[lnum_index + len(lnum_old):index_l],
|
||||
"0",
|
||||
self.pairs[index_r:rnum_index],
|
||||
rnum_new,
|
||||
self.pairs[rnum_index + len(rnum_old):]
|
||||
])
|
||||
return True
|
||||
|
||||
for i in range(1, len(self.pairs)):
|
||||
if self.pairs[i - 1] not in ["[", "]", ","] and self.pairs[i] not in ["[", "]", ","]:
|
||||
number = int(self.pairs[i-1:i+1])
|
||||
self.pairs = self.pairs.replace(str(number), "[%d,%d]" % (number // 2, int(ceil(number / 2))), 1)
|
||||
return True
|
||||
if big_num_match := re_bignum.search(self.pairs):
|
||||
num = int(big_num_match.group())
|
||||
self.pairs = self.pairs.replace(big_num_match.group(), "[%d,%d]" % (num // 2, int(ceil(num / 2))), 1)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def getMagnitude(self) -> int:
|
||||
pairs = self.pairs
|
||||
while "[" in pairs:
|
||||
for i in range(len(pairs)):
|
||||
if pairs[i] == "]":
|
||||
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
|
||||
while re_pair.search(pairs):
|
||||
for num1, num2 in re_pair.findall(pairs):
|
||||
pairs = pairs.replace("[%s,%s]" % (num1, num2), str(int(num1) * 3 + int(num2) * 2))
|
||||
|
||||
return int(pairs)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user