99 python3 astar.py
1010"""
1111
12- from collections .abc import Callable , Iterable
1312import heapq
13+ from collections .abc import Callable , Iterable
1414
15- # Type aliases for readability (PEP 585 built-in generics, PEP 604 unions)
15+ # Type aliases (PEP 585 built-in generics, PEP 604 unions)
1616Node = tuple [int , int ]
1717NeighborsFn = Callable [[Node ], Iterable [tuple [Node , float ]]]
1818HeuristicFn = Callable [[Node , Node ], float ]
@@ -28,24 +28,29 @@ def astar(
2828 A* algorithm for pathfinding on a graph defined by a neighbor function.
2929
3030 A* maintains:
31- - g[n]: cost from start to node n (best known so far)
32- - f[n] = g[n] + h(n, goal): estimated total cost through n to goal
33- - open_list: min-heap of candidate nodes prioritized by smallest f-score
34- - closed_list: set of nodes already expanded (best path to them fixed)
31+ * g[n]: cost from start to node n (best known so far)
32+ * f[n] = g[n] + h(n, goal): estimated total cost through n to goal
33+ * open_list: min-heap of candidate nodes by smallest f-score
34+ * closed_list: nodes already expanded (best path to them fixed)
3535
3636 :param start: starting node
3737 :param goal: target node
3838 :param neighbors: function returning (neighbor, step_cost) pairs for a node
3939 :param h: admissible heuristic h(n, goal) estimating remaining cost
40- :return: list of nodes from start to goal (inclusive), or None if no path
40+ :return: path from start to goal (inclusive), or None if no path
4141
4242 Examples:
4343 >>> def _h(a: Node, b: Node) -> float: # Manhattan distance
4444 ... (x1, y1), (x2, y2) = a, b
4545 ... return abs(x1 - x2) + abs(y1 - y2)
4646 >>> def _nbrs(p: Node):
4747 ... x, y = p
48- ... return [((x + 1, y), 1), ((x - 1, y), 1), ((x, y + 1), 1), ((x, y - 1), 1)]
48+ ... return [
49+ ... ((x + 1, y), 1),
50+ ... ((x - 1, y), 1),
51+ ... ((x, y + 1), 1),
52+ ... ((x, y - 1), 1),
53+ ... ]
4954 >>> path = astar((0, 0), (2, 2), _nbrs, _h)
5055 >>> path is not None and path[0] == (0, 0) and path[-1] == (2, 2)
5156 True
@@ -103,7 +108,7 @@ def astar(
103108
104109
105110def heuristic (n : Node , goal : Node ) -> float :
106- """Manhattan (L1) distance heuristic for 4-connected grid movement with unit costs."""
111+ """Manhattan (L1) distance for 4-connected grid movement with unit costs."""
107112 x1 , y1 = n
108113 x2 , y2 = goal
109114 return abs (x1 - x2 ) + abs (y1 - y2 )
@@ -131,5 +136,4 @@ def neighbors(node: Node) -> Iterable[tuple[Node, float]]:
131136 path = astar (start , goal , neighbors , heuristic )
132137 print ("Path found:" , path )
133138 # Expected (one optimal path; yours may differ but length should be 10 moves + start):
134- # Path found: [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5),
135- # (1, 5), (2, 5), (3, 5), (4, 5), (5, 5)]
139+ # Path found: [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (1, 5), (2, 5), (3, 5), (4, 5), (5, 5)
0 commit comments