Solve 2019 day 24

This commit is contained in:
2024-10-13 08:54:39 -04:00
parent 67914a642a
commit 5dc7c4392f
2 changed files with 109 additions and 1 deletions

107
2019/d24.py Normal file
View File

@@ -0,0 +1,107 @@
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))