1+ from collections import deque
2+ from typing import List
3+ from path import Solution
4+
5+ class Solution :
6+ def shortestPathBinaryMatrix (self , grid : List [List [int ]]) -> int :
7+ ROWS , COLS = len (grid ), len (grid [0 ])
8+ if grid [0 ][0 ] == 1 :
9+ return - 1
10+ length = 1
11+ visit = set ()
12+ q = deque ()
13+ q .append ((0 ,0 ))
14+ visit .add ((0 ,0 ))
15+
16+ while q :
17+ for i in range (len (q )):
18+ row , col = q .popleft ()
19+ if row == ROWS - 1 and col == COLS - 1 :
20+ return length
21+ directions = [
22+ # diagonals
23+ [- 1 ,- 1 ], [- 1 , 1 ], [1 , - 1 ], [1 , 1 ],
24+ # straight
25+ [0 , 1 ], [0 , - 1 ], [1 , 0 ], [- 1 , 0 ]
26+ ]
27+ for dr , dc in directions :
28+ if min (row + dr , col + dc ) < 0 :
29+ continue
30+ if row + dr == ROWS or col + dc == COLS :
31+ continue
32+ if (row + dr , col + dc ) in visit :
33+ continue
34+ if grid [row + dr ][col + dc ] == 1 :
35+ continue
36+ visit .add ((row + dr ,col + dc ))
37+ q .append ((row + dr , col + dc ))
38+ length += 1
39+ return - 1
40+
41+
42+ def test_shortest_path ():
43+ solution = Solution ()
44+
45+ # Test 1: Example 1 from problem - 2x2 grid
46+ grid1 = [[0 ,1 ],
47+ [1 ,0 ]]
48+ assert solution .shortestPathBinaryMatrix (grid1 ) == 2 , "Test 1 Failed"
49+ print ("✓ Test 1 passed: Example 1 - 2x2 grid" )
50+
51+ # Test 2: Example 2 from problem - 3x3 grid
52+ grid2 = [[0 ,0 ,0 ],
53+ [1 ,1 ,0 ],
54+ [1 ,1 ,0 ]]
55+ assert solution .shortestPathBinaryMatrix (grid2 ) == 4 , "Test 2 Failed"
56+ print ("✓ Test 2 passed: Example 2 - 3x3 grid with path" )
57+
58+ # Test 3: Example 3 from problem - no path (starting cell blocked)
59+ grid3 = [[1 ,0 ,0 ],
60+ [1 ,1 ,0 ],
61+ [1 ,1 ,0 ]]
62+ assert solution .shortestPathBinaryMatrix (grid3 ) == - 1 , "Test 3 Failed"
63+ print ("✓ Test 3 passed: Example 3 - starting cell blocked" )
64+
65+ # Test 4: Direct diagonal path
66+ grid4 = [[0 ,0 ,0 ],
67+ [0 ,0 ,0 ],
68+ [0 ,0 ,0 ]]
69+ assert solution .shortestPathBinaryMatrix (grid4 ) == 3 , "Test 4 Failed"
70+ print ("✓ Test 4 passed: Direct diagonal path" )
71+
72+ # Test 5: Ending cell blocked
73+ grid5 = [[0 ,0 ,0 ],
74+ [0 ,0 ,0 ],
75+ [0 ,0 ,1 ]]
76+ assert solution .shortestPathBinaryMatrix (grid5 ) == - 1 , "Test 5 Failed"
77+ print ("✓ Test 5 passed: Ending cell blocked" )
78+
79+ # Test 6: No path exists (wall in middle)
80+ grid6 = [[0 ,0 ,1 ],
81+ [1 ,1 ,1 ],
82+ [1 ,0 ,0 ]]
83+ assert solution .shortestPathBinaryMatrix (grid6 ) == - 1 , "Test 6 Failed"
84+ print ("✓ Test 6 passed: No path exists" )
85+
86+ # Test 7: Single cell (edge case)
87+ grid7 = [[0 ]]
88+ assert solution .shortestPathBinaryMatrix (grid7 ) == 1 , "Test 7 Failed"
89+ print ("✓ Test 7 passed: Single cell grid" )
90+
91+ # Test 8: Single cell blocked
92+ grid8 = [[1 ]]
93+ assert solution .shortestPathBinaryMatrix (grid8 ) == - 1 , "Test 8 Failed"
94+ print ("✓ Test 8 passed: Single cell blocked" )
95+
96+ # Test 9: Longer path needed
97+ grid9 = [[0 ,0 ,0 ,0 ],
98+ [1 ,1 ,1 ,0 ],
99+ [0 ,0 ,0 ,0 ],
100+ [0 ,1 ,1 ,0 ]]
101+ result9 = solution .shortestPathBinaryMatrix (grid9 )
102+ assert result9 == 6 , f"Test 9 Failed: Expected 5, got { result9 } "
103+ print ("✓ Test 9 passed: Longer path with obstacles" )
104+
105+
106+ print ("\n ✅ All tests passed!" )
107+
108+ if __name__ == "__main__" :
109+ test_shortest_path ()
0 commit comments