Get shortest path to a cell in a 2D array in Python

前端 未结 2 1986
伪装坚强ぢ
伪装坚强ぢ 2021-01-03 05:23

I have a 2D array, arr, where each cell in it has a value 1, 2 or 3, for example, arr[0][0] = 3, arr[2][1] = 2, and arr[0][4] = 1.

I want t

相关标签:
2条回答
  • 2021-01-03 05:38

    You can use a simple breadth first search for this. Basically, each cell in your grid corresponds to a node in the graph, with edges between adjacent cells. Start at the starting position, and keep expanding passable cells until you find a goal cell.

    def bfs(grid, start):
        queue = collections.deque([[start]])
        seen = set([start])
        while queue:
            path = queue.popleft()
            x, y = path[-1]
            if grid[y][x] == goal:
                return path
            for x2, y2 in ((x+1,y), (x-1,y), (x,y+1), (x,y-1)):
                if 0 <= x2 < width and 0 <= y2 < height and grid[y2][x2] != wall and (x2, y2) not in seen:
                    queue.append(path + [(x2, y2)])
                    seen.add((x2, y2))
    

    Grid setup and results: (Note that I'm using symbols instead of numbers, simply for the reason that it's easier to visually parse the grid this way and to verify the solution.)

    wall, clear, goal = "#", ".", "*"
    width, height = 10, 5
    grid = ["..........",
            "..*#...##.",
            "..##...#*.",
            ".....###..",
            "......*..."]
    path = bfs(grid, (5, 2))
    # [(5, 2), (4, 2), (4, 3), (4, 4), (5, 4), (6, 4)]
    
    0 讨论(0)
  • 2021-01-03 05:46

    If the list is not too big, the easiest solution I find is using the where function of the NumPy library to find the cells which have the value you are looking for. So, you will need to convert your list into a NumPy array.

    The code below might be simplified to make it shorter and more efficient, but in this way it will be clearer. By the way, you can compute two kind of distances: the typical Euclidean and the Manhattan.

    If there is more than one target cell at the same distance of the origin cell, min_coords corresponds to the first cell found (first by rows, then by columns).

    import numpy as np
    
    # The list needs to be transformed into an array in order to use the np.where method
    # arr = np.random.randint(5, size=(6, 6))
    arr = np.array([[0, 0, 0, 1, 1, 3],
                    [0, 0, 2, 1, 1, 0],
                    [0, 0, 1, 1, 1, 1],
                    [3, 0, 3, 1, 1, 1], ])
    
    # Origin cell to make the search
    x0, y0 = (1, 1)
    targetValue = 3
    
    # This is the keypoint of the problem: find the positions of the cells containing the searched value
    positions = np.where(arr == targetValue)
    x, y = positions
    
    dx = abs(x0 - x)  # Horizontal distance
    dy = abs(y0 - y)  # Vertical distance
    
    # There are different criteria to compute distances
    euclidean_distance = np.sqrt(dx ** 2 + dy ** 2)
    manhattan_distance = abs(dx + dy)
    my_distance = euclidean_distance  # Criterion choice
    min_dist = min(my_distance)
    print(min_dist)
    
    min_pos = np.argmin(my_distance)  # This method will only return the first occurrence (!)
    min_coords = x[min_pos], y[min_pos]
    print(min_coords)
    
    0 讨论(0)
提交回复
热议问题