From c14c0435754ae622d62b1bb1bfacdb3989de56d8 Mon Sep 17 00:00:00 2001 From: David GAILLETON Date: Wed, 18 Mar 2026 14:10:05 +0100 Subject: [PATCH] Rework and some fixes --- Makefile | 2 +- a_maze_ing.py | 7 +-- pyproject.toml | 4 -- src/amaz_lib/MazeGenerator.py | 90 ++++++++++++++++++++++++++++++ src/amaz_lib/__init__.py | 4 +- src/amaz_lib/classes/Cell.py | 2 +- src/amaz_lib/classes/Maze.py | 18 ++++-- src/amaz_lib/generators/kruskal.py | 83 --------------------------- test.txt | 33 +++++++---- 9 files changed, 134 insertions(+), 109 deletions(-) create mode 100644 src/amaz_lib/MazeGenerator.py delete mode 100644 src/amaz_lib/generators/kruskal.py diff --git a/Makefile b/Makefile index 6b7b186..877546f 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ clean: rm -rf __pycache__ .mypy_cache lint: - uv run flake8 . + uv run flake8 . --exclude=.venv uv run mypy . --warn-return-any --warn-unused-ignores --ignore-missing-imports --disallow-untyped-defs --check-untyped-defs lint-strict: diff --git a/a_maze_ing.py b/a_maze_ing.py index ad30819..f2e955f 100644 --- a/a_maze_ing.py +++ b/a_maze_ing.py @@ -1,12 +1,11 @@ -from numpy import ma -from src.amaz_lib import kruskal +from src.amaz_lib import MazeGenerator from src.amaz_lib import Maze def main() -> None: try: - maze = Maze(maze=None) - for alg in kruskal(10, 10): + maze = Maze(maze=None, start=(1, 1), end=(16, 15)) + for alg in MazeGenerator.Kruskal.kruskal(20, 20): maze.set_maze(alg) maze.export_maze("test.txt") except Exception as err: diff --git a/pyproject.toml b/pyproject.toml index ce9d7ed..9b6646b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,3 @@ dev = [ [tool.mypy] python_version = "3.10" -exclude = [ - ".venv", - "venv", -] diff --git a/src/amaz_lib/MazeGenerator.py b/src/amaz_lib/MazeGenerator.py new file mode 100644 index 0000000..63dcd0c --- /dev/null +++ b/src/amaz_lib/MazeGenerator.py @@ -0,0 +1,90 @@ +from typing import Generator +import numpy as np +from .classes.Cell import Cell +import math + + +class MazeGenerator: + class Kruskal: + @staticmethod + def walls_to_maze( + walls: list[tuple[int, int]], height: int, width: int + ) -> np.ndarray: + maze: np.ndarray = np.array( + [[Cell(value=0) for _ in range(width)] for _ in range(height)] + ) + for wall in walls: + x, y = wall + match y - x: + case 1: + maze[math.trunc((x / width))][x % width].set_est(True) + maze[math.trunc((y / width))][y % width].set_west(True) + case 5: + maze[math.trunc((x / width))][x % width].set_south( + True + ) + maze[math.trunc((y / width))][y % width].set_north( + True + ) + return maze + + @staticmethod + def is_in_same_set( + sets: list[list[int]], wall: tuple[int, int] + ) -> bool: + a, b = wall + for set in sets: + if a in set and b in set: + return True + if a in set or b in set: + return False + return False + + @staticmethod + def merge_sets(sets: list[list[int]], wall: tuple[int, int]) -> None: + a, b = wall + base_set = None + for set in sets: + if base_set is None and (a in set or b in set): + base_set = set + elif base_set and (a in set or b in set): + base_set += set + sets.remove(set) + + @classmethod + def kruskal( + cls, height: int, width: int + ) -> Generator[np.ndarray, None, np.ndarray]: + sets = [[i] for i in range(height * width)] + walls = [] + for h in range(height): + for w in range(width - 1): + walls += [(w + (width * h), w + (width * h) + 1)] + for w in range(width): + for h in range(height - 1): + walls += [(w + (width * h), w + (width * h) + width)] + np.random.shuffle(walls) + + yield cls.walls_to_maze(walls, height, width) + for wall in walls: + if not cls.is_in_same_set(sets, wall): + cls.merge_sets(sets, wall) + walls.remove(wall) + yield cls.walls_to_maze(walls, height, width) + return cls.walls_to_maze(walls, height, width) + + +def main(): + try: + for alg in MazeGenerator.Kruskal.kruskal(10, 10): + maze = alg + # print(maze) + # print() + print(maze) + + except GeneratorExit as maze: + print(maze) + + +if __name__ == "__main__": + main() diff --git a/src/amaz_lib/__init__.py b/src/amaz_lib/__init__.py index 03ae356..cf2963d 100644 --- a/src/amaz_lib/__init__.py +++ b/src/amaz_lib/__init__.py @@ -1,7 +1,7 @@ from .classes.Cell import Cell from .classes.Maze import Maze -from .generators.kruskal import kruskal +from .MazeGenerator import MazeGenerator __version__ = "1.0.0" __author__ = "us" -__all__ = ["Cell", "Maze", "kruskal"] +__all__ = ["Cell", "Maze", "MazeGenerator"] diff --git a/src/amaz_lib/classes/Cell.py b/src/amaz_lib/classes/Cell.py index 0dbde40..d6675bc 100644 --- a/src/amaz_lib/classes/Cell.py +++ b/src/amaz_lib/classes/Cell.py @@ -5,7 +5,7 @@ class Cell(BaseModel): value: int = Field(ge=0, le=15) def __str__(self) -> str: - return hex(self.value).removeprefix("0x") + return hex(self.value).removeprefix("0x").upper() def set_value(self, value: int) -> None: self.value = value diff --git a/src/amaz_lib/classes/Maze.py b/src/amaz_lib/classes/Maze.py index 79b1faa..bfc5ab5 100644 --- a/src/amaz_lib/classes/Maze.py +++ b/src/amaz_lib/classes/Maze.py @@ -1,15 +1,19 @@ from dataclasses import dataclass + +import numpy from .Cell import Cell @dataclass class Maze: - maze: list[list[Cell]] + maze: numpy.ndarray + start: tuple[int, int] + end: tuple[int, int] - def get_maze(self) -> list[list[Cell]] | None: + def get_maze(self) -> numpy.ndarray | None: return self.maze - def set_maze(self, new_maze: list[list[Cell]]) -> None: + def set_maze(self, new_maze: numpy.ndarray) -> None: self.maze = new_maze def __str__(self) -> str: @@ -20,8 +24,14 @@ class Maze: for cell in line: res += cell.__str__() res += "\n" + res += "\n" + res += f"{self.start[0]},{self.start[1]}\n" + res += f"{self.end[0]},{self.end[1]}\n" return res - def export_maze(self, file_name: str): + def export_maze(self, file_name: str) -> None: with open(file_name, "w") as file: file.write(self.__str__()) + + def solver(self) -> str: + pass diff --git a/src/amaz_lib/generators/kruskal.py b/src/amaz_lib/generators/kruskal.py deleted file mode 100644 index cf45c87..0000000 --- a/src/amaz_lib/generators/kruskal.py +++ /dev/null @@ -1,83 +0,0 @@ -from typing import Generator -import numpy as np -from ..classes.Cell import Cell -import math - - -def walls_to_maze( - walls: list[tuple[int, int]], - height: int, - width: int, -) -> np.ndarray: - maze: np.ndarray = np.array( - [[Cell(value=0) for _ in range(width)] for _ in range(height)] - ) - for wall in walls: - x, y = wall - match y - x: - case 1: - maze[math.trunc((x / width))][x % width].set_est(True) - maze[math.trunc((y / width))][y % width].set_west(True) - case 5: - maze[math.trunc((x / width))][x % width].set_south(True) - maze[math.trunc((y / width))][y % width].set_north(True) - return maze - - -def is_in_same_set(sets: list[list[int]], wall: tuple[int, int]) -> bool: - a, b = wall - for set in sets: - if a in set and b in set: - return True - if a in set or b in set: - return False - return False - - -def merge_sets(sets: list[list[int]], wall: tuple[int, int]) -> None: - a, b = wall - base_set = None - for set in sets: - if base_set is None and (a in set or b in set): - base_set = set - elif base_set and (a in set or b in set): - base_set += set - sets.remove(set) - - -def kruskal( - height: int, width: int -) -> Generator[np.ndarray, None, np.ndarray]: - sets = [[i] for i in range(height * width)] - walls = [] - for h in range(height): - for w in range(width - 1): - walls += [(w + (width * h), w + (width * h) + 1)] - for w in range(width): - for h in range(height - 1): - walls += [(w + (width * h), w + (width * h) + width)] - np.random.shuffle(walls) - - yield walls_to_maze(walls, height, width) - for wall in walls: - if not is_in_same_set(sets, wall): - merge_sets(sets, wall) - walls.remove(wall) - yield walls_to_maze(walls, height, width) - return walls_to_maze(walls, height, width) - - -def main(): - try: - for alg in kruskal(10, 10): - maze = alg - # print(maze) - # print() - print(maze) - - except GeneratorExit as maze: - print(maze) - - -if __name__ == "__main__": - main() diff --git a/test.txt b/test.txt index 217e942..3ea62f1 100644 --- a/test.txt +++ b/test.txt @@ -1,10 +1,23 @@ -2a80002a80 -2a80282800 -282aaaa800 -2a82a802a8 -2802800280 -002aaaaa80 -2a80280280 -00282aa828 -002a82aaa8 -2aa8000028 +2AAA802AAAA8282AAAA8 +000282A8280282A80028 +002A8280280028280000 +2AA82A82AA82A82AA800 +02A8002A8028002A8280 +282A8282AAA828002AA8 +0028282A8282A82A82A8 +2A8002AA80002A802A80 +002802802A8280028280 +0282AA82A82AA80282A8 +2802AAA8282AA8282AA8 +000002A8028282AAA828 +02AAA800002A82A80000 +2AAAA82A82AA800282A8 +282AA82A8282A82AA828 +00002AAA82828282AAA8 +02A82A80282802A80028 +282A8000280028002AA8 +02AA82A82A82AAAAAAA8 +2A80000002AAAAA80000 + +1,1 +16,15