Added Puzzle.py

This commit is contained in:
Andrew Scott 2022-08-30 00:21:11 -04:00
parent 8dea1ccff0
commit 2671d317ff
Signed by: a
GPG key ID: 3EB62D0BBB8DB381

140
Puzzle.py Normal file
View file

@ -0,0 +1,140 @@
from typing import Deque
def solve_puzzle(Board: list, Source: tuple, Destination: tuple):
"""Finds a solution to a 2-D puzzle using a breadth first search
Parameters
----------
Board : list
A graph represented as an adjacency matrix
Source : tuple
The starting point on the board
Destination : tuple
The goal position
"""
queue = Deque()
queue.append(Source)
visited = {}
if is_valid(Source[0], Source[1], Board, visited):
visited[Source] = 0
if Source == Destination:
return [Destination]
else:
return None
while len(queue) > 0:
r, c = queue.popleft()
possible_moves = [(1, 0), (0, 1), (-1, 0), (0, -1)]
for move_row, move_col in possible_moves:
row, col = r + move_row, c + move_col
if is_valid(row, col, Board, visited):
queue.append((row, col))
visited[(row, col)] = visited[(r, c)] + 1
if (row, col) == Destination:
return get_path(row, col, visited)
return None
def is_valid(x: int, y: int, Board: list, visited: dict) -> bool:
"""Helper for solve_puzzle() to determine if a move is valid
Parameters
----------
x : int
Row
y : int
Column
Board : list
A graph represented as an adjacency matrix
visited : dict
Coordinates that have been visited
Returns
-------
bool
True if the move is valid, otherwise False
"""
exists = False
valid = False
if (x >= 0 and y >= 0) and (x < len(Board) and y < len(Board[0])):
exists = True
target = (x, y)
if exists:
if Board[x][y] != "#" and target not in visited:
valid = True
return valid and exists
def get_path(row: int, col: int, visited: dict) -> tuple:
"""Helper for solve_puzzle() to assemble the steps and moves into lists
Parameters
----------
row : int
Row on the board
col : int
Column on the board
visited : dict
Coordinates that have been visited
Returns
-------
tuple
List of tuples containing coordinates traversed, and list of directions
"""
steps = visited[(row, col)]
steps -= 1
path = [(row, col)]
directions = []
while steps >= 0:
if (row - 1, col) in visited and visited[(row - 1, col)] == steps:
path.append((row - 1, col))
directions.append("D")
row -= 1
if (row + 1, col) in visited and visited[(row + 1, col)] == steps:
path.append((row + 1, col))
directions.append("U")
row += 1
if (row, col - 1) in visited and visited[(row, col - 1)] == steps:
path.append((row, col - 1))
directions.append("R")
col -= 1
if (row, col + 1) in visited and visited[(row, col + 1)] == steps:
path.append((row, col + 1))
directions.append("L")
col += 1
steps -= 1
path.reverse()
directions.reverse()
return (path, directions)
# ------------------------------ Basic Testing --------------------------------#
if __name__ == "__main__":
puzzle = [
["-", "-", "-", "-", "-"],
["-", "-", "#", "-", "-"],
["-", "-", "-", "-", "-"],
["#", "-", "#", "#", "-"],
["-", "#", "-", "-", "-"],
]
source = (0, 2)
destination = (2, 2)
# source = (0, 0)
# destination = (4, 4)
result = solve_puzzle(puzzle, source, destination)
print(result)