diff --git a/2024/inputs/.gitkeep b/2024/inputs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/2024/src/aoc/__main__.py b/2024/src/aoc/__main__.py index 88467ba..9534731 100644 --- a/2024/src/aoc/__main__.py +++ b/2024/src/aoc/__main__.py @@ -1,5 +1,6 @@ import datetime import time +from typing import IO import click @@ -19,8 +20,9 @@ from aoc import days "-t", "--time", "timing", is_flag=True, help="Print elapsed time afterwards" ) @click.argument("day", required=True) -def main(day: int, timing: bool, data: str) -> None: +def main(day: int, timing: bool, data: IO[str]) -> None: runner_class = days.get_runner(day) + data = data.read() start = time.perf_counter_ns() diff --git a/2024/src/aoc/days/day1.py b/2024/src/aoc/days/day1.py index b27f33d..5fcb923 100644 --- a/2024/src/aoc/days/day1.py +++ b/2024/src/aoc/days/day1.py @@ -1,13 +1,28 @@ +from collections import defaultdict +from io import StringIO from typing import Any -from . import SeparateRunner +import numpy + +from . import CombinedRunner -class DayRunner(SeparateRunner): +class DayRunner(CombinedRunner): @classmethod - def part1(cls, _data: str) -> Any: - return "Hello" + def run_both(cls, data: str) -> tuple[Any, Any]: + data = StringIO(data) + nums = numpy.loadtxt(data, dtype=numpy.int32) - @classmethod - def part2(cls, _data: str) -> Any: - return "world!" + left = nums[..., 0] + right = nums[..., 1] + + left.sort() + right.sort() + + diff = numpy.abs(left - right).sum() + + counts = defaultdict(int) + for val in right: + counts[val] += 1 + + return diff, sum(counts[v] * v for v in left) diff --git a/2024/tests/samples/01.txt b/2024/tests/samples/01.txt new file mode 100644 index 0000000..b8af9ad --- /dev/null +++ b/2024/tests/samples/01.txt @@ -0,0 +1,6 @@ +3 4 +4 3 +2 5 +1 3 +3 9 +3 3 diff --git a/2024/tests/test_day1.py b/2024/tests/test_day1.py new file mode 100644 index 0000000..b6650bb --- /dev/null +++ b/2024/tests/test_day1.py @@ -0,0 +1,14 @@ +import os + +from aoc.days.day1 import DayRunner + +def get_data() -> str: + sample = os.path.dirname(__file__) + "/samples/01.txt" + with open(sample, mode="rt", encoding="utf-8") as f: + return f.read() + +def test_sample_part1(): + assert DayRunner.part1(get_data()) == 11 + +def test_sample_part2(): + assert DayRunner.part2(get_data()) == 31