-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathregexp_hack.py
executable file
·83 lines (60 loc) · 1.65 KB
/
regexp_hack.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
#!/usr/bin/env python3
import re
import sys
def parse_input(fin):
rules = {}
for line in map(str.rstrip, fin):
if not line:
break
rule_id, options = line.split(': ')
rule_id = int(rule_id)
if '"' in options:
rule = options[1:-1]
else:
rule = []
for option in options.split('|'):
rule.append(tuple(map(int, option.split())))
rules[rule_id] = rule
return rules
def build_regexp(rules, rule=0):
rule = rules[rule]
if type(rule) is str:
return rule
options = []
for option in rule:
option = ''.join(build_regexp(rules, r) for r in option)
options.append(option)
return '(' + '|'.join(options) + ')'
def build_regexp_special(rules, rule=0):
if rule == 8:
return '(' + build_regexp_special(rules, 42) + ')+'
if rule == 11:
a = build_regexp_special(rules, 42)
b = build_regexp_special(rules, 31)
options = []
for n in range(1, 51):
options.append('{a}{{{n}}}{b}{{{n}}}'.format(a=a, b=b, n=n))
return '(' + '|'.join(options) + ')'
rule = rules[rule]
if type(rule) is str:
return rule
options = []
for option in rule:
option = ''.join(build_regexp_special(rules, r) for r in option)
options.append(option)
return '(' + '|'.join(options) + ')'
# Open the first argument as input or use stdin if no arguments were given
fin = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin
with fin:
rules = parse_input(fin)
rexp1 = re.compile('^' + build_regexp(rules) + '$')
rexp2 = re.compile('^' + build_regexp_special(rules) + '$')
valid1 = 0
valid2 = 0
for msg in map(str.rstrip, fin):
if rexp1.match(msg):
valid1 += 1
if rexp2.match(msg):
valid2 += 1
print('Part 1:', valid1)
print('Part 2:', valid2)