advent-of-code/2020/Python/day19.py

86 lines
2.5 KiB
Python
Raw Normal View History

2020-12-19 15:59:59 +01:00
import re
2020-12-19 16:54:17 +01:00
from functools import cache
2020-12-19 15:59:59 +01:00
def parse_data():
rules = {}
strings = []
with open("input.txt") as file:
for line in file:
line = line.rstrip()
if not line:
continue
if line[0].isdigit():
rule_id, rule_or = line.split(": ")
rule_id = int(rule_id)
rule_or = rule_or.split(" | ")
rule_entry = []
if rule_or[0][0] == '"':
rules[rule_id] = rule_or[0][1]
else:
for rule in rule_or:
rule_entry.append(list(map(int, rule.split(" "))))
rules[rule_id] = rule_entry
else:
strings.append(line)
return rules, strings
def solve_p1(rules, strings) -> int:
2020-12-19 16:54:17 +01:00
@cache
2020-12-19 16:51:36 +01:00
def convert_to_regex(rule_idx: int) -> str:
2020-12-19 15:59:59 +01:00
rule = rules[rule_idx]
if isinstance(rule, str):
return rule
else:
out = "("
for rule_option in rule:
2020-12-19 16:51:36 +01:00
out += "".join(map(convert_to_regex, rule_option)) + "|"
2020-12-19 15:59:59 +01:00
return out[:-1] + ")"
2020-12-19 16:51:36 +01:00
pattern_str = convert_to_regex(0)+"$"
pattern = re.compile(pattern_str)
matching = 0
for string in strings:
if pattern.match(string):
matching += 1
return matching
def solve_p2(rules, strings) -> int:
2020-12-19 16:54:17 +01:00
@cache
2020-12-19 16:51:36 +01:00
def convert_to_regex2(rule_idx: int) -> str:
rule = rules[rule_idx]
if isinstance(rule, str):
return rule
else:
out = "("
if rule_idx not in [8, 11]:
for rule_option in rule:
for index in rule_option:
out += convert_to_regex2(index)
out += "|"
return out[:-1] + ")"
elif rule_idx == 8:
return out + convert_to_regex2(42) + "+)"
2020-12-19 16:54:17 +01:00
elif rule_idx == 11: # I'm not proud of this at all, but it worked
2020-12-19 16:51:36 +01:00
return out + convert_to_regex2(42) + f"({convert_to_regex2(42)}({convert_to_regex2(42)}({convert_to_regex2(42)}{convert_to_regex2(31)})?{convert_to_regex2(31)})?{convert_to_regex2(31)})?" + convert_to_regex2(31) + ")"
pattern_str = convert_to_regex2(0) + "$"
2020-12-19 15:59:59 +01:00
pattern = re.compile(pattern_str)
matching = 0
for string in strings:
if pattern.match(string):
matching += 1
return matching
RULES, STRINGS = parse_data()
print(solve_p1(RULES, STRINGS))
2020-12-19 16:51:36 +01:00
print(solve_p2(RULES, STRINGS))