From f26da8a6ccddb5037b91ffffd3b2843611b52713 Mon Sep 17 00:00:00 2001 From: kirill Date: Sun, 24 May 2026 21:32:03 +0300 Subject: [PATCH] main.py added --- svetlakovkyu/02/main.py | 165 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 svetlakovkyu/02/main.py diff --git a/svetlakovkyu/02/main.py b/svetlakovkyu/02/main.py new file mode 100644 index 0000000..8a358bd --- /dev/null +++ b/svetlakovkyu/02/main.py @@ -0,0 +1,165 @@ +import csv +import os +import sys + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "codes")) + +from maze import TextFileMazeBuilder, MazeSolver, BFSStrategy, DFSStrategy, AStarStrategy +from maze_generator import generate_all + +try: + import matplotlib.pyplot as plt + import matplotlib + matplotlib.use("Agg") + HAS_PLT = True +except ImportError: + HAS_PLT = False + +BASE_DIR = os.path.dirname(__file__) +MAZES_DIR = os.path.join(BASE_DIR, "mazes") +RESULTS_DIR = os.path.join(BASE_DIR, "results") +RUNS = 7 + +MAZE_FILES = [ + ("small", "small.txt"), + ("medium", "medium.txt"), + ("large", "large.txt"), + ("empty", "empty.txt"), + ("no_exit", "no_exit.txt"), +] + + +def run(): + os.makedirs(RESULTS_DIR, exist_ok=True) + + if not os.path.exists(MAZES_DIR) or not os.listdir(MAZES_DIR): + generate_all(MAZES_DIR) + + strategies = [BFSStrategy(), DFSStrategy(), AStarStrategy()] + builder = TextFileMazeBuilder() + all_results = [] + + for label, filename in MAZE_FILES: + path = os.path.join(MAZES_DIR, filename) + if not os.path.exists(path): + continue + + maze = builder.build_from_file(path) + print(f"\nMaze: {label} ({maze.width}x{maze.height})") + + solver = MazeSolver(maze, strategies[0]) + + for strategy in strategies: + solver.set_strategy(strategy) + times, visited_list, lengths = [], [], [] + + for _ in range(RUNS): + stats = solver.solve() + times.append(stats.time_ms) + visited_list.append(stats.visited) + lengths.append(stats.path_length) + + avg_time = sum(times) / RUNS + avg_visited = sum(visited_list) / RUNS + avg_len = sum(lengths) / RUNS + + found = f"length={avg_len:.0f}" if avg_len > 0 else "not found" + print(f" {strategy.name:<6} time={avg_time:.4f} ms visited={avg_visited:.0f} {found}") + + all_results.append({ + "maze": label, + "strategy": strategy.name, + "time_ms": round(avg_time, 4), + "visited_cells": round(avg_visited, 1), + "path_length": round(avg_len, 1), + }) + + save_csv(all_results) + save_plots(all_results) + show_sample() + print("\nDone. See results/ and docs/") + + +def save_csv(results): + path = os.path.join(RESULTS_DIR, "results_maze.csv") + with open(path, "w", newline="", encoding="utf-8") as f: + writer = csv.DictWriter( + f, fieldnames=["maze", "strategy", "time_ms", "visited_cells", "path_length"] + ) + writer.writeheader() + writer.writerows(results) + print(f"\nCSV saved: {path}") + + +def save_plots(results): + if not HAS_PLT: + return + + mazes = list(dict.fromkeys(r["maze"] for r in results)) + strategies = list(dict.fromkeys(r["strategy"] for r in results)) + colors = ["#2196F3", "#FF5722", "#4CAF50"] + + def val(maze, strat, key): + for r in results: + if r["maze"] == maze and r["strategy"] == strat: + return float(r[key]) + return 0.0 + + metrics = [ + ("time_ms", "Time (ms)"), + ("visited_cells", "Visited cells"), + ("path_length", "Path length"), + ] + + fig, axes = plt.subplots( + len(metrics), len(mazes), + figsize=(3.5 * len(mazes), 4 * len(metrics)) + ) + + def fmt(v): + if v == 0: + return "0" + if v >= 100: + return f"{v:.0f}" + if v >= 1: + return f"{v:.2f}" + return f"{v:.3f}" + + for row_i, (key, ylabel) in enumerate(metrics): + for col_i, maze in enumerate(mazes): + ax = axes[row_i][col_i] + vals = [val(maze, s, key) for s in strategies] + bars = ax.bar(strategies, vals, color=colors[:len(strategies)]) + if row_i == 0: + ax.set_title(maze, fontsize=9) + if col_i == 0: + ax.set_ylabel(ylabel) + for bar, v in zip(bars, vals): + ax.text( + bar.get_x() + bar.get_width() / 2, + bar.get_height() * 1.02, + fmt(v), ha="center", va="bottom", fontsize=7 + ) + ax.tick_params(axis="x", labelsize=8) + + plt.tight_layout() + out = os.path.join(RESULTS_DIR, "benchmark_plot.png") + plt.savefig(out, dpi=120) + plt.close() + print(f"Chart saved: {out}") + + +def show_sample(): + path = os.path.join(MAZES_DIR, "sample.txt") + if not os.path.exists(path): + return + builder = TextFileMazeBuilder() + maze = builder.build_from_file(path) + solver = MazeSolver(maze, BFSStrategy()) + stats = solver.solve() + print("\nSample maze with BFS path:") + print(maze.render(path=stats.path)) + + +if __name__ == "__main__": + run()