Advertisement
Guest User

Advent of Code Day 16

a guest
Dec 16th, 2020
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.12 KB | None | 0 0
  1. """Day 16 of Advent of Code 2020 Solution"""
  2.  
  3. from itertools import chain
  4. import re
  5.  
  6.  
  7. def ticket_io(file_location):
  8.     with open(file_location, "r") as f:
  9.         data = f.read().split("\n\n")
  10.  
  11.     fields = {}
  12.     for row in data[0].split("\n"):
  13.         row = row.split(":")
  14.         row_name = row[0]
  15.  
  16.         pattern = r"(\d+-\d+)"
  17.         v_pairs = []
  18.         for l_h in re.findall(pattern, row[1]):
  19.             low, high = l_h.split("-")
  20.             low, high = int(low), int(high)
  21.             v_pairs.append((low, high))
  22.         fields[row_name] = v_pairs
  23.  
  24.     my_ticket = [int(i) for i in data[1].split("\n")[1].split(",")]
  25.  
  26.     nearby_tickets = []
  27.     for ticket in data[2].split("\n")[1:]:
  28.         nearby_tickets.append([int(i) for i in ticket.split(",")])
  29.  
  30.     return {"fields": fields, "my_ticket": my_ticket, "nearby_tickets": nearby_tickets}
  31.  
  32.  
  33. def validate_tickets(ticket_info) -> list[list[int]]:
  34.     validated_nearby_tickets = []
  35.     field_ranges = [*chain.from_iterable(ticket_info["fields"].values())]
  36.     for ticket in ticket_info["nearby_tickets"]:
  37.         ticket_val_bool = [False] * len(ticket)
  38.         for i, val in enumerate(ticket):
  39.             field_range_bool = [False] * len(field_ranges)
  40.             for j, r in enumerate(field_ranges):
  41.                 if r[0] <= val <= r[1]:
  42.                     field_range_bool[j] = True
  43.             if any(field_range_bool):
  44.                 ticket_val_bool[i] = True
  45.         if all(ticket_val_bool):
  46.             validated_nearby_tickets.append(ticket)
  47.     return validated_nearby_tickets
  48.  
  49.  
  50. def part_a(file_location):
  51.     pattern = r"(\d+-\d+)"
  52.     with open(file_location, "r") as f:
  53.         data = f.read().split("\n\n")
  54.     v_pairs = []
  55.     for v in data[0].split("\n"):
  56.         for l_h in re.findall(pattern, v):
  57.             low, high = l_h.split("-")
  58.             low, high = int(low), int(high)
  59.             v_pairs.append((low, high))
  60.  
  61.     error_rate = 0
  62.     for ticket in data[2].split("\n")[1:]:
  63.         for val in [int(i) for i in ticket.strip().split(",")]:
  64.             found = [False] * len(v_pairs)
  65.             for i, pair in enumerate(v_pairs):
  66.                 if pair[0] <= val <= pair[1]:
  67.                     found[i] = True
  68.             if not any(found):
  69.                 error_rate += val
  70.     return error_rate
  71.  
  72.  
  73. def value_in_field(field, val) -> bool:
  74.     val_bool = [False] * len(val)
  75.     for i, val in enumerate(val):
  76.         field_bool = [False] * len(field)
  77.         for j, field_range in enumerate(field):
  78.             if field_range[0] <= val <= field_range[1]:
  79.                 field_bool[j] = True
  80.         if any(field_bool):
  81.             val_bool[i] = True
  82.     return all(val_bool)
  83.  
  84.  
  85. def part_b(file_location):
  86.     ticket_info = ticket_io(file_location)
  87.     valid_tickets = validate_tickets(ticket_info)
  88.     ticket_len = len(valid_tickets[0])
  89.     field_position = {field: [] for field in ticket_info["fields"].keys()}
  90.     available_fields = {*ticket_info["fields"].keys()}
  91.     found_positions = set()
  92.     while available_fields:
  93.         for position in range(ticket_len):
  94.             if position not in found_positions:
  95.                 ticket_position_vals = [v[position] for v in valid_tickets]
  96.                 for field in available_fields:
  97.                     if value_in_field(
  98.                         ticket_info["fields"][field], ticket_position_vals
  99.                     ):
  100.                         field_position[field].append(position)
  101.         for field in field_position:
  102.             if field in available_fields:
  103.                 if len(field_position[field]) == 1:
  104.                     available_fields.remove(field)
  105.                     found_positions.add(field_position[field][0])
  106.                 else:
  107.                     field_position[field] = []
  108.  
  109.     departure_fields = [field for field in field_position if field[:9] == "departure"]
  110.     output = 1
  111.     for field in departure_fields:
  112.         output *= ticket_info["my_ticket"][field_position[field][0]]
  113.  
  114.     return output
  115.  
  116.  
  117. if __name__ == "__main__":
  118.     file_location = r"data\day16.txt"
  119.     print(part_a(file_location))
  120.     print(part_b(file_location))
  121.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement