updated AOCDay Interface

This commit is contained in:
Stefan Harmuth 2021-12-27 16:29:46 +01:00
parent 709b0f471b
commit 117eeec768
2 changed files with 92 additions and 17 deletions

View File

@ -1,5 +1,6 @@
import os
from typing import List, Any, Type, Union
from tools.stopwatch import StopWatch
from typing import Any, Callable, Dict, List, Tuple, Type, Union
from .tools import get_script_dir
BASE_PATH = get_script_dir()
@ -8,14 +9,13 @@ INPUTS_PATH = os.path.join(BASE_PATH, 'inputs')
class AOCDay:
day: int
input: List # our input is always a list of str/lines
test_solutions_p1: List
test_solutions_p2: List
input: List[str] # our input is always a list of str/lines
inputs: List[List[Tuple[Any, str]]]
part_func: List[Callable]
def __init__(self, day: int):
self.day = day
with open(os.path.join(INPUTS_PATH, "input%02d" % day)) as f:
self.input = f.read().splitlines()
self.part_func = [self.part1, self.part2]
def part1(self) -> Any:
pass
@ -23,9 +23,55 @@ class AOCDay:
def part2(self) -> Any:
pass
def runPart(self, part: int, verbose: bool = False, measure_runtime: bool = False, timeit_number: int = 50):
case_count = 0
for solution, input_file in self.inputs[part]:
exec_time = None
answer = None
self._loadInput(input_file)
if not measure_runtime or case_count < len(self.input[part]) - 1:
answer = self.part_func[part]()
else:
stopwatch = StopWatch()
for _ in range(timeit_number):
answer = self.part_func[part]()
stopwatch.stop()
exec_time = str(stopwatch)
if solution is None:
printSolution(self.day, part + 1, answer, solution, case_count, exec_time)
# FIXME: self._submit(part + 1, answer)
else:
if verbose or answer != solution:
printSolution(self.day, part + 1, answer, solution, case_count, exec_time)
if answer != solution:
return False
case_count += 1
if case_count == len(self.inputs[part]) and not verbose:
printSolution(self.day, part + 1, answer, exec_time=exec_time)
def run(self, parts: int = 3, verbose: bool = False, measure_runtime: bool = False, timeit_number: int = 50):
if parts & 1:
self.runPart(0, verbose, measure_runtime, timeit_number)
if parts & 2:
self.runPart(1, verbose, measure_runtime, timeit_number)
def _loadInput(self, filename):
with open(os.path.join(INPUTS_PATH, filename)) as f:
self.input = f.read().splitlines()
def _downloadInput(self, filename):
pass
def _submit(self, answer):
pass
def test_part1(self, silent: bool = False) -> bool:
live_input = self.input.copy()
for case, solution in enumerate(self.test_solutions_p1):
for case, solution in enumerate(self.inputs_p1):
with open(os.path.join(INPUTS_PATH, "test_input%02d_1_%d" % (self.day, case))) as f:
self.input = f.read().splitlines()
@ -43,7 +89,7 @@ class AOCDay:
def test_part2(self, silent: bool = False) -> bool:
live_input = self.input.copy()
for case, solution in enumerate(self.test_solutions_p2):
for case, solution in enumerate(self.inputs_p2):
with open(os.path.join(INPUTS_PATH, "test_input%02d_2_%d" % (self.day, case))) as f:
self.input = f.read().splitlines()
@ -112,21 +158,15 @@ class AOCDay:
return return_array
def printSolution(day: int, part: int, solution: Any, test: Any = None, test_case: int = 0, exec_time: float = None):
def printSolution(day: int, part: int, solution: Any, test: Any = None, test_case: int = 0, exec_time: str = None):
if exec_time is None:
time_output = ""
else:
units = ['s', 'ms', 'µs', 'ns']
unit = 0
while exec_time < 1:
exec_time *= 1000
unit += 1
time_output = " (Average run time: %1.2f%s)" % (exec_time, units[unit])
time_output = " (Average run time: %s)" % exec_time
if test is not None:
print(
"%s (TEST day%d/part%d/case%d) -- got '%s' -- expected '%s'%s"
"%s (TEST day%d/part%d/case%d): got '%s'; expected '%s'%s"
% ("OK" if test == solution else "FAIL", day, part, test_case, solution, test, time_output)
)
else:

35
tools/stopwatch.py Normal file
View File

@ -0,0 +1,35 @@
from time import time
from .types import FloatOrNone
class StopWatch:
started: FloatOrNone = None
stopped: FloatOrNone = None
def __init__(self, auto_start=True):
if auto_start:
self.start()
def start(self):
self.started = time()
self.stopped = None
def stop(self) -> float:
self.stopped = time()
return self.elapsed()
def elapsed(self) -> float:
if self.stopped is None:
return time() - self.started
else:
return self.stopped - self.started
def __str__(self):
units = ['s', 'ms', 'µs', 'ns']
unit = 0
elapsed = self.elapsed()
while elapsed < 1:
elapsed *= 1000
unit += 1
return "%1.2f%s" % (elapsed, units[unit])