From c871a9ea245d490305052ee49429726abc503b7d Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 7 Dec 2024 10:35:58 +0100 Subject: [PATCH] Implement 2024 day 7 --- 2024/src/aoc/days/day7.py | 61 +++++++++++++++++++++++++++++++++++++++ 2024/tests/samples/07.txt | 9 ++++++ 2024/tests/test_day07.py | 17 +++++++++++ 3 files changed, 87 insertions(+) create mode 100644 2024/src/aoc/days/day7.py create mode 100644 2024/tests/samples/07.txt create mode 100644 2024/tests/test_day07.py diff --git a/2024/src/aoc/days/day7.py b/2024/src/aoc/days/day7.py new file mode 100644 index 0000000..67ac735 --- /dev/null +++ b/2024/src/aoc/days/day7.py @@ -0,0 +1,61 @@ +from . import SeparateRunner + + +def parse_input(input: str) -> tuple[int, list[int]]: + result = [] + + for line in input.strip().split("\n"): + test, nums = line.split(": ") + result.append((int(test), list(map(int, nums.split(" "))))) + + return result + + +def is_possible(target: int, nums: list[int], cur: int) -> bool: + if cur == target and not nums: + return True + + if cur > target or not nums: + return False + + head = nums[0] + remainder = nums[1:] + + return is_possible(target, remainder, cur + head) or is_possible( + target, remainder, cur * head + ) + + +def is_possible2(target: int, nums: list[int], cur: int) -> bool: + if cur == target and not nums: + return True + + if cur > target or not nums: + return False + + head = nums[0] + remainder = nums[1:] + + return ( + is_possible2(target, remainder, cur + head) + or is_possible2(target, remainder, cur * head) + or is_possible2(target, remainder, int(f"{cur}{head}")) + ) + + +class DayRunner(SeparateRunner): + @classmethod + def part1(cls, input: str) -> int: + lines = parse_input(input) + + return sum( + target for target, nums in lines if is_possible(target, nums[1:], nums[0]) + ) + + @classmethod + def part2(cls, input: str) -> int: + lines = parse_input(input) + + return sum( + target for target, nums in lines if is_possible2(target, nums[1:], nums[0]) + ) diff --git a/2024/tests/samples/07.txt b/2024/tests/samples/07.txt new file mode 100644 index 0000000..fc6e099 --- /dev/null +++ b/2024/tests/samples/07.txt @@ -0,0 +1,9 @@ +190: 10 19 +3267: 81 40 27 +83: 17 5 +156: 15 6 +7290: 6 8 6 15 +161011: 16 10 13 +192: 17 8 14 +21037: 9 7 18 13 +292: 11 6 16 20 diff --git a/2024/tests/test_day07.py b/2024/tests/test_day07.py new file mode 100644 index 0000000..b80ba94 --- /dev/null +++ b/2024/tests/test_day07.py @@ -0,0 +1,17 @@ +import os + +from aoc.days.day7 import DayRunner + + +def get_data() -> str: + sample = os.path.dirname(__file__) + "/samples/07.txt" + with open(sample, mode="rt", encoding="utf-8") as f: + return f.read() + + +def test_sample_part1() -> None: + assert DayRunner.part1(get_data()) == 3749 + + +def test_sample_part2() -> None: + assert DayRunner.part2(get_data()) == 11387