-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbase.py
91 lines (60 loc) · 1.69 KB
/
base.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
from dataclasses import dataclass, field
from math import floor, log
import time
from traceback import format_exc
from puzzle_input import PuzzleInput
RED = '\033[91m'
GREEN = '\033[92m'
RESET = '\033[0m'
YELLOW = '\033[93m'
@dataclass
class Duration:
start: float
stop: float = field(default_factory=time.time)
precision: int = 4
width: int = 12
elapsed: float = None
_color: str = None
_factor: int = None
_scaled: float = None
_unit: float = None
def __post_init__(self):
self.elapsed = self.stop - self.start
power = floor(log(self.elapsed, 1000))
self._factor = 1000 ** power
self._scaled = self.elapsed / self._factor
unit = 'smu'[-power]
self._unit = 'sec' if unit == 's' else unit + 's '
self._color = [RED, YELLOW, GREEN][-power]
def __str__(self):
return ('{}{:>8.%sf} {:<3}{}' % self.precision).format(
self._color, self._scaled, self._unit, RESET
)
@dataclass
class Result:
elapsed: Duration
expected: int
input_name: str
observed: int | str
correct: None = None
def __post_init__(self):
self.correct = self.observed == self.expected
class Solution:
def parse(self, line: str) -> str:
return line
def solve(self, lines: list[str]) -> int:
raise NotImplementedError
def _solve(self, puzzle_input: PuzzleInput) -> Result:
lines = [self.parse(line) for line in puzzle_input.lines]
start = time.time()
try:
observed = self.solve(lines)
except Exception:
observed = format_exc()
end = time.time()
return Result(
elapsed=Duration(start, end),
expected=puzzle_input.solution,
input_name=puzzle_input.path.name,
observed=observed,
)