lots of cleanup

This commit is contained in:
Ruediger Ludwig 2022-12-10 19:30:10 +01:00
parent 7d0d3e504e
commit 0385cbd62e
26 changed files with 337 additions and 417 deletions

View file

@ -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

View file

@ -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
View 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')

View file

@ -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

View file

@ -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