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