JonathanGupton

Advent of Code 2025 - Day 02 - Python

Dec 2nd, 2025
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.18 KB | None | 0 0
  1. from dataclasses import dataclass
  2. from typing import Generator
  3.  
  4.  
  5. @dataclass(slots=True, frozen=True)
  6. class IDRange:
  7.     start: int
  8.     stop: int
  9.  
  10.     def __iter__(self):
  11.         """Handle creating the inclusive range"""
  12.         for i in range(self.start, self.stop + 1):
  13.             yield i
  14.  
  15.  
  16. def parse_data(filepath: str) -> list[IDRange]:
  17.     ids = []
  18.     with open(filepath, "r") as f:
  19.         for line in f.readlines():
  20.             for pair in line.split(","):
  21.                 l, r = map(int, pair.split("-"))
  22.                 ids.append(IDRange(l, r))
  23.     return ids
  24.  
  25.  
  26. def all_duplicated(id: int) -> bool:
  27.     """
  28.    >>> assert all_duplicated(11) is True
  29.    >>> assert all_duplicated(22) is True
  30.    >>> assert all_duplicated(1010) is True
  31.    >>> assert all_duplicated(1188511885) is True
  32.    >>> assert all_duplicated(222222) is True
  33.    >>> assert all_duplicated(446446) is True
  34.    >>> assert all_duplicated(38593859) is True
  35.    >>> assert all_duplicated(12) is False
  36.    >>> assert all_duplicated(999) is False
  37.    >>> assert all_duplicated(9999) is True
  38.    """
  39.     id_str = str(id)
  40.     if len(id_str) % 2 != 0:
  41.         return False
  42.     half = len(id_str) // 2
  43.     if id_str[0:half] == id_str[half : len(id_str)]:
  44.         return True
  45.     return False
  46.  
  47.  
  48. def any_duplicated(id: int) -> bool:
  49.     """
  50.    >>> assert any_duplicated(12341234) is True
  51.    >>> assert any_duplicated(123123123) is True
  52.    >>> assert any_duplicated(1212121212) is True
  53.    >>> assert any_duplicated(2121212118) is False
  54.    >>> assert any_duplicated(2121212119) is False
  55.    >>> assert any_duplicated(2121212121) is True
  56.    """
  57.     id_str = str(id)
  58.     id_length = len(id_str)
  59.     for size in range(1, (id_length // 2) + 1):
  60.         segments, r = divmod(id_length, size)
  61.         if r != 0:
  62.             continue
  63.         splits = [
  64.             id_str[size * segment : size * segment + size]
  65.             for segment in range(segments)
  66.         ]
  67.         if all(splits[0] == splits[i] for i in range(len(splits))):
  68.             return True
  69.     return False
  70.  
  71.  
  72. def invalid_from_range(
  73.     id_range: IDRange, dup_func=all_duplicated
  74. ) -> Generator[int, None, None]:
  75.     """
  76.    >>> id_range = IDRange(11, 22)
  77.    >>> assert [*invalid_from_range(id_range, any_duplicated)] == [11, 22]
  78.    >>> id_range = IDRange(95, 115)
  79.    >>> assert [*invalid_from_range(id_range, any_duplicated)] == [99, 111]
  80.    >>> id_range = IDRange(998, 1012)
  81.    >>> assert [*invalid_from_range(id_range, any_duplicated)] == [999, 1010]
  82.    >>> id_range = IDRange(1188511880, 1188511890)
  83.    >>> assert [*invalid_from_range(id_range, any_duplicated)] == [1188511885]
  84.    >>> id_range = IDRange(222220, 222224)
  85.    >>> assert [*invalid_from_range(id_range, any_duplicated)] == [222222]
  86.    >>> id_range = IDRange(1698522, 1698528)
  87.    >>> assert [*invalid_from_range(id_range, any_duplicated)] == []
  88.    >>> id_range = IDRange(446443, 446449)
  89.    >>> assert [*invalid_from_range(id_range, any_duplicated)] == [446446]
  90.    >>> id_range = IDRange(38593856,38593862)
  91.    >>> assert [*invalid_from_range(id_range, any_duplicated)] == [38593859]
  92.    >>> id_range = IDRange(565653, 565659)
  93.    >>> assert [*invalid_from_range(id_range, any_duplicated)] == [565656]
  94.    >>> id_range = IDRange(824824821,824824827)
  95.    >>> assert [*invalid_from_range(id_range, any_duplicated)] == [824824824]
  96.    >>> id_range = IDRange(2121212118,2121212124)
  97.    >>> assert [*invalid_from_range(id_range, any_duplicated)] == [2121212121]
  98.    """
  99.     for i in id_range:
  100.         if dup_func(i):
  101.             yield i
  102.  
  103.  
  104. def calculate_total_invalid_ids(ids: list[IDRange], dup_func=all_duplicated) -> int:
  105.     invalid_id_total = 0
  106.     for id_range in ids:
  107.         for id in id_range:
  108.             if dup_func(id):
  109.                 invalid_id_total += id
  110.     return invalid_id_total
  111.  
  112.  
  113. def part_a():
  114.     fp = "day02.txt"
  115.     id_ranges = parse_data(fp)
  116.     total = calculate_total_invalid_ids(id_ranges)
  117.     print(total)
  118.  
  119.  
  120. def part_b():
  121.     fp = "day02.txt"
  122.     id_ranges = parse_data(fp)
  123.     total = calculate_total_invalid_ids(id_ranges, any_duplicated)
  124.     print(total)
  125.  
  126.  
  127. if __name__ == "__main__":
  128.     part_a()
  129.     part_b()
  130.  
Add Comment
Please, Sign In to add comment