You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
3.9 KiB
135 lines
3.9 KiB
import copy |
|
from queue import PriorityQueue |
|
|
|
MAX_PRIO = ord('z') - ord('a') |
|
log_this_is_n = 0 |
|
n_solutions = 0 |
|
|
|
q = PriorityQueue() |
|
point_cost = {} |
|
|
|
def log_every_n(message): |
|
global log_this_is_n |
|
|
|
log_this_is_n = (log_this_is_n + 1) % 100000 |
|
|
|
if log_this_is_n == 0: |
|
print(message) |
|
|
|
|
|
class PossiblePath: |
|
def __init__(self, y, x, visited): |
|
self.x = x |
|
self.y = y |
|
self.visited = tuple(visited) |
|
|
|
def __lt__(self, other): |
|
return (len(self.visited) < len(other.visited) or |
|
self.x < other.x or |
|
self.y < other.y) |
|
|
|
|
|
def MakeCandidate(x, y, visited, value_diff): |
|
if (y, x) in point_cost and point_cost[(y, x)] <= len(visited): |
|
return |
|
point_cost[(y, x)] = len(visited) |
|
|
|
prio_valuediff = value_diff * -1 |
|
prio_distance = (max(End[0], x) - min(End[0], x)) + (max(End[1], y) - min(End[1], y)) |
|
prio_lettervalue = MAX_PRIO - grid[y][x] |
|
prio_pathlen = (gridX * gridY) - len(visited) |
|
path = PossiblePath(y, x, visited) |
|
q.put((prio_valuediff, prio_distance, path)) |
|
|
|
|
|
def findPath(): |
|
global fewestSteps |
|
global n_solutions |
|
while not q.empty(): |
|
_, _, path = q.get() |
|
|
|
if (path.y, path.x) in point_cost and point_cost[(path.y, path.x)] < len(path.visited): |
|
# We already have a better path to the current point. |
|
continue |
|
|
|
log_every_n('Inspecting: %dx%d, visited %d points, %d solutions' % (path.x, path.y, len(path.visited), n_solutions)) |
|
visited = list(path.visited) |
|
if (path.y, path.x) in visited: |
|
continue |
|
visited.append((path.y, path.x)) |
|
|
|
if (not (fewestSteps == None)) and (len(visited) - 1 >= fewestSteps): |
|
continue |
|
if [path.x, path.y] == End: |
|
print('Visited: ', visited) |
|
print('Steps: ', len(visited) - 1) |
|
fewestSteps = len(visited) - 1 |
|
n_solutions += 1 |
|
continue |
|
|
|
if path.x > 0: |
|
if grid[path.y][path.x - 1] <= grid[path.y][path.x] + 1: |
|
valDiff = grid[path.y][path.x - 1] - grid[path.y][path.x] |
|
MakeCandidate(path.x - 1, path.y, visited, valDiff) |
|
if path.x < gridX: |
|
if grid[path.y][path.x + 1] <= grid[path.y][path.x] + 1: |
|
valDiff = grid[path.y][path.x + 1] - grid[path.y][path.x] |
|
MakeCandidate(path.x + 1, path.y, visited, valDiff) |
|
if path.y > 0: |
|
if grid[path.y - 1][path.x] <= grid[path.y][path.x] + 1: |
|
valDiff = grid[path.y - 1][path.x] - grid[path.y][path.x] |
|
MakeCandidate(path.x, path.y - 1, visited, valDiff) |
|
if path.y < gridY: |
|
if grid[path.y + 1][path.x] <= grid[path.y][path.x] + 1: |
|
valDiff = grid[path.y + 1][path.x] - grid[path.y][path.x] |
|
MakeCandidate(path.x, path.y + 1, visited, valDiff) |
|
|
|
|
|
with open('input12.txt','r') as f: |
|
inp = f.read().splitlines(keepends=False) |
|
|
|
grid = [] |
|
fewestSteps = None |
|
|
|
|
|
for i in range(len(inp)): |
|
grid.append([]) |
|
for j in range(len(inp[i])): |
|
if inp[i][j] == 'S': |
|
Start = [j, i] |
|
grid[i].append(0) |
|
elif inp[i][j] == 'E': |
|
End = [j, i] |
|
grid[i].append(ord('z') - ord('a')) |
|
else: |
|
grid[i].append(ord(inp[i][j])-ord('a')) |
|
|
|
gridX = len(grid[0]) - 1 |
|
gridY = len(grid) - 1 |
|
|
|
_x = Start[0] |
|
_y = Start[1] |
|
|
|
if Start[0] > 0: |
|
if grid[_y][_x - 1] <= 1: |
|
MakeCandidate(_x - 1, _y, [(_y, _x)], grid[_y][_x - 1]) |
|
if Start[0] < gridX: |
|
if grid[_y][_x + 1] <= 1: |
|
MakeCandidate(_x + 1, _y, [(_y, _x)], grid[_y][_x + 1]) |
|
if Start[1] > 0: |
|
if grid[_y - 1][_x] <= 1: |
|
MakeCandidate(_x, _y - 1, [(_y, _x)], grid[_y - 1][_x]) |
|
if Start[1] < gridY: |
|
if grid[_y + 1][_x] <= 1: |
|
MakeCandidate(_x, _y + 1, [(_y, _x)], grid[_y + 1][_x]) |
|
|
|
findPath() |
|
|
|
print(fewestSteps) |
|
#for x in grid: |
|
# tempa = '' |
|
# for y in x: |
|
# tempa += chr(y + 97) |
|
# print(tempa) |
|
|
|
|