feat: add solution 2025/05

This commit is contained in:
2025-12-05 07:24:00 +01:00
parent 00000090e4
commit 00000100ef
2 changed files with 133 additions and 0 deletions

11
data/example/2025/05.txt Normal file
View File

@@ -0,0 +1,11 @@
3-5
10-14
16-20
12-18
1
5
8
11
17
32

View File

@@ -0,0 +1,122 @@
from typing import Any, Self
class Range:
def __init__(self, start: int, end: int) -> None:
self.start = start
self.end = end
def __str__(self) -> str:
return f"{self.start}..={self.end}"
def __repr__(self) -> str:
return f"Range({self.start}, {self.end})"
def __len__(self) -> int:
return max(self.end - self.start + 1, 0)
def __eq__(self, value: object, /) -> bool:
if not isinstance(value, Range):
return False
return self.start == value.start and self.end == value.end
def __contains__(self, value: int) -> bool:
return self.start <= value <= self.end
def discard(self, other: Self) -> list[Self]:
r1, r2 = self.start, self.end
d1, d2 = other.start, other.end
res = []
if r1 < d1:
t = min(r2, d1 - 1)
res.append(Range(r1, t))
if r1 < d1 and r2 > d2:
res.append(Range(d2 + 1, r2))
if d1 <= r1 <= d2:
res.append(Range(d2 + 1, r2))
if r1 > d2:
res.append(self)
return list(filter(len, res))
def _parse_input(input_data) -> tuple[list[Range], list[int]]:
_ranges, _ids = input_data.split("\n\n")
ranges = []
for r in _ranges.splitlines():
a, b = r.split("-")
ranges.append(Range(int(a), int(b)))
ids = list(map(int, _ids.splitlines()))
return ranges, ids
def part_1(input_data: str) -> Any:
ranges, ids = _parse_input(input_data)
c = 0
for i in ids:
for r in ranges:
if i in r:
c += 1
break
return c
def part_2(input_data: str) -> Any:
ranges, _ = _parse_input(input_data)
res: list[Range] = []
for i, r1 in enumerate(ranges):
acc = [r1]
for r2 in ranges[i + 1 :]:
nacc = []
for r3 in acc:
nacc.extend(r3.discard(r2))
acc = nacc
res.extend(acc)
return sum(map(len, res))
def test_range():
r1 = Range(1, 3)
r2 = Range(1, 0)
# len
assert len(r1) == 3
assert len(r2) == 0
# contains
assert 0 not in r1
assert 1 in r1
assert 2 in r1
assert 3 in r1
assert 4 not in r1
# eq
assert Range(2, 2) == Range(2, 2)
assert Range(300, 1234) == Range(300, 1234)
assert Range(2, 3) != Range(2, 2)
# discard
r3 = Range(2, 2)
assert r1.discard(r2) == [r1]
assert r1.discard(r3) == [Range(1, 1), Range(3, 3)]
def test_part_1(example_data):
assert part_1(example_data) == 3
def test_part_2(example_data):
assert part_2(example_data) == 14