My Advent of Code solutions in Python. kevinyap.ca/2019/12/going-fast-in-advent-of-code/
advent-of-code python
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Switch pathfinding algorithm to A*

+35 -11
+35 -11
2016/day24.py
··· 1 1 import fileinput 2 - from collections import deque 2 + import heapq 3 3 from itertools import combinations, permutations 4 4 5 5 DIRS = [ ··· 17 17 return False 18 18 19 19 20 - def bfs(grid, start, goal): 21 - horizon = deque([(start, 0)]) 22 - seen = set(start) 20 + def heuristic(a, b): 21 + x1, y1 = a 22 + x2, y2 = b 23 + return abs(x1 - x2) + abs(y1 - y2) 24 + 25 + 26 + def a_star(grid, start, goal): 27 + """ 28 + Returns the length of the shortest path, minimizing f(n) = g(n) + h(n) 29 + as a search strategy. Using a closed set to skip over nodes that have 30 + already seen is valid so long as h(n) is admissible. 31 + """ 23 32 24 - while horizon: 25 - (x, y), dst = horizon.pop() 33 + frontier = [] 34 + seen = set() 35 + cost_to = {start: 0} # this is g(n) 36 + 37 + heapq.heappush(frontier, (0, start)) 38 + 39 + while frontier: 40 + _priority, (x, y) = heapq.heappop(frontier) 26 41 27 42 if (x, y) == goal: 28 - return dst 43 + return cost_to[goal] 44 + 45 + seen.add((x, y)) 29 46 30 47 for dx, dy in DIRS: 31 48 nx, ny = x + dx, y + dy 32 - if (nx, ny) not in seen and valid(grid, nx, ny): 33 - horizon.appendleft(((nx, ny), dst + 1)) 34 - seen.add((nx, ny)) 49 + 50 + if (nx, ny) in seen or not valid(grid, nx, ny): 51 + continue 52 + 53 + new_dist = cost_to[x, y] + 1 54 + 55 + if (nx, ny) not in cost_to or new_dist < cost_to[nx, ny]: 56 + cost_to[nx, ny] = new_dist 57 + priority = new_dist + heuristic(goal, (nx, ny)) 58 + heapq.heappush(frontier, (priority, (nx, ny))) 35 59 36 60 37 61 def navigate(distances, path, complete=False): ··· 59 83 distances = {} 60 84 61 85 for a, b in combinations(range(max(locations) + 1), 2): 62 - distances[a, b] = distances[b, a] = bfs(grid, locations[a], locations[b]) 86 + distances[a, b] = distances[b, a] = a_star(grid, locations[a], locations[b]) 63 87 64 88 paths = list(permutations(range(1, max(locations) + 1))) 65 89 print "Fewest steps to visit all numbers:", min(navigate(distances, path) for path in paths)