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 collections import deque
|
||||||
|
from enum import Enum
|
||||||
from tools.aoc import AOCDay
|
from tools.aoc import AOCDay
|
||||||
from tools.coordinate import Coordinate
|
from tools.coordinate import Coordinate
|
||||||
from tools.grid import Grid
|
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:
|
def sokoban(grid: Grid, start: Coordinate, moves: str) -> Grid:
|
||||||
for move in moves:
|
for move in moves:
|
||||||
dir_ = MOVES[move]
|
dir_ = MOVES[move]
|
||||||
next_pos = start + dir_
|
next_pos = start + dir_
|
||||||
if grid.get(next_pos) == ".":
|
if grid.get(next_pos) == Tile.WALL:
|
||||||
start += dir_
|
|
||||||
continue
|
continue
|
||||||
elif grid.get(next_pos) == "#":
|
elif grid.get(next_pos) == Tile.EMPTY:
|
||||||
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")
|
|
||||||
start = next_pos
|
start = next_pos
|
||||||
grid.set(start, ".")
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if move in ["<", ">"]:
|
# neither a wall, nor empty space? There must be a box in the way
|
||||||
# easy mode
|
to_move = set()
|
||||||
pos_behind_box = next_pos + dir_
|
wall_in_the_way = False
|
||||||
while grid.get(pos_behind_box) in ["[", "]"]:
|
queue = deque([next_pos])
|
||||||
pos_behind_box += dir_ * 2
|
while queue:
|
||||||
|
pos = queue.popleft()
|
||||||
if grid.get(pos_behind_box) == "#":
|
pos_tile = grid.get(pos)
|
||||||
|
if pos_tile == Tile.EMPTY:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
while pos_behind_box != start:
|
if pos_tile == Tile.WALL:
|
||||||
grid.set(pos_behind_box, grid.get(pos_behind_box - dir_))
|
wall_in_the_way = True
|
||||||
pos_behind_box -= dir_
|
break
|
||||||
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
|
|
||||||
|
|
||||||
Q.append(pos + dir_)
|
if (pos, pos_tile) in to_move:
|
||||||
if grid.get(pos) == "[":
|
continue
|
||||||
boxes.add((pos, pos + (1, 0)))
|
|
||||||
Q.append(pos + dir_ + (1, 0))
|
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:
|
else:
|
||||||
boxes.add((pos + (-1, 0), pos))
|
queue.append(pos + (-1, 0))
|
||||||
Q.append(pos + dir_ + (-1, 0))
|
|
||||||
|
|
||||||
if wall_in_the_way:
|
if wall_in_the_way:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for box_l, box_r in boxes:
|
for box, _ in to_move:
|
||||||
grid.set(box_l, ".")
|
grid.set(box, Tile.EMPTY)
|
||||||
grid.set(box_r, ".")
|
|
||||||
|
|
||||||
for box_l, box_r in boxes:
|
for box, box_tile in to_move:
|
||||||
grid.set(box_l + dir_, "[")
|
grid.set(box + dir_, box_tile)
|
||||||
grid.set(box_r + dir_, "]")
|
|
||||||
|
|
||||||
start = next_pos
|
start = next_pos
|
||||||
|
|
||||||
@ -108,7 +95,7 @@ class Day(AOCDay):
|
|||||||
map_, moves = self.getMultiLineInputAsArray()
|
map_, moves = self.getMultiLineInputAsArray()
|
||||||
if part2:
|
if part2:
|
||||||
map_ = ["".join([LARGER[x] for x in y]) for y in map_]
|
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]
|
start = list(grid.find("@"))[0]
|
||||||
grid.set(start, ".")
|
grid.set(start, ".")
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user