def part_one(): with open('data.txt', 'r') as f: data = f.read() fields, your_ticket, nearby_tickets = data.split('\n\n') # Build dictionary of fields and valid ranges all_ranges = RangeSet() fields = fields.split('\n') fields_dict = {} for field_line in fields: field_name, field_ranges = field_line.split(':') field_ranges = field_ranges.split('or') for field_range in field_ranges: if field_name in fields_dict: fields_dict[field_name] = fields_dict[field_name].union( RangeSet(field_range)) else: fields_dict[field_name] = RangeSet(field_range) all_ranges = all_ranges.union(RangeSet(field_range)) # Nearby tickets part_one_answer = 0 nearby_tickets = nearby_tickets.split('\n')[1:] for ticket in nearby_tickets: for field_value in ticket.split(','): if field_value not in all_ranges: part_one_answer += int(field_value) return part_one_answer
def testUnion(self): """test RangeSet.union()""" r1 = RangeSet("1-100,102,105-242,800") self.assertEqual(len(r1), 240) r2 = RangeSet("243-799,1924-1984") self.assertEqual(len(r2), 618) r3 = r1.union(r2) self.assertEqual(type(r3), RangeSet) self.assertEqual(r3.padding, None) self.assertEqual(len(r3), 240 + 618) self.assertEqual(str(r3), "1-100,102,105-800,1924-1984") r4 = r1 | r2 self.assertEqual(len(r4), 240 + 618) self.assertEqual(str(r4), "1-100,102,105-800,1924-1984") # test with overlap r2 = RangeSet("200-799") r3 = r1.union(r2) self.assertEqual(len(r3), 797) self.assertEqual(str(r3), "1-100,102,105-800") r4 = r1 | r2 self.assertEqual(len(r4), 797) self.assertEqual(str(r4), "1-100,102,105-800")
def testUnion(self): """test RangeSet.union()""" r1 = RangeSet("1-100,102,105-242,800") self.assertEqual(len(r1), 240) r2 = RangeSet("243-799,1924-1984") self.assertEqual(len(r2), 618) r3 = r1.union(r2) self.assertEqual(type(r3), RangeSet) self.assertEqual(r3.padding, None) self.assertEqual(len(r3), 240+618) self.assertEqual(str(r3), "1-100,102,105-800,1924-1984") r4 = r1 | r2 self.assertEqual(len(r4), 240+618) self.assertEqual(str(r4), "1-100,102,105-800,1924-1984") # test with overlap r2 = RangeSet("200-799") r3 = r1.union(r2) self.assertEqual(len(r3), 797) self.assertEqual(str(r3), "1-100,102,105-800") r4 = r1 | r2 self.assertEqual(len(r4), 797) self.assertEqual(str(r4), "1-100,102,105-800")
def part_two(): with open('data.txt', 'r') as f: data = f.read() fields, your_ticket, nearby_tickets = data.split('\n\n') # Build dictionary of fields and valid ranges all_ranges = RangeSet() fields = fields.split('\n') for field_line in fields: field_name, field_ranges = field_line.split(':') field_ranges = field_ranges.split('or') for field_range in field_ranges: if field_name in fields_dict: fields_dict[field_name]['range'] = fields_dict[field_name][ 'range'].union(RangeSet(field_range)) else: fields_dict[field_name] = { 'range': RangeSet(field_range), 'possible_indexes': [] } all_ranges = all_ranges.union(RangeSet(field_range)) # Nearby tickets valid_tickets = [] nearby_tickets = nearby_tickets.split('\n')[1:] for ticket in nearby_tickets: all_fields_ok = True for field_value in ticket.split(','): if field_value not in all_ranges: all_fields_ok = False if all_fields_ok: valid_tickets.append([int(x) for x in ticket.split(',')]) # Include own ticket to valid_tickets your_ticket = [int(x) for x in your_ticket.split('\n')[1].split(',')] valid_tickets.append(your_ticket) # pprint(valid_tickets, width=120) for field in fields_dict: for i in range(len(your_ticket)): # is field valid for all tickets index i? field_valid_for_all = True for valid_ticket in valid_tickets: if valid_ticket[i] not in fields_dict[field]['range']: field_valid_for_all = False break if field_valid_for_all: fields_dict[field]['possible_indexes'].append(i) pprint(fields_dict, width=120) solution = solve(fields_dict.keys(), is_solution_valid, len(fields_dict.keys())) result = 1 for i in range(len(solution)): if solution[i].startswith('departure'): result *= your_ticket[i] return result