from lib import get_data, Grid2D, add2 from collections import defaultdict data = get_data(__file__) g = Grid2D(data) seen = set() while True: h = g.hash() if h in seen: break else: seen.add(h) gn = g.clone_with_val(".") for r in range(g.n_rows): for c in range(g.n_cols): p = (r, c) nb_bugs = sum(1 for nb in g.neighbors_ort(p) if g[nb] == "#") if g[p] == "#" and nb_bugs == 1: gn[p] = "#" if g[p] == "." and nb_bugs in [1, 2]: gn[p] = "#" g = gn t = 0 p = 1 for r in range(g.n_rows): for c in range(g.n_cols): if g[(r, c)] == "#": t += p p *= 2 print(t) N = (-1, 0) E = (0, 1) S = (1, 0) W = (0, -1) DIRS = [N, E, S, W] ROW, COL = 0, 1 # data = get_data(__file__) g = Grid2D(data) bugs = [(0, r, c) for (r, c) in g.find("#")] middle = (g.n_rows // 2, g.n_cols // 2) rows, cols = g.n_rows, g.n_cols def get_edge(side): edges = { S: [(0, c) for c in range(cols)], N: [(rows - 1, c) for c in range(cols)], W: [(r, cols - 1) for r in range(rows)], E: [(r, 0) for r in range(rows)], } return edges[side] def get_neighbors(pos): level, row, col = pos neighbors = [] for d in DIRS: nb = add2((row, col), d) if nb == middle: for ir, ic in get_edge(d): neighbors.append((level - 1, ir, ic)) elif nb[ROW] in {-1, rows} or nb[COL] in {-1, cols}: nr, nc = nb if nr == -1: neighbors.append((level + 1, *add2(middle, N))) if nr == rows: neighbors.append((level + 1, *add2(middle, S))) if nc == -1: neighbors.append((level + 1, *add2(middle, W))) if nc == cols: neighbors.append((level + 1, *add2(middle, E))) else: nr, nc = nb neighbors.append((level, nr, nc)) return neighbors assert len(get_neighbors((0, 1, 1))) == 4 assert len(get_neighbors((0, 3, 3))) == 4 assert len(get_neighbors((0, 0, 3))) == 4 assert len(get_neighbors((0, 0, 4))) == 4 assert len(get_neighbors((0, 2, 3))) == 8 for _ in range(200): neighbors = defaultdict(int) current_bugs = set(bugs) for pos in bugs: for nb in get_neighbors(pos): neighbors[nb] += 1 new_bugs = [] for pos, count in neighbors.items(): if pos in current_bugs and count == 1: new_bugs.append(pos) if pos not in current_bugs and count in [1, 2]: new_bugs.append(pos) bugs = new_bugs print(len(bugs))