From 31466e37439aaa51f6a5d31e80cdfd07ffe8a6ec Mon Sep 17 00:00:00 2001 From: mddcorporation Date: Thu, 7 May 2026 15:54:10 +0300 Subject: [PATCH] =?UTF-8?q?[5]=20=D0=BF=D0=B0=D1=80=D0=B0=20=D0=BB=D0=B0?= =?UTF-8?q?=D0=B1=D0=B8=D1=80=D0=B8=D0=BD=D1=82=D0=BE=D0=B2=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VaravinVV/docs/data/task2/easy.txt | 10 +++ VaravinVV/docs/data/task2/main.py | 101 +++++++-------------------- VaravinVV/docs/data/task2/noexit.txt | 5 ++ 3 files changed, 42 insertions(+), 74 deletions(-) create mode 100644 VaravinVV/docs/data/task2/easy.txt create mode 100644 VaravinVV/docs/data/task2/noexit.txt diff --git a/VaravinVV/docs/data/task2/easy.txt b/VaravinVV/docs/data/task2/easy.txt new file mode 100644 index 0000000..ccbfb9a --- /dev/null +++ b/VaravinVV/docs/data/task2/easy.txt @@ -0,0 +1,10 @@ +########## +#S ### # +## ## # # +# ## # # +# #### # # +# # # # +### # +### ### ## +# ### E# +########## \ No newline at end of file diff --git a/VaravinVV/docs/data/task2/main.py b/VaravinVV/docs/data/task2/main.py index f5b246d..e4a6850 100644 --- a/VaravinVV/docs/data/task2/main.py +++ b/VaravinVV/docs/data/task2/main.py @@ -51,23 +51,18 @@ class Maze: class MazeBuilder(abc.ABC): - """Абстрактный строитель лабиринта.""" @abc.abstractmethod def build_from_file(self, filename: str) -> Maze: - """Построить лабиринт из файла.""" pass class TextFileMazeBuilder(MazeBuilder): - """Строитель лабиринта из текстового файла. - # - стена, пробел - проход, S - старт, E - выход.""" - def build_from_file(self, filename: str) -> Maze: lines = [] with open(filename, 'r', encoding='utf-8') as f: for line in f: line = line.rstrip('\n') - if line: #игнорируем пустые строки + if line: #игнорируем пустые строки lines.append(line) if not lines: @@ -77,7 +72,7 @@ class TextFileMazeBuilder(MazeBuilder): width = max(len(line) for line in lines) maze = Maze(width, height) - # Инициализируем сетку пустыми клетками (по умолчанию стенами) + #инициализируем сетку пустыми клетками,по умолчанию стенами maze.grid = [[Cell(x, y, is_wall=True) for x in range(width)] for y in range(height)] start_cell = None @@ -88,11 +83,9 @@ class TextFileMazeBuilder(MazeBuilder): if x >= width: continue if ch == '#': - # стена (уже создана по умолчанию) continue elif ch == ' ': - # проход - cell = Cell(x, y, is_wall=False) + cell = Cell(x, y, is_wall=False) elif ch == 'S': cell = Cell(x, y, is_wall=False, is_start=True) start_cell = cell @@ -100,49 +93,38 @@ class TextFileMazeBuilder(MazeBuilder): cell = Cell(x, y, is_wall=False, is_exit=True) exit_cell = cell else: - # любой другой символ считаем проходом + #любой другой символ считаем проходом cell = Cell(x, y, is_wall=False) maze.set_cell(x, y, cell) - # Проверяем наличие старта и выхода if start_cell is None: - raise ValueError("В лабиринте отсутствует стартовая клетка (S)") + raise ValueError("отсутствует стартовая клетка (S)") #invalid check if exit_cell is None: - raise ValueError("В лабиринте отсутствует выход (E)") + raise ValueError("отсутствует выход (E)") maze.start_cell = start_cell maze.exit_cell = exit_cell return maze - -# ============================== Паттерн Strategy ============================== - class PathFindingStrategy(abc.ABC): - """Интерфейс стратегии поиска пути.""" @abc.abstractmethod def find_path(self, maze: Maze, start: Cell, exit_: Cell) -> Tuple[List[Cell], int]: - """ - Возвращает (путь в виде списка клеток от start до exit_, количество посещённых клеток). - Если пути нет, возвращает ([], visited_count). - """ pass - +#дальше скорее математика, методы вроде ещё в том семаке разбирали class BFSStrategy(PathFindingStrategy): - """Поиск в ширину — гарантирует кратчайший путь.""" - def find_path(self, maze: Maze, start: Cell, exit_: Cell) -> Tuple[List[Cell], int]: if start is exit_: return [start], 1 - queue = deque([start]) + queue = deque([start]) #используйте deque 👍 visited: Set[Cell] = {start} parent: Dict[Cell, Optional[Cell]] = {start: None} while queue: current = queue.popleft() if current is exit_: - # восстановление пути + #восстановление пути path = [] cur = current while cur is not None: @@ -161,8 +143,6 @@ class BFSStrategy(PathFindingStrategy): class DFSStrategy(PathFindingStrategy): - """Поиск в глубину — не гарантирует кратчайший путь, но быстр.""" - def find_path(self, maze: Maze, start: Cell, exit_: Cell) -> Tuple[List[Cell], int]: if start is exit_: return [start], 1 @@ -192,18 +172,13 @@ class DFSStrategy(PathFindingStrategy): class AStarStrategy(PathFindingStrategy): - """Алгоритм A* с манхэттенской эвристикой.""" - @staticmethod def _heuristic(cell: Cell, target: Cell) -> int: - """Манхэттенское расстояние.""" - return abs(cell.x - target.x) + abs(cell.y - target.y) + return abs(cell.x - target.x) + abs(cell.y - target.y) #самая простая эвристика def find_path(self, maze: Maze, start: Cell, exit_: Cell) -> Tuple[List[Cell], int]: if start is exit_: return [start], 1 - - # Приоритетная очередь: (f, counter, cell) counter = 0 open_set = [(0, counter, start)] g_score: Dict[Cell, int] = {start: 0} @@ -217,7 +192,7 @@ class AStarStrategy(PathFindingStrategy): if current in closed_set: continue closed_set.add(current) - visited_count = len(closed_set) # количество обработанных клеток + visited_count = len(closed_set) if current is exit_: path = [] @@ -242,30 +217,20 @@ class AStarStrategy(PathFindingStrategy): return [], visited_count - -# ============================== Статистика ============================== - @dataclass class SearchStats: - """Статистика поиска.""" - time_ms: float # время выполнения в миллисекундах - visited_cells: int # количество посещённых клеток - path_length: int # длина найденного пути (0 если пути нет) - path_found: bool # найден ли путь + time_ms: float #время выполнения в мс + visited_cells: int #количество посещённых клеток + path_length: int #длина найденного пути (0 если пути нет) + path_found: bool #найден ли путь - -# ============================== Паттерн Observer ============================== - -class Observer(abc.ABC): - """Интерфейс наблюдателя.""" - @abc.abstractmethod +class Observer(abc.ABC): #я забыл что я там писать хотел после наблюдателя удачи мне завтра разобрать + @abc.abstractmethod #а я (гугл + хабр) разобрал снова балбесина!!! def update(self, event_type: str, data: Any = None) -> None: - """Получить уведомление от субъекта.""" pass class Subject: - """Субъект, за которым наблюдают.""" def __init__(self): self._observers: List[Observer] = [] @@ -281,25 +246,18 @@ class Subject: for observer in self._observers: observer.update(event_type, data) - -# ============================== MazeSolver (оркестратор) ============================== - class MazeSolver(Subject): - """Решатель лабиринта, использующий стратегию поиска.""" def __init__(self, maze: Maze, strategy: Optional[PathFindingStrategy] = None): super().__init__() self.maze = maze self._strategy = strategy - def set_strategy(self, strategy: PathFindingStrategy) -> None: - """Сменить алгоритм поиска.""" + def set_strategy(self, strategy: PathFindingStrategy) -> None: #смена алгоритма self._strategy = strategy def solve(self) -> Optional[SearchStats]: - """Выполнить поиск пути с текущей стратегией. - Возвращает статистику или None, если стратегия не установлена.""" if self._strategy is None: - print("Стратегия не установлена.") + print("где стратегия?") return None self.notify("solving_start", {"strategy": self._strategy.__class__.__name__}) @@ -325,8 +283,7 @@ class MazeSolver(Subject): self.notify("solving_end", {"stats": stats}) return stats -class ConsoleView(Observer): - """Отображает лабиринт и найденный путь в консоли.""" +class ConsoleView(Observer): #красиво в консоль выводит лабиринт def __init__(self, maze: Maze): self.maze = maze self.last_path: List[Cell] = [] @@ -339,11 +296,9 @@ class ConsoleView(Observer): self.last_path = [] self.render(no_path=True) elif event_type == "solving_start": - print(f"\n== Поиск пути (алгоритм: {data['strategy']}) ==\n") + print(f"\nпоиск пути (алгоритм: {data['strategy']})\n") def render(self, no_path: bool = False) -> None: - """Отрисовать лабиринт с текущим найденным путём.""" - # Создаём множество клеток пути для быстрой проверки path_set = set(self.last_path) if self.last_path else set() for y in range(self.maze.height): @@ -366,11 +321,11 @@ class ConsoleView(Observer): print(''.join(row)) if no_path: - print("\nПуть не найден!") + print("\nнет пути (no way)") elif self.last_path: - print(f"\nНайден путь длиной {len(self.last_path)} клеток.") + print(f"\nнайден путь длиной {len(self.last_path)} клеток") else: - print("\nОжидание решения...") + print("\nожидание решения") def main(): import sys @@ -381,20 +336,18 @@ def main(): filename = sys.argv[1] - # Строим лабиринт из файла (Builder) + #строится лабиринт из файла builder = TextFileMazeBuilder() try: maze = builder.build_from_file(filename) except Exception as e: - print(f"Ошибка загрузки лабиринта: {e}") + print(f"ошибка загрузки лабиринта: {e}") return - # Создаём решатель и прикрепляем наблюдателя + #наблюдатель и решатель прикрепляются solver = MazeSolver(maze) view = ConsoleView(maze) solver.attach(view) - - # Меню выбора стратегии strategies = { "1": BFSStrategy(), "2": DFSStrategy(), diff --git a/VaravinVV/docs/data/task2/noexit.txt b/VaravinVV/docs/data/task2/noexit.txt new file mode 100644 index 0000000..dd3f0bf --- /dev/null +++ b/VaravinVV/docs/data/task2/noexit.txt @@ -0,0 +1,5 @@ +##### +#S### +##### +###E# +##### \ No newline at end of file