def a(): grid, width, height = u.make_grid(lines) def ahead(cuke, pos): x, y = pos if cuke == '>': return ((x + 1) % width, y) else: return (x, (y + 1) % height) def move(grid, cuke): changed = False newgrid = {} for pos, c in grid.items(): if pos not in newgrid: newgrid[pos] = c ap = ahead(cuke, pos) if c == cuke and grid[ap] == '.': changed = True newgrid[ap] = c newgrid[pos] = '.' return newgrid, changed for step in itertools.count(1): grid, c1 = move(grid, '>') grid, c2 = move(grid, 'v') if not c1 and not c2: return step
def a(): grid, w, h = u.make_grid(lines, lambda v, p: int(v)) flashes = 0 for _ in range(100): flashes += len(step(grid)) return flashes
def b(): grid, width, height = u.make_grid( lines, lambda val, pos: val if val != "." else None) def neighbors(pos): for d in ds: npos = (pos[0] + d[0], pos[1] + d[1]) while npos not in grid and 0 <= npos[0] <= width and 0 <= npos[ 1] <= height: npos = (npos[0] + d[0], npos[1] + d[1]) if npos in grid: yield npos while True: count = 0 counts = Counter() for pos, c in grid.items(): if c == "#": count += 1 counts.update(neighbors(pos)) done = True for pos, c in grid.items(): s = counts[pos] if c == "L" and s == 0: grid[pos] = "#" done = False elif c == "#" and s >= 5: grid[pos] = "L" done = False if done: return count
def a(): grid, width, height = u.make_grid(lines, lambda v, p: int(v)) def neighbors(pos): for n in u.orthogonal(grid, pos): yield (n, grid[n]) pred, dist = u.dijkstra((0, 0), neighbors) return dist[width - 1, height - 1] pass
def b(): g, width, height = u.make_grid(lines, lambda v, p: int(v)) grid = {} for x, y in g: risk = g[x, y] for col in range(5): for row in range(5): nx = row * width + x ny = col * height + y grid[nx, ny] = ((risk + col + row - 1) % 9) + 1 def neighbors(pos): for n in u.orthogonal(grid, pos): yield (n, grid[n]) pred, dist = u.dijkstra((0, 0), neighbors) return dist[5 * width - 1, 5 * height - 1]
def a(): grid, _, _ = u.make_grid(lines, lambda val, pos: val if val != "." else None) while True: count = 0 counts = Counter() for pos, c in grid.items(): if c == "#": count += 1 counts.update(u.all_neighbors(grid, pos)) done = True for pos, c in grid.items(): s = counts[pos] if c == "L" and s == 0: grid[pos] = "#" done = False elif c == "#" and s >= 4: grid[pos] = "L" done = False if done: return count
from aocd import data, lines #type: ignore 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 import heapq ints = u.ints(data) intlines = u.lmap(u.ints, lines) toklines = [line.split(' ') for line in lines] grid, _, _ = u.make_grid(lines, lambda v, p: int(v)) def is_basin(p): return all(grid[p] < grid[n] for n in u.orthogonal(grid, p)) def a(): return sum(h + 1 for p, h in grid.items() if is_basin(p)) def b(): sizes = [0, 0, 0] def nbrs(p): return (n for n in u.orthogonal(grid, p) if grid[n] < 9)
def b(): grid, w, h = u.make_grid(lines, lambda v, p: int(v)) for s in itertools.count(1): flashed = step(grid) if len(flashed) == len(grid): return s