You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
44 lines
1.1 KiB
44 lines
1.1 KiB
#!/usr/bin/env python3
|
|
|
|
import sys
|
|
import re
|
|
|
|
def parse_rules(lines):
|
|
rules = {}
|
|
for line in lines:
|
|
rule, pattern = line.split(':')
|
|
alternatives = pattern.split('|')
|
|
rules[int(rule)] = [a.strip(' ').split(' ') for a in alternatives]
|
|
return rules
|
|
|
|
def memo(f):
|
|
mem = {}
|
|
def helper(x):
|
|
if x not in mem: mem[x] = f(x)
|
|
return mem[x]
|
|
return helper
|
|
|
|
@memo
|
|
def expr(rule):
|
|
if rule == 8:
|
|
return expr(42) + '+'
|
|
if rule == 11:
|
|
return '(?:' + expr(42) + '(?=a*(\1?+b)b*(\2?+c)))+\1' + expr(31) + ')'
|
|
global rules
|
|
if type(rule) is str:
|
|
try: rule = int(rule)
|
|
except ValueError: return rule[1]
|
|
pattern = rules[rule]
|
|
res = ["".join(expr(dep) for dep in alt) for alt in pattern]
|
|
if len(res) == 1: return res[0]
|
|
return "(" + "|".join(res) + ")"
|
|
|
|
if __name__ == '__main__':
|
|
rules, messages = open(sys.argv[1]).read().split('\n\n')
|
|
rules = parse_rules(rules.split('\n'))
|
|
count = 0
|
|
messages = messages.split("\n")
|
|
for m in messages:
|
|
if bool(re.match('^' + expr(0) + '$', m)):
|
|
count += 1
|
|
print(count)
|
|
|