Files
aocpy/2024/d15.py
2024-12-18 22:09:38 -05:00

93 lines
1.9 KiB
Python

from lib import get_data
from lib import Grid2D
DIRS = {
"^": (-1, 0),
">": (0, 1),
"v": (1, 0),
"<": (0, -1),
}
data = get_data(__file__)
data, moves = data.split("\n\n")
g = Grid2D(data)
def simulate(grid: Grid2D, moves: str):
(p,) = g.find("@")
for c in moves:
if c == "\n":
continue
d = DIRS[c]
to_move = set([p])
row = to_move
blocked = False
while True:
nrow = set()
for (
r,
c,
) in row:
np = r + d[0], c + d[1]
if g[np] == "#":
blocked = True
elif g[np] == "O":
nrow.add(np)
elif g[np] == "[":
nrow.add(np)
if d == (1, 0) or d == (-1, 0):
nrow.add((np[0], np[1] + 1))
elif g[np] == "]":
if d == (1, 0) or d == (-1, 0):
nrow.add((np[0], np[1] - 1))
nrow.add(np)
to_move |= row
row = nrow
if len(row) == 0 or blocked:
break
if not blocked:
to_place = {}
p = p[0] + d[0], p[1] + d[1]
for tm in to_move:
np = tm[0] + d[0], tm[1] + d[1]
to_place[np] = g[tm]
g[tm] = "."
for pos, c in to_place.items():
g[pos] = c
def score(g: Grid2D) -> int:
os = g.find("O")
if os:
return sum(r * 100 + c for r, c in os)
return sum(r * 100 + c for r, c in g.find("["))
simulate(g, moves)
print(score(g))
ndata = ""
for c in data:
if c == "#":
ndata += "##"
elif c == "O":
ndata += "[]"
elif c == ".":
ndata += ".."
elif c == "@":
ndata += "@."
else:
ndata += c
g = Grid2D(ndata)
(p,) = g.find("@")
simulate(g, moves)
print(score(g))
exit()