def main(): weights = {} for y, line in enumerate(Path('input', '15').read_text().splitlines()): for x, c in enumerate(line): weights[Vector([x, y])] = int(c) target = Vector([x, y]) cursor = Vector([0, 0]) state = State(weights, cursor) while cursor != target: cursor = state.update(cursor) print(state.costs[target])
def main(): with Path('input', '19').open() as f: scanners = [ Scanner([Vector(map(int, p.split(','))) for p in chunk[1:]]) for chunk in readchunks(f) ] scanners[0].loc = zero oriented = {scanners[0]} while True: toorient = [s for s in scanners if s not in oriented] if not toorient: break oriented_ = set() for s in toorient: for t in oriented: if s.reorient(t): oriented_.add(s) break oriented |= oriented_ def distances(): for i, s in enumerate(scanners): for t in scanners[i + 1:]: yield (s.loc - t.loc).manhattan() print(max(distances()))
def main(): d = Diagram() with Path('input', '5').open() as f: for line in f: start, _, end = line.split() d.line(*(Vector(map(int, p.split(','))) for p in [start, end])) print(sum(1 for n in d.points.values() if n >= 2))
def main(): with Path('input', '20').open() as f: (algo,), lines = readchunks(f) algo = ['#' == c for c in algo] image = Image({Vector([x, y]): '#' == c for y, l in enumerate(lines) for x, c in enumerate(l)}) for _ in range(50): image.apply(algo) print(image.lit())
def main(): grid = Grid() for y, line in enumerate(Path('input', '11').read_text().splitlines()): for x, c in enumerate(line): grid[Vector([x, y])] = int(c) s = 1 while True: if len(grid) == grid.step(): print(s) break s += 1
def main(): grid = Grid() for y, line in enumerate(Path('input', '9').read_text().splitlines()): for x, c in enumerate(line): if '9' != c: grid.add(Vector([x, y])) basins = [] while grid: basins.append(grid.takebasin()) basins.sort() print(reduce(mul, basins[-3:]))
def main(): lines = Path('input', '25').read_text().splitlines() floor = Floor(len(lines[0]), len(lines)) for y, l in enumerate(lines): for x, c in enumerate(l): if '.' != c: (floor.east if '>' == c else floor.south).add(Vector([x, y])) n = 1 while floor.step(): n += 1 print(n)
def main(): weights = {} for y, line in enumerate(Path('input', '15').read_text().splitlines()): for x, c in enumerate(line): weights[Vector([x, y])] = int(c) w = x + 1 h = y + 1 ww = hh = 5 weights_ = weights.copy() for yy in range(hh): for xx in range(ww): if xx or yy: for (x, y), weight in weights_.items(): weights[Vector([xx * w + x, yy * h + y])] = (weight + xx + yy - 1) % 9 + 1 target = Vector([ww * w - 1, hh * h - 1]) cursor = Vector([0, 0]) state = State(weights, cursor) while cursor != target: cursor = state.update(cursor) print(state.costs[target])
class Grid(dict): kernel = [Vector([intcos(k), intsin(k)]) for k in range(4)] def _islow(self, k): for d in self.kernel: n = self.get(k + d) if n is not None and n <= self[k]: return return True def lowpoints(self): for k, n in self.items(): if self._islow(k): yield n
class Grid(set): kernel = [Vector([intcos(k), intsin(k)]) for k in range(4)] def takebasin(self): points = [self.pop()] n = 1 while points: points_ = [] for p in points: for d in self.kernel: q = p + d if q in self: self.remove(q) points_.append(q) n += 1 points = points_ return n
def main(): with Path('input', '19').open() as f: scanners = [ Scanner([Vector(map(int, p.split(','))) for p in chunk[1:]]) for chunk in readchunks(f) ] oriented = {scanners[0]} while True: toorient = [s for s in scanners if s not in oriented] if not toorient: break oriented_ = set() for s in toorient: for t in oriented: if s.reorient(t): oriented_.add(s) break oriented |= oriented_ print(len({b for s in scanners for b in s.beacons}))
class Grid(dict): kernel = [Vector([x, y]) for x in range(-1, 2) for y in range(-1, 2) if x or y] def step(self): for p in self: self[p] += 1 flashed = set() while True: points = {p for p, e in self.items() if p not in flashed and e > 9} if not points: for f in flashed: self[f] = 0 return len(flashed) flashed |= points for p in points: for d in self.kernel: q = p + d if q in self: self[q] += 1
#!/usr/bin/env python3 from adventlib import intcos, intsin, Vector from collections import defaultdict from heapq import heappop, heappush from pathlib import Path inf = float('inf') steps = [Vector([intcos(x), intsin(x)]) for x in range(4)] class State: def __init__(self, weights, cursor): self.costs = {} self.rcosts = defaultdict(set) self.allcosts = [] for p in weights: self._put(p, 0 if p == cursor else inf) self.weights = weights def _put(self, p, cost): self.costs[p] = cost s = self.rcosts[cost] if not s: heappush(self.allcosts, cost) s.add(p) def _remove(self, p): cost = self.costs.pop(p) self.rcosts[cost].remove(p) return cost
def step(self): return self._step(self.east, Vector([1, 0])) + self._step( self.south, Vector([0, 1]))
def _getmap(u, v): (a, i), = ([a, i] for i in range(3) for a in [-1, 1] if a * u[i] == v[0]) (b, j), = ([a, i] for i in range(3) for a in [-1, 1] if a * u[i] == v[1]) (c, k), = ([a, i] for i in range(3) for a in [-1, 1] if a * u[i] == v[2]) return lambda u: Vector([a * u[i], b * u[j], c * u[k]])
#!/usr/bin/env python3 from adventlib import readchunks, Vector from pathlib import Path def _getmap(u, v): (a, i), = ([a, i] for i in range(3) for a in [-1, 1] if a * u[i] == v[0]) (b, j), = ([a, i] for i in range(3) for a in [-1, 1] if a * u[i] == v[1]) (c, k), = ([a, i] for i in range(3) for a in [-1, 1] if a * u[i] == v[2]) return lambda u: Vector([a * u[i], b * u[j], c * u[k]]) zero = Vector([0, 0, 0]) class Scanner: def __init__(self, beacons): self.characters = [{ tuple(sorted(map(abs, b - o))): b for b in beacons } for o in beacons] assert all(len(c) == len(beacons) for c in self.characters) self.beacons = beacons def reorient(self, that): for c in self.characters: for d in that.characters: keys = c.keys() & d.keys() if len(keys) >= 12: co = c[0, 0, 0]
#!/usr/bin/env python3 from adventlib import readchunks, Vector from pathlib import Path tile = [Vector([x, y]) for y in range(-1, 2) for x in range(-1, 2)] infinity = Vector([float('inf')] * 2) class Image: border = 0 def __init__(self, pixels): self.pixels = pixels def _number(self, p, borderpixels_add = lambda q: None): n = 0 for d in tile: q = p + d if q in self.pixels: k = self.pixels[q] else: borderpixels_add(q) k = self.border n = (n << 1) + k return n def apply(self, algo): pixels = {} borderpixels = set() for p in self.pixels:
def main(): grid = Grid() for y, line in enumerate(Path('input', '11').read_text().splitlines()): for x, c in enumerate(line): grid[Vector([x, y])] = int(c) print(sum(grid.step() for _ in range(100)))
def main(): grid = Grid() for y, line in enumerate(Path('input', '9').read_text().splitlines()): for x, c in enumerate(line): grid[Vector([x, y])] = int(c) print(sum(1 + n for n in grid.lowpoints()))