# shortest path from a source cell to a destination cell of a binary matrix through cells consisting only of 1 s | python3 program for the above approach ; stores the coordinates of the matrix cell ; stores coordinates of a cell and its distance ; check if the given cell is valid or not ; stores the moves of the directions of adjacent cells ; function to find the shortest path from the source to destination in the given matrix ; stores the distance for each cell from the source cell ; distance of source cell is 0 ; initialize a visited array ; mark source cell as visited ; create a queue for bfs ; distance of source cell is 0 ; enqueue source cell ; keeps track of whether destination is reached or not ; iterate until queue is not empty ; deque front of the queue ; if the destination cell is reached , then find the path ; assign the distance of destination to the distance matrix ; stores the smallest path ; iterate until source is reached ; append d ; append u ; append r ; append l ; reverse the backtracked path ; explore all adjacent directions ; if the current cell is valid cell and can be traversed ; mark the adjacent cells as visited ; enque the adjacent cells ; update the distance of the adjacent cells ; if the destination is not reachable ; 

from collections import deque


class Point:
    def __init__(self, xx, yy):
        self .x = xx
        self .y = yy


class Node:
    def __init__(self, P, d):
        self .pt = P
        self .dist = d


def isValid(row, col):
    return (row >= 0) and (col >= 0) and (row < 4) and (col < 4)


dRow = [-1, 0, 0, 1]
dCol = [0, -1, 1, 0]


def pathMoves(mat, src, dest):
    d = [[-1 for i in range(4)]for i in range(4)]
    d[src .x][src .y] = 0
    visited = [[False for i in range(4)]for i in range(4)]
    visited[src .x][src .y] = True
    q = deque()
    s = Node(src, 0)
    q .append(s)
    ok = False
    while (len(q) > 0):
        curr = q .popleft()
        pt = curr .pt
        if (pt .x == dest .x and pt .y == dest .y):
            xx, yy = pt .x, pt .y
            dist = curr .dist
            d[pt .x][pt .y] = dist
            pathmoves = ""
            while (xx != src .x or yy != src .y):
                if (xx > 0 and d[xx - 1][yy] == dist - 1):
                    pathmoves += 'D'
                    xx -= 1
                if (xx < 4 - 1 and d[xx + 1][yy] == dist - 1):
                    pathmoves += 'U'
                    xx += 1
                if (yy > 0 and d[xx][yy - 1] == dist - 1):
                    pathmoves += 'R'
                    yy -= 1
                if (yy < 4 - 1 and d[xx][yy + 1] == dist - 1):
                    pathmoves += 'L'
                    yy += 1
                dist -= 1
            pathmoves = pathmoves[::-1]
            print(pathmoves, end="")
            ok = True
            break
        for i in range(4):
            row = pt .x + dRow[i]
            col = pt .y + dCol[i]
            if (
                isValid(
                    row,
                    col) and (
                    mat[row][col] == '1' or mat[row][col] == 's' or mat[row][col] == 'd') and (
                    not visited[row][col])):
                visited[row][col] = True
                adjCell = Node(Point(row, col), curr .dist + 1)
                q .append(adjCell)
                d[row][col] = curr .dist + 1
    if (not ok):
        print(-1)


if __name__ == '__main__':
    mat = [['0', '1', '0', '1'], ['1', '0', '1', '1'],
           ['0', '1', '1', '1'], ['1', '1', '1', '0']]
    src = Point(0, 3)
    dest = Point(3, 0)
    pathMoves(mat, src, dest)

# Expected output:
DLDLDL