Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """Day 16 of Advent of Code 2020 Solution"""
- from itertools import chain
- import re
- def ticket_io(file_location):
- with open(file_location, "r") as f:
- data = f.read().split("\n\n")
- fields = {}
- for row in data[0].split("\n"):
- row = row.split(":")
- row_name = row[0]
- pattern = r"(\d+-\d+)"
- v_pairs = []
- for l_h in re.findall(pattern, row[1]):
- low, high = l_h.split("-")
- low, high = int(low), int(high)
- v_pairs.append((low, high))
- fields[row_name] = v_pairs
- my_ticket = [int(i) for i in data[1].split("\n")[1].split(",")]
- nearby_tickets = []
- for ticket in data[2].split("\n")[1:]:
- nearby_tickets.append([int(i) for i in ticket.split(",")])
- return {"fields": fields, "my_ticket": my_ticket, "nearby_tickets": nearby_tickets}
- def validate_tickets(ticket_info) -> list[list[int]]:
- validated_nearby_tickets = []
- field_ranges = [*chain.from_iterable(ticket_info["fields"].values())]
- for ticket in ticket_info["nearby_tickets"]:
- ticket_val_bool = [False] * len(ticket)
- for i, val in enumerate(ticket):
- field_range_bool = [False] * len(field_ranges)
- for j, r in enumerate(field_ranges):
- if r[0] <= val <= r[1]:
- field_range_bool[j] = True
- if any(field_range_bool):
- ticket_val_bool[i] = True
- if all(ticket_val_bool):
- validated_nearby_tickets.append(ticket)
- return validated_nearby_tickets
- def part_a(file_location):
- pattern = r"(\d+-\d+)"
- with open(file_location, "r") as f:
- data = f.read().split("\n\n")
- v_pairs = []
- for v in data[0].split("\n"):
- for l_h in re.findall(pattern, v):
- low, high = l_h.split("-")
- low, high = int(low), int(high)
- v_pairs.append((low, high))
- error_rate = 0
- for ticket in data[2].split("\n")[1:]:
- for val in [int(i) for i in ticket.strip().split(",")]:
- found = [False] * len(v_pairs)
- for i, pair in enumerate(v_pairs):
- if pair[0] <= val <= pair[1]:
- found[i] = True
- if not any(found):
- error_rate += val
- return error_rate
- def value_in_field(field, val) -> bool:
- val_bool = [False] * len(val)
- for i, val in enumerate(val):
- field_bool = [False] * len(field)
- for j, field_range in enumerate(field):
- if field_range[0] <= val <= field_range[1]:
- field_bool[j] = True
- if any(field_bool):
- val_bool[i] = True
- return all(val_bool)
- def part_b(file_location):
- ticket_info = ticket_io(file_location)
- valid_tickets = validate_tickets(ticket_info)
- ticket_len = len(valid_tickets[0])
- field_position = {field: [] for field in ticket_info["fields"].keys()}
- available_fields = {*ticket_info["fields"].keys()}
- found_positions = set()
- while available_fields:
- for position in range(ticket_len):
- if position not in found_positions:
- ticket_position_vals = [v[position] for v in valid_tickets]
- for field in available_fields:
- if value_in_field(
- ticket_info["fields"][field], ticket_position_vals
- ):
- field_position[field].append(position)
- for field in field_position:
- if field in available_fields:
- if len(field_position[field]) == 1:
- available_fields.remove(field)
- found_positions.add(field_position[field][0])
- else:
- field_position[field] = []
- departure_fields = [field for field in field_position if field[:9] == "departure"]
- output = 1
- for field in departure_fields:
- output *= ticket_info["my_ticket"][field_position[field][0]]
- return output
- if __name__ == "__main__":
- file_location = r"data\day16.txt"
- print(part_a(file_location))
- print(part_b(file_location))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement