This repository was archived by the owner on May 13, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathpart2.py
129 lines (103 loc) · 2.47 KB
/
part2.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import argparse
import os.path
import re
import pytest
from support import timing
INPUT_TXT = os.path.join(os.path.dirname(__file__), 'input.txt')
def compute(s: str) -> int:
rules, lines = s.split('\n\n')
rules_s = {}
for line in rules.splitlines():
k, _, v = line.partition(': ')
rules_s[k] = v
def _get_re(s: str) -> str:
if s == '|':
return s
rule_s = rules_s[s]
if rule_s.startswith('"'):
return rule_s.strip('"')
else:
return f'({"".join(_get_re(part) for part in rule_s.split())})'
re_42 = re.compile(_get_re('42'))
re_31 = re.compile(_get_re('31'))
count = 0
for line in lines.splitlines():
pos = 0
count_42 = 0
while match := re_42.match(line, pos):
count_42 += 1
pos = match.end()
count_31 = 0
while match := re_31.match(line, pos):
count_31 += 1
pos = match.end()
if 0 < count_31 < count_42 and pos == len(line):
count += 1
return count
INPUT_S = '''\
42: 9 14 | 10 1
9: 14 27 | 1 26
10: 23 14 | 28 1
1: "a"
11: 42 31
5: 1 14 | 15 1
19: 14 1 | 14 14
12: 24 14 | 19 1
16: 15 1 | 14 14
31: 14 17 | 1 13
6: 14 14 | 1 14
2: 1 24 | 14 4
0: 8 11
13: 14 3 | 1 12
15: 1 | 14
17: 14 2 | 1 7
23: 25 1 | 22 14
28: 16 1
4: 1 1
20: 14 14 | 1 15
3: 5 14 | 16 1
27: 1 6 | 14 18
14: "b"
21: 14 1 | 1 14
25: 1 1 | 1 14
22: 14 14
8: 42
26: 14 22 | 1 20
18: 15 15
7: 14 5 | 1 21
24: 14 1
abbbbbabbbaaaababbaabbbbabababbbabbbbbbabaaaa
bbabbbbaabaabba
babbbbaabbbbbabbbbbbaabaaabaaa
aaabbbbbbaaaabaababaabababbabaaabbababababaaa
bbbbbbbaaaabbbbaaabbabaaa
bbbababbbbaaaaaaaabbababaaababaabab
ababaaaaaabaaab
ababaaaaabbbaba
baabbaaaabbaaaababbaababb
abbbbabbbbaaaababbbbbbaaaababb
aaaaabbaabaaaaababaa
aaaabbaaaabbaaa
aaaabbaabbaaaaaaabbbabbbaaabbaabaaa
babaaabbbaaabaababbaabababaaab
aabbbbbaabbbaaaaaabbbbbababaaaaabbaaabba
'''
INPUT_2_S = INPUT_S.split('\n\n')[0] + '\n\naaaabbaaaabbaaa'
@pytest.mark.parametrize(
('input_s', 'expected'),
(
(INPUT_S, 12),
(INPUT_2_S, 0),
),
)
def test(input_s: str, expected: int) -> None:
assert compute(input_s) == expected
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument('data_file', nargs='?', default=INPUT_TXT)
args = parser.parse_args()
with open(args.data_file) as f, timing():
print(compute(f.read()))
return 0
if __name__ == '__main__':
exit(main())