lots of cleanup
This commit is contained in:
parent
7d0d3e504e
commit
0385cbd62e
26 changed files with 337 additions and 417 deletions
|
|
@ -1,37 +0,0 @@
|
|||
from typing import Iterable, Iterator
|
||||
|
||||
from .provider import EofException, Provider
|
||||
|
||||
|
||||
class CharProvider(Provider[str]):
|
||||
data: Iterator[str]
|
||||
|
||||
def __init__(self, data: Iterator[str] | Iterable[str]) -> None:
|
||||
if isinstance(data, Iterator):
|
||||
self.data = data
|
||||
else:
|
||||
self.data = iter(data)
|
||||
self.peeked: list[str] = []
|
||||
|
||||
def _ensure_next(self) -> str:
|
||||
if not self.peeked:
|
||||
try:
|
||||
self.peeked = [next(self.data)]
|
||||
except StopIteration:
|
||||
raise EofException() from None
|
||||
return self.peeked[0]
|
||||
|
||||
def peek(self) -> str:
|
||||
return self._ensure_next()
|
||||
|
||||
def get(self) -> str:
|
||||
result = self._ensure_next()
|
||||
self.peeked = self.peeked[1:]
|
||||
return result
|
||||
|
||||
def finished(self) -> bool:
|
||||
try:
|
||||
self._ensure_next()
|
||||
return False
|
||||
except EofException:
|
||||
return True
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
from advent.common.provider import EofException
|
||||
from .char_provider import CharProvider
|
||||
|
||||
|
||||
class ReaderException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class CharReader:
|
||||
@staticmethod
|
||||
def read_word(provider: CharProvider, word: str) -> str:
|
||||
result = ''
|
||||
for expected_char in word:
|
||||
try:
|
||||
char = provider.get()
|
||||
if char == expected_char:
|
||||
result += char
|
||||
else:
|
||||
raise ReaderException(f'Expected {word} but received {result}{char}')
|
||||
except EofException:
|
||||
raise ReaderException(f'Expected {word} but received {result}[EOF]')
|
||||
|
||||
return word
|
||||
|
||||
@staticmethod
|
||||
def read_unsigned_int(provider: CharProvider) -> int:
|
||||
if not provider.peek().isdigit():
|
||||
raise ReaderException('Expected unsigned int')
|
||||
|
||||
number = 0
|
||||
while not provider.finished() and provider.peek().isdigit():
|
||||
number = number * 10 + int(provider.get())
|
||||
return number
|
||||
19
advent/common/input.py
Normal file
19
advent/common/input.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
from pathlib import Path, PurePath
|
||||
from typing import Iterator, TypeVar
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
def read_lines(day: int, file_name: str) -> Iterator[str]:
|
||||
'''
|
||||
Returns an iterator over the content of the mentioned file
|
||||
All lines are striped of an eventual trailing '\n' their
|
||||
'''
|
||||
with open(
|
||||
Path.cwd()
|
||||
/ PurePath('advent/days/day{0:02}/data'.format(day))
|
||||
/ PurePath(file_name),
|
||||
'rt',
|
||||
) as file:
|
||||
while line := file.readline():
|
||||
yield line.rstrip('\n')
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
from abc import abstractmethod
|
||||
from typing import Iterable, Iterator, Protocol, TypeVar
|
||||
|
||||
|
||||
T = TypeVar('T', covariant=True)
|
||||
|
||||
|
||||
class EofException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Provider(Iterator[T], Iterable[T], Protocol[T]):
|
||||
@abstractmethod
|
||||
def peek(self) -> T:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def get(self) -> T:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def finished(self) -> bool:
|
||||
...
|
||||
|
||||
def __next__(self) -> T:
|
||||
if self.finished():
|
||||
raise StopIteration()
|
||||
return self.get()
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
from pathlib import Path, PurePath
|
||||
from typing import Callable, Generator, Iterator, ParamSpec, TypeVar
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
def read_data(day: int, file_name: str) -> Iterator[str]:
|
||||
'''
|
||||
Returns an iterator over the content of the mentioned file
|
||||
All lines are striped of an eventual trailing '\n' their
|
||||
'''
|
||||
with open(
|
||||
Path.cwd()
|
||||
/ PurePath('advent/days/day{0:02}/data'.format(day))
|
||||
/ PurePath(file_name),
|
||||
'rt',
|
||||
) as file:
|
||||
while True:
|
||||
line = file.readline()
|
||||
if line:
|
||||
yield line if line[-1] != '\n' else line[:-1]
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
def split_set(full_set: set[T], predicate: Callable[[T], bool]) -> tuple[set[T], set[T]]:
|
||||
''' Splits a set in two sorted by the predicate '''
|
||||
true_set: set[T] = set()
|
||||
false_set: set[T] = set()
|
||||
for item in full_set:
|
||||
(true_set if predicate(item) else false_set).add(item)
|
||||
return true_set, false_set
|
||||
|
||||
|
||||
P = ParamSpec('P')
|
||||
Y = TypeVar('Y')
|
||||
S = TypeVar('S')
|
||||
R = TypeVar('R')
|
||||
|
||||
|
||||
def coroutine(func: Callable[P, Generator[Y, S, R]]) -> Callable[P, Generator[Y, S, R]]:
|
||||
def start(*args: P.args, **kwargs: P.kwargs) -> Generator[Y, S, R]:
|
||||
cr = func(*args, **kwargs)
|
||||
next(cr)
|
||||
return cr
|
||||
return start
|
||||
Loading…
Add table
Add a link
Reference in a new issue