Solve 2024:15 p2 "Warehouse Woes"
Glad this one is over. 150 lines of pure mayhem.
This commit is contained in:
parent
7c2b4c835a
commit
7688ddb763
1 changed files with 102 additions and 121 deletions
|
|
@ -1,164 +1,145 @@
|
||||||
import re
|
from output import D, matrix
|
||||||
from collections import Counter, defaultdict, deque
|
|
||||||
from heapq import heappop, heappush
|
|
||||||
from itertools import chain, combinations, compress, permutations
|
|
||||||
|
|
||||||
from output import ADJ, DD, D, ccw, cw, ints, matrix, mdbg, mhd, vdbg
|
|
||||||
|
|
||||||
|
|
||||||
def solve(data):
|
def solve(data):
|
||||||
o = {k:v for k, v in zip("^>v<", D)}
|
O = {k: v for k, v in zip("^>v<", D)}
|
||||||
grid, movements = data.split("\n\n")
|
grid, movements = data.split("\n\n")
|
||||||
grid, H, W = matrix(grid)
|
grid, H, W = matrix(grid)
|
||||||
movements = "".join(movements.split())
|
movements = "".join(movements.split())
|
||||||
grid1 = {(r, c):col for r, row in enumerate(grid) for c, col in enumerate(row)}
|
|
||||||
grid2 = {}
|
grid_1 = {
|
||||||
for k, v in grid1.items():
|
(r, c): value for r, row in enumerate(grid) for c, value in enumerate(row)
|
||||||
r2, c2 = k
|
}
|
||||||
match v:
|
|
||||||
|
grid_2 = {}
|
||||||
|
for pos, value in grid_1.items():
|
||||||
|
r2, c2 = pos
|
||||||
|
match value:
|
||||||
case "O":
|
case "O":
|
||||||
grid2[(r2, c2 * 2)] = "["
|
grid_2[(r2, c2 * 2)] = "["
|
||||||
grid2[(r2, c2 * 2 + 1)] = "]"
|
grid_2[(r2, c2 * 2 + 1)] = "]"
|
||||||
case "@":
|
case "@":
|
||||||
grid2[(r2, c2 * 2)] = "@"
|
grid_2[(r2, c2 * 2)] = "@"
|
||||||
grid2[(r2, c2 * 2 + 1)] = "."
|
grid_2[(r2, c2 * 2 + 1)] = "."
|
||||||
case _:
|
case _:
|
||||||
grid2[(r2, c2 * 2)] = v
|
grid_2[(r2, c2 * 2)] = value
|
||||||
grid2[(r2, c2 * 2 + 1)] = v
|
grid_2[(r2, c2 * 2 + 1)] = value
|
||||||
ans = []
|
|
||||||
for grid in [grid1, grid2]:
|
answers = []
|
||||||
pos = [(r, c) for r in range(H) for c in range(W) if grid[(r,c)] == "@"][0]
|
|
||||||
for T, move in enumerate(movements):
|
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
|
r, c = pos
|
||||||
targets = closest(grid, r, c, move, W, H)
|
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):
|
if "." not in map(lambda pv: pv[1], targets):
|
||||||
continue
|
continue
|
||||||
dr, dc = o[move]
|
|
||||||
moved = False
|
|
||||||
if grid[(r + dr, c + dc)] == ".":
|
if grid[(r + dr, c + dc)] == ".":
|
||||||
moved = True
|
moved = True
|
||||||
if grid[(r + dr, c + dc)] == "O" or (grid[(r + dr, c + dc)] in "[]" and dc != 0):
|
|
||||||
|
if grid[(r + dr, c + dc)] == "O" or (
|
||||||
|
grid[(r + dr, c + dc)] in "[]" and dc != 0
|
||||||
|
):
|
||||||
canmove = False
|
canmove = False
|
||||||
flips = []
|
flips = []
|
||||||
|
|
||||||
for tpos, tvalue in targets:
|
for tpos, tvalue in targets:
|
||||||
flips.append((tpos, tvalue))
|
flips.append((tpos, tvalue))
|
||||||
|
|
||||||
if tvalue == "#":
|
if tvalue == "#":
|
||||||
break
|
break
|
||||||
|
|
||||||
if tvalue == ".":
|
if tvalue == ".":
|
||||||
canmove = True
|
canmove = True
|
||||||
break
|
break
|
||||||
|
|
||||||
if canmove:
|
if canmove:
|
||||||
rotated = [rtv for rtp, rtv in flips]
|
rotated = [value for _, value in flips]
|
||||||
rotated = rotated[-1:] + rotated[:-1]
|
rotated = rotated[-1:] + rotated[:-1]
|
||||||
for fi, rtp in enumerate(flips):
|
|
||||||
rtp, *_ = rtp
|
for offset, pos in enumerate(flips):
|
||||||
grid[rtp] = rotated[fi]
|
grid[pos[0]] = rotated[offset]
|
||||||
|
|
||||||
moved = True
|
moved = True
|
||||||
|
|
||||||
if grid[(r + dr, c + dc)] in "[]" and dc == 0 and dr != 0:
|
if grid[(r + dr, c + dc)] in "[]" and dc == 0 and dr != 0:
|
||||||
# move cluster of boxes
|
canmove = True
|
||||||
canmove = False
|
bs = set()
|
||||||
flips = []
|
bmod = O[move][0]
|
||||||
for tpos, tvalue in targets:
|
|
||||||
flips.append((tpos, tvalue))
|
Q = [(r + bmod, c)]
|
||||||
if tvalue == "#":
|
|
||||||
break
|
while Q:
|
||||||
if tvalue == ".":
|
rr, cc = Q.pop(0)
|
||||||
canmove = True
|
|
||||||
break
|
if (rr, cc) in bs:
|
||||||
if tvalue == "[":
|
continue
|
||||||
# look on right side
|
|
||||||
# targets = closest(grid, r, c, move)
|
bs.add((rr, cc))
|
||||||
pass
|
|
||||||
if tvalue == "]":
|
if grid[(rr, cc)] == "#":
|
||||||
# look on right side
|
canmove = False
|
||||||
# targets = closest(grid, r, c, move)
|
continue
|
||||||
pass
|
|
||||||
|
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:
|
if canmove:
|
||||||
rotated = [rtv for rtp, rtv in flips]
|
patchset = {
|
||||||
rotated = rotated[-1:] + rotated[:-1]
|
(rr, cc): (rr + bmod, cc)
|
||||||
for fi, rtp in enumerate(flips):
|
for rr, cc in bs
|
||||||
rtp, *_ = rtp
|
if grid[(rr, cc)] != "."
|
||||||
grid[rtp] = rotated[fi]
|
}
|
||||||
|
|
||||||
|
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
|
moved = True
|
||||||
pass
|
|
||||||
if moved:
|
if moved:
|
||||||
grid[(r, c)] = "."
|
grid[(r, c)] = "."
|
||||||
grid[(r + dr, c + dc)] = "@"
|
grid[(r + dr, c + dc)] = "@"
|
||||||
pos = r + dr, c + dc
|
pos = r + dr, c + dc
|
||||||
if False and T > 67:
|
|
||||||
print(T, move)
|
answers.append(sum(k[0] * 100 + k[1] for k, v in grid.items() if v in "O["))
|
||||||
print(targets)
|
|
||||||
show(grid, H, W)
|
p1, p2 = answers
|
||||||
input("--- any key or gtfo ---")
|
|
||||||
ans.append(sum(k[0] * 100 + k[1] for k, v in grid.items() if v in "O["))
|
|
||||||
p1, p2 = ans
|
|
||||||
return p1, p2
|
return p1, p2
|
||||||
|
|
||||||
def show(grid, H, W):
|
|
||||||
for r in range(H):
|
|
||||||
for c in range(W):
|
|
||||||
print(grid[(r,c)], end="")
|
|
||||||
print("")
|
|
||||||
print("")
|
|
||||||
|
|
||||||
def closest(grid, r, c, move, W, H):
|
|
||||||
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)]
|
|
||||||
return targets
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import os
|
|
||||||
|
|
||||||
# use dummy data
|
|
||||||
inp = """
|
|
||||||
##########
|
|
||||||
#..O..O.O#
|
|
||||||
#......O.#
|
|
||||||
#.OO..O.O#
|
|
||||||
#..O@..O.#
|
|
||||||
#O#..O...#
|
|
||||||
#O..O..O.#
|
|
||||||
#.OO.O.OO#
|
|
||||||
#....O...#
|
|
||||||
##########
|
|
||||||
|
|
||||||
<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
|
|
||||||
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
|
|
||||||
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
|
|
||||||
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
|
|
||||||
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
|
|
||||||
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
|
|
||||||
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
|
|
||||||
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
|
|
||||||
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
|
|
||||||
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^
|
|
||||||
|
|
||||||
""".strip()
|
|
||||||
|
|
||||||
# uncomment to instead use stdin
|
|
||||||
# import sys; inp = sys.stdin.read().strip()
|
|
||||||
|
|
||||||
# uncomment to use AoC provided puzzle input
|
|
||||||
with open("./input/15.txt", "r") as f:
|
with open("./input/15.txt", "r") as f:
|
||||||
insp = f.read().strip()
|
inp = f.read().strip()
|
||||||
|
|
||||||
# uncomment to do initial data processing shared by part 1-2
|
|
||||||
p1, p2 = solve(inp)
|
p1, p2 = solve(inp)
|
||||||
|
|
||||||
print(p1)
|
print(p1)
|
||||||
os.system(f"echo {p1} | wl-copy")
|
|
||||||
print(p2)
|
print(p2)
|
||||||
os.system(f"echo {p2} | wl-copy")
|
|
||||||
|
|
||||||
# uncomment and replace 0 with actual output to refactor code
|
|
||||||
# and ensure nonbreaking changes
|
|
||||||
# assert p1 == 1426855
|
|
||||||
# assert p2 == 0
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue