From 998fc1d2409e60d74d0aefb38630be59ba977eaf Mon Sep 17 00:00:00 2001 From: Tom van der Lee Date: Thu, 30 Jul 2026 20:05:32 +0200 Subject: Added day 5 wip --- day5/__init__.py | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ day5/example.txt | 11 +++++++ day5/test_init.py | 23 +++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 day5/__init__.py create mode 100644 day5/example.txt create mode 100644 day5/test_init.py diff --git a/day5/__init__.py b/day5/__init__.py new file mode 100644 index 0000000..399aedc --- /dev/null +++ b/day5/__init__.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +from abc import ABC +from typing import Iterator + +from aoc import BaseAssignment, I, T + + +class Assignment(BaseAssignment, ABC): + def parse_item(cls, item: str) -> Iterator[range | None | int]: + try: + [start, end] = item.split("-") + yield range(int(start), int(end) + 1) + except ValueError: + if item == "": + yield None + else: + yield int(item) + + def read_input(self, example=False) -> Iterator[tuple[list[range], list[int]]]: + ranges = [] + ids = [] + + read_ranges = True + for item in super().read_input(example): + if item is None: + read_ranges = False + continue + + if read_ranges: + ranges.append(item) + else: + ids.append(item) + + yield (ranges, ids) + + @classmethod + def find_fresh_ranges_for_id(cls, id: int, ranges: list[range]) -> Iterator[range]: + for r in ranges: + if id in r: + yield r + + +class AssignmentOne(Assignment): + example_result = 3 + + def run(self, input: Iterator[tuple[list[range], list[int]]]) -> T: + ranges, ids = next(input) + + fresh_ids = [] + for id in ids: + if len(list(self.find_fresh_ranges_for_id(id, ranges))) > 0: + fresh_ids.append(id) + + return len(fresh_ids) + + +class AssignmentTwo(Assignment): + example_result = 14 + + @classmethod + def merge_ranges(cls, ranges: list[range]) -> list[range]: + if not ranges: + return [] + + ranges = sorted(ranges, key=lambda r: r.start) + merged = [ranges[0]] + for r in ranges[1:]: + last = merged[-1] + if not (last.stop < r.start): + merged[-1] = range(last.start, max(last.stop, r.stop)) + else: + merged.append(r) + return merged + + def run(self, input: Iterator[tuple[list[range], list[int]]]) -> T: + ranges, ids = next(input) + + fresh_ranges = set() + + for id in ids: + for r in self.find_fresh_ranges_for_id(id, ranges): + fresh_ranges.add(r) + + fresh_ranges = self.merge_ranges(list(fresh_ranges)) + + return sum([r.stop - r.start for r in fresh_ranges]) diff --git a/day5/example.txt b/day5/example.txt new file mode 100644 index 0000000..2e9078d --- /dev/null +++ b/day5/example.txt @@ -0,0 +1,11 @@ +3-5 +10-14 +16-20 +12-18 + +1 +5 +8 +11 +17 +32 diff --git a/day5/test_init.py b/day5/test_init.py new file mode 100644 index 0000000..018387b --- /dev/null +++ b/day5/test_init.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +from unittest import result + +import pytest + +from day5 import AssignmentTwo + + +class TestAssignmentTwo: + data = [ + [ + [range(3, 6), range(10, 15), range(16, 21), range(12, 19)], + [range(3, 6), range(10, 21)], + ], + [[range(2, 8), range(4, 6)], [range(2, 8)]], + [[range(4, 6), range(2, 8)], [range(2, 8)]], + [[range(1, 3), range(3, 6)], [range(1, 6)]], + [[range(3, 6), range(1, 3)], [range(1, 6)]], + ] + + @pytest.mark.parametrize("ranges,result", data) + def test_merge_ranges(self, ranges: list[range], result: list[range]): + assert AssignmentTwo.merge_ranges(ranges) == result -- cgit v1.2.3