lines = open("input.txt", "r").read().splitlines() relief = [] starting_points = [] points = [] s = None e = None for i, line in enumerate(lines): els = [] for j, letter in enumerate(line): if letter == "a": starting_points.append((i, j)) if letter == "S": els.append(1) s = (i, j) starting_points.append((i, j)) elif letter == "E": els.append(26) e = (i, j) else: els.append(ord(letter) - 96) points.append((i, j)) relief.append(els) def neighbours(node): n = [] if node[0] > 0 and relief[node[0]][node[1]] + 1 >= relief[node[0] - 1][node[1]]: n.append((node[0] - 1, node[1])) if ( node[0] < len(relief) - 1 and relief[node[0]][node[1]] + 1 >= relief[node[0] + 1][node[1]] ): n.append((node[0] + 1, node[1])) if node[1] > 0 and relief[node[0]][node[1]] + 1 >= relief[node[0]][node[1] - 1]: n.append((node[0], node[1] - 1)) if ( node[1] < len(relief[0]) - 1 and relief[node[0]][node[1]] + 1 >= relief[node[0]][node[1] + 1] ): n.append((node[0], node[1] + 1)) return n def h(node): return abs(e[0] - node[0]) + abs(e[1] - node[1]) def a_star_search(start, goal): queue = [start] gscore = {x: 9999999 for x in points} gscore[start] = 0 fscore = {x: 9999999 for x in points} fscore[start] = h(start) while len(queue) > 0: queue = sorted({x: fscore[x] for x in queue}, key=lambda x: x[1]) current = queue.pop(0) if current[0] == goal[0] and current[1] == goal[1]: return fscore[current] for n in neighbours(current): newg = gscore[current] + 1 if newg < gscore[n]: gscore[n] = newg fscore[n] = newg + h(n) if n not in queue: queue.append(n) return None scenic = [] for starting_point in starting_points: scene = a_star_search(starting_point, e) if scene is not None: scenic.append(scene) print(sorted(scenic)[0])