Ugly day 22.
This commit is contained in:
parent
72ffd399b3
commit
dd88a1838d
346
2022/day22.py
346
2022/day22.py
@ -2,14 +2,15 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
VOID = 0
|
VOID, EMPTY, WALL = 0, 1, 2
|
||||||
EMPTY = 1
|
|
||||||
WALL = 2
|
|
||||||
TILE_FROM_CHAR = {" ": VOID, ".": EMPTY, "#": WALL}
|
TILE_FROM_CHAR = {" ": VOID, ".": EMPTY, "#": WALL}
|
||||||
|
|
||||||
|
SCORES = {"E": 0, "S": 1, "W": 2, "N": 3}
|
||||||
|
|
||||||
|
|
||||||
board_map_s, direction_s = sys.stdin.read().split("\n\n")
|
board_map_s, direction_s = sys.stdin.read().split("\n\n")
|
||||||
|
|
||||||
@ -27,23 +28,6 @@ directions = [
|
|||||||
int(p1) if p2 else p1 for p1, p2 in re.findall(R"(([0-9])+|L|R)", direction_s)
|
int(p1) if p2 else p1 for p1, p2 in re.findall(R"(([0-9])+|L|R)", direction_s)
|
||||||
]
|
]
|
||||||
|
|
||||||
invert = False
|
|
||||||
|
|
||||||
y0 = 0
|
|
||||||
x0 = np.where(board[0] == EMPTY)[0][0]
|
|
||||||
r0 = "E"
|
|
||||||
|
|
||||||
if invert:
|
|
||||||
board = board[::-1, ::-1]
|
|
||||||
y0 = board.shape[0] - 1
|
|
||||||
x0 = np.where(board[-1, :] == EMPTY)[0][-1]
|
|
||||||
r0 = "W"
|
|
||||||
# print(
|
|
||||||
# "\n".join(
|
|
||||||
# "".join(next(k for k, v in TILE_FROM_CHAR.items() if v == c) for c in row)
|
|
||||||
# for row in board
|
|
||||||
# )
|
|
||||||
# )
|
|
||||||
|
|
||||||
# find on each row and column the first and last non-void
|
# find on each row and column the first and last non-void
|
||||||
row_first_non_void = np.argmax(board != VOID, axis=1)
|
row_first_non_void = np.argmax(board != VOID, axis=1)
|
||||||
@ -52,6 +36,75 @@ col_first_non_void = np.argmax(board != VOID, axis=0)
|
|||||||
col_last_non_void = board.shape[0] - np.argmax(board[::-1, :] != VOID, axis=0) - 1
|
col_last_non_void = board.shape[0] - np.argmax(board[::-1, :] != VOID, axis=0) - 1
|
||||||
|
|
||||||
|
|
||||||
|
faces = np.zeros_like(board)
|
||||||
|
size = np.gcd(board.shape[0], board.shape[1])
|
||||||
|
for row in range(0, board.shape[0], size):
|
||||||
|
for col in range(row_first_non_void[row], row_last_non_void[row], size):
|
||||||
|
faces[row : row + size, col : col + size] = faces.max() + 1
|
||||||
|
|
||||||
|
SIZE = np.gcd(*board.shape)
|
||||||
|
|
||||||
|
# TODO: deduce this from the actual cube...
|
||||||
|
faces_wrap: dict[int, dict[str, Callable[[int, int], tuple[int, int, str]]]]
|
||||||
|
if board.shape == (12, 16): # example
|
||||||
|
faces_wrap = {
|
||||||
|
1: {
|
||||||
|
"W": lambda y, x: (4, 4 + y, "S"), # 3N
|
||||||
|
"N": lambda y, x: (4, 11 - x, "S"), # 2N
|
||||||
|
"E": lambda y, x: (11 - y, 15, "W"), # 6E
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
"W": lambda y, x: (11, 19 - y, "N"), # 6S
|
||||||
|
"N": lambda y, x: (0, 11 - y, "S"), # 1N
|
||||||
|
"S": lambda y, x: (11, 11 - x, "N"), # 5S
|
||||||
|
},
|
||||||
|
3: {
|
||||||
|
"N": lambda y, x: (x - 4, 8, "E"), # 1W
|
||||||
|
"S": lambda y, x: (15 - x, 8, "E"), # 5W
|
||||||
|
},
|
||||||
|
4: {"E": lambda y, x: (8, 19 - y, "S")}, # 6N
|
||||||
|
5: {
|
||||||
|
"W": lambda y, x: (7, 15 - y, "N"), # 3S
|
||||||
|
"S": lambda y, x: (7, 11 - x, "N"), # 2S
|
||||||
|
},
|
||||||
|
6: {
|
||||||
|
"N": lambda y, x: (19 - x, 11, "W"), # 4E
|
||||||
|
"E": lambda y, x: (11 - y, 11, "W"), # 1E
|
||||||
|
"S": lambda y, x: (19 - x, 0, "E"), # 2W
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
else:
|
||||||
|
faces_wrap = {
|
||||||
|
1: {
|
||||||
|
"W": lambda y, x: (3 * SIZE - y - 1, 0, "E"), # 4W
|
||||||
|
"N": lambda y, x: (2 * SIZE + x, 0, "E"), # 6W
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
"N": lambda y, x: (4 * SIZE - 1, x - 2 * SIZE, "N"), # 6S
|
||||||
|
"E": lambda y, x: (3 * SIZE - y - 1, 2 * SIZE - 1, "W"), # 5E
|
||||||
|
"S": lambda y, x: (x - SIZE, 2 * SIZE - 1, "W"), # 3E
|
||||||
|
},
|
||||||
|
3: {
|
||||||
|
"W": lambda y, x: (2 * SIZE, y - SIZE, "S"), # 4N
|
||||||
|
"E": lambda y, x: (SIZE - 1, SIZE + y, "N"), # 2S
|
||||||
|
},
|
||||||
|
4: {
|
||||||
|
"W": lambda y, x: (3 * SIZE - y - 1, SIZE, "E"), # 1W
|
||||||
|
"N": lambda y, x: (SIZE + x, SIZE, "E"), # 3W
|
||||||
|
},
|
||||||
|
5: {
|
||||||
|
"E": lambda y, x: (3 * SIZE - y - 1, 3 * SIZE - 1, "W"), # 2E
|
||||||
|
"S": lambda y, x: (2 * SIZE + x, SIZE - 1, "W"), # 6E
|
||||||
|
},
|
||||||
|
6: {
|
||||||
|
"W": lambda y, x: (0, y - 2 * SIZE, "S"), # 1N
|
||||||
|
"E": lambda y, x: (3 * SIZE - 1, y - 2 * SIZE, "N"), # 5S
|
||||||
|
"S": lambda y, x: (0, x + 2 * SIZE, "S"), # 2N
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def wrap_part_1(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
def wrap_part_1(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
||||||
if r0 == "E":
|
if r0 == "E":
|
||||||
return y0, row_first_non_void[y0], r0
|
return y0, row_first_non_void[y0], r0
|
||||||
@ -66,184 +119,107 @@ def wrap_part_1(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
|||||||
|
|
||||||
|
|
||||||
def wrap_part_2(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
def wrap_part_2(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
||||||
if r0 == "E":
|
cube = faces[y0, x0]
|
||||||
if y0 in range(0, 4):
|
assert r0 in faces_wrap[cube]
|
||||||
y0 = board.shape[0] - y0 - 1
|
return faces_wrap[cube][r0](y0, x0)
|
||||||
return y0, row_last_non_void[y0], "W"
|
|
||||||
elif y0 in range(4, 8):
|
|
||||||
print(x0, row_last_non_void[8], row_last_non_void[8] - (y0 - 4))
|
|
||||||
x0 = row_last_non_void[8] - (y0 - 4)
|
|
||||||
return col_first_non_void[x0], x0, "S"
|
|
||||||
else:
|
|
||||||
y0 = board.shape[0] - y0 - 1
|
|
||||||
return y0, row_last_non_void[y0], "W"
|
|
||||||
elif r0 == "S":
|
|
||||||
if x0 in range(0, 4):
|
|
||||||
y0 = board.shape[0] - 1
|
|
||||||
return y0, row_first_non_void[y0] + 3 - x0, "N"
|
|
||||||
elif x0 in range(4, 8):
|
|
||||||
y0 = col_last_non_void[x0] + 8 - x0
|
|
||||||
return y0, row_first_non_void[y0], "E"
|
|
||||||
elif x0 in range(8, 12):
|
|
||||||
# 8 -> 3, 9 -> 2
|
|
||||||
x0 = board.shape[0] - x0 - 1
|
|
||||||
return col_last_non_void[x0], x0, "N"
|
|
||||||
else:
|
|
||||||
y0 = col_first_non_void[0] + board.shape[1] - x0 - 1
|
|
||||||
return y0, row_first_non_void[y0], "W"
|
|
||||||
elif r0 == "W":
|
|
||||||
if y0 in range(0, 4):
|
|
||||||
x0 = 4 + y0
|
|
||||||
return col_first_non_void[x0], x0, "S"
|
|
||||||
elif y0 in range(4, 8):
|
|
||||||
x0 = board.shape[1] - (y0 - 4) - 1
|
|
||||||
return board.shape[0] - 1, x0, "N"
|
|
||||||
else:
|
|
||||||
x0 = 4 + board.shape[0] - y0 - 1
|
|
||||||
return col_last_non_void[x0], x0, "N"
|
|
||||||
elif r0 == "N":
|
|
||||||
if x0 in range(0, 4):
|
|
||||||
y0 = 0
|
|
||||||
return y0, row_first_non_void[y0] + 3 - x0, "S"
|
|
||||||
elif x0 in range(4, 8):
|
|
||||||
y0 = x0 - 4
|
|
||||||
return y0, row_first_non_void[y0], "E"
|
|
||||||
elif x0 in range(8, 12):
|
|
||||||
x0 = 11 - x0
|
|
||||||
return col_first_non_void[x0], x0, "S"
|
|
||||||
else:
|
|
||||||
y0 = 4 + board.shape[0] - x0 - 1
|
|
||||||
return y0, row_last_non_void[y0], "W"
|
|
||||||
|
|
||||||
assert False
|
|
||||||
|
|
||||||
|
|
||||||
# for i in range(4):
|
def run(wrap: Callable[[int, int, str], tuple[int, int, str]]) -> tuple[int, int, str]:
|
||||||
# print(wrap_part_2(i, 8 + i - 1, "E"))
|
|
||||||
|
|
||||||
# exit()
|
y0 = 0
|
||||||
|
x0 = np.where(board[0] == EMPTY)[0][0]
|
||||||
|
r0 = "E"
|
||||||
|
|
||||||
|
for direction in directions:
|
||||||
wrap = wrap_part_2
|
if isinstance(direction, int):
|
||||||
|
while direction > 0:
|
||||||
# directions = directions[:5]
|
if r0 == "E":
|
||||||
|
xi = np.where(board[y0, x0 + 1 : x0 + direction + 1] == WALL)[0]
|
||||||
print(y0, x0, r0)
|
if len(xi):
|
||||||
|
x0 = x0 + xi[0]
|
||||||
facing = np.zeros_like(board, dtype=str)
|
direction = 0
|
||||||
facing.fill(" ")
|
elif (
|
||||||
facing[board != VOID] = "."
|
x0 + direction < board.shape[1]
|
||||||
facing[board == WALL] = "#"
|
and board[y0, x0 + direction] == EMPTY
|
||||||
|
):
|
||||||
for direction in directions:
|
x0 = x0 + direction
|
||||||
# print(f"{y0} {x0} {r0} ({direction})")
|
|
||||||
# r1 = {"N": "S", "S": "N", "W": "E", "E": "W"}[r0]
|
|
||||||
# print(f"{board.shape[0] - y0 - 1} {board.shape[1] - x0 - 1} {r1} ({direction})")
|
|
||||||
facing[y0, x0] = {"E": ">", "W": "<", "N": "^", "S": "v"}[r0]
|
|
||||||
|
|
||||||
if isinstance(direction, int):
|
|
||||||
while direction > 0:
|
|
||||||
if r0 == "E":
|
|
||||||
xi = np.where(board[y0, x0 + 1 : x0 + direction + 1] == WALL)[0]
|
|
||||||
# if y0 == 12 and x0 == 81:
|
|
||||||
# print(
|
|
||||||
# xi,
|
|
||||||
# board[y0, x0 + 1 : x0 + direction],
|
|
||||||
# board[y0, x0 + direction],
|
|
||||||
# )
|
|
||||||
if len(xi):
|
|
||||||
# print("E1")
|
|
||||||
x0 = x0 + xi[0]
|
|
||||||
direction = 0
|
|
||||||
elif (
|
|
||||||
x0 + direction < board.shape[1]
|
|
||||||
and board[y0, x0 + direction] == EMPTY
|
|
||||||
):
|
|
||||||
# print("E2")
|
|
||||||
x0 = x0 + direction
|
|
||||||
direction = 0
|
|
||||||
else:
|
|
||||||
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
|
||||||
if board[y0_t, x0_t] == WALL:
|
|
||||||
x0 = row_last_non_void[y0]
|
|
||||||
direction = 0
|
direction = 0
|
||||||
else:
|
else:
|
||||||
direction = direction - (row_last_non_void[y0] - x0) - 1
|
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
if board[y0_t, x0_t] == WALL:
|
||||||
elif r0 == "S":
|
x0 = row_last_non_void[y0]
|
||||||
yi = np.where(board[y0 + 1 : y0 + direction + 1, x0] == WALL)[0]
|
direction = 0
|
||||||
if len(yi):
|
else:
|
||||||
y0 = y0 + yi[0]
|
direction = direction - (row_last_non_void[y0] - x0) - 1
|
||||||
direction = 0
|
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||||
elif (
|
elif r0 == "S":
|
||||||
y0 + direction < board.shape[0]
|
yi = np.where(board[y0 + 1 : y0 + direction + 1, x0] == WALL)[0]
|
||||||
and board[y0 + direction, x0] == EMPTY
|
if len(yi):
|
||||||
):
|
y0 = y0 + yi[0]
|
||||||
y0 = y0 + direction
|
direction = 0
|
||||||
direction = 0
|
elif (
|
||||||
else:
|
y0 + direction < board.shape[0]
|
||||||
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
and board[y0 + direction, x0] == EMPTY
|
||||||
if board[y0_t, x0_t] == WALL:
|
):
|
||||||
y0 = col_last_non_void[x0]
|
y0 = y0 + direction
|
||||||
direction = 0
|
direction = 0
|
||||||
else:
|
else:
|
||||||
direction = direction - (col_last_non_void[x0] - y0) - 1
|
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
if board[y0_t, x0_t] == WALL:
|
||||||
elif r0 == "W":
|
y0 = col_last_non_void[x0]
|
||||||
left = max(x0 - direction - 1, 0)
|
direction = 0
|
||||||
xi = np.where(board[y0, left:x0] == WALL)[0]
|
else:
|
||||||
if len(xi):
|
direction = direction - (col_last_non_void[x0] - y0) - 1
|
||||||
x0 = left + xi[-1] + 1
|
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||||
direction = 0
|
elif r0 == "W":
|
||||||
elif x0 - direction >= 0 and board[y0, x0 - direction] == EMPTY:
|
left = max(x0 - direction - 1, 0)
|
||||||
x0 = x0 - direction
|
xi = np.where(board[y0, left:x0] == WALL)[0]
|
||||||
direction = 0
|
if len(xi):
|
||||||
else:
|
x0 = left + xi[-1] + 1
|
||||||
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
direction = 0
|
||||||
if board[y0_t, x0_t] == WALL:
|
elif x0 - direction >= 0 and board[y0, x0 - direction] == EMPTY:
|
||||||
x0 = row_first_non_void[y0]
|
x0 = x0 - direction
|
||||||
direction = 0
|
direction = 0
|
||||||
else:
|
else:
|
||||||
direction = direction - (x0 - row_first_non_void[y0]) - 1
|
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
if board[y0_t, x0_t] == WALL:
|
||||||
elif r0 == "N":
|
x0 = row_first_non_void[y0]
|
||||||
top = max(y0 - direction - 1, 0)
|
direction = 0
|
||||||
yi = np.where(board[top:y0, x0] == WALL)[0]
|
else:
|
||||||
if len(yi):
|
direction = direction - (x0 - row_first_non_void[y0]) - 1
|
||||||
y0 = top + yi[-1] + 1
|
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||||
direction = 0
|
elif r0 == "N":
|
||||||
elif y0 - direction >= 0 and board[y0 - direction, x0] == EMPTY:
|
top = max(y0 - direction - 1, 0)
|
||||||
y0 = y0 - direction
|
yi = np.where(board[top:y0, x0] == WALL)[0]
|
||||||
direction = 0
|
if len(yi):
|
||||||
else:
|
y0 = top + yi[-1] + 1
|
||||||
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
direction = 0
|
||||||
if board[y0_t, x0_t] == WALL:
|
elif y0 - direction >= 0 and board[y0 - direction, x0] == EMPTY:
|
||||||
y0 = col_first_non_void[x0]
|
y0 = y0 - direction
|
||||||
direction = 0
|
direction = 0
|
||||||
else:
|
else:
|
||||||
direction = direction - (y0 - col_first_non_void[x0]) - 1
|
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||||
y0, x0, r0 = y0_t, x0_t, r0_t
|
if board[y0_t, x0_t] == WALL:
|
||||||
else:
|
y0 = col_first_non_void[x0]
|
||||||
r0 = {
|
direction = 0
|
||||||
"E": {"L": "N", "R": "S"},
|
else:
|
||||||
"N": {"L": "W", "R": "E"},
|
direction = direction - (y0 - col_first_non_void[x0]) - 1
|
||||||
"W": {"L": "S", "R": "N"},
|
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||||
"S": {"L": "E", "R": "W"},
|
else:
|
||||||
}[r0][direction]
|
r0 = {
|
||||||
|
"E": {"L": "N", "R": "S"},
|
||||||
|
"N": {"L": "W", "R": "E"},
|
||||||
|
"W": {"L": "S", "R": "N"},
|
||||||
|
"S": {"L": "E", "R": "W"},
|
||||||
|
}[r0][direction]
|
||||||
|
|
||||||
facing[y0, x0] = {"E": ">", "W": "<", "N": "^", "S": "v"}[r0]
|
return y0, x0, r0
|
||||||
|
|
||||||
print("\n".join(map("".join, facing)))
|
|
||||||
|
|
||||||
if invert:
|
y1, x1, r1 = run(wrap_part_1)
|
||||||
print(y0, x0, r0, "->", end=" ")
|
answer_1 = 1000 * (1 + y1) + 4 * (1 + x1) + SCORES[r1]
|
||||||
x0, y0, r0 = (
|
|
||||||
board.shape[1] - x0 - 1,
|
|
||||||
board.shape[0] - y0 - 1,
|
|
||||||
{"N": "S", "S": "N", "W": "E", "E": "W"}[r0],
|
|
||||||
)
|
|
||||||
print(y0, x0, r0)
|
|
||||||
|
|
||||||
score = {"E": 0, "S": 1, "W": 2, "N": 3}
|
|
||||||
answer_1 = 1000 * (1 + y0) + 4 * (1 + x0) + score[r0]
|
|
||||||
print(f"answer 1 is {answer_1}")
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
|
y2, x2, r2 = run(wrap_part_2)
|
||||||
|
answer_2 = 1000 * (1 + y2) + 4 * (1 + x2) + SCORES[r2]
|
||||||
|
print(f"answer 2 is {answer_2}")
|
||||||
|
Loading…
Reference in New Issue
Block a user