49 lines
1.5 KiB
Python
49 lines
1.5 KiB
Python
#!/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+)$")
|
|
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:])))
|
|
if "," in line:
|
|
tickets.append(tuple(map(int, line.split(','))))
|
|
|
|
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)
|