updated AOCDay Interface
This commit is contained in:
parent
709b0f471b
commit
117eeec768
74
tools/aoc.py
74
tools/aoc.py
@ -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
35
tools/stopwatch.py
Normal 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])
|
||||
Loading…
Reference in New Issue
Block a user