mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-23 21:11:08 +00:00
UPDATED rat_in_maze.py (#9148)
* UPDATED rat_in_maze.py * Update reddit.py in Webprogramming b/c it was causing error in pre-commit tests while raising PR. * UPDATED rat_in_maze.py * fixed return type to only maze,otherwise raise valueError. * fixed whitespaces error,improved matrix visual. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * updated. * Try * updated * updated * Apply suggestions from code review --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss <cclauss@me.com>
This commit is contained in:
parent
d5806258d4
commit
c16d2f8865
|
@ -1,91 +1,164 @@
|
||||||
from __future__ import annotations
|
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]]:
|
||||||
"""
|
"""
|
||||||
This method solves the "rat in maze" problem.
|
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 :
|
Parameters :
|
||||||
maze(2D matrix) : maze
|
- maze: A two dimensional matrix of zeros and ones.
|
||||||
|
- source_row: The row index of the starting point.
|
||||||
|
- source_column: The column index of the starting point.
|
||||||
|
- destination_row: The row index of the destination point.
|
||||||
|
- destination_column: The column index of the destination point.
|
||||||
Returns:
|
Returns:
|
||||||
Return: True if the maze has a solution or False if it does not.
|
- solution: A 2D matrix representing the solution path if it exists.
|
||||||
|
Raises:
|
||||||
|
- ValueError: If no solution exists or if the source or
|
||||||
|
destination coordinates are invalid.
|
||||||
|
Description:
|
||||||
|
This method navigates through a maze represented as an n by n matrix,
|
||||||
|
starting from a specified source cell and
|
||||||
|
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],
|
>>> maze = [[0, 1, 0, 1, 1],
|
||||||
... [0, 0, 0, 0, 0],
|
... [0, 0, 0, 0, 0],
|
||||||
... [1, 0, 1, 0, 1],
|
... [1, 0, 1, 0, 1],
|
||||||
... [0, 0, 1, 0, 0],
|
... [0, 0, 1, 0, 0],
|
||||||
... [1, 0, 0, 1, 0]]
|
... [1, 0, 0, 1, 0]]
|
||||||
>>> solve_maze(maze)
|
>>> solve_maze(maze,0,0,len(maze)-1,len(maze)-1) # doctest: +NORMALIZE_WHITESPACE
|
||||||
[1, 0, 0, 0, 0]
|
[[0, 1, 1, 1, 1],
|
||||||
[1, 1, 1, 1, 0]
|
[0, 0, 0, 0, 1],
|
||||||
[0, 0, 0, 1, 0]
|
[1, 1, 1, 0, 1],
|
||||||
[0, 0, 0, 1, 1]
|
[1, 1, 1, 0, 0],
|
||||||
[0, 0, 0, 0, 1]
|
[1, 1, 1, 1, 0]]
|
||||||
True
|
|
||||||
|
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],
|
>>> maze = [[0, 1, 0, 1, 1],
|
||||||
... [0, 0, 0, 0, 0],
|
... [0, 0, 0, 0, 0],
|
||||||
... [0, 0, 0, 0, 1],
|
... [0, 0, 0, 0, 1],
|
||||||
... [0, 0, 0, 0, 0],
|
... [0, 0, 0, 0, 0],
|
||||||
... [0, 0, 0, 0, 0]]
|
... [0, 0, 0, 0, 0]]
|
||||||
>>> solve_maze(maze)
|
>>> solve_maze(maze,0,0,len(maze)-1,len(maze)-1) # doctest: +NORMALIZE_WHITESPACE
|
||||||
[1, 0, 0, 0, 0]
|
[[0, 1, 1, 1, 1],
|
||||||
[1, 0, 0, 0, 0]
|
[0, 1, 1, 1, 1],
|
||||||
[1, 0, 0, 0, 0]
|
[0, 1, 1, 1, 1],
|
||||||
[1, 0, 0, 0, 0]
|
[0, 1, 1, 1, 1],
|
||||||
[1, 1, 1, 1, 1]
|
[0, 0, 0, 0, 0]]
|
||||||
True
|
|
||||||
|
|
||||||
>>> maze = [[0, 0, 0],
|
>>> maze = [[0, 0, 0],
|
||||||
... [0, 1, 0],
|
... [0, 1, 0],
|
||||||
... [1, 0, 0]]
|
... [1, 0, 0]]
|
||||||
>>> solve_maze(maze)
|
>>> solve_maze(maze,0,0,len(maze)-1,len(maze)-1) # doctest: +NORMALIZE_WHITESPACE
|
||||||
[1, 1, 1]
|
[[0, 0, 0],
|
||||||
[0, 0, 1]
|
[1, 1, 0],
|
||||||
[0, 0, 1]
|
[1, 1, 0]]
|
||||||
True
|
|
||||||
|
|
||||||
>>> maze = [[0, 1, 0],
|
>>> maze = [[1, 0, 0],
|
||||||
... [0, 1, 0],
|
... [0, 1, 0],
|
||||||
... [1, 0, 0]]
|
... [1, 0, 0]]
|
||||||
>>> solve_maze(maze)
|
>>> solve_maze(maze,0,1,len(maze)-1,len(maze)-1) # doctest: +NORMALIZE_WHITESPACE
|
||||||
No solution exists!
|
[[1, 0, 0],
|
||||||
False
|
[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) # doctest: +NORMALIZE_WHITESPACE
|
||||||
|
[[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)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: No solution exists!
|
||||||
|
|
||||||
|
>>> maze = [[0, 0],
|
||||||
|
... [1, 1]]
|
||||||
|
>>> solve_maze(maze,0,0,len(maze)-1,len(maze)-1)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: No solution exists!
|
||||||
|
|
||||||
>>> maze = [[0, 1],
|
>>> maze = [[0, 1],
|
||||||
... [1, 0]]
|
... [1, 0]]
|
||||||
>>> solve_maze(maze)
|
>>> solve_maze(maze,2,0,len(maze)-1,len(maze)-1)
|
||||||
No solution exists!
|
Traceback (most recent call last):
|
||||||
False
|
...
|
||||||
|
ValueError: Invalid source or destination coordinates
|
||||||
|
|
||||||
|
>>> maze = [[1, 0, 0],
|
||||||
|
... [0, 1, 0],
|
||||||
|
... [1, 0, 0]]
|
||||||
|
>>> solve_maze(maze,0,1,len(maze),len(maze)-1)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Invalid source or destination coordinates
|
||||||
"""
|
"""
|
||||||
size = len(maze)
|
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)
|
||||||
|
):
|
||||||
|
raise ValueError("Invalid source or destination coordinates")
|
||||||
# We need to create solution object to save path.
|
# We need to create solution object to save path.
|
||||||
solutions = [[0 for _ in range(size)] for _ in range(size)]
|
solutions = [[1 for _ in range(size)] for _ in range(size)]
|
||||||
solved = run_maze(maze, 0, 0, solutions)
|
solved = run_maze(
|
||||||
|
maze, source_row, source_column, destination_row, destination_column, solutions
|
||||||
|
)
|
||||||
if solved:
|
if solved:
|
||||||
print("\n".join(str(row) for row in solutions))
|
return solutions
|
||||||
else:
|
else:
|
||||||
print("No solution exists!")
|
raise ValueError("No solution exists!")
|
||||||
return solved
|
|
||||||
|
|
||||||
|
|
||||||
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]],
|
||||||
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
This method is recursive starting from (i, j) and going in one of four directions:
|
This method is recursive starting from (i, j) and going in one of four directions:
|
||||||
up, down, left, right.
|
up, down, left, right.
|
||||||
If a path is found to destination it returns True otherwise it returns False.
|
If a path is found to destination it returns True otherwise it returns False.
|
||||||
Parameters:
|
Parameters
|
||||||
maze(2D matrix) : maze
|
maze: A two dimensional matrix of zeros and ones.
|
||||||
i, j : coordinates of matrix
|
i, j : coordinates of matrix
|
||||||
solutions(2D matrix) : solutions
|
solutions: A two dimensional matrix of solutions.
|
||||||
Returns:
|
Returns:
|
||||||
Boolean if path is found True, Otherwise False.
|
Boolean if path is found True, Otherwise False.
|
||||||
"""
|
"""
|
||||||
size = len(maze)
|
size = len(maze)
|
||||||
# Final check point.
|
# Final check point.
|
||||||
if i == j == (size - 1):
|
if i == destination_row and j == destination_column and maze[i][j] == 0:
|
||||||
solutions[i][j] = 1
|
solutions[i][j] = 0
|
||||||
return True
|
return True
|
||||||
|
|
||||||
lower_flag = (not i < 0) and (not j < 0) # Check lower bounds
|
lower_flag = (not i < 0) and (not j < 0) # Check lower bounds
|
||||||
|
@ -93,21 +166,27 @@ def run_maze(maze: list[list[int]], i: int, j: int, solutions: list[list[int]])
|
||||||
|
|
||||||
if lower_flag and upper_flag:
|
if lower_flag and upper_flag:
|
||||||
# check for already visited and block points.
|
# 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:
|
if block_flag:
|
||||||
# check visited
|
# check visited
|
||||||
solutions[i][j] = 1
|
solutions[i][j] = 0
|
||||||
|
|
||||||
# check for directions
|
# check for directions
|
||||||
if (
|
if (
|
||||||
run_maze(maze, i + 1, j, solutions)
|
run_maze(maze, i + 1, j, destination_row, destination_column, solutions)
|
||||||
or run_maze(maze, i, j + 1, solutions)
|
or run_maze(
|
||||||
or run_maze(maze, i - 1, j, solutions)
|
maze, i, j + 1, destination_row, destination_column, solutions
|
||||||
or run_maze(maze, i, j - 1, 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 True
|
||||||
|
|
||||||
solutions[i][j] = 0
|
solutions[i][j] = 1
|
||||||
return False
|
return False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -115,4 +194,4 @@ def run_maze(maze: list[list[int]], i: int, j: int, solutions: list[list[int]])
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import doctest
|
import doctest
|
||||||
|
|
||||||
doctest.testmod()
|
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user