From d2e6975a5045de238d0a2cd709df74368d59503c Mon Sep 17 00:00:00 2001 From: meosyam Date: Thu, 3 Sep 2026 15:10:39 +0000 Subject: [PATCH] [2] add solving methods --- meosyam/docs/data/2/main.py | 162 +++++++++++++++++++++++++++++++++++- 1 file changed, 158 insertions(+), 4 deletions(-) diff --git a/meosyam/docs/data/2/main.py b/meosyam/docs/data/2/main.py index 2b7c8b8..5f7442c 100644 --- a/meosyam/docs/data/2/main.py +++ b/meosyam/docs/data/2/main.py @@ -1,4 +1,9 @@ import sys +import time +from collections import deque +import heapq +from dataclasses import dataclass + class Cell: def __init__(self, x, y, is_wall=False, is_start=False, is_exit=False): @@ -70,12 +75,138 @@ class MazeBuilder: return Maze(width, height, cells, start, exit_cell) -def print_maze(maze): +class PathFindingStrategy: + def find_path(self, maze, start, exit): + raise NotImplementedError + + +class BFSStrategy(PathFindingStrategy): + def find_path(self, maze, start, exit): + if start == exit: + return [start], 1 + queue = deque([start]) + visited = {start} + parent = {start: None} + visited_count = 1 + while queue: + current = queue.popleft() + if current == exit: + path = [] + while current: + path.append(current) + current = parent[current] + path.reverse() + return path, visited_count + for neighbor in maze.get_neighbors(current): + if neighbor not in visited: + visited.add(neighbor) + parent[neighbor] = current + queue.append(neighbor) + visited_count += 1 + return [], visited_count + + +class DFSStrategy(PathFindingStrategy): + def find_path(self, maze, start, exit): + if start == exit: + return [start], 1 + stack = [start] + visited = {start} + parent = {start: None} + visited_count = 1 + while stack: + current = stack.pop() + if current == exit: + path = [] + while current: + path.append(current) + current = parent[current] + path.reverse() + return path, visited_count + for neighbor in maze.get_neighbors(current): + if neighbor not in visited: + visited.add(neighbor) + parent[neighbor] = current + stack.append(neighbor) + visited_count += 1 + return [], visited_count + + +class AStarStrategy(PathFindingStrategy): + @staticmethod + def manhattan(cell, target): + return abs(cell.x - target.x) + abs(cell.y - target.y) + + def find_path(self, maze, start, exit): + if start == exit: + return [start], 1 + open_set = [] + counter = 0 + heapq.heappush(open_set, (0, counter, start)) + g_score = {start: 0} + f_score = {start: self.manhattan(start, exit)} + parent = {start: None} + visited_count = 0 + visited = set() + while open_set: + _, _, current = heapq.heappop(open_set) + if current in visited: + continue + visited.add(current) + visited_count += 1 + if current == exit: + path = [] + while current: + path.append(current) + current = parent[current] + path.reverse() + return path, visited_count + for neighbor in maze.get_neighbors(current): + tentative_g = g_score[current] + 1 + if neighbor not in g_score or tentative_g < g_score[neighbor]: + parent[neighbor] = current + g_score[neighbor] = tentative_g + f = tentative_g + self.manhattan(neighbor, exit) + f_score[neighbor] = f + counter += 1 + heapq.heappush(open_set, (f, counter, neighbor)) + return [], visited_count + + +@dataclass +class SearchStats: + time_ms: float + visited_cells: int + path_length: int + + +class MazeSolver: + def __init__(self, maze, strategy=None): + self.maze = maze + self.strategy = strategy + + def set_strategy(self, strategy): + self.strategy = strategy + + def solve(self): + if self.strategy is None: + raise ValueError("Strategy not set") + start_time = time.perf_counter() + path, visited = self.strategy.find_path(self.maze, self.maze.start, self.maze.exit) + end_time = time.perf_counter() + time_ms = (end_time - start_time) * 1000 + return path, SearchStats(time_ms, visited, len(path) if path else 0) + + +def print_maze(maze, path=None): + path_set = set(path) if path else set() for y in range(maze.height): row = [] for x in range(maze.width): cell = maze.get_cell(x, y) - if cell.is_start: + if cell in path_set and not cell.is_start and not cell.is_exit: + row.append('*') + elif cell.is_start: row.append('S') elif cell.is_exit: row.append('E') @@ -91,12 +222,35 @@ def main(): filename = sys.argv[1] else: filename = 'maze1.txt' + try: maze = MazeBuilder.build_from_file(filename) print(f"Maze loaded ({maze.width}x{maze.height})") - print_maze(maze) + print("Select algorithm: (1) BFS, (2) DFS, (3) A*") + choice = input("Choice: ").strip() + if choice == '1': + strategy = BFSStrategy() + elif choice == '2': + strategy = DFSStrategy() + elif choice == '3': + strategy = AStarStrategy() + else: + print("Invalid, using BFS") + strategy = BFSStrategy() + + solver = MazeSolver(maze, strategy) + path, stats = solver.solve() + if path: + print(f"Path found! Length: {len(path)}") + print(f"Visited cells: {stats.visited_cells}") + print(f"Time: {stats.time_ms:.4f} ms") + print_maze(maze, path) + else: + print("No path found.") + print(f"Visited cells: {stats.visited_cells}") + print(f"Time: {stats.time_ms:.4f} ms") except Exception as e: print(f"Error: {e}") if __name__ == '__main__': - main() + main() \ No newline at end of file