Skip to content

Commit 00af4f7

Browse files
committed
Everybody Codes: tidy 2025/07
1 parent 9f6d493 commit 00af4f7

1 file changed

Lines changed: 22 additions & 13 deletions

File tree

everybody_codes/event2025/quest_07.py

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,41 @@
22

33
import collections
44
import functools
5+
import typing
56
from lib import parsers
67

78

8-
def solve(part: int, data: str) -> int:
9+
def solve(part: int, data: list[list[str | list[str]]]) -> int | str:
910
"""Solve the parts."""
10-
rev_pairs = collections.defaultdict(set)
11-
pairs = collections.defaultdict(set)
12-
for line in data.split("\n\n")[1].splitlines():
13-
a, b = line.split(" > ")
11+
names, rules = typing.cast(tuple[list[str], list[list[str]]], data)
12+
13+
# Parse the rules into maps.
14+
rule_prior = collections.defaultdict(set)
15+
rule_next = collections.defaultdict(set)
16+
for a, b in rules:
1417
for c in b.split(","):
15-
pairs[a].add(c)
16-
rev_pairs[c].add(a)
18+
rule_next[a].add(c)
19+
rule_prior[c].add(a)
1720

1821
@functools.cache
1922
def possibilities(size: int, letter: str) -> int:
23+
"""Count the number of possible names that can be formed."""
2024
if size == 11:
2125
return 1
2226
count = 0 if size < 7 else 1
2327
size += 1
24-
return count + sum(possibilities(size, i) for i in pairs[letter])
28+
return count + sum(possibilities(size, i) for i in rule_next[letter])
2529

26-
total = 0
27-
names = data.split("\n\n")[0].split(",")
30+
# Dedupe names which have a prefix also included.
2831
if part == 3:
29-
names = set(names)
30-
names = {n for n in names if not any(n != m and n.startswith(m) for m in names)}
32+
filtered = set(names)
33+
filtered = {n for n in names if not any(n != m and n.startswith(m) for m in names)}
34+
names = list(filtered)
3135

36+
total = 0
3237
for idx, name in enumerate(names, start=1):
3338
for a, b in zip(name, name[1:]):
34-
if a not in rev_pairs[b]:
39+
if a not in rule_prior[b]:
3540
break
3641
else:
3742
if part == 1:
@@ -43,6 +48,10 @@ def possibilities(size: int, letter: str) -> int:
4348
return total
4449

4550

51+
PARSER = parsers.ParseBlocks([
52+
parsers.ParseMultiWords(str, separator=","),
53+
parsers.BaseParseMultiPerLine(word_separator=" > "),
54+
])
4655
TEST_DATA = [
4756
"""\
4857
Oronris,Urakris,Oroneth,Uraketh

0 commit comments

Comments
 (0)