Files
advent-of-code-2024/puzzles/2.py
2024-12-04 22:08:54 -08:00

64 lines
1.8 KiB
Python

from itertools import islice
from typing import Iterator
from more_itertools import ilen
test_input = """
7 6 4 2 1
1 2 7 8 9
9 7 6 2 1
1 3 2 4 5
8 6 4 4 1
1 3 6 7 9
""".strip()
test_solution_p1 = 2
test_solution_p2 = 4
def solve_p1(puzzle_input: str) -> int:
reports = _parse_reports(puzzle_input)
delta_reports = (_deltas(report) for report in reports)
safe_delta_reports = filter(_is_gradual_monotonic, delta_reports)
return ilen(safe_delta_reports)
def solve_p2(puzzle_input: str) -> int:
reports = _parse_reports(puzzle_input)
dampened_report_collections = (_dampen_permutations(report) for report in reports)
delta_report_collections = (
(_deltas(report) for report in report_collection)
for report_collection in dampened_report_collections
)
safe_report_collections = filter(
lambda delta_report_collection: any(
_is_gradual_monotonic(delta_report)
for delta_report in delta_report_collection
),
delta_report_collections,
)
return ilen(safe_report_collections)
def _parse_reports(puzzle_input: str) -> Iterator[tuple[int, ...]]:
lines = puzzle_input.splitlines()
return (tuple(int(level) for level in line.split(" ")) for line in lines)
def _deltas(report: tuple[int, ...]) -> tuple[int, ...]:
pairs = zip(report, islice(report, 1, None))
return tuple(b - a for a, b in pairs)
def _is_gradual_monotonic(delta_report: tuple[int]) -> bool:
sign = 1 if delta_report[0] > 0 else -1
return all(
delta != 0 and delta / abs(delta) == sign and abs(delta) < 4
for delta in delta_report
)
def _dampen_permutations(report: tuple[int, ...]) -> Iterator[tuple[int, ...]]:
yield report
yield from (report[:i] + report[i + 1 :] for i in range(0, len(report)))