diff --git a/2020/day19.py b/2020/day19.py new file mode 100644 index 0000000..d95a67c --- /dev/null +++ b/2020/day19.py @@ -0,0 +1,60 @@ +import re +import sys + + +rules, frules, messages = {}, {}, [] +srules = {} + + +def main(): + lines = [line.rstrip() for line in sys.stdin] + step = 0 + for line in lines: + if not line: + step += 1 + continue + if step == 0: + rid, rcontent = line.split(": ") + if '"' in rcontent: + frules[int(rid)] = rcontent.strip('"') + else: + rules[int(rid)] = tuple(map( + lambda seq: tuple(map(int, seq.split())), + rcontent.split(" | ") + )) + else: + messages.append(line) + + # Part 1 + rule_0 = re.compile("^" + get_regex(0) + "$") + valids = list(filter(lambda m: rule_0.match(m) is not None, messages)) + print("Num valids:", len(valids)) + + # Part 2 + del rules[8] + rule_42 = get_regex(42) + srules[8] = rule_42 + "+" + del rules[11] + rule_31 = get_regex(31) + srules[11] = "(" + "|".join( + f"{rule_42}{{{i}}}{rule_31}{{{i}}}" + for i in range(1, 10) # haha + ) + ")" + rule_0 = re.compile("^" + get_regex(0) + "$") + valids = list(filter(lambda m: rule_0.match(m) is not None, messages)) + print("Num valids with fake loop:", len(valids)) + + +def get_regex(rule_id): + if (char := frules.get(rule_id)): + return char + if (regex := srules.get(rule_id)): + return regex + seq_res = [] + for seq in rules[rule_id]: + seq_res.append("".join(get_regex(r) for r in seq)) + return f"({'|'.join(seq_res)})" + + +if __name__ == "__main__": + main()