############################# # --- Day 12: Rain Risk --- # ############################# import AOCUtils moves = {"E": (1, 0), "N": (0, 1), "W": (-1, 0), "S": (0, -1)} ############################# navigation = AOCUtils.loadInput(12) pos = (0, 0) facing = 0 for inst in navigation: action, n = inst[0], int(inst[1:]) if action in moves: delta = moves[action] pos = (pos[0] + (delta[0] * n), pos[1] + (delta[1] * n)) elif action == "L": facing = (facing + (n // 90)) % 4 elif action == "R": facing = (facing - (n // 90)) % 4 elif action == "F": delta = list(moves.values())[facing] pos = (pos[0] + (delta[0] * n), pos[1] + (delta[1] * n))
#################################################### # --- Day 2: I Was Told There Would Be No Math --- # #################################################### import AOCUtils #################################################### presents = AOCUtils.loadInput(2) presents = [tuple(map(int, present.split("x"))) for present in presents] totalPaper = 0 for present in presents: l, w, h = present paper = 2 * l * w + 2 * w * h + 2 * h * l + min(l * w, w * h, h * l) totalPaper += paper print("Part 1: {}".format(totalPaper)) totalRibbon = 0 for present in presents: l, w, h = present ribbon = 2 * min(l + w, w + h, h + l) + l * w * h totalRibbon += ribbon print("Part 2: {}".format(totalRibbon)) AOCUtils.printTimeTaken()
# --- Day 10: Balance Bots --- # ################################ import AOCUtils class Bot: def __init__(self): self.chips = [] self.lowType, self.lowID = None, None self.highType, self.highID = None, None ################################ instructions = AOCUtils.loadInput(10) bots = dict() for inst in instructions: inst = inst.split() if inst[0] == "bot": botID = int(inst[1]) if botID not in bots: bots[botID] = Bot() bots[botID].lowType = inst[5] bots[botID].lowID = int(inst[6]) bots[botID].highType = inst[10] bots[botID].highID = int(inst[11]) elif inst[0] == "value":
vm = VM(memory) vm.run() print("".join([chr(c) for c in vm.output])) while not vm.halted: vm.output = [] vm.run(input() + "\n") print("".join([chr(c) for c in vm.output])) exit() def oppositeDoor(direction): opp = {"north": "south", "south": "north", "east": "west", "west": "east"} return opp[direction] rawProgram = AOCUtils.loadInput(25) memory = [int(i) for i in rawProgram.split(",")] blacklist = set([ "infinite loop", "molten lava", "giant electromagnet", "photons", "escape pod" ]) vm = VM(memory) vm.run() finalState = None maxItemsFound = 0 # BFS through all rooms, storing (room, inventory) visited states visited = set()
######################################## # --- Day 1: No Time for a Taxicab --- # ######################################## import AOCUtils ######################################## steps = AOCUtils.loadInput(1) steps = [s.strip() for s in steps.split(",")] directions = [(-1, 0), (0, 1), (1, 0), (0, -1)] # NESW, clockwise pos = (0, 0) facing = 0 visited = set() hq = None for step in steps: d, n = step[0], int(step[1:]) facing += 1 if d == "R" else -1 direction = directions[facing % 4] for _ in range(n): pos = (pos[0] + direction[0], pos[1] + direction[1]) if not hq: if pos not in visited: visited.add(pos) else: hq = pos
# print(" | ".join(k+": "+"{:<7}".format(str(v)) for k, v in self.registers.items())) self.pc += 1 def isPrime(n): for i in range(2, int(n**0.5) + 1): if n % i == 0: return False return True ############################################# code = AOCUtils.loadInput(23) program = Program(code) program.run() print("Part 1: {}".format(program.mulCount)) # program = Program(code, 1) # program.run() # print("Part 2: {}".format(program.registers["h"])) b0 = int(code[0].split()[-1]) * 100 + 100000 nonPrimesAmt = 0 for b in range(b0, b0 + 17000 + 1, 17): if not isPrime(b): nonPrimesAmt += 1
neighbors += int(grid[i + 1][j - 1] == "#") if i + 1 < sizeX: neighbors += int(grid[i + 1][j] == "#") if i + 1 < sizeX and j + 1 < sizeY: neighbors += int(grid[i + 1][j + 1] == "#") if grid[i][j] == "#": newGrid[i][j] = "#" if neighbors in [2, 3] else "." elif grid[i][j] == ".": newGrid[i][j] = "#" if neighbors == 3 else "." return newGrid ############################################ startGrid = [list(s) for s in AOCUtils.loadInput(18)] grid = [row[:] for row in startGrid] for _ in range(100): grid = step(grid, part=1) print("Part 1: {}".format(sum(row.count("#") for row in grid))) grid = [row[:] for row in startGrid] for _ in range(100): grid = step(grid, part=2) print("Part 2: {}".format(sum(row.count("#") for row in grid))) AOCUtils.printTimeTaken()
queue = deque([(self.start, 0, 0)]) visited = set() while queue: cur, level, dist = queue.popleft() if (cur, level) in visited: continue visited.add((cur, level)) if level == 0 and cur == self.end: break if level > 0 and cur in self.outerPortals: queue.append((self.outerPortals[cur], level-1, dist+1)) elif cur in self.innerPortals: queue.append((self.innerPortals[cur], level+1, dist+1)) for m in [(0, -1), (0, 1), (-1, 0), (1, 0)]: step = (cur[0]+m[0], cur[1]+m[1]) if self.__isWalkable(step): queue.append((step, level, dist+1)) return dist rawMaze = [list(s) for s in AOCUtils.loadInput(20)] maze = Maze(rawMaze) print("Part 1: {}".format(maze.getMinDistance())) print("Part 2: {}".format(maze.getMinDistanceLayers())) AOCUtils.printTimeTaken()
import AOCUtils def replaceNth(s, old, new, n): find = s.find(old) for _ in range(n - 1): find = s.find(old, find + 1) if find == -1: return s return s[:find] + new + s[find + len(old):] ######################################## rawInput = AOCUtils.loadInput(19) replacements = [r.split(" => ") for r in rawInput[:-2]] molecule = rawInput[-1] newMolecules = set() for old, new in replacements: for i in range(molecule.count(old)): newMolecule = replaceNth(molecule, old, new, i + 1) newMolecules.add(newMolecule) print("Part 1: {}".format(len(newMolecules))) ''' X != Rn, Ar, Y e => XX
##################################### # --- Day 19: A Series of Tubes --- # ##################################### import AOCUtils ##################################### diagram = AOCUtils.loadInput(19) h, w = len(diagram), len(diagram[0]) cx, cy = None, None for y in range(w): if diagram[0][y] != " ": cx, cy = 0, y break seenLetters = [] steps = 0 px, py = -1, cy nx, ny = 1, cy while diagram[cx][cy] != " ": if diagram[cx][cy].isalpha(): seenLetters.append(diagram[cx][cy]) if diagram[cx][cy] != "+": nx, ny = cx+cx-px, cy+cy-py else: for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
########################## import AOCUtils def distToOrigin(p): x, y = p if (x >= 0) == (y >= 0): return abs(x + y) else: return max(abs(x), abs(y)) ########################## path = AOCUtils.loadInput(11).split(",") # X axis rotated 30 deg (L/R is SW/NE) directions = { "nw": (-1, 1), "n": (0, 1), "ne": (1, 0), "sw": (-1, 0), "s": (0, -1), "se": (1, -1) } steps = [(0, 0)] for p in path: x, y = steps[-1] dx, dy = directions[p]
################################## # --- Day 22: Grid Computing --- # ################################## import AOCUtils from collections import deque ################################## rawNodes = AOCUtils.loadInput(22)[2:] nodes = dict() for rawNode in rawNodes: rawNode = rawNode.split() name, size, used, avail, pct = rawNode x, y = name.split("-")[1:] x, y = int(x[1:]), int(y[1:]) size, used = int(size[:-1]), int(used[:-1]) avail, pct = int(avail[:-1]), int(pct[:-1]) nodes[(x, y)] = {"size": size, "used": used, "avail": avail, "pct": pct} viableCount = 0 for a in nodes: for b in nodes: if a == b: continue if nodes[a]["used"] != 0 and nodes[a]["used"] < nodes[b]["avail"]: viableCount += 1
# of linear congruences (assumes all elements in mods are coprime) def chineseRemainderTheorem(mods, remainders): # Given linear congruences x%3 = 2, x%5 = 3, x%7 = 2, # x = chineseRemainderTheorem([3, 5, 7], [2, 3, 2]) N = 1 for m in mods: N *= m x = sum(r * N // m * modinv(N // m, m) for m, r in zip(mods, remainders)) return x % N ################################## notes = AOCUtils.loadInput(13) arrivedAtBusStop = int(notes[0]) schedule = notes[1].split(",") nextArrivals = [] for i, busID in enumerate(schedule): if busID == "x": continue busInterval = int(busID) sinceLastArrival = arrivedAtBusStop % busInterval untilNextArrival = busInterval - sinceLastArrival nextArrivals.append((untilNextArrival, busInterval)) nextArrivals.sort()
self.removed = False p, v, a = rawParticle.split(", ") self.p = [int(i) for i in p[3:-1].split(",")] self.v = [int(i) for i in v[3:-1].split(",")] self.a = [int(i) for i in a[3:-1].split(",")] def update(self): if not self.removed: self.v = tuple(v + a for v, a in zip(self.v, self.a)) self.p = tuple(p + v for p, v in zip(self.p, self.v)) ################################## rawParticles = AOCUtils.loadInput(20) particles = [Particle(i, p) for i, p in enumerate(rawParticles)] for _ in range(1000): for p in particles: p.update() m = min(particles, key=lambda p: sum(map(abs, p.p))) print("Part 1: {}".format(m.pid)) particles = [Particle(i, p) for i, p in enumerate(rawParticles)] for _ in range(1000): for p in particles: p.update()
if part == 2: for _ in range(2016): s = hashlib.md5(s.encode()).hexdigest() for c in range(len(s) - 3 - 1): if len(set(s[c:c + 3])) == 1: possibleKeys[s[c]].append(i) break for c in range(len(s) - 5 - 1): if len(set(s[c:c + 5])) == 1: for keyi in possibleKeys[s[c]]: if keyi + 1 <= i <= keyi + 1000: otpKeys.add(keyi) break i += 1 return sorted(otpKeys)[63] ################################ salt = AOCUtils.loadInput(14) print("Part 1: {}".format(getOTP(salt, part=1))) print("Part 2: {}".format(getOTP(salt, part=2))) AOCUtils.printTimeTaken()
if xVal != 0: self.pc += yVal - 1 elif inst == "tgl": n = self.pc + xVal if 0 <= n < len(self.program): if n in self.toggled: self.toggled.remove(n) else: self.toggled.add(n) self.pc += 1 ################################# program = AOCUtils.loadInput(23) # vm = VM(program) # vm.registers["a"] = 7 # vm.run() # print("Part 1: {}".format(vm.registers["a"])) # vm = VM(program) # vm.registers["a"] = 12 # vm.run() # print("Part 2: {}".format(vm.registers["a"])) X = int(program[19].split()[1]) Y = int(program[20].split()[1]) a = factorial(7) + X * Y
def countTrees(forest, deltaW, deltaH): h, w = len(forest), len(forest[0]) trees = 0 curH, curW = 0, 0 for curH in range(0, h, deltaH): trees += int(forest[curH][curW] == "#") curW = (curW + deltaW) % w return trees ###################################### forest = AOCUtils.loadInput(3) p1 = countTrees(forest, 3, 1) print("Part 1: {}".format(p1)) p2 = countTrees(forest, 1, 1) p2 *= countTrees(forest, 3, 1) p2 *= countTrees(forest, 5, 1) p2 *= countTrees(forest, 7, 1) p2 *= countTrees(forest, 1, 2) print("Part 2: {}".format(p2)) AOCUtils.printTimeTaken()
################################## # --- Day 1: Inverse Captcha --- # ################################## import AOCUtils ################################## digits = str(AOCUtils.loadInput(1)) totalSum = sum( int(digits[i]) for i in range(len(digits)) if digits[i] == digits[i - 1]) print("Part 1: {}".format(totalSum)) skip = len(digits) // 2 totalSum = sum( int(digits[i]) for i in range(len(digits)) if digits[i] == digits[(i + skip) % len(digits)]) print("Part 2: {}".format(totalSum)) AOCUtils.printTimeTaken()
import AOCUtils def allTuplesWithSum(n, total): if n == 1: yield (total, ) return for i in range(total + 1): for t in allTuplesWithSum(n - 1, total - i): yield (i, ) + t ############################################# rawIngredients = AOCUtils.loadInput(15) ingredients = [] for rawIngredient in rawIngredients: rawIngredient = rawIngredient.split() ingredient = { "capacity": int(rawIngredient[2][:-1]), "durability": int(rawIngredient[4][:-1]), "flavor": int(rawIngredient[6][:-1]), "texture": int(rawIngredient[8][:-1]), "calories": int(rawIngredient[10]) } ingredients.append(ingredient)
################################## # --- Day 6: Binary Boarding --- # ################################## import AOCUtils ################################## rawAnswers = AOCUtils.loadInput(6) for i in range(len(rawAnswers)): if rawAnswers[i] == "": rawAnswers[i] = "\n" rawGroups = " ".join(rawAnswers).split("\n") groups = [[set(answer) for answer in rawGroup.split()] for rawGroup in rawGroups] p1 = sum(len(set.union(*group)) for group in groups) print("Part 1: {}".format(p1)) p2 = sum(len(set.intersection(*group)) for group in groups) print("Part 2: {}".format(p2)) AOCUtils.printTimeTaken()
#################################### # --- Day 6: Signals and Noise --- # #################################### import AOCUtils #################################### messages = AOCUtils.loadInput(6) n = len(messages[0]) counts = [dict() for _ in range(n)] for message in messages: for i, c in enumerate(message): if c not in counts[i]: counts[i][c] = 0 counts[i][c] += 1 corrected = "".join([max((ct, c) for c, ct in count.items())[1] for count in counts]) print("Part 1: {}".format(corrected)) corrected = "".join([max((-ct, c) for c, ct in count.items())[1] for count in counts]) print("Part 2: {}".format(corrected)) AOCUtils.printTimeTaken()
####################################### # --- Day 24: Air Duct Spelunking --- # ####################################### import AOCUtils from collections import deque from itertools import permutations ####################################### ducts = AOCUtils.loadInput(24) points = dict() for x in range(len(ducts)): for y in range(len(ducts[0])): if ducts[x][y] in "0123456789": points[ducts[x][y]] = (x, y) # Get minimum distance from all points to all points allDistances = dict() for a, start in points.items(): for b, dest in points.items(): if (b, a) in allDistances: allDistances[(a, b)] = allDistances[(b, a)] continue if a == b: allDistances[(a, b)] = 0 continue queue = deque([(start, 0)]) visited = set()
if holdingWeights.count(w) == 1: # Unique weight originalWeight = w originalName = name else: # Other weights goalWeight = w # Final answer, escalate to parent calls deltaWeight = goalWeight - originalWeight newWeight = programs[originalName].w + deltaWeight return (newWeight, None) # Memoize result and return totalWeight[p] = programs[p].w + sum(holdingWeights) return (None, totalWeight[p]) return getWeights(root)[0] ################################### programs = {} for p in AOCUtils.loadInput(7): p = p.split() programs[p[0]] = Program(p) root = topoSort(programs)[0] print("Part 1: {}".format(root)) print("Part 2: {}".format(fixBalance(programs, root))) AOCUtils.printTimeTaken()
############################################# # --- Day 17: No Such Thing as Too Much --- # ############################################# import AOCUtils from itertools import combinations ############################################# containers = AOCUtils.loadInput(17) eggnog = 150 containerAmounts = [] for i in range(len(containers)+1): for combination in combinations(containers, i): if sum(combination) == eggnog: containerAmounts.append(i) p1 = len(containerAmounts) print("Part 1: {}".format(p1)) p2 = containerAmounts.count(min(containerAmounts)) print("Part 2: {}".format(p2)) AOCUtils.printTimeTaken()
############################ # --- Day 16: Aunt Sue --- # ############################ import AOCUtils ############################ rawAunts = AOCUtils.loadInput(16) aunts = dict() for rawAunt in rawAunts: rawAunt = rawAunt.split() auntID = int(rawAunt[1][:-1]) aunt = dict() for i in range(2, len(rawAunt), 2): thing = rawAunt[i].rstrip(":") amount = int(rawAunt[i + 1].rstrip(",")) aunt[thing] = amount aunts[auntID] = aunt tape = { "children": 3, "cats": 7, "samoyeds": 2, "pomeranians": 3, "akitas": 0, "vizslas": 0, "goldfish": 5,
################################# # --- Day 1: Not Quite Lisp --- # ################################# import AOCUtils ################################# directions = AOCUtils.loadInput(1) directions = [1 if c == "(" else -1 for c in directions] print("Part 1: {}".format(sum(directions))) cur = 0 for i, c in enumerate(directions): cur += c if cur == -1: print("Part 2: {}".format(i+1)) break AOCUtils.printTimeTaken()
recursiveCopy2 = list(player2)[:top2] score1, score2 = playGame2(recursiveCopy1, recursiveCopy2) p1Wins = (score1 > score2) else: p1Wins = (top1 > top2) if p1Wins: player1.append(top1) player1.append(top2) else: player2.append(top2) player2.append(top1) return getScore(player1), getScore(player2) ############################### rawDecks = AOCUtils.loadInput(22) rawPlayer1, rawPlayer2 = "\n".join(rawDecks).split("\n\n") rawPlayer1 = [int(i) for i in rawPlayer1.split("\n")[1:]] rawPlayer2 = [int(i) for i in rawPlayer2.split("\n")[1:]] print("Part 1: {}".format(max(playGame1(rawPlayer1, rawPlayer2)))) print("Part 2: {}".format(max(playGame2(rawPlayer1, rawPlayer2)))) AOCUtils.printTimeTaken()
for pos in active: for delta in moves: neighbor = tuple(k + d for k, d in zip(pos, delta)) toBeUpdated.add(neighbor) newActive = set(active) for pos in toBeUpdated: neighbors = 0 for delta in moves: neighbor = tuple(k + d for k, d in zip(pos, delta)) neighbors += int(neighbor in active) if pos in active and neighbors not in [2, 3]: newActive.remove(pos) elif pos not in active and neighbors == 3: newActive.add(pos) active = newActive return len(active) ################################ rawGrid = AOCUtils.loadInput(17) print("Part 1: {}".format(conwayCubes(rawGrid, 3))) print("Part 2: {}".format(conwayCubes(rawGrid, 4))) AOCUtils.printTimeTaken()
out = ~get(cmd[1]) & 0xFFFF elif op == "LSHIFT": out = get(cmd[0]) << get(cmd[2]) elif op == "RSHIFT": out = get(cmd[0]) >> get(cmd[2]) else: out = get(cmd[0]) wires[wire] = out return wires[wire] return get(wire) ######################################### rawCommands = AOCUtils.loadInput(7) commands = dict() for cmd in rawCommands: op, out = cmd.split(" -> ") commands[out] = op wires = dict() p1 = getWire(commands, wires, "a") print("Part 1: {}".format(p1)) wires = {"b": p1} p2 = getWire(commands, wires, "a") print("Part 1: {}".format(p2))
def getState(self, c): return str([moon.getState(c) for moon in self.moons]) def lcm2(x, y): return abs(x * y) // gcd(x, y) def lcmN(a): l = lcm2(a[0], a[1]) for i in a[2:]: l = lcm2(l, i) return l rawMoons = AOCUtils.loadInput(12) moons = [Moon(rawMoon) for rawMoon in rawMoons] system = MoonSystem(moons) for step in range(1000): system.step() print("Part 1: {}".format(system.getTotalEnergy())) periods = [0 for _ in range(3)] seen = [set() for _ in range(3)] system = MoonSystem(moons) step = 0 while not all(periods): for c in range(3): if not periods[c]: