generated from public/aoc_template
day15 - cleanup
This commit is contained in:
parent
00a4fdb529
commit
d27138f2b0
89
day15.py
89
day15.py
@ -1,4 +1,5 @@
|
||||
from collections import deque
|
||||
from enum import Enum
|
||||
from tools.aoc import AOCDay
|
||||
from tools.coordinate import Coordinate
|
||||
from tools.grid import Grid
|
||||
@ -20,71 +21,57 @@ LARGER = {
|
||||
}
|
||||
|
||||
|
||||
class Tile(str, Enum):
|
||||
EMPTY = "."
|
||||
WALL = "#"
|
||||
BOX = "O"
|
||||
BOX_LEFT = "["
|
||||
BOX_RIGHT = "]"
|
||||
|
||||
|
||||
def sokoban(grid: Grid, start: Coordinate, moves: str) -> Grid:
|
||||
for move in moves:
|
||||
dir_ = MOVES[move]
|
||||
next_pos = start + dir_
|
||||
if grid.get(next_pos) == ".":
|
||||
start += dir_
|
||||
if grid.get(next_pos) == Tile.WALL:
|
||||
continue
|
||||
elif grid.get(next_pos) == "#":
|
||||
continue
|
||||
elif grid.get(next_pos) == "O":
|
||||
pos_behind_box = next_pos + dir_
|
||||
while grid.get(pos_behind_box) == "O":
|
||||
pos_behind_box += dir_
|
||||
|
||||
if grid.get(pos_behind_box) == "#":
|
||||
continue
|
||||
|
||||
grid.set(pos_behind_box, "O")
|
||||
elif grid.get(next_pos) == Tile.EMPTY:
|
||||
start = next_pos
|
||||
grid.set(start, ".")
|
||||
continue
|
||||
|
||||
if move in ["<", ">"]:
|
||||
# easy mode
|
||||
pos_behind_box = next_pos + dir_
|
||||
while grid.get(pos_behind_box) in ["[", "]"]:
|
||||
pos_behind_box += dir_ * 2
|
||||
|
||||
if grid.get(pos_behind_box) == "#":
|
||||
# neither a wall, nor empty space? There must be a box in the way
|
||||
to_move = set()
|
||||
wall_in_the_way = False
|
||||
queue = deque([next_pos])
|
||||
while queue:
|
||||
pos = queue.popleft()
|
||||
pos_tile = grid.get(pos)
|
||||
if pos_tile == Tile.EMPTY:
|
||||
continue
|
||||
|
||||
while pos_behind_box != start:
|
||||
grid.set(pos_behind_box, grid.get(pos_behind_box - dir_))
|
||||
pos_behind_box -= dir_
|
||||
else:
|
||||
# recursive mode
|
||||
wall_in_the_way = False
|
||||
Q = deque([next_pos])
|
||||
boxes = set()
|
||||
while Q:
|
||||
pos = Q.popleft()
|
||||
if grid.get(pos) == "#":
|
||||
wall_in_the_way = True
|
||||
break
|
||||
elif grid.get(pos) == ".":
|
||||
continue
|
||||
if pos_tile == Tile.WALL:
|
||||
wall_in_the_way = True
|
||||
break
|
||||
|
||||
Q.append(pos + dir_)
|
||||
if grid.get(pos) == "[":
|
||||
boxes.add((pos, pos + (1, 0)))
|
||||
Q.append(pos + dir_ + (1, 0))
|
||||
if (pos, pos_tile) in to_move:
|
||||
continue
|
||||
|
||||
to_move.add((pos, pos_tile))
|
||||
queue.append(pos + dir_)
|
||||
if pos_tile in [Tile.BOX_LEFT, Tile.BOX_RIGHT]:
|
||||
if pos_tile == Tile.BOX_LEFT:
|
||||
queue.append(pos + (1, 0))
|
||||
else:
|
||||
boxes.add((pos + (-1, 0), pos))
|
||||
Q.append(pos + dir_ + (-1, 0))
|
||||
queue.append(pos + (-1, 0))
|
||||
|
||||
if wall_in_the_way:
|
||||
continue
|
||||
if wall_in_the_way:
|
||||
continue
|
||||
|
||||
for box_l, box_r in boxes:
|
||||
grid.set(box_l, ".")
|
||||
grid.set(box_r, ".")
|
||||
for box, _ in to_move:
|
||||
grid.set(box, Tile.EMPTY)
|
||||
|
||||
for box_l, box_r in boxes:
|
||||
grid.set(box_l + dir_, "[")
|
||||
grid.set(box_r + dir_, "]")
|
||||
for box, box_tile in to_move:
|
||||
grid.set(box + dir_, box_tile)
|
||||
|
||||
start = next_pos
|
||||
|
||||
@ -108,7 +95,7 @@ class Day(AOCDay):
|
||||
map_, moves = self.getMultiLineInputAsArray()
|
||||
if part2:
|
||||
map_ = ["".join([LARGER[x] for x in y]) for y in map_]
|
||||
grid = Grid.from_data(map_, default=".")
|
||||
grid = Grid.from_data(map_, default=Tile.EMPTY, translate={r"\.#O\[\]": Tile})
|
||||
start = list(grid.find("@"))[0]
|
||||
grid.set(start, ".")
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user