Day 19.1 test implementation Day 19.1 (Python) Day 19.2 (Python) Day 19 comments and formatting (Python) Day 19 READMEs
74 lines
1.8 KiB
Python
74 lines
1.8 KiB
Python
import re
|
|
from typing import Dict
|
|
import time
|
|
|
|
char_regex = re.compile(r"^\"([a-z])\"$") # group 1 contains interesting information
|
|
or_rule_regex = re.compile(r"^((\d+ ?)+) \| ((\d+ ?)+)$") # group 1 and 3 contain interesting info
|
|
single_rule_regex = re.compile(r"^((\d+ ?)+)$") # group 0 and 1 both contain the same interesting information
|
|
|
|
rules = {
|
|
0: "4 1 5",
|
|
1: "2 3 | 3 2",
|
|
2: "4 4 | 5 5",
|
|
3: "4 5 | 5 4",
|
|
4: "\"a\"",
|
|
5: "\"b\"",
|
|
}
|
|
|
|
def generate_compound_rule(ruleset:Dict[int, str], compound:str) -> str:
|
|
o = ""
|
|
for x in [int(a) for a in compound.split(" ")]:
|
|
o += generate_rule(ruleset, rule=x)
|
|
return o
|
|
|
|
|
|
memo = {}
|
|
|
|
|
|
def generate_rule(ruleset:Dict[int, str], rule:int=0) -> str:
|
|
|
|
if rule in memo:
|
|
return memo[rule]
|
|
|
|
output = ""
|
|
|
|
rule_content = ruleset[rule]
|
|
|
|
r = char_regex.match(rule_content)
|
|
if r:
|
|
# is a single character
|
|
return r.group(1)
|
|
|
|
# if we get here, that means there are multiple options for the rule
|
|
# hence we need to open a new set of brackets
|
|
output += "("
|
|
|
|
r = or_rule_regex.match(rule_content)
|
|
if r:
|
|
# rule is an OR rule
|
|
output += generate_compound_rule(ruleset, r.group(1))
|
|
output += "|"
|
|
output += generate_compound_rule(ruleset, r.group(3))
|
|
|
|
r = single_rule_regex.match(rule_content)
|
|
if r:
|
|
# rule is a simple sequence rule
|
|
output += generate_compound_rule(ruleset, r.group(1))
|
|
|
|
# close original set of brackets
|
|
output += ")"
|
|
|
|
memo[rule] = output
|
|
|
|
return output
|
|
|
|
|
|
rules, _ = open("input.txt").read().strip().split("\n\n")
|
|
|
|
rules_dict = {}
|
|
for x in rules.split("\n"):
|
|
num, definition = x.split(":")
|
|
rules_dict[int(num.strip())] = definition.strip()
|
|
|
|
res = generate_rule(rules_dict)
|
|
print("^" + res + "$")
|