diff --git a/2024/src/aoc/days/day11.py b/2024/src/aoc/days/day11.py new file mode 100644 index 0000000..cd0cb6c --- /dev/null +++ b/2024/src/aoc/days/day11.py @@ -0,0 +1,50 @@ +import functools +from collections import defaultdict + +from . import CombinedRunner + + +@functools.cache +def blink_num(num: int) -> tuple[int, ...]: + if num == 0: + return (1,) + + num_str = str(num) + num_len = len(num_str) + + if num_len % 2 == 0: + half = num_len // 2 + return (int(num_str[:half]), int(num_str[half:])) + + return (num * 2024,) + + +def step(nums: dict[int, int]) -> dict[int, int]: + result = defaultdict(int) + + for num, count in nums.items(): + for transformed in blink_num(num): + result[transformed] += count + + return result + + +class DayRunner(CombinedRunner): + @classmethod + def run_both(cls, input: str) -> tuple[int, int]: + nums = [int(val) for val in input.strip().split(" ")] + + counts = defaultdict(int) + + for num in nums: + counts[num] += 1 + + for _ in range(25): + counts = step(counts) + + part1 = sum(counts.values()) + + for _ in range(50): + counts = step(counts) + + return part1, sum(counts.values()) diff --git a/2024/tests/test_day11.py b/2024/tests/test_day11.py new file mode 100644 index 0000000..c839c1f --- /dev/null +++ b/2024/tests/test_day11.py @@ -0,0 +1,7 @@ +from aoc.days.day11 import DayRunner + +SAMPLE = "125 17" + + +def test_sample_part1() -> None: + assert DayRunner.part1(SAMPLE) == 55312