Better project setup, now with a structure UV likes

This commit is contained in:
2024-11-22 10:28:10 +01:00
parent fd6b58022d
commit ee5eb931a9
7 changed files with 56 additions and 2 deletions

0
2024/src/aoc/__init__.py Normal file
View File

37
2024/src/aoc/__main__.py Normal file
View File

@@ -0,0 +1,37 @@
import datetime
import time
import click
from aoc import days
@click.command()
@click.option(
"-i",
"--input",
"data",
type=click.File(mode="rt", encoding="utf8"),
default="-",
help="Problem input file",
)
@click.option("-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:
runner_class = days.get_runner(day)
start = time.perf_counter_ns()
part1, part2 = runner_class.run_both(data)
if timing:
elapsed = time.perf_counter_ns() - start
delta = datetime.timedelta(microseconds=elapsed / 1000)
click.echo(f"Elapsed: {delta}", err=True)
click.echo(part1)
click.echo(part2)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,44 @@
import importlib
from abc import ABC, abstractmethod
from typing import Any, cast
class Runner(ABC):
@classmethod
@abstractmethod
def run_both(cls, data: str) -> tuple[Any, Any]:
pass
@classmethod
@abstractmethod
def part1(cls, data: str) -> Any:
pass
@classmethod
@abstractmethod
def part2(cls, data: str) -> Any:
pass
class SeparateRunner(Runner):
@classmethod
def run_both(cls, data: str) -> tuple[Any, Any]:
return (cls.part1(data), cls.part2(data))
class CombinedRunner(Runner):
@classmethod
def part1(cls, data: str) -> Any:
return cls.run_both(data)[0]
@classmethod
def part2(cls, data: str) -> Any:
return cls.run_both(data)[1]
def get_runner(day: int) -> type[Runner]:
runner_module = importlib.import_module(f".day{day}", package=__name__)
assert issubclass(runner_module.DayRunner, Runner)
return cast(type[Runner], runner_module.DayRunner)

13
2024/src/aoc/days/day1.py Normal file
View File

@@ -0,0 +1,13 @@
from typing import Any
from . import SeparateRunner
class DayRunner(SeparateRunner):
@classmethod
def part1(cls, _data: str) -> Any:
return "Hello"
@classmethod
def part2(cls, _data: str) -> Any:
return "world!"