def run() -> (int, int): cups = [int(c) for c in read_as.lines("input/23.txt")[0]] links_p1, links_p2 = Links(), Links() for i in range(len(cups) - 1): links_p1.set(cups[i], cups[i + 1]) links_p2.set(cups[i], cups[i + 1]) links_p1.set(cups[-1], cups[0]) links_p2.set(cups[-1], 10) links_p2.set(1000000, cups[0]) links_p1.run(100, 9, cups[0]) links_p2.run(10000000, 1000000, cups[0]) p1 = 0 next_cup = links_p1.get(1) while next_cup != 1: p1 = (10 * p1) + next_cup next_cup = links_p1.get(next_cup) p2 = links_p2.get(1) * links_p2.get(links_p2.get(1)) return (p1, p2)
def run() -> (int, int): lines = read_as.lines("input/14.txt") results_p1, results_p2 = {}, {} mask_bits_p1, mask_bits_p2 = [], [] for line in lines: op, arg = line.split(" = ") if op == "mask": mask_bits_p1 = [(i, char) for (i, char) in enumerate(arg) if char != "X"] mask_bits_p2 = [(i, char) for (i, char) in enumerate(arg) if char != "0"] else: index = int(op[4:-1]) # P1 bitstring = list("{0:036b}".format(int(arg))) for (i, m) in mask_bits_p1: bitstring[i] = m results_p1[index] = int("".join(bitstring), 2) # P2 indexstring = list("{0:036b}".format(index)) for (i, m) in mask_bits_p2: indexstring[i] = m for addr in all_perms(indexstring): results_p2[int("".join(addr), 2)] = int(arg) return (sum(results_p1.values()), sum(results_p2.values()))
def run() -> (int, int): pub_1, pub_2 = [int(line) for line in read_as.lines("input/25.txt")] m = 20201227 loop, n = 1, 1 while (n := (n * 7) % m) not in {pub_1, pub_2}: loop += 1
def run() -> (int, int): adapters = sorted([int(line) for line in read_as.lines("input/10.txt")]) jumps = Counter([adapters[i] - adapters[i-1] for i in range(1, len(adapters))]) jumps[adapters[0]] += 1 jumps[3] += 1 return(jumps[1] * jumps[3], paths_to_target(adapters))
def run() -> (int, int): ship = Ship(1 + 0j, False) ship_wp = Ship(10 + 1j, True) for instr in read_as.lines("input/12.txt"): command, val = instr[0], int(instr[1:]) ship.move(command, val) ship_wp.move(command, val) return (ship.manhattan(), ship_wp.manhattan())
def run() -> (int, int): nums = [int(num) for num in read_as.lines("input/9.txt")] window = 25 for i in range(window, len(nums)): num = nums[i] if sum_of_window(num, nums[i - window:i]) == False: break return (num, subseq_sum(num, nums))
def run() -> (int, int): bags = {} for line in read_as.lines("input/7.txt"): (colour, contents) = line.split(" bags contain ") bags[colour] = re.findall(r"([0-9]+) ([a-z ]+) bags?[,.]", contents) bags_containing = sum([ contains_shiny_gold(colour, bags) for colour in bags if colour != "shiny gold" ]) return (bags_containing, num_contents("shiny gold", bags) - 1)
def run() -> (int, int): seat_indices = [ seat_to_index(seat) for seat in read_as.lines("input/5.txt") ] max_seat = max(seat_indices) min_seat = min(seat_indices) seat_sum = sum(seat_indices) missing_seat = sum(range(min_seat, max_seat + 1)) - seat_sum return (max_seat, missing_seat)
def run() -> (int, int): right = [1, 3, 5, 7, 1] down = [1, 1, 1, 1, 2] trees = [0, 0, 0, 0, 0] r = 0 for row in read_as.lines("input/3.txt"): for i in range(0, len(trees)): if r % down[i] == 0: trees[i] += row[(r * right[i] // down[i]) % len(row)] == "#" r += 1 return (trees[1], prod(trees))
def run() -> (int, int): lines = read_as.lines("input/13.txt") departure_time = int(lines[0]) buses = [ (i, int(bus)) for (i, bus) in enumerate(lines[1].split(",")) if bus != "x"] time_to_wait = math.inf bus_to_take = 0 for (_, bus_num) in buses: new_time = bus_num - (departure_time % bus_num) if new_time < time_to_wait: time_to_wait = new_time bus_to_take = bus_num # p2 == Chinese Remainder Theorem return (time_to_wait * bus_to_take, 894954360381385)
def run() -> (int, int): visited = set() for path in read_as.lines("input/24.txt"): north, east = 0, 0 for move in re.findall("[ns]?[ew]", path): north, east = { 'e': (north, east + 2), 'ne': (north + 1, east + 1), 'se': (north - 1, east + 1), 'w': (north, east - 2), 'nw': (north + 1, east - 1), 'sw': (north - 1, east - 1) }[move] visited ^= {(north, east)} return (len(visited), len(update(visited, 100)))
def run() -> (int, int): lines = read_as.lines("input/21.txt") possible = defaultdict(list) all_ingreds = [] for line in lines: ingredients, allergens = line.split("(contains") ingredients = ingredients.strip().split(' ') allergens = allergens.strip(' )').split(", ") all_ingreds.extend(ingredients) for allergen in allergens: possible[allergen].append(set(ingredients)) possible = {a: set.intersection(*i) for (a, i) in possible.items()} known_allergens = {} while len(possible) > 0: known = [(i, deepcopy(a).pop()) for (i, a) in possible.items() if len(a) == 1] for (known_a, known_i) in known: known_allergens[known_a] = known_i possible = { a: {x for x in i if x != known_i} for (a, i) in possible.items() if a != known_a } total_non_allergens = len( [i for i in all_ingreds if i not in known_allergens.values()]) canonical_danger_list = [ i for (a, i) in sorted(known_allergens.items(), key=lambda x: x[0]) ] return (total_non_allergens, ",".join(canonical_danger_list))
def run() -> (int, int): lines = read_as.lines("input/18.txt") total_p1 = sum(int(compute(line, False)) for line in lines) total_p2 = sum(int(compute(line, True)) for line in lines) return (total_p1, total_p2)
def run() -> (int, int): nums = set(int(line) for line in read_as.lines("input/1.txt")) return pair(nums, 2020).pop(), trips(nums, 2020).pop()