mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-12-18 01:00:15 +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
|
||||
|
||||
|
||||
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.
|
||||
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: 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:
|
||||
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],
|
||||
... [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) # doctest: +NORMALIZE_WHITESPACE
|
||||
[[0, 1, 1, 1, 1],
|
||||
[0, 0, 0, 0, 1],
|
||||
[1, 1, 1, 0, 1],
|
||||
[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) # doctest: +NORMALIZE_WHITESPACE
|
||||
[[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) # doctest: +NORMALIZE_WHITESPACE
|
||||
[[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) # doctest: +NORMALIZE_WHITESPACE
|
||||
[[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) # 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],
|
||||
... [1, 0]]
|
||||
>>> solve_maze(maze)
|
||||
No solution exists!
|
||||
False
|
||||
>>> solve_maze(maze,2,0,len(maze)-1,len(maze)-1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
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)
|
||||
# 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.
|
||||
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
|
||||
raise ValueError("No solution exists!")
|
||||
|
||||
|
||||
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:
|
||||
up, down, left, right.
|
||||
If a path is found to destination it returns True otherwise it returns False.
|
||||
Parameters:
|
||||
maze(2D matrix) : maze
|
||||
Parameters
|
||||
maze: A two dimensional matrix of zeros and ones.
|
||||
i, j : coordinates of matrix
|
||||
solutions(2D matrix) : solutions
|
||||
solutions: A two dimensional matrix of solutions.
|
||||
Returns:
|
||||
Boolean if path is found True, Otherwise False.
|
||||
"""
|
||||
size = len(maze)
|
||||
# Final check point.
|
||||
if i == j == (size - 1):
|
||||
solutions[i][j] = 1
|
||||
if i == destination_row and j == destination_column and maze[i][j] == 0:
|
||||
solutions[i][j] = 0
|
||||
return True
|
||||
|
||||
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:
|
||||
# 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
|
||||
|
||||
solutions[i][j] = 0
|
||||
solutions[i][j] = 1
|
||||
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__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
||||
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
|
||||
|
|
Loading…
Reference in New Issue
Block a user