Restructure solver modules with classes and unittest suites

This commit is contained in:
2024-12-09 20:47:50 -08:00
parent 7c021ab87f
commit bee7f5e59e
11 changed files with 995 additions and 698 deletions

View File

@@ -1,40 +1,58 @@
import re
from functools import reduce
from typing import Literal, override
from unittest import TestCase
test_input_p1 = """
xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))
"""
test_input_p2 = """
xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))
"""
test_solution_p1 = 161
test_solution_p2 = 48
instruction_pattern = re.compile(r"mul\((\d+),(\d+)\)|(do(?:n't)?)\(\)")
from puzzles._solver import Solver
def solve_p1(puzzle_input: str) -> int:
instructions = (
tuple(map(int, match[:2]))
for match in instruction_pattern.findall(puzzle_input)
if match[0]
)
return sum(a * b for a, b in instructions)
class DayThreeSolver(Solver):
memory: tuple[int, int] | Literal["do", "don't"]
@override
def __init__(self, puzzle_input: str):
matches = re.findall(r"mul\((\d+),(\d+)\)|(do(?:n't)?)\(\)", puzzle_input)
self.memory = tuple(
(int(a), int(b)) if a else enable_flag for a, b, enable_flag in matches
)
@override
def solve_p1(self) -> int:
total = 0
for match in self.memory:
match match:
case a, b:
total += a * b
return total
@override
def solve_p2(self) -> int:
total = 0
enabled = True
for match in self.memory:
match match:
case "do":
enabled = True
case "don't":
enabled = False
case a, b:
if enabled:
total += a * b
return total
def solve_p2(puzzle_input: str) -> int:
instructions = (
match[2] or tuple(map(int, match[:2]))
for match in instruction_pattern.findall(puzzle_input)
)
return reduce(
lambda a, i: (
(1 if i == "do" else 0, a[1])
if isinstance(i, str)
else (a[0], a[1] + a[0] * i[0] * i[1])
),
instructions,
(1, 0),
)[1]
class TestDayThreeSolver(TestCase):
def test_solve_p1(self):
solver = DayThreeSolver(
"xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))\n"
)
self.assertEqual(solver.solve_p1(), 161)
def test_solve_p2(self):
solver = DayThreeSolver(
"xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))\n"
)
self.assertEqual(solver.solve_p2(), 48)