78 lines
2.1 KiB
Python
78 lines
2.1 KiB
Python
from math import prod
|
|
|
|
with open('input') as f:
|
|
rules, my_ticket, other = f.read().strip().split("\n\n")
|
|
|
|
rules = dict([r.split(': ') for r in rules.strip().split("\n")])
|
|
my_ticket = list(map(int, my_ticket.strip().split("\n")[1].split(',')))
|
|
other = [list(map(int, ticket.split(','))) for ticket in other.strip().split("\n")[1:]]
|
|
|
|
class Condition:
|
|
def __init__(self, xs, xe, ys, ye):
|
|
self.xs = xs
|
|
self.xe = xe
|
|
self.ys = ys
|
|
self.ye = ye
|
|
|
|
@classmethod
|
|
def from_str(cls, s):
|
|
l = [int(y) for x in s.split(" or ") for y in x.split('-')]
|
|
return cls(*l)
|
|
|
|
def __call__(self, x):
|
|
return self.xs<=x<=self.xe or self.ys<=x<=self.ye
|
|
def __str__(self):
|
|
return f'{self.xs}<=x<={self.xe} or {self.ys}<=x<={self.ye}'
|
|
__repr__ = __str__
|
|
|
|
rules = {k: Condition.from_str(v) for k, v in rules.items()}
|
|
|
|
|
|
valid_tickets = []
|
|
k = 0
|
|
for ticket in other:
|
|
valid = True
|
|
for value in ticket:
|
|
f_valid = False
|
|
for f in rules.values():
|
|
if f(value):
|
|
f_valid = True
|
|
if not f_valid:
|
|
valid = False
|
|
k += value
|
|
if valid:
|
|
valid_tickets.append(ticket)
|
|
|
|
print(k)
|
|
|
|
trans = {i: k for i, k in enumerate(rules.keys())}
|
|
soup = [[[None
|
|
for _ in range(len(trans))]
|
|
for _ in range(len(valid_tickets[0]))]
|
|
for _ in range(len(valid_tickets))]
|
|
for i_t, ticket in enumerate(valid_tickets):
|
|
for i_v, value in enumerate(ticket):
|
|
for i_f, k in trans.items():
|
|
soup[i_t][i_v][i_f] = rules[k](value)
|
|
|
|
|
|
rev_trans = {i: [] for i in range(len(valid_tickets[0]))}
|
|
for i_vv in range(len(valid_tickets[0])):
|
|
for i_f in trans:
|
|
valid = True
|
|
for i_t in range(len(valid_tickets)):
|
|
if not soup[i_t][i_vv][i_f]:
|
|
valid = False
|
|
break
|
|
if valid:
|
|
rev_trans[i_vv].append(trans[i_f])
|
|
rev_trans = sorted([(i, set(f)) for i, f in rev_trans.items()], key=lambda x: len(x[1]))
|
|
d = {}
|
|
e = set()
|
|
for i, f in rev_trans:
|
|
d[i] = f-e
|
|
e = e|f
|
|
print(prod(my_ticket[i] for i, f in d.items() if 'departure' in list(f)[0]))
|
|
|
|
print("done")
|