-
-
Notifications
You must be signed in to change notification settings - Fork 46.6k
UPDATED rat_in_maze.py #9148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UPDATED rat_in_maze.py #9148
Changes from 3 commits
9450821
9a1d65f
741bb72
1b2a9e6
726bc5c
d9e1956
49e6dee
b59a85d
cedaf35
775d6cd
c740da3
591c098
9c89c79
1539b6f
e169d07
8013870
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,125 @@ | ||
from __future__ import annotations | ||
|
||
|
||
def solve_maze(maze: list[list[int]]) -> bool: | ||
def solve_maze( | ||
maze: list[list[int]], | ||
source_row: int, | ||
source_column: int, | ||
destination_row: int, | ||
destination_column: int, | ||
) -> list[list[int]] | None: | ||
""" | ||
This method solves the "rat in maze" problem. | ||
In this problem we have some n by n matrix, a start point and an end point. | ||
We want to go from the start to the end. In this matrix zeroes represent walls | ||
and ones paths we can use. | ||
Parameters : | ||
maze(2D matrix) : maze | ||
- maze(2D matrix) : maze | ||
- source_row (int): The row index of the starting point. | ||
- source_column (int): The column index of the starting point. | ||
- destination_row (int): The row index of the destination point. | ||
- destination_column (int): The column index of the destination point. | ||
cclauss marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Returns: | ||
Return: True if the maze has a solution or False if it does not. | ||
Return: solution(2D matrix) if path exist ,otherwise None. | ||
Description: | ||
This method navigates through a maze represented as an n by n matrix, | ||
starting from a specified source cell and | ||
cclauss marked this conversation as resolved.
Show resolved
Hide resolved
|
||
aiming to reach a destination cell. | ||
The maze consists of walls (1s) and open paths (0s). | ||
By providing custom row and column values, the source and destination | ||
cells can be adjusted. | ||
>>> maze = [[0, 1, 0, 1, 1], | ||
... [0, 0, 0, 0, 0], | ||
... [1, 0, 1, 0, 1], | ||
... [0, 0, 1, 0, 0], | ||
... [1, 0, 0, 1, 0]] | ||
>>> solve_maze(maze) | ||
[1, 0, 0, 0, 0] | ||
[1, 1, 1, 1, 0] | ||
[0, 0, 0, 1, 0] | ||
[0, 0, 0, 1, 1] | ||
[0, 0, 0, 0, 1] | ||
True | ||
>>> solve_maze(maze,0,0,len(maze)-1,len(maze)-1) | ||
[[0, 1, 1, 1, 1], [0, 0, 0, 0, 1], [1, 1, 1, 0, 1],\ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is the output on the same line now? It makes reading the solution harder. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://docs.python.org/3/library/doctest.html#doctest.NORMALIZE_WHITESPACE will allow you to have doctests that ignore the whitespace so the matrix can look like a matrix. |
||
[1, 1, 1, 0, 0], [1, 1, 1, 1, 0]] | ||
|
||
Note: | ||
In the output maze, the zeros (0s) represent one of the possible | ||
paths from the source to the destination. | ||
|
||
>>> maze = [[0, 1, 0, 1, 1], | ||
... [0, 0, 0, 0, 0], | ||
... [0, 0, 0, 0, 1], | ||
... [0, 0, 0, 0, 0], | ||
... [0, 0, 0, 0, 0]] | ||
>>> solve_maze(maze) | ||
[1, 0, 0, 0, 0] | ||
[1, 0, 0, 0, 0] | ||
[1, 0, 0, 0, 0] | ||
[1, 0, 0, 0, 0] | ||
[1, 1, 1, 1, 1] | ||
True | ||
>>> solve_maze(maze,0,0,len(maze)-1,len(maze)-1) | ||
[[0, 1, 1, 1, 1], [0, 1, 1, 1, 1], [0, 1, 1, 1, 1],\ | ||
[0, 1, 1, 1, 1], [0, 0, 0, 0, 0]] | ||
|
||
>>> maze = [[0, 0, 0], | ||
... [0, 1, 0], | ||
... [1, 0, 0]] | ||
>>> solve_maze(maze) | ||
[1, 1, 1] | ||
[0, 0, 1] | ||
[0, 0, 1] | ||
True | ||
>>> solve_maze(maze,0,0,len(maze)-1,len(maze)-1) | ||
[[0, 0, 0], [1, 1, 0], [1, 1, 0]] | ||
|
||
>>> maze = [[0, 1, 0], | ||
>>> maze = [[1, 0, 0], | ||
... [0, 1, 0], | ||
... [1, 0, 0]] | ||
>>> solve_maze(maze) | ||
No solution exists! | ||
False | ||
>>> solve_maze(maze,0,1,len(maze)-1,len(maze)-1) | ||
[[1, 0, 0], [1, 1, 0], [1, 1, 0]] | ||
|
||
>>> maze = [[1, 1, 0, 0, 1, 0, 0, 1], | ||
... [1, 0, 1, 0, 0, 1, 1, 1], | ||
... [0, 1, 0, 1, 0, 0, 1, 0], | ||
... [1, 1, 1, 0, 0, 1, 0, 1], | ||
... [0, 1, 0, 0, 1, 0, 1, 1], | ||
... [0, 0, 0, 1, 1, 1, 0, 1], | ||
... [0, 1, 0, 1, 0, 1, 1, 1], | ||
... [1, 1, 0, 0, 0, 0, 0, 1]] | ||
>>> solve_maze(maze,0,2,len(maze)-1,2) | ||
[[1, 1, 0, 0, 1, 1, 1, 1], [1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 1, 1, 0, 1, 1, 1],\ | ||
[1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 0, 0, 1, 1, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1],\ | ||
[1, 1, 0, 1, 1, 1, 1, 1], [1, 1, 0, 1, 1, 1, 1, 1]] | ||
>>> maze = [[1, 0, 0], | ||
... [0, 1, 1], | ||
... [1, 0, 1]] | ||
>>> solve_maze(maze,0,1,len(maze)-1,len(maze)-1) | ||
|
||
>>> maze = [[0, 0], | ||
... [1, 1]] | ||
>>> solve_maze(maze,0,0,len(maze)-1,len(maze)-1) | ||
|
||
>>> maze = [[0, 1], | ||
... [1, 0]] | ||
>>> solve_maze(maze) | ||
No solution exists! | ||
False | ||
>>> solve_maze(maze,2,0,len(maze)-1,len(maze)-1) | ||
|
||
>>> maze = [[1, 0, 0], | ||
... [0, 1, 1], | ||
... [1, 0, 0]] | ||
>>> solve_maze(maze,0,1,len(maze),len(maze)-1) | ||
|
||
""" | ||
size = len(maze) | ||
# Check if source and destination coordinates are Invalid. | ||
if not (0 <= source_row <= size - 1 and 0 <= source_column <= size - 1) or ( | ||
not (0 <= destination_row <= size - 1 and 0 <= destination_column <= size - 1) | ||
): | ||
return None | ||
# We need to create solution object to save path. | ||
solutions = [[0 for _ in range(size)] for _ in range(size)] | ||
solved = run_maze(maze, 0, 0, solutions) | ||
solutions = [[1 for _ in range(size)] for _ in range(size)] | ||
solved = run_maze( | ||
maze, source_row, source_column, destination_row, destination_column, solutions | ||
) | ||
if solved: | ||
print("\n".join(str(row) for row in solutions)) | ||
return solutions | ||
else: | ||
print("No solution exists!") | ||
return solved | ||
return None | ||
|
||
|
||
def run_maze(maze: list[list[int]], i: int, j: int, solutions: list[list[int]]) -> bool: | ||
def run_maze( | ||
maze: list[list[int]], | ||
i: int, | ||
j: int, | ||
destination_row: int, | ||
destination_column: int, | ||
solutions: list[list[int]], | ||
) -> list[list[int]] | None: | ||
""" | ||
This method is recursive starting from (i, j) and going in one of four directions: | ||
up, down, left, right. | ||
If a path is found to destination it returns True otherwise it returns False. | ||
Parameters: | ||
Parameters | ||
maze(2D matrix) : maze | ||
i, j : coordinates of matrix | ||
solutions(2D matrix) : solutions | ||
cclauss marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
@@ -84,32 +128,38 @@ def run_maze(maze: list[list[int]], i: int, j: int, solutions: list[list[int]]) | |
""" | ||
size = len(maze) | ||
# Final check point. | ||
if i == j == (size - 1): | ||
solutions[i][j] = 1 | ||
return True | ||
if i == destination_row and j == destination_column and maze[i][j] == 0: | ||
solutions[i][j] = 0 | ||
return solutions | ||
|
||
lower_flag = (not i < 0) and (not j < 0) # Check lower bounds | ||
upper_flag = (i < size) and (j < size) # Check upper bounds | ||
|
||
if lower_flag and upper_flag: | ||
# check for already visited and block points. | ||
block_flag = (not solutions[i][j]) and (not maze[i][j]) | ||
block_flag = (solutions[i][j]) and (not maze[i][j]) | ||
if block_flag: | ||
# check visited | ||
solutions[i][j] = 1 | ||
solutions[i][j] = 0 | ||
|
||
# check for directions | ||
if ( | ||
run_maze(maze, i + 1, j, solutions) | ||
or run_maze(maze, i, j + 1, solutions) | ||
or run_maze(maze, i - 1, j, solutions) | ||
or run_maze(maze, i, j - 1, solutions) | ||
run_maze(maze, i + 1, j, destination_row, destination_column, solutions) | ||
or run_maze( | ||
maze, i, j + 1, destination_row, destination_column, solutions | ||
) | ||
or run_maze( | ||
maze, i - 1, j, destination_row, destination_column, solutions | ||
) | ||
or run_maze( | ||
maze, i, j - 1, destination_row, destination_column, solutions | ||
) | ||
): | ||
return True | ||
return solutions | ||
|
||
solutions[i][j] = 0 | ||
return False | ||
return False | ||
solutions[i][j] = 1 | ||
return None | ||
return None | ||
|
||
|
||
if __name__ == "__main__": | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returning two different datatypes pushes work on the caller. Please consider raising an exception if there is no solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my remark in the general discussion of this Pull Request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.