aoc2020/day16.py
2020-12-16 06:51:06 +01:00

118 lines
3.7 KiB
Python

import aoclib
DAY = 16
TEST_SOLUTION_PART1 = 71
TEST_SOLUTION_PART2 = 7
def part1(test_mode=False):
my_input = aoclib.getInputAsArray(day=DAY, test=test_mode)
restraints = {}
other_tickets = []
for i, line in enumerate(my_input):
if not line:
other_tickets = my_input[i+5:]
break
field, limits = line.split(": ")
limit_low, limit_hi = limits.split(" or ")
min_low, max_low = limit_low.split("-")
min_hi, max_hi = limit_hi.split("-")
restraints[field] = [(int(min_low), int(max_low)), (int(min_hi), int(max_hi))]
invalid_numbers = []
for ticket in other_tickets:
for number in ticket.split(","):
valid = False
number = int(number)
for field in restraints:
if restraints[field][0][0] <= number <= restraints[field][0][1] or \
restraints[field][1][0] <= number <= restraints[field][1][1]:
valid = True
break
if not valid:
invalid_numbers.append(number)
return sum(invalid_numbers)
def part2(test_mode=False):
my_input = aoclib.getInputAsArray(day=DAY, test=test_mode)
restraints = {}
possible_positions = {}
my_ticket = ''
other_tickets = []
for i, line in enumerate(my_input):
if not line:
my_ticket = my_input[i+2]
other_tickets = my_input[i+5:]
break
field, limits = line.split(": ")
limit_low, limit_hi = limits.split(" or ")
min_low, max_low = limit_low.split("-")
min_hi, max_hi = limit_hi.split("-")
restraints[field] = [(int(min_low), int(max_low)), (int(min_hi), int(max_hi))]
num_fields = len(my_ticket.split(','))
for field in restraints:
possible_positions[field] = [x for x in range(num_fields)]
for ticket in other_tickets:
invalid = False
for position, number in enumerate(ticket.split(",")):
valid = False
number = int(number)
for field in restraints:
if restraints[field][0][0] <= number <= restraints[field][0][1] or \
restraints[field][1][0] <= number <= restraints[field][1][1]:
valid = True
break
if not valid:
invalid = True
break
if invalid:
continue
for position, number in enumerate(ticket.split(",")):
number = int(number)
for field in restraints:
if not restraints[field][0][0] <= number <= restraints[field][0][1] and \
not restraints[field][1][0] <= number <= restraints[field][1][1]:
possible_positions[field].remove(position)
single_possibilities = []
while 1:
all_done = True
for field, possibilities in possible_positions.items():
possible_position = possibilities[0]
if len(possibilities) == 1 and possible_position not in single_possibilities:
all_done = False
single_possibilities.append(possible_position)
for check_field in possible_positions:
try:
if len(possible_positions[check_field]) > 1:
possible_positions[check_field].remove(possible_position)
except ValueError:
pass
if all_done:
break
answer = 1
my_ticket = [int(x) for x in my_ticket.split(",")]
for field in restraints:
if field.startswith('departure'):
answer *= my_ticket[possible_positions[field][0]]
return answer