Comply with mypy conventions
This commit is contained in:
parent
6a514d342f
commit
5e76b029a0
113
src/Year_2020/P19.py
Normal file
113
src/Year_2020/P19.py
Normal file
@ -0,0 +1,113 @@
|
||||
# --- Day 19: Monster Messages ---
|
||||
|
||||
# You land in an airport surrounded by dense forest. As you walk to your high
|
||||
# speed train, the Elves at the Mythical Information Bureau contact you again.
|
||||
# They think their satellite has collected an image of a sea monster!
|
||||
# Unfortunately, the connection to the satellite is having problems, and many
|
||||
# of the messages sent back from the satellite have been corrupted.
|
||||
|
||||
# They sent you a list of the rules valid messages should obey and a list of
|
||||
# received messages they've collected so far (your puzzle input).
|
||||
|
||||
# The rules for valid messages (the top part of your puzzle input) are numbered
|
||||
# and build upon each other. For example:
|
||||
|
||||
# 0: 1 2
|
||||
# 1: "a"
|
||||
# 2: 1 3 | 3 1
|
||||
# 3: "b"
|
||||
|
||||
# Some rules, like 3: "b", simply match a single character (in this case, b).
|
||||
|
||||
# The remaining rules list the sub-rules that must be followed; for example,
|
||||
# the rule 0: 1 2 means that to match rule 0, the text being checked must match
|
||||
# rule 1, and the text after the part that matched rule 1 must then match rule
|
||||
# 2.
|
||||
|
||||
# Some of the rules have multiple lists of sub-rules separated by a pipe (|).
|
||||
# This means that at least one list of sub-rules must match. (The ones that
|
||||
# match might be different each time the rule is encountered.) For example, the
|
||||
# rule 2: 1 3 | 3 1 means that to match rule 2, the text being checked must
|
||||
# match rule 1 followed by rule 3 or it must match rule 3 followed by rule 1.
|
||||
|
||||
# Fortunately, there are no loops in the rules, so the list of possible matches
|
||||
# will be finite. Since rule 1 matches a and rule 3 matches b, rule 2 matches
|
||||
# either ab or ba. Therefore, rule 0 matches aab or aba.
|
||||
|
||||
# Here's a more interesting example:
|
||||
|
||||
# 0: 4 1 5
|
||||
# 1: 2 3 | 3 2
|
||||
# 2: 4 4 | 5 5
|
||||
# 3: 4 5 | 5 4
|
||||
# 4: "a"
|
||||
# 5: "b"
|
||||
|
||||
# Here, because rule 4 matches a and rule 5 matches b, rule 2 matches two
|
||||
# letters that are the same (aa or bb), and rule 3 matches two letters that are
|
||||
# different (ab or ba).
|
||||
|
||||
# Since rule 1 matches rules 2 and 3 once each in either order, it must match
|
||||
# two pairs of letters, one pair with matching letters and one pair with
|
||||
# different letters. This leaves eight possibilities: aaab, aaba, bbab, bbba,
|
||||
# abaa, abbb, baaa, or babb.
|
||||
|
||||
# Rule 0, therefore, matches a (rule 4), then any of the eight options from
|
||||
# rule 1, then b (rule 5): aaaabb, aaabab, abbabb, abbbab, aabaab, aabbbb,
|
||||
# abaaab, or ababbb.
|
||||
|
||||
# The received messages (the bottom part of your puzzle input) need to be
|
||||
# checked against the rules so you can determine which are valid and which are
|
||||
# corrupted. Including the rules and the messages together, this might look
|
||||
# like:
|
||||
|
||||
# 0: 4 1 5
|
||||
# 1: 2 3 | 3 2
|
||||
# 2: 4 4 | 5 5
|
||||
# 3: 4 5 | 5 4
|
||||
# 4: "a"
|
||||
# 5: "b"
|
||||
|
||||
# ababbb
|
||||
# bababa
|
||||
# abbbab
|
||||
# aaabbb
|
||||
# aaaabbb
|
||||
|
||||
# Your goal is to determine the number of messages that completely match rule
|
||||
# 0. In the above example, ababbb and abbbab match, but bababa, aaabbb, and
|
||||
# aaaabbb do not, producing the answer 2. The whole message must match all of
|
||||
# rule 0; there can't be extra unmatched characters in the message. (For
|
||||
# example, aaaabbb might appear to match rule 0 above, but it has an extra
|
||||
# unmatched b on the end.)
|
||||
|
||||
# How many messages completely match rule 0?
|
||||
|
||||
import re
|
||||
|
||||
with open("files/P19.txt", "r") as f:
|
||||
rules, messages = [f.split("\n") for f in f.read().strip().split("\n\n")]
|
||||
|
||||
|
||||
def dfs(tree, node, depth):
|
||||
rule = ""
|
||||
for next in tree[node].split():
|
||||
if next == "|":
|
||||
rule += next
|
||||
elif next.isdigit():
|
||||
rule += dfs(tree, next, depth + 1)
|
||||
else:
|
||||
return next[1]
|
||||
return "(" + rule + ")"
|
||||
|
||||
|
||||
def part_1():
|
||||
rules_dict = dict([rule.split(": ") for rule in rules])
|
||||
rule_0 = re.compile(dfs(rules_dict, "0", 0))
|
||||
total = sum([1 for message in messages if rule_0.fullmatch(message)])
|
||||
|
||||
print(f"There are {total} messages completely matching rule 0")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
part_1()
|
Loading…
Reference in New Issue
Block a user