问题
I am trying to find the shortest way to get from one point in a 2D array (one coordinate with x and y values representing its position in the array) to another.
I would like to output an array of coordinates which must be travelled through to get from the initial to the final coordinates.
One example of an array like this could be
arr = [
[15, 7, 3],
[1, 2, 6],
[7, 4, 67]
]
In this case, we can say that we will begin at arr[0][0]
and end at arr[2][2]
. Thus, the coordinates would be (0, 0)
and (2, 2)
.
The expected output would be: [(0, 2), (1, 2), (2, 2), (2, 1)]
or something of the same length.
What I tried
I managed to make a semi-successful function below, but it is very inefficient and time-consuming in larger cases.
import math
arr = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8]
]
coor1 = (0, 0) # seen as 2 in the arr array
coor2 = (2, 2) # seen as 7 in the arr array
def pythagoras(a, b):
# find pythagorean distances between the two
distance_y = max(a[0], b[0]) - min(a[0], b[0])
distance_x = max(a[1], b[1]) - min(a[1], b[1])
# calculate pythagorean distance to 3 d.p.
pythag_distance = round(math.sqrt(distance_x**2 + distance_y**2), 3)
return pythag_distance
def find_shortest_path(arr, position, target):
''' finds shortest path between two coordinates, can't go diagonally '''
coordinates_for_distances = []
distances = []
for i in range(len(arr)):
for r in range(len(arr)):
coordinates_for_distances.append((i, r))
distances.append(pythagoras((i, r), target))
route = []
while position != target:
acceptable_y_range = [position[1] + 1, position[1] - 1]
acceptable_x_range = [position[0] + 1, position[0] - 1]
possibilities = []
distance_possibilities = []
for i in range(len(coordinates_for_distances)):
if coordinates_for_distances[i][0] == position[0] and coordinates_for_distances[i][1] in acceptable_y_range:
possibilities.append(coordinates_for_distances[i])
distance_possibilities.append(distances[i])
elif coordinates_for_distances[i][1] == position[1] and coordinates_for_distances[i][0] in acceptable_x_range:
possibilities.append(coordinates_for_distances[i])
distance_possibilities.append(distances[i])
zipped_lists = zip(distance_possibilities, possibilities)
minimum = min(zipped_lists)
position = minimum[1]
route.append(position)
return route
回答1:
In order to find the shortest path between a pair of coordinates, we can translate this to a graph problem, in which each coordinate is a graph node. Now under this setting, finding the shortest paths between two nodes is a well known graph theory problem, and is fairly easy to solve with the right tools.
We can use NetworkX, which actually has a Graph generator, that returns the 2d grid graph of mxn
nodes, each being connected to its nearest neighbors. Which is perfect for out case:
import networkx as nx
from matplotlib import pyplot as plt
G = nx.grid_2d_graph(3,3)
plt.figure(figsize=(6,6))
pos = nx.spring_layout(G, iterations=100)
nx.draw(G, pos=pos,
node_color='lightgreen',
with_labels=True,
node_size=600)
Now we can use networkX's nx.bidirectional_shortest_path to find the shortest path between both coordinates:
coor1 = (0, 2) # seen as 2 in the arr array
coor2 = (2, 1) # seen as 7 in the arr array
nx.bidirectional_shortest_path(G, source=coor1, target=coor2)
# [(0, 2), (1, 2), (2, 2), (2, 1)]
Note that nx.grid_2d_graph
will generate grid graphs with up to an arbitrarily large m
and n
, but bare in mind that there's no layout specifically intended for grid graphs, so you might not quite get the graph representations as you'd expect. But for relatively small graphs, you should be able to visualize the grid as shown above.
来源:https://stackoverflow.com/questions/61912697/how-to-find-the-shortest-path-between-two-coordinates-in-a-2-dimensional-array