wip
This commit is contained in:
83
aoc/run.py
Normal file
83
aoc/run.py
Normal file
@@ -0,0 +1,83 @@
|
||||
import importlib.util
|
||||
import pathlib
|
||||
from aoc import exceptions
|
||||
from typing import Any, Callable
|
||||
import time
|
||||
|
||||
|
||||
_ANSI_ITALIC: str = "\x1b[3m"
|
||||
_ANSI_BOLD: str = "\x1b[1m"
|
||||
_ANSI_RESET: str = "\x1b[0m"
|
||||
|
||||
|
||||
def _pprint_ns(ns: int) -> str:
|
||||
if ns >= 1_000_000_000:
|
||||
s = ns / 1_000_000_000
|
||||
return f"{s:.2f}s"
|
||||
elif ns >= 1_000_000:
|
||||
ms = ns / 1_000_000
|
||||
return f"{ms:.2f}ms"
|
||||
elif ns >= 1_000:
|
||||
us = ns / 1_000
|
||||
return f"{us:.2f}µs"
|
||||
else:
|
||||
return f"{ns}ns"
|
||||
|
||||
|
||||
def _pprint_result(
|
||||
year: int, day: int, part: int | str, result: Any, duration_ns: int
|
||||
) -> None:
|
||||
part = f"{_ANSI_BOLD}{year}/{day:02}/{part}{_ANSI_RESET}"
|
||||
|
||||
if result is None:
|
||||
solved = f"{_ANSI_ITALIC}(unsolved){_ANSI_RESET}"
|
||||
print(f"{part}: {solved}")
|
||||
else:
|
||||
if isinstance(result, list) or isinstance(result, tuple):
|
||||
result = "\n".join(str(r) for r in result)
|
||||
solved = f"{_ANSI_ITALIC}(elapsed: {_pprint_ns(duration_ns)}){_ANSI_RESET}"
|
||||
print(f"{part}: {solved}\n{result}")
|
||||
|
||||
|
||||
def _run_func(
|
||||
f: Callable[[str], Any], year: int, day: int, part: int | str, input_data: str
|
||||
) -> None:
|
||||
t_1 = time.perf_counter_ns()
|
||||
result = f(input_data)
|
||||
t_2 = time.perf_counter_ns()
|
||||
|
||||
_pprint_result(year, day, part, result, t_2 - t_1)
|
||||
|
||||
|
||||
def run_day(year: int, day: int, input_data: str, path_base: pathlib.Path) -> None:
|
||||
try:
|
||||
module_path = path_base / f"year_{year}" / f"day_{day:02}.py"
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
f"year_{year}.day_{day:02}", module_path
|
||||
)
|
||||
if spec is None or spec.loader is None:
|
||||
raise exceptions.AocError()
|
||||
solution_module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(solution_module)
|
||||
except (ModuleNotFoundError, exceptions.AocError) as e:
|
||||
raise exceptions.AocError(
|
||||
f"solution module for {year}/{day:02} not found: run 'python main.py create --year {year} {day}'"
|
||||
) from e
|
||||
|
||||
p_1 = getattr(solution_module, "part_1", None)
|
||||
p_2 = getattr(solution_module, "part_2", None)
|
||||
|
||||
if p_1 is not None and p_2 is not None:
|
||||
_run_func(p_1, year, day, 1, input_data)
|
||||
_run_func(p_2, year, day, 2, input_data)
|
||||
return
|
||||
|
||||
p_1_2 = getattr(solution_module, "part_1_2", None)
|
||||
|
||||
if p_1_2 is not None:
|
||||
_run_func(p_1_2, year, day, "1&2", input_data)
|
||||
return
|
||||
|
||||
raise exceptions.AocError(
|
||||
f"{year}/{day:02} must define part_1 and part_2 or part_1_2"
|
||||
)
|
||||
Reference in New Issue
Block a user