136 lines
3.4 KiB
Python
136 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import sys
|
|
|
|
import numpy as np
|
|
import scipy as sp
|
|
|
|
dtype = np.int32
|
|
|
|
input_file = sys.argv[1]
|
|
|
|
with open(input_file) as fd:
|
|
lines = [line.rstrip() for line in fd.readlines()]
|
|
|
|
height = len(lines)
|
|
width = len(lines[0])
|
|
start = height - 2, 1
|
|
stop = 1, width - 2
|
|
|
|
directions = [
|
|
(-1, 0), # ^ North
|
|
(0, 1), # > East
|
|
(1, 0), # v South
|
|
(0, -1), # < West
|
|
]
|
|
directions_keys = ("^", ">", "v", "<")
|
|
|
|
walls = np.zeros((height, width), dtype)
|
|
for i in range(height):
|
|
for j in range(width):
|
|
if lines[i][j] == "#":
|
|
walls[i, j] = 1
|
|
invwalls = 1 - walls
|
|
|
|
# print("Walls")
|
|
# print(walls)
|
|
|
|
# TEST 4
|
|
|
|
scores = np.zeros((height, width, len(directions)), dtype)
|
|
scores[start[0], start[1], 1] = 1
|
|
|
|
for i in range(1000):
|
|
print("Step", i)
|
|
oldscores = scores.copy()
|
|
for od, odir in enumerate(directions):
|
|
for nd, ndir in enumerate(directions):
|
|
score = scores[:, :, nd]
|
|
moved = sp.ndimage.shift(oldscores[:, :, od], ndir)
|
|
increment = 1 if nd == od else 1001
|
|
moved = (moved + increment) * (moved > 0)
|
|
moved = moved * invwalls
|
|
mask = (moved > 0) & ((score == 0) | (score > moved))
|
|
scores[:, :, nd] = (score * ~mask) + (moved * mask)
|
|
|
|
# for d, dir in enumerate(directions):
|
|
# print("Direction", directions_keys[d])
|
|
# print(scores[:, :, d])
|
|
|
|
if (scores == oldscores).all():
|
|
break
|
|
else:
|
|
print("Limit!")
|
|
|
|
end_score = min(filter(lambda d: d > 0, scores[stop])) - 1
|
|
print(f"{end_score=}")
|
|
|
|
# TEST 3
|
|
|
|
# scores = [np.zeros((height, width), dtype) for _ in directions]
|
|
# scores[1][start] = 1
|
|
#
|
|
# for i in range(100):
|
|
# print("Step", i)
|
|
# for od, odir in enumerate(directions):
|
|
# oldscore = scores[od].copy()
|
|
# for nd, ndir in enumerate(directions):
|
|
# score = scores[nd]
|
|
# moved = sp.ndimage.shift(oldscore, ndir)
|
|
# increment = 1 if nd == od else 1001
|
|
# moved = (moved + increment) * (moved > 0)
|
|
# moved = moved * invwalls
|
|
# mask = (moved > 0) & ((score == 0) | (score > moved))
|
|
# scores[nd] = (score * ~mask) + (moved * mask)
|
|
#
|
|
# final_score = None
|
|
# for d, dir in enumerate(directions):
|
|
# print("Direction", directions_keys[d])
|
|
# print(scores[d])
|
|
# end_score = scores[d][stop]
|
|
# if end_score > 0:
|
|
# if final_score is None or end_score < final_score:
|
|
# final_score = end_score
|
|
#
|
|
# if final_score:
|
|
# final_score -= 1
|
|
# print(f"{final_score=}")
|
|
# break
|
|
# else:
|
|
# print("Limit!")
|
|
|
|
|
|
# TEST 2
|
|
|
|
# score = np.zeros((height, width), dtype)
|
|
# score[start] = 1
|
|
#
|
|
# for i in range(10):
|
|
# print("Step", i)
|
|
# oldscore = score.copy()
|
|
# for nd, ndir in enumerate(directions):
|
|
# moved = sp.ndimage.shift(oldscore, ndir)
|
|
# moved = (moved + 1) * (moved > 0)
|
|
# moved = moved * invwalls
|
|
# mask = (moved > 0) & ((score == 0) | (score > moved))
|
|
# score = (score * ~mask) + (moved * mask)
|
|
# print(score)
|
|
|
|
# TEST 1
|
|
|
|
# directions = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]], dtype)
|
|
#
|
|
# visited = np.zeros((height, width), dtype)
|
|
# visited[start] = 1
|
|
#
|
|
# for i in range(1000):
|
|
# print("Step", i)
|
|
# new = sp.signal.convolve2d(visited, directions, mode="same")
|
|
# visited = (((new > 0) - walls) > 0)
|
|
# print(visited * 1)
|
|
# if visited[stop]:
|
|
# break
|
|
# else:
|
|
# print("Limit!")
|
|
# print(i)
|