-
Notifications
You must be signed in to change notification settings - Fork 0
/
19.2.py
56 lines (45 loc) · 1.3 KB
/
19.2.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
import re
with open('input/19.txt') as f:
content = f.read().split("\n\n")
rules = content[0].split("\n")
messages = content[1].split("\n")
def make_regex(rules, chars, i, depth=0):
# base rule
if i in chars:
return chars[i]
# lol
if depth == 14:
return ''
terms = []
# make a regex with ORs
for term in rules[i]:
terms.append(''.join(make_regex(rules, chars, t, depth+1) for t in term))
return '(' + '|'.join(terms) + ')'
def parse_into_regex(rules):
parsed_rules = {}
characters = {}
# go through all rules and build up lists of terms
for r in rules:
i, rule = r.split(': ')
i = int(i)
# convert new rules
if i == 8:
rule = '42 | 42 8'
elif i == 11:
rule = '42 31 | 42 11 31'
# save our direct characters
if '"' in rule:
characters[i] = rule[1]
continue
# get the terms grouped on either side of the OR
for side in rule.split('|'):
terms = []
for term in side.strip().split(' '):
terms.append(int(term))
if i not in parsed_rules:
parsed_rules[i] = []
parsed_rules[i].append(terms)
# print(parsed_rules, characters)
return make_regex(parsed_rules, characters, 0)
regex = parse_into_regex(rules)
print(len([match for match in messages if re.match('^' + regex + '$', match)]))