#!/usr/bin/env python from aoc import get_input # AoC import re # regex from collections import defaultdict as dd data = get_input(16).strip() stuff = data.split("\n\n") params = stuff[0].split("\n") myticket = stuff[1].split("\n")[1] tickets = stuff[2].split("\n") tickets.pop(0) def parseParam(param): name, rnga1, rnga2, rngb1, rngb2 = re.match(r"(\w+ *\w*): ([0-9]+)-([0-9]+) or ([0-9]+)-([0-9]+)", param).groups() rng1 = range(int(rnga1), int(rnga2) + 1) rng2 = range(int(rngb1), int(rngb2) + 1) return name, rng1, rng2 ranges = dict() for i in range(len(params)): par = params[i] name, rng1, rng2 = parseParam(par) ranges[name] = (rng1, rng2) def parseTicket(ticket): return [int(n) for n in ticket.split(",")] myticket = parseTicket(myticket) badvals = [] goodtickets = [ti for ti in tickets] for i in range(len(tickets)): if( i > 0 ): ticket = tickets[i] vals = parseTicket(ticket) for v in vals: checks = [] for cl, rng in ranges.items(): for r in rng: checks.append( v in r ) valid = any(check for check in checks) if(not valid): badvals.append(v) break if( not valid ): goodtickets.remove(ticket) tickets = [parseTicket(t) for t in goodtickets] ticketlen = len(tickets[0]) works = dd(set) for i in range(ticketlen): clthing = dict() for cl, rng in ranges.items(): clthing[cl] = 0 for ticket in goodtickets: ticket = parseTicket(ticket) num = ticket[i] for cl, rng in ranges.items(): clcount = 0 if(num in rng[0] or num in rng[1]): clcount += 1 clthing[cl] += clcount for cl, count in clthing.items(): if( count == len(goodtickets) ): works[i].add(cl) used = set() while( any( [len(paramwork) > 1 for paramwork in works.values()] ) ): for index, cl in works.items(): if(len(cl) > 1): works[index] = (cl | used) ^ used else: used.add(next(iter(cl))) thenums = [] for i, cl in works.items(): num = myticket[i] cl = list(cl) if( "departure" in cl[0] ): thenums.append(num) import math print("Part 1", sum(badvals)) print("Part 2:", math.prod(thenums))