From 4c14b6d0b37ba3cb606a5e2b01cb35f1cc0be702 Mon Sep 17 00:00:00 2001 From: tseremonnikovaaa Date: Sun, 24 May 2026 20:09:28 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B0=D1=82=D1=82=D0=B5=D1=80=D0=BD=20St?= =?UTF-8?q?rategy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tseremonnikovaaa/lab2/docs/data/main2.py | 195 +++++++++++++++++------ 1 file changed, 145 insertions(+), 50 deletions(-) diff --git a/tseremonnikovaaa/lab2/docs/data/main2.py b/tseremonnikovaaa/lab2/docs/data/main2.py index fdfb3bf..4cc5f6c 100644 --- a/tseremonnikovaaa/lab2/docs/data/main2.py +++ b/tseremonnikovaaa/lab2/docs/data/main2.py @@ -1,74 +1,51 @@ -import os import time import csv -from collections import deque import heapq +from collections import deque from abc import ABC, abstractmethod +import matplotlib.pyplot as plt +import pandas as pd from dataclasses import dataclass -from typing import List, Tuple, Optional, Dict, Any -import random +import os + -@dataclass class Cell: """Клетка лабиринта""" - x: int - y: int - is_wall: bool = False - is_start: bool = False - is_exit: bool = False - weight: int = 1 - - def is_passable(self) -> bool: + def __init__(self, x, y, is_wall=False): + self.x = x + self.y = y + self.is_wall = is_wall + self.is_start = False + self.is_exit = False + + def is_passable(self): return not self.is_wall - - def __hash__(self): - return hash((self.x, self.y)) - - def __eq__(self, other): - return self.x == other.x and self.y == other.y if other else False class Maze: """Лабиринт""" - - def __init__(self, width: int, height: int): + def __init__(self, width, height): self.width = width self.height = height - self._cells: List[List[Optional[Cell]]] = [[None for _ in range(width)] for _ in range(height)] - self.start: Optional[Cell] = None - self.exit: Optional[Cell] = None - - def set_cell(self, x: int, y: int, cell: Cell) -> None: + self.cells = [[Cell(x, y) for x in range(width)] for y in range(height)] + self.start = None + self.exit = None + + def get_cell(self, x, y): if 0 <= x < self.width and 0 <= y < self.height: - self._cells[y][x] = cell - - def get_cell(self, x: int, y: int) -> Optional[Cell]: - if 0 <= x < self.width and 0 <= y < self.height: - return self._cells[y][x] + return self.cells[y][x] return None - - def get_neighbors(self, cell: Cell) -> List[Cell]: + + def get_neighbors(self, cell): neighbors = [] - directions = [(0, 1), (0, -1), (1, 0), (-1, 0)] - - for dx, dy in directions: + for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]: nx, ny = cell.x + dx, cell.y + dy - neighbor = self.get_cell(nx, ny) - if neighbor and neighbor.is_passable(): - neighbors.append(neighbor) - + nb = self.get_cell(nx, ny) + if nb and nb.is_passable(): + neighbors.append(nb) return neighbors - def get_all_cells(self) -> List[Cell]: - cells = [] - for y in range(self.height): - for x in range(self.width): - cell = self.get_cell(x, y) - if cell: - cells.append(cell) - return cells - - def __str__(self) -> str: + def __str__(self): result = "" for y in range(self.height): for x in range(self.width): @@ -85,3 +62,121 @@ class Maze: result += " " result += "\n" return result + +class MazeBuilder(ABC): + @abstractmethod + def build_from_file(self, filename): + pass + + +class TextFileMazeBuilder(MazeBuilder): + def build_from_file(self, filename): + with open(filename, 'r', encoding='utf-8') as f: + lines = [line.rstrip('\n') for line in f.readlines()] + height = len(lines) + width = max(len(line) for line in lines) + maze = Maze(width, height) + + for y, line in enumerate(lines): + for x, ch in enumerate(line): + cell = maze.get_cell(x, y) + if ch == '#': + cell.is_wall = True + elif ch == 'S': + cell.is_start = True + maze.start = cell + elif ch == 'E': + cell.is_exit = True + maze.exit = cell + else: + cell.is_wall = False + return maze + + +class PathFindingStrategy(ABC): + @abstractmethod + def find_path(self, maze, start, exit): + pass + + +class BFSStrategy(PathFindingStrategy): + """Поиск в ширину""" + + def find_path(self, maze, start, exit): + visited = set() + if start == exit: + return [start], 1 + queue = deque([start]) + visited.add(start) + parent = {start: None} + while queue: + current = queue.popleft() + for nb in maze.get_neighbors(current): + if nb not in visited: + visited.add(nb) + parent[nb] = current + if nb == exit: + path = [] + node = nb + while node is not None: + path.append(node) + node = parent[node] + path.reverse() + return path, len(visited) + queue.append(nb) + return [], len(visited) + + +class DFSStrategy(PathFindingStrategy): + """Поиск в глубину""" + + def find_path(self, maze, start, exit): + visited = set() + stack = [(start, [start])] + while stack: + current, path = stack.pop() + if current == exit: + return path, len(visited) + visited.add(current) + for nb in maze.get_neighbors(current): + if nb not in visited: + stack.append((nb, path + [nb])) + return [], len(visited) + + +class AStarStrategy(PathFindingStrategy): + """Алгоритм A""" + + def heuristic(self, cell, exit): + return abs(cell.x - exit.x) + abs(cell.y - exit.y) + + def find_path(self, maze, start, exit): + open_set = [] + counter = 0 + heapq.heappush(open_set, (0, counter, start)) + counter += 1 + came_from = {} + g_score = {start: 0} + f_score = {start: self.heuristic(start, exit)} + visited = set() + while open_set: + _, _, current = heapq.heappop(open_set) + visited.add(current) + if current == exit: + path = [] + node = current + while node in came_from: + path.append(node) + node = came_from[node] + path.append(start) + path.reverse() + return path, len(visited) + for nb in maze.get_neighbors(current): + tentative_g = g_score[current] + 1 + if tentative_g < g_score.get(nb, float('inf')): + came_from[nb] = current + g_score[nb] = tentative_g + f = tentative_g + self.heuristic(nb, exit) + heapq.heappush(open_set, (f, counter, nb)) + counter += 1 + return [], len(visited) \ No newline at end of file