1from typing import Iterator
2
3
4class RunewordEntry:
5 def __init__(self, name: str, recipe: tuple[str, ...]) -> None:
6 self.name: str = name
7 self.recipe: tuple[str, ...] = tuple(recipe)
8 self.progress: int = 0
9
10 @property
11 def fully_matched(self) -> bool:
12 return self.progress == len(self.recipe)
13
14 def advance(self, rune: str) -> None:
15 if not self.fully_matched and rune == self.recipe[self.progress]:
16 self.progress += 1
17
18
19class RunewordsCalculator:
20 def __init__(self, runewords: dict[str, tuple[str, ...]]) -> None:
21 self._entries: list[RunewordEntry] = [RunewordEntry(name, recipe) for name, recipe in runewords.items()]
22 self._returned: set[int] = set()
23
24 def __iter__(self) -> Iterator[str | None]:
25 return self
26
27 def __next__(self) -> str | None:
28 if len(self._returned) == len(self._entries):
29 raise StopIteration
30
31 for idx, entry in enumerate(self._entries):
32 if idx in self._returned:
33 continue
34 if entry.fully_matched:
35 self._returned.add(idx)
36 return entry.name
37
38 return None
39
40 def add_runes(self, runes: list[str]) -> None:
41 for rune in runes:
42 for entry in self._entries:
43 entry.advance(rune)
.......
----------------------------------------------------------------------
Ran 7 tests in 0.000s
OK