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
|
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
|
from .tools import get_script_dir
|
||||||
|
|
||||||
BASE_PATH = get_script_dir()
|
BASE_PATH = get_script_dir()
|
||||||
@ -8,14 +9,13 @@ INPUTS_PATH = os.path.join(BASE_PATH, 'inputs')
|
|||||||
|
|
||||||
class AOCDay:
|
class AOCDay:
|
||||||
day: int
|
day: int
|
||||||
input: List # our input is always a list of str/lines
|
input: List[str] # our input is always a list of str/lines
|
||||||
test_solutions_p1: List
|
inputs: List[List[Tuple[Any, str]]]
|
||||||
test_solutions_p2: List
|
part_func: List[Callable]
|
||||||
|
|
||||||
def __init__(self, day: int):
|
def __init__(self, day: int):
|
||||||
self.day = day
|
self.day = day
|
||||||
with open(os.path.join(INPUTS_PATH, "input%02d" % day)) as f:
|
self.part_func = [self.part1, self.part2]
|
||||||
self.input = f.read().splitlines()
|
|
||||||
|
|
||||||
def part1(self) -> Any:
|
def part1(self) -> Any:
|
||||||
pass
|
pass
|
||||||
@ -23,9 +23,55 @@ class AOCDay:
|
|||||||
def part2(self) -> Any:
|
def part2(self) -> Any:
|
||||||
pass
|
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:
|
def test_part1(self, silent: bool = False) -> bool:
|
||||||
live_input = self.input.copy()
|
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:
|
with open(os.path.join(INPUTS_PATH, "test_input%02d_1_%d" % (self.day, case))) as f:
|
||||||
self.input = f.read().splitlines()
|
self.input = f.read().splitlines()
|
||||||
|
|
||||||
@ -43,7 +89,7 @@ class AOCDay:
|
|||||||
|
|
||||||
def test_part2(self, silent: bool = False) -> bool:
|
def test_part2(self, silent: bool = False) -> bool:
|
||||||
live_input = self.input.copy()
|
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:
|
with open(os.path.join(INPUTS_PATH, "test_input%02d_2_%d" % (self.day, case))) as f:
|
||||||
self.input = f.read().splitlines()
|
self.input = f.read().splitlines()
|
||||||
|
|
||||||
@ -112,21 +158,15 @@ class AOCDay:
|
|||||||
return return_array
|
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:
|
if exec_time is None:
|
||||||
time_output = ""
|
time_output = ""
|
||||||
else:
|
else:
|
||||||
units = ['s', 'ms', 'µs', 'ns']
|
time_output = " (Average run time: %s)" % exec_time
|
||||||
unit = 0
|
|
||||||
while exec_time < 1:
|
|
||||||
exec_time *= 1000
|
|
||||||
unit += 1
|
|
||||||
|
|
||||||
time_output = " (Average run time: %1.2f%s)" % (exec_time, units[unit])
|
|
||||||
|
|
||||||
if test is not None:
|
if test is not None:
|
||||||
print(
|
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)
|
% ("OK" if test == solution else "FAIL", day, part, test_case, solution, test, time_output)
|
||||||
)
|
)
|
||||||
else:
|
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