Skip to content

Instantly share code, notes, and snippets.

@SebbyLaw
Created December 16, 2020 06:18
Show Gist options
  • Save SebbyLaw/a6e915e05835bbd682094f80a894115e to your computer and use it in GitHub Desktop.
Save SebbyLaw/a6e915e05835bbd682094f80a894115e to your computer and use it in GitHub Desktop.
AOC 2020 day 16
import functools
import operator
with open('input.txt') as f:
inp = f.read()
class Range:
def __init__(self, lower, upper):
self.lower = int(lower)
self.upper = int(upper)
def match(self, string):
return self.lower <= int(string) <= self.upper
def __repr__(self):
return 'lower={0.lower} upper={0.upper}'.format(self)
class Rule:
def __init__(self, string):
x = string.split(': ')
self.name = x[0]
self.ranges = tuple(Range(*p.split('-')) for p in x[1].split(' or '))
def match(self, string):
return any(r.match(string) for r in self.ranges)
def __repr__(self):
return '<{0.name} ranges={0.ranges}>'.format(self)
rules = [*map(Rule, inp.split('\n\n')[0].splitlines())]
def find_invalid(s):
for n in s.split(','):
if not any(rule.match(n) for rule in rules):
return n
other_tickets = inp.split('\n\n')[-1].splitlines()[1:]
print('part 1:', sum(map(int, filter(None, map(find_invalid, other_tickets)))))
valid_tickets = [t for t in other_tickets if find_invalid(t) is None]
num_fields = len(other_tickets[0].split(','))
fields = {}
for rule in rules:
valid_fields = []
fields[rule.name] = valid_fields
for i in range(num_fields):
a = map(lambda s: int(s.split(',')[i]), valid_tickets)
if all(rule.match(n) for n in a):
valid_fields.append(i)
# fields as tuples, sorted by number of valid fields
fat = [(k, v) for k, v in fields.items()]
fat.sort(key=lambda f: len(f[1]))
mapped = {k: None for k in range(num_fields)}
done = set()
for name, l in fat:
n = (set(l) - done).pop()
mapped[n] = name
done.add(n)
my_ticket = {}
my_ticket_as_list = inp.split('\n\n')[1].splitlines()[-1].split(',')
for idx, v in mapped.items():
my_ticket[v] = my_ticket_as_list[idx]
print('part 2:', functools.reduce(operator.mul, (int(v) for k, v in my_ticket.items() if k.startswith('departure'))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment