Files
aoc2024/day2/solver.py

70 lines
2.1 KiB
Python

from typing import Callable, Iterator
import sys
def check_report_basic(levels: tuple[int, ...]) -> bool:
safe = True
differences = [next_level - level for level, next_level in zip(levels, levels[1:])]
safe = safe and (
all(-3 <= diff <= -1 for diff in differences)
or all(1 <= diff <= 3 for diff in differences)
)
return safe
def check_report_damp(levels: tuple[int, ...]) -> bool:
# Obvious solution is using check_report_basic iteratively..
# Is there a better solution?
safe = check_report_basic(levels)
safe = safe or any(check_report_basic(levels[:i] + levels[i+1:]) for i in range(len(levels)))
return safe
def tester(data: dict[tuple[int, ...], bool], checker: Callable[[tuple[int, ...]], bool]):
for report, expected in data.items():
assert (checker(report) is expected), f"Check failed: {report=} should be {expected=}"
def tests():
print("Testing basic check")
data = {
(7, 6, 4, 2, 1): True,
(1, 2, 7, 8, 9): False,
(9, 7, 6, 2, 1): False,
(1, 3, 2, 4, 5): False,
(8, 6, 4, 4, 1): False,
(1, 3, 6, 7, 9): True,
}
tester(data, check_report_basic)
print("Basic check passed.")
print("Testing dampened check.")
data = {
(7, 6, 4, 2, 1): True,
(1, 2, 7, 8, 9): False,
(9, 7, 6, 2, 1): False,
(1, 3, 2, 4, 5): True,
(8, 6, 4, 4, 1): True,
(1, 3, 6, 7, 9): True,
}
tester(data, check_report_damp)
print("Damp check passed.")
def main():
tests()
filename = sys.argv[1]
reports = load_data(filename)
total = sum(map(check_report_basic, reports))
print(f"Total safe reports without damping: {total}")
reports = load_data(filename)
total = sum(map(check_report_damp, reports))
print(f"Total safe reports with damping: {total}")
def load_data(filename) -> Iterator[tuple[int, ...]]:
with open(filename) as f:
for line in f:
if line.strip():
yield tuple(map(int, line.split()))
if __name__ == '__main__':
main()