def run(data): data += '\n' data = data.replace('\n', ' else 0\nΣ = max(Σ, *wtf().values())\n') data = data.replace('inc', '+=').replace('dec', '-=') d = crazydict() exec(data, {}, d) b = d.pop('Σ') return max(d.values()), b
def exe(data): data += "\n" data = data.replace("\n", " else 0\nΣ = max(Σ, *wtf().values())\n") data = data.replace("inc", "+=").replace("dec", "-=") d = crazydict() exec(data, {}, d) b = d.pop("Σ") return max(d.values()), b
def part_b(data): registers = {}.fromkeys("abcd", 12) patch_target = dedent("""\ cpy b c inc a dec c jnz c -2 dec d jnz d -5""") patch = dedent("""\ mul b d a cpy 0 c cpy 0 d pass pass pass""") patch_length = len(patch.splitlines()) assert patch_length == len(patch_target.splitlines()) patch_start = len(data[:data.find(patch_target)].splitlines()) patched_area = range(patch_start + 1, patch_start + 1 + patch_length) patched_data = data.replace(patch_target, patch, 1) lines = patched_data.splitlines() registers = compute(reg=registers, lines=lines, original_data=data, patched_area=patched_area) return registers["a"]
def run(data): d = {} for line in data.replace(' <->', ',').splitlines(): xs = [int(x) for x in line.split(', ')] d[tuple(xs)] = set(xs) while True: for tuple_, set1 in d.items(): try: match = next(k for k, set2 in d.items() if k != tuple_ and set1 & set2) except StopIteration: # no match for this key - keep looking continue else: # merging match and set1 d[tuple_] = set1 | d.pop(match) break else: # no match for any key - we are done! break [set0] = [v for v in d.values() if 0 in v] a = len(set0) b = len(d) return a, b
def reduce(data): length = len(data) while True: for char in reacts: data = data.replace(char, '') if len(data) != length: length = len(data) else: break return len(data)
def react(data, remove=None): if remove is not None: data = data.replace(remove, "").replace(remove.swapcase(), "") result = [] for char in data: if result and char == result[-1].swapcase(): result.pop() else: result.append(char) return "".join(result)
def parsed(data): # decompose "flip" operations into cut + stride data = data.replace("deal into new stack", "cut -1\ndeal with increment -1") ops = [] for line in data.splitlines(): op, *crap, n = line.split() n = int(n) assert op in {"cut", "deal"} ops.append((op, n)) return ops
def get_distance_matrix(data): n_rows = 1 + data.count('\n') maze = np.fromstring(data.replace('\n', ''), dtype='S1').reshape(n_rows, -1).astype('U1') targets = sorted([x for x in data if x.isdigit()]) n = len(targets) states = [] for target in targets: [row], [col] = np.where(maze == target) states.append(complex(col, -row)) d = np.zeros((n, n), dtype=int) for a, b in combinations(range(n), 2): d[a, b] = d[b, a] = bfs(states[a], states[b], maze) return d
def tubemaze(data): A = np.fromiter(data.replace('\n', ''), dtype='U1').reshape(len(data.splitlines()), -1) x = np.array([-1, A[0].argmax()], dtype=int) v = np.array([1, 0], dtype=int) letters = '' for i in count(): x += v a = A[tuple(x)] if a == '+': v = v[::-1] if A[tuple(x + v)] == ' ': v *= -1 elif a not in '-| ': letters += a elif a == ' ': return letters, i
def tubemaze(data): A = np.fromiter(data.replace("\n", ""), dtype="U1") A = A.reshape(len(data.splitlines()), -1) x = np.array([-1, A[0].argmax()], dtype=int) v = np.array([1, 0], dtype=int) letters = "" for i in count(): x += v a = A[tuple(x)] if a == "+": v = v[::-1] if A[tuple(x + v)] == " ": v *= -1 elif a not in "-| ": letters += a elif a == " ": return letters, i
def part_ab(data): d = {} for line in data.replace(" <->", ",").splitlines(): xs = [int(x) for x in line.split(", ")] d[tuple(xs)] = set(xs) while True: for tuple_, set1 in d.items(): try: match = next(k for k, set2 in d.items() if k != tuple_ and set1 & set2) except StopIteration: continue # no match for this key - keep looking else: d[tuple_] = set1 | d.pop(match) break # merged match and set1 else: break # no match for any key - we are done! [set0] = [v for v in d.values() if 0 in v] a = len(set0) b = len(d) return a, b
def parsed(data): h = len(data.splitlines()) A = np.fromiter(data.replace("\n", ""), dtype="<U1").reshape(h, -1) A = (A == "|").astype(complex) + (A == "#").astype(complex) * 1j return A
class Machine: def __init__(self, a=0, b=0): self.regs = {'a': a, 'b': b} self.i = 0 def run(self, program): while 0 <= self.i < len(program): op, *args = program[self.i].split(' ') if op in ('jmp', 'jie', 'jio'): if (op == 'jie' and self.regs[args[0]] % 2 == 0 or op == 'jio' and self.regs[args[0]] == 1): self.i += int(args[1]) continue elif op == 'jmp': self.i += int(args[0]) continue if op == 'hlf': self.regs[args[0]] = int(self.regs[args[0]] / 2) elif op == 'tpl': self.regs[args[0]] *= 3 elif op == 'inc': self.regs[args[0]] += 1 self.i += 1 return self.regs['b'] program = data.replace(',', '').split('\n') print('part 1:', Machine().run(program)) print('part 2:', Machine(a=1).run(program))
def part_2(data): return min([reduce(data.replace(chr(i), '').replace(chr(i + 32), '')) for i in range(65, 65 + 26)])
from aocd import data, lines, submit import sys from collections import Counter, defaultdict, deque import functools from sortedcontainers import SortedList, SortedDict, SortedSet import itertools import u import math import time import operator low, high = u.ints(data.replace("-", " ")) pws = [[(p // 10 ** (5 - e)) % 10 for e in range(6)] for p in range(low, high + 1)] def asc(pw): return all(pw[i] <= pw[i + 1] for i in range(len(pw) - 1)) def group(p): return (len(list(g)) for _, g in itertools.groupby(p)) def nosubmit(answer, part): print(f"Part {part}:\n{answer}") # submit = nosubmit print(f"File line count: {len(lines)}")
while d: tok = d.popleft() if tok == "(": val = evaluate(d, part=part) elif tok.isdigit(): val = int(tok) elif tok in "+*": op = tok elif tok == ")": return prev if val is not None: if op == "+": prev += val elif op == "*": if part == "b": while d and d[0] == "+": d.popleft() r = d.popleft() if r.isdigit(): val += int(r) elif r == "(": val += evaluate(d, part=part) prev *= val val = None return prev lines = data.replace(" ", "").splitlines() print("part a:", sum([evaluate(deque(line), part="a") for line in lines])) print("part b:", sum([evaluate(deque(line), part="b") for line in lines]))
def read_data(data): lines = data.split('\n') rows = len(lines) cols = len(lines[0]) return np.array(list(data.replace('\n', ''))).reshape(rows, cols)
""" --- Day 12: Digital Plumber --- https://adventofcode.com/2017/day/12 """ import networkx as nx from aocd import data graph = nx.Graph() for line in data.replace(" <->", ",").splitlines(): n0, *nodes = [int(n) for n in line.split(", ")] graph.add_node(n0) for node in nodes: graph.add_edge(n0, node) [a] = [len(g) for g in nx.connected_components(graph) if 0 in g] b = nx.number_connected_components(graph) print("part a:", a) print("part b:", b)
""" --- Day 13: Transparent Origami --- https://adventofcode.com/2021/day/13 """ from aocd import data from aoc_wim.ocr import AOCR from ast import literal_eval zs, folds = data.replace(",", "+").split("\n\n") d = {literal_eval(z + "j"): "#" for z in zs.split()} for i, fold in enumerate(folds.splitlines()): axis, n = fold.split("=") n = int(n) for z in [*d]: if axis[-1] == "y" and z.imag > n: z_ = complex(z.real, 2 * n - z.imag) elif axis[-1] == "x" and z.real > n: z_ = complex(2 * n - z.real, z.imag) else: continue d[z_] = "#" del d[z] if i == 0: a = len(d) print("part a:", a) print("part b:", AOCR[d])
""" --- Day 9: Stream Processing --- https://adventofcode.com/2017/day/9 """ import re from aocd import data n_removed = 0 while "!!" in data: data = data.replace("!!", "") data = re.sub("!.", "", data) n_removed += len(data) - len(re.sub("<.*?>", "", data)) n_removed -= 2 * len(re.findall("<.*?>", data)) data = re.sub("<.*?>", "", data) score = 0 nesting = 0 for c in data: if c == "{": nesting += 1 elif c == "}": score += nesting nesting -= 1 print("part a:", score) print("part b:", n_removed)
def part_b(data): result = len(data) for x in set(data.lower()): m = part_a(data.replace(x, "").replace(x.upper(), "")) result = min(m, result) return result
from itertools import product, chain from operator import itemgetter from collections import defaultdict import networkx as nx def neighbours(p): yield (p[0] - 1, p[1]) yield (p[0] + 1, p[1]) yield (p[0], p[1] - 1) yield (p[0], p[1] + 1) from aocd import data as grid grid = grid.replace(" ", "#").split("\n") n, m = len(grid), len(grid[0]) g = defaultdict(lambda: '#', {(i, j): grid[i][j] for i, j in product(range(n), range(m))}) apos = defaultdict(list) for p in filter(lambda p: g[p] == '.', product(range(n), range(m))): for x in filter(lambda k: g[k].isalpha(), neighbours(p)): for y in filter(lambda k: g[k].isalpha(), neighbours(x)): s = ''.join(map(g.get, sorted([x, y]))) apos[s].append(p) lvls = len(apos) * 2 def solve_1(): graph = nx.Graph() for i, j in filter(lambda p: g[p] == '.', product(range(n), range(m))): for ni, nj in filter(lambda p: g[p] == '.', neighbours((i, j))): graph.add_edge((i, j), (ni, nj))
from aocd import data data = data.replace('ne', 'a').replace('se', 'b').replace('sw', 'c').replace('nw', 'd') DIRS = dict(a=1 - 1j, b=1j, c=-1 + 1j, d=-1j, e=1, w=-1) tiles = [sum(DIRS[c] for c in tile) for tile in data.splitlines()] floor = {} for tile in tiles: floor[tile] = not floor.get(tile, False) black = {p for p, v in floor.items() if v} # 244 print(f'part1 {len(black)}') def step(pos, black): n = sum(1 for d in DIRS.values() if (pos + d) in black) return ((pos in black) and not (n == 0 or n > 2)) or n == 2 for day in range(100): neighbors = {p + d for p in black for d in DIRS.values()} black = {p for p in black | neighbors if step(p, black)} # 3665 print(f'part2 {len(black)}')
--- Day 19: Monster Messages --- https://adventofcode.com/2020/day/19 """ from aocd import data def match(message, remaining): if not message or not remaining: return not message and not remaining first, *rest = remaining rule = rules[first] if rule in ("a", "b"): if message.startswith(rule): return match(message[1:], rest) return False return any(match(message, t + rest) for t in rule) rules_raw, messages = data.replace('"', "").split("\n\n") messages = messages.splitlines() rules = dict(r.split(": ") for r in rules_raw.splitlines()) for k, v in rules.items(): if v not in "ab": rules[k] = [t.split() for t in v.split("|")] print("part a:", sum(match(m, ["0"]) for m in messages)) rules["8"].append(["42", "8"]) rules["11"].append(["42", "11", "31"]) print("part b:", sum(match(m, ["0"]) for m in messages))