#!/usr/bin/env python3 import re import numpy as np lines = (x.strip() for x in open("input.txt")) REGEX_RANGES = re.compile(r"^([a-z ]+): (\d+)-(\d+) or (\d+)-(\d+)$") REGEX_TICKET = re.compile(r"^(\d+,)*\d+$") read_step = 0 names = np.array([], dtype=str) groups = [] tickets = [] for line in lines: match = REGEX_RANGES.match(line) if match: m_groups = match.groups() names = np.append(names, [m_groups[0]]) groups.append(list(map(int, m_groups[1:]))) match = REGEX_TICKET.match(line) if match: ticket = tuple(map(int, line.split(','))) tickets.append(ticket) groups = np.array(groups) tickets = np.array(tickets, dtype=np.int32) ranges = np.concatenate((groups[:, :2], groups[:, 2:]), axis=0) valids = np.full(tickets.shape, False) for idx, elem in np.ndenumerate(tickets): valids[idx] = np.any(np.logical_and(ranges[:, 0] <= elem, elem <= ranges[:, 1])) tickets = tickets[np.all(valids, axis=1)] valids = np.full(tickets.shape, False) matches = np.full((groups.shape[0], groups.shape[0]), False) for idx in np.ndindex(matches.shape): a = np.logical_or(np.logical_and( groups[idx[0], 0] <= tickets[:, idx[1]], groups[idx[0], 1] >= tickets[:, idx[1]] ), np.logical_and( groups[idx[0], 2] <= tickets[:, idx[1]], groups[idx[0], 3] >= tickets[:, idx[1]] )) matches[idx] = np.all(a) product = 1 for idx in np.argsort(np.count_nonzero(matches, axis=0)): name = names[matches[:, idx]][0] matches = np.logical_and(matches.T, np.logical_not(matches[:, idx])).T if name.startswith("departure"): product *= tickets[0, idx] print(product)