From 1923a02552db6f5cc4a9499f79088d09ed8efc89 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 21 May 2026 18:59:59 +0300 Subject: [PATCH] =?UTF-8?q?[2]=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=BF=D0=B5=D1=80=D0=B2=D1=8B=D1=85=20?= =?UTF-8?q?=D1=82=D1=80=D1=91=D1=85=20=D1=8D=D1=82=D0=B0=D0=BF=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MylnikovAS/task_2/docs/data/steps_123.py | 190 +++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 MylnikovAS/task_2/docs/data/steps_123.py diff --git a/MylnikovAS/task_2/docs/data/steps_123.py b/MylnikovAS/task_2/docs/data/steps_123.py new file mode 100644 index 0000000..fffb5a4 --- /dev/null +++ b/MylnikovAS/task_2/docs/data/steps_123.py @@ -0,0 +1,190 @@ +import time +import csv +from collections import deque +import heapq +from abc import ABC, abstractmethod + + +class Cell: + def __init__(self, x: int, y: int): + self.x = x + self.y = y + self.isWall = False + self.isStart = False + self.isExit = False + self.weight = 1 + + def isPassable(self) -> bool: + return not self.isWall + + def __lt__(self, other): + return (self.x, self.y) < (other.x, other.y) + + +class Maze: + def __init__(self, width: int, height: int): + self.width = width + self.height = height + self.cells = [[Cell(x, y) for y in range(height)] for x in range(width)] + self.start = None + self.exit = None + + def getCell(self, x: int, y: int) -> Cell: + if 0 <= x < self.width and 0 <= y < self.height: + return self.cells[x][y] + return None + + def getNeighbors(self, cell: Cell): + neighbors = [] + directions = [(0, -1), (0, 1), (-1, 0), (1, 0)] + for dx, dy in directions: + nx, ny = cell.x + dx, cell.y + dy + neighbor = self.getCell(nx, ny) + if neighbor and neighbor.isPassable(): + neighbors.append(neighbor) + return neighbors + + +class MazeBuilder(ABC): + @abstractmethod + def buildFromStringList(self, lines: list) -> Maze: + pass + + +class TextMazeBuilder(MazeBuilder): + + def buildFromStringList(self, lines: list) -> Maze: + height = len(lines) + width = len(lines[0]) if height > 0 else 0 + maze = Maze(width, height) + + for y, line in enumerate(lines): + for x, char in enumerate(line): + cell = maze.getCell(x, y) + if char == '#': + cell.isWall = True + elif char == 'S': + cell.isStart = True + maze.start = cell + elif char == 'E': + cell.isExit = True + maze.exit = cell + elif char == 'W': + cell.weight = 3 + elif char == 'D': + cell.weight = 2 + return maze + + +class PathFindingStrategy(ABC): + def __init__(self): + self.visited_count = 0 + + @abstractmethod + def findPath(self, maze: Maze, start: Cell, exit: Cell) -> list: + pass + + def _reconstruct_path(self, came_from: dict, start: Cell, exit: Cell) -> list: + if exit not in came_from: + return [] + path = [] + current = exit + while current != start: + path.append(current) + current = came_from[current] + path.append(start) + path.reverse() + return path + + +class BFSStrategy(PathFindingStrategy): + def findPath(self, maze: Maze, start: Cell, exit: Cell) -> list: + self.visited_count = 0 + queue = deque([start]) + came_from = {start: None} + + while queue: + current = queue.popleft() + self.visited_count += 1 + if current == exit: + break + for neighbor in maze.getNeighbors(current): + if neighbor not in came_from: + queue.append(neighbor) + came_from[neighbor] = current + return self._reconstruct_path(came_from, start, exit) + + +class DFSStrategy(PathFindingStrategy): + def findPath(self, maze: Maze, start: Cell, exit: Cell) -> list: + self.visited_count = 0 + stack = [start] + came_from = {start: None} + + while stack: + current = stack.pop() + self.visited_count += 1 + if current == exit: + break + for neighbor in maze.getNeighbors(current): + if neighbor not in came_from: + stack.append(neighbor) + came_from[neighbor] = current + return self._reconstruct_path(came_from, start, exit) + + +class AStarStrategy(PathFindingStrategy): + def findPath(self, maze: Maze, start: Cell, exit: Cell) -> list: + self.visited_count = 0 + + def heuristic(a, b): + return abs(a.x - b.x) + abs(a.y - b.y) + + pq = [] + heapq.heappush(pq, (0, start)) + came_from = {start: None} + g_score = {start: 0} + + while pq: + _, current = heapq.heappop(pq) + self.visited_count += 1 + if current == exit: + break + + for neighbor in maze.getNeighbors(current): + tentative_g_score = g_score[current] + neighbor.weight + + if neighbor not in g_score or tentative_g_score < g_score[neighbor]: + came_from[neighbor] = current + g_score[neighbor] = tentative_g_score + f_score = tentative_g_score + heuristic(neighbor, exit) + heapq.heappush(pq, (f_score, neighbor)) + + return self._reconstruct_path(came_from, start, exit) + + +class DijkstraStrategy(PathFindingStrategy): + + def findPath(self, maze: Maze, start: Cell, exit: Cell) -> list: + self.visited_count = 0 + pq = [] + heapq.heappush(pq, (0, start)) + came_from = {start: None} + g_score = {start: 0} + + while pq: + current_g, current = heapq.heappop(pq) + self.visited_count += 1 + if current == exit: + break + + for neighbor in maze.getNeighbors(current): + tentative_g_score = g_score[current] + neighbor.weight + + if neighbor not in g_score or tentative_g_score < g_score[neighbor]: + came_from[neighbor] = current + g_score[neighbor] = tentative_g_score + heapq.heappush(pq, (tentative_g_score, neighbor)) + + return self._reconstruct_path(came_from, start, exit) +