import shared import matrix from dijkstar import Graph, find_path, algorithm #def dj_walk(mx, start, end): # def next_cost(c, val): # if val > c+1: # return 9999 # else: # return val # # start = start[1], start[0] # end = end[1], end[0] # # # Dijkstra from RedBlobGames # frontier = PriorityQueue() # frontier.put(start, 0) # came_from = dict() # cost_so_far = dict() # came_from[start] = None # cost_so_far[start] = 0 # last = None # while not frontier.empty(): # x, y = frontier.get() # cur = (x, y) # if cur == end: # break # for _n in matrix.get_neighbors(mx, x=x, y=y, _dict=True): # nxt = (_n["x"], _n["y"]) # v = _n["value"] # # new_cost = next_cost(cost_so_far[cur], v) # if nxt not in cost_so_far or new_cost < cost_so_far[nxt]: # cost_so_far[nxt] = new_cost # priority = new_cost # frontier.put(nxt, priority) # came_from[nxt] = cur # last = cur # print(len(cost_so_far)) criteria = lambda _cur, _neighbor: _neighbor - _cur <= 1 def build_graph(mx): graph = Graph() for y, row in enumerate(mx): for x, _ in enumerate(row): neighbors = matrix.valid_neighbors(mx, x=x, y=y, criteria=criteria) for neighbor in neighbors: graph.add_edge((y, x), (neighbor['y'],neighbor['x']), 1) return graph #SEEN = [] #def walk(mx, y, x, seen=[]): # print(len(seen)) # valid_next = matrix.valid_neighbors(mx, y, x, criteria=criteria) # print(valid_next) # matrix.highlight( mx, red=seen, green=[ *valid_next, ], blue=[ END, ],) # for next_yx in valid_next: # if next_yx not in seen: # seen.append(next_yx) # _y, _x = next_yx # walk(mx, _y, _x, seen) # else: # seen.append(next_yx) def elev(yx): y,x = yx return mx[y][x] def part1(mx): start = matrix.find_in_matrix(mx, "S") end = matrix.find_in_matrix(mx, "E") mx[start[0]][start[1]] = "a" mx[end[0]][end[1]] = "z" matrix.apply_to_all(mx, lambda x: ord(x) - ord('a')) #walk(mx, cur[0],cur[0], seen=[(cur[0],cur[1])]) #dj_walk(mx, cur, END) graph = build_graph(mx) path = find_path(graph, start, end) print(len(path.nodes)) def part2(mx): end = matrix.find_in_matrix(mx, "E") s = matrix.find_in_matrix(mx, "S") mx[s[0]][s[1]] = "a" mx[end[0]][end[1]] = "z" starts = matrix.find_in_matrix(mx, 'a', one=False) matrix.apply_to_all(mx, lambda x: ord(x) - ord('a')) graph = build_graph(mx) n_counts = [] for start in starts: #walk(mx, cur[0],cur[0], seen=[(cur[0],cur[1])]) #dj_walk(mx, cur, END) try: path = find_path(graph, start, end) n_counts.append(len(path.nodes)-1) except algorithm.NoPathError: pass print(n_counts) print(min(n_counts)) def main(): mx = matrix.load_matrix_file(shared.get_fname(12), matrix.split_word_to_chr_list) #part1(mx) part2(mx) if __name__ == "__main__": main()