68 lines
1.9 KiB
Python
68 lines
1.9 KiB
Python
|
# /usr/bin/env python3
|
||
|
import re
|
||
|
from collections import defaultdict
|
||
|
|
||
|
"""
|
||
|
identify invalid nearby tickets by considering only whether tickets contain values that are not valid for any field.
|
||
|
"""
|
||
|
|
||
|
|
||
|
def main():
|
||
|
rules, my_ticket, tickets = open("input.txt").read().split("\n\n")
|
||
|
rules = parse_fields(rules)
|
||
|
tickets = tickets.splitlines()[1:]
|
||
|
print("Ticket scanning error rate ", part1(tickets, rules))
|
||
|
part2(tickets, rules)
|
||
|
|
||
|
|
||
|
def parse_fields(fields):
|
||
|
fields_dict = {}
|
||
|
for field in fields.splitlines():
|
||
|
k, v = field.split(": ")
|
||
|
ranges = re.findall(r"(\d+)-(\d+)", v)
|
||
|
fields_dict[k] = [range(int(r[0]), int(r[1]) + 1) for r in ranges]
|
||
|
return fields_dict
|
||
|
|
||
|
|
||
|
def part1(tickets, rules):
|
||
|
scanning_error_rate = 0
|
||
|
for ticket in tickets:
|
||
|
scanning_error_rate += sum(validate_ticket(ticket, rules))
|
||
|
return scanning_error_rate
|
||
|
|
||
|
|
||
|
def validate_ticket(ticket, rules):
|
||
|
invalid_fields = []
|
||
|
for value in ticket.split(","):
|
||
|
value = int(value)
|
||
|
validations = (any(value in r for r in rule) for rule in rules.values())
|
||
|
if not any(validations):
|
||
|
invalid_fields.append(value)
|
||
|
return invalid_fields
|
||
|
|
||
|
|
||
|
def part2(tickets, rules):
|
||
|
# filter only valid tickets
|
||
|
valid_tickets = [ticket for ticket in tickets if validate_ticket(ticket, rules) == []]
|
||
|
|
||
|
# field => [matching_rules]
|
||
|
# eliminate field with only one matching rule
|
||
|
all_matching_rules = {}
|
||
|
for ticket in valid_tickets:
|
||
|
possible_matching_rules = defaultdict(set)
|
||
|
for field_index, field_value in enumerate(ticket.split(",")):
|
||
|
field_value = int(field_value)
|
||
|
for name, rule in rules.items():
|
||
|
match = {r: field_value in r for r in rule}
|
||
|
if any(match.values()):
|
||
|
possible_matching_rules[name].add(field_index)
|
||
|
all_matching_rules[ticket]= possible_matching_rules
|
||
|
a = 1
|
||
|
|
||
|
# repeat
|
||
|
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|