145 lines
4.1 KiB
Python
145 lines
4.1 KiB
Python
from output import D, matrix
|
|
|
|
|
|
def solve(data):
|
|
O = {k: v for k, v in zip("^>v<", D)}
|
|
grid, movements = data.split("\n\n")
|
|
grid, H, W = matrix(grid)
|
|
movements = "".join(movements.split())
|
|
|
|
grid_1 = {
|
|
(r, c): value for r, row in enumerate(grid) for c, value in enumerate(row)
|
|
}
|
|
|
|
grid_2 = {}
|
|
for pos, value in grid_1.items():
|
|
r2, c2 = pos
|
|
match value:
|
|
case "O":
|
|
grid_2[(r2, c2 * 2)] = "["
|
|
grid_2[(r2, c2 * 2 + 1)] = "]"
|
|
case "@":
|
|
grid_2[(r2, c2 * 2)] = "@"
|
|
grid_2[(r2, c2 * 2 + 1)] = "."
|
|
case _:
|
|
grid_2[(r2, c2 * 2)] = value
|
|
grid_2[(r2, c2 * 2 + 1)] = value
|
|
|
|
answers = []
|
|
|
|
for grid, W in [(grid_1, W), (grid_2, W * 2)]:
|
|
pos = next((r, c) for r in range(H) for c in range(W) if grid[(r, c)] == "@")
|
|
|
|
for move in movements:
|
|
r, c = pos
|
|
dr, dc = O[move]
|
|
moved = False
|
|
|
|
match move:
|
|
case "^":
|
|
targets = [((v, c), grid[(v, c)]) for v in range(r)][::-1]
|
|
case "<":
|
|
targets = [((r, v), grid[(r, v)]) for v in range(c)][::-1]
|
|
case "v":
|
|
targets = [((v, c), grid[(v, c)]) for v in range(r + 1, H)]
|
|
case ">":
|
|
targets = [((r, v), grid[(r, v)]) for v in range(c + 1, W)]
|
|
|
|
if "." not in map(lambda pv: pv[1], targets):
|
|
continue
|
|
|
|
if grid[(r + dr, c + dc)] == ".":
|
|
moved = True
|
|
|
|
if grid[(r + dr, c + dc)] == "O" or (
|
|
grid[(r + dr, c + dc)] in "[]" and dc != 0
|
|
):
|
|
canmove = False
|
|
flips = []
|
|
|
|
for tpos, tvalue in targets:
|
|
flips.append((tpos, tvalue))
|
|
|
|
if tvalue == "#":
|
|
break
|
|
|
|
if tvalue == ".":
|
|
canmove = True
|
|
break
|
|
|
|
if canmove:
|
|
rotated = [value for _, value in flips]
|
|
rotated = rotated[-1:] + rotated[:-1]
|
|
|
|
for offset, pos in enumerate(flips):
|
|
grid[pos[0]] = rotated[offset]
|
|
|
|
moved = True
|
|
|
|
if grid[(r + dr, c + dc)] in "[]" and dc == 0 and dr != 0:
|
|
canmove = True
|
|
bs = set()
|
|
bmod = O[move][0]
|
|
|
|
Q = [(r + bmod, c)]
|
|
|
|
while Q:
|
|
rr, cc = Q.pop(0)
|
|
|
|
if (rr, cc) in bs:
|
|
continue
|
|
|
|
bs.add((rr, cc))
|
|
|
|
if grid[(rr, cc)] == "#":
|
|
canmove = False
|
|
continue
|
|
|
|
if grid[(rr, cc)] in "@.":
|
|
continue
|
|
|
|
match grid[(rr, cc)]:
|
|
case "]":
|
|
Q.append((rr + bmod, cc))
|
|
Q.append((rr, cc - 1))
|
|
case "[":
|
|
Q.append((rr + bmod, cc))
|
|
Q.append((rr, cc + 1))
|
|
|
|
if canmove:
|
|
patchset = {
|
|
(rr, cc): (rr + bmod, cc)
|
|
for rr, cc in bs
|
|
if grid[(rr, cc)] != "."
|
|
}
|
|
|
|
dotset = set(bs) - set(patchset.values())
|
|
|
|
for psf, pst in sorted(patchset.items())[::-bmod]:
|
|
psnv = grid[psf]
|
|
grid[pst] = psnv
|
|
|
|
for rk in dotset:
|
|
grid[rk] = "."
|
|
|
|
moved = True
|
|
|
|
if moved:
|
|
grid[(r, c)] = "."
|
|
grid[(r + dr, c + dc)] = "@"
|
|
pos = r + dr, c + dc
|
|
|
|
answers.append(sum(k[0] * 100 + k[1] for k, v in grid.items() if v in "O["))
|
|
|
|
p1, p2 = answers
|
|
return p1, p2
|
|
|
|
|
|
if __name__ == "__main__":
|
|
with open("./input/15.txt", "r") as f:
|
|
inp = f.read().strip()
|
|
|
|
p1, p2 = solve(inp)
|
|
|
|
print(p1)
|
|
print(p2)
|