input: Write a function to find the shortest path between two points in a matrix using BFS. If the end point is reachable, return the length of the shortest path. Return -1 if the end point is not reachable.
  def shortest_path(matrix, start, end):
    queue = []
    min_len = -1
    queue.append([start])
    while queue:
      path = queue.pop(0)
      x, y = path[-1]
      if (x, y) == end:
        min_len = len(path)
        break
      for dx, dy in [[-1, 0], [1, 0], [0, -1], [0, 1]]:
        new_x, new_y = x + dx, y + dy
        if 0 <= new_x < len(matrix) and 0 <= new_y < len(matrix[0]):
          if matrix[new_x][new_y] == 0:
            queue.append(path + [(new_x, new_y)])
    return min_len
  
  assert shortest_path([[2, 3, 5], [1, 7, 6], [3, 0, 9]], (0, 0), (2, 2))==-1
  assert shortest_path([[0, 0, 0], [1, 0, 1], [3, 0, 0]], (0, 0), (2, 2))==5
  assert shortest_path([[0, 1, 0], [1, 0, 1], [0, 0, 0]], (0, 0), (2, 2))==5
  assert shortest_path([[0, 1, 1], [1, 1, 1], [1, 1, 0]], (0, 0), (2, 2))==-1
  assert shortest_path([], (0, 0), (2, 2))==-1
output: def shortest_path(matrix, start, end):
    queue = []
    min_len = -1
    queue.append([start])
    while queue:
      path = queue.pop(0)
      x, y = path[-1]
      if (x, y) == end:
        min_len = len(path) - 1
        break
      for dx, dy in [[-1, 0], [1, 0], [0, -1], [0, 1]]:
        new_x, new_y = x + dx, y + dy
        if 0 <= new_x < len(matrix) and 0 <= new_y < len(matrix[0]):
          if matrix[new_x][new_y] == 0:
            matrix[new_x][new_y] = 1
            queue.append(path + [(new_x, new_y)])
    return min_len