From b822b9c5243b69e6f100d154a559490b47831d5c Mon Sep 17 00:00:00 2001 From: rybakovaa Date: Sun, 17 May 2026 22:06:27 +0300 Subject: [PATCH] [1][2] lab1 structures and lab2 maze --- rybakovaa/428b.md | 1 + rybakovaa/lab1/docs/data/lab1.py | 327 +++++++++++++ rybakovaa/lab1/docs/data/order_impact.png | Bin 0 -> 27835 bytes rybakovaa/lab1/docs/data/results.csv | 37 ++ .../lab1/docs/data/struct_comparison.png | Bin 0 -> 30915 bytes rybakovaa/lab1/docs/report.md | 25 + rybakovaa/lab2/docs/data/laba2.py | 428 ++++++++++++++++++ rybakovaa/lab2/docs/data/maze_empty.txt | 50 ++ rybakovaa/lab2/docs/data/maze_large.txt | 100 ++++ rybakovaa/lab2/docs/data/maze_medium.txt | 50 ++ rybakovaa/lab2/docs/data/maze_no_exit.txt | 20 + rybakovaa/lab2/docs/data/maze_small.txt | 10 + .../lab2/docs/data/maze_time_comparison.png | Bin 0 -> 29436 bytes rybakovaa/lab2/docs/data/resultslab.csv | 16 + rybakovaa/lab2/docs/report.md | 49 ++ 15 files changed, 1113 insertions(+) create mode 100644 rybakovaa/428b.md create mode 100644 rybakovaa/lab1/docs/data/lab1.py create mode 100644 rybakovaa/lab1/docs/data/order_impact.png create mode 100644 rybakovaa/lab1/docs/data/results.csv create mode 100644 rybakovaa/lab1/docs/data/struct_comparison.png create mode 100644 rybakovaa/lab1/docs/report.md create mode 100644 rybakovaa/lab2/docs/data/laba2.py create mode 100644 rybakovaa/lab2/docs/data/maze_empty.txt create mode 100644 rybakovaa/lab2/docs/data/maze_large.txt create mode 100644 rybakovaa/lab2/docs/data/maze_medium.txt create mode 100644 rybakovaa/lab2/docs/data/maze_no_exit.txt create mode 100644 rybakovaa/lab2/docs/data/maze_small.txt create mode 100644 rybakovaa/lab2/docs/data/maze_time_comparison.png create mode 100644 rybakovaa/lab2/docs/data/resultslab.csv create mode 100644 rybakovaa/lab2/docs/report.md diff --git a/rybakovaa/428b.md b/rybakovaa/428b.md new file mode 100644 index 0000000..225a97e --- /dev/null +++ b/rybakovaa/428b.md @@ -0,0 +1 @@ +428b diff --git a/rybakovaa/lab1/docs/data/lab1.py b/rybakovaa/lab1/docs/data/lab1.py new file mode 100644 index 0000000..56c11e1 --- /dev/null +++ b/rybakovaa/lab1/docs/data/lab1.py @@ -0,0 +1,327 @@ +import time +import random +import csv +import os +import sys + +sys.setrecursionlimit(20000) + +BASE = os.path.dirname(os.path.abspath(__file__)) +DATA_PATH = BASE + +N = 10000 +REPEAT = 5 + + +def ll_insert(head, name, phone): + new_node = {"name": name, "phone": phone, "next": head} + return new_node + + +def ll_find(head, name): + curr = head + while curr: + if curr["name"] == name: + return curr["phone"] + curr = curr["next"] + return None + + +def ll_delete(head, name): + if head is None: + return None + if head["name"] == name: + return head["next"] + curr = head + while curr["next"]: + if curr["next"]["name"] == name: + curr["next"] = curr["next"]["next"] + return head + curr = curr["next"] + return head + + +def ll_list_all(head): + result = [] + curr = head + while curr: + result.append((curr["name"], curr["phone"])) + curr = curr["next"] + result.sort() + return result + + +BUCKET_SIZE = 1000 + + +def ht_insert(buckets, name, phone): + idx = hash(name) % len(buckets) + buckets[idx] = ll_insert(buckets[idx], name, phone) + + +def ht_find(buckets, name): + idx = hash(name) % len(buckets) + return ll_find(buckets[idx], name) + + +def ht_delete(buckets, name): + idx = hash(name) % len(buckets) + buckets[idx] = ll_delete(buckets[idx], name) + + +def ht_list_all(buckets): + result = [] + for bucket in buckets: + curr = bucket + while curr: + result.append((curr["name"], curr["phone"])) + curr = curr["next"] + result.sort() + return result + + +def bst_insert(root, name, phone): + if root is None: + return {"name": name, "phone": phone, "left": None, "right": None} + if name < root["name"]: + root["left"] = bst_insert(root["left"], name, phone) + elif name > root["name"]: + root["right"] = bst_insert(root["right"], name, phone) + else: + root["phone"] = phone + return root + + +def bst_find(root, name): + if root is None: + return None + if name == root["name"]: + return root["phone"] + if name < root["name"]: + return bst_find(root["left"], name) + return bst_find(root["right"], name) + + +def bst_delete(root, name): + if root is None: + return None + if name < root["name"]: + root["left"] = bst_delete(root["left"], name) + elif name > root["name"]: + root["right"] = bst_delete(root["right"], name) + else: + if root["left"] is None: + return root["right"] + if root["right"] is None: + return root["left"] + temp = root["right"] + while temp["left"]: + temp = temp["left"] + root["name"] = temp["name"] + root["phone"] = temp["phone"] + root["right"] = bst_delete(root["right"], temp["name"]) + return root + + +def bst_list_all(root): + result = [] + + def walk(node): + if node is None: + return + walk(node["left"]) + result.append((node["name"], node["phone"])) + walk(node["right"]) + + walk(root) + return result + + +def make_records(n): + records = [] + for i in range(n): + records.append((f"User_{i:05d}", f"8-900-{i % 10000:04d}")) + return records + + +records_all = make_records(N) +records_shuffled = records_all[:] +random.shuffle(records_shuffled) +records_sorted = sorted(records_all) + +all_names = [name for name, phone in records_all] +find_existing = random.sample(all_names, 100) +find_missing = [f"None_{i}" for i in range(10)] +find_names = find_existing + find_missing +random.shuffle(find_names) +delete_names = random.sample(all_names, 50) + +all_results = [] +summary = [] + + +def build_structure(struct_type, records): + if struct_type == "LinkedList": + head = None + for name, phone in records: + head = ll_insert(head, name, phone) + return head + if struct_type == "HashTable": + buckets = [None] * BUCKET_SIZE + for name, phone in records: + ht_insert(buckets, name, phone) + return buckets + root = None + for name, phone in records: + root = bst_insert(root, name, phone) + return root + + +def do_find(struct_type, container, names): + for name in names: + if struct_type == "LinkedList": + ll_find(container, name) + elif struct_type == "HashTable": + ht_find(container, name) + else: + bst_find(container, name) + + +def do_delete(struct_type, container, names): + if struct_type == "LinkedList": + for name in names: + container = ll_delete(container, name) + return container + if struct_type == "HashTable": + for name in names: + ht_delete(container, name) + return container + for name in names: + container = bst_delete(container, name) + return container + + +def run_one_test(struct_type, mode_name, records): + ins_times = [] + find_times = [] + del_times = [] + + for run in range(REPEAT): + start = time.perf_counter() + container = build_structure(struct_type, records) + ins_times.append(time.perf_counter() - start) + + start = time.perf_counter() + do_find(struct_type, container, find_names) + find_times.append(time.perf_counter() - start) + + start = time.perf_counter() + do_delete(struct_type, container, delete_names) + del_times.append(time.perf_counter() - start) + + all_results.append([ + struct_type, mode_name, f"Run {run + 1}", + ins_times[-1], find_times[-1], del_times[-1], + ]) + + avg_ins = sum(ins_times) / REPEAT + avg_find = sum(find_times) / REPEAT + avg_del = sum(del_times) / REPEAT + + all_results.append([ + struct_type, mode_name, "AVERAGE", avg_ins, avg_find, avg_del, + ]) + summary.append({ + "name": struct_type, + "mode": mode_name, + "ins": avg_ins, + "find": avg_find, + "del": avg_del, + }) + + +print("Запуск экспериментов...") +for mode_name, data in [("случайный", records_shuffled), ("сортированный", records_sorted)]: + for struct_type in ["LinkedList", "HashTable", "BST"]: + print(f" {struct_type} ({mode_name})") + run_one_test(struct_type, mode_name, data) + +csv_path = os.path.join(DATA_PATH, "results.csv") +with open(csv_path, "w", newline="", encoding="utf-8-sig") as f: + writer = csv.writer(f, delimiter=";") + writer.writerow(["Структура", "Режим", "Итерация", "Вставка", "Поиск", "Удаление"]) + writer.writerows(all_results) + +print("CSV сохранён:", csv_path) + +try: + import matplotlib.pyplot as plt + + plt.rcParams["font.sans-serif"] = ["Segoe UI", "Arial", "Tahoma", "DejaVu Sans"] + plt.rcParams["axes.unicode_minus"] = False + + labels = ["insert", "find", "delete"] + structs = ["LinkedList", "HashTable", "BST"] + colors = ["#5dade2", "#e67e22", "#58d68d"] + + fig1, axs = plt.subplots(1, 3, figsize=(15, 5)) + fig1.suptitle("Влияние порядка данных") + + for i, s_name in enumerate(structs): + rand_d = next(r for r in summary if r["name"] == s_name and r["mode"] == "случайный") + sort_d = next(r for r in summary if r["name"] == s_name and r["mode"] == "сортированный") + x = [0, 1, 2] + w = 0.35 + axs[i].bar([p - w / 2 for p in x], [rand_d["ins"], rand_d["find"], rand_d["del"]], w, label="случайный") + axs[i].bar([p + w / 2 for p in x], [sort_d["ins"], sort_d["find"], sort_d["del"]], w, label="сортированный") + axs[i].set_title(s_name) + axs[i].set_xticks(x) + axs[i].set_xticklabels(labels) + axs[i].legend() + axs[i].grid(axis="y", alpha=0.3) + + plt.tight_layout() + plt.savefig(os.path.join(DATA_PATH, "order_impact.png")) + plt.close() + + fig2, axs2 = plt.subplots(1, 3, figsize=(15, 5)) + fig2.suptitle(f"Сравнение структур (N={N})") + + for i, key in enumerate(["ins", "find", "del"]): + vals = [] + names = [] + for r in summary: + names.append(f"{r['name']}\n({r['mode'][:4]})") + vals.append(r[key]) + axs2[i].bar(names, vals, color=colors * 2) + axs2[i].set_title(labels[i]) + axs2[i].tick_params(axis="x", rotation=20) + + plt.tight_layout() + plt.savefig(os.path.join(DATA_PATH, "struct_comparison.png")) + plt.close() + print("Графики сохранены") +except ImportError: + print("matplotlib не установлен") + +report_path = os.path.join(os.path.dirname(BASE), "report.md") +with open(report_path, "w", encoding="utf-8-sig") as f: + f.write("# Отчёт: сравнение структур данных\n\n") + f.write(f"N = {N}, повторов = {REPEAT}\n\n") + f.write("| Структура | Режим | Вставка (с) | Поиск (с) | Удаление (с) |\n") + f.write("| --- | --- | --- | --- | --- |\n") + for r in summary: + f.write( + f"| {r['name']} | {r['mode']} | {r['ins']:.6f} | {r['find']:.6f} | {r['del']:.6f} |\n" + ) + f.write("\n## Графики\n\n") + f.write("![Сравнение](data/struct_comparison.png)\n\n") + f.write("![Порядок данных](data/order_impact.png)\n\n") + f.write("## Выводы\n\n") + f.write("- BST на отсортированных данных сильно тормозит (вырождение дерева).\n") + f.write("- Хеш-таблица быстра на поиске и слабо зависит от порядка вставки.\n") + f.write("- Связный список медленный при поиске.\n") + f.write("- Для частого поиска предпочтительна хеш-таблица.\n") + +print("Отчёт:", report_path) +print("Готово.") diff --git a/rybakovaa/lab1/docs/data/order_impact.png b/rybakovaa/lab1/docs/data/order_impact.png new file mode 100644 index 0000000000000000000000000000000000000000..b25a98ab3ebc7ce70e862c4b26f09abdac4da6e1 GIT binary patch literal 27835 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 literal 0 HcmV?d00001 diff --git a/rybakovaa/lab1/docs/data/results.csv b/rybakovaa/lab1/docs/data/results.csv new file mode 100644 index 0000000..06e543e --- /dev/null +++ b/rybakovaa/lab1/docs/data/results.csv @@ -0,0 +1,37 @@ +Структура;Режим;Итерация;Вставка;Поиск;Удаление +LinkedList;случайный;Run 1;0.002766899997368455;0.027239699964411557;0.015202199923805892 +LinkedList;случайный;Run 2;0.0023452999303117394;0.02690729999449104;0.014689600095152855 +LinkedList;случайный;Run 3;0.0026440999936312437;0.028060800046660006;0.01486769993789494 +LinkedList;случайный;Run 4;0.002523000002838671;0.02711769996676594;0.014554499997757375 +LinkedList;случайный;Run 5;0.0022324000019580126;0.02935329999309033;0.015334900002926588 +LinkedList;случайный;AVERAGE;0.0025023399852216245;0.027735759993083774;0.01492977999150753 +HashTable;случайный;Run 1;0.0037400999572128057;7.149996235966682e-05;3.490003291517496e-05 +HashTable;случайный;Run 2;0.004325399990193546;9.180000051856041e-05;4.499999340623617e-05 +HashTable;случайный;Run 3;0.006647299975156784;9.760004468262196e-05;4.809990059584379e-05 +HashTable;случайный;Run 4;0.004817900015041232;8.430005982518196e-05;4.279997665435076e-05 +HashTable;случайный;Run 5;0.0045270000118762255;7.889990229159594e-05;3.660004585981369e-05 +HashTable;случайный;AVERAGE;0.004811539989896118;8.481999393552541e-05;4.147998988628388e-05 +BST;случайный;Run 1;0.020208499976433814;0.00017140002455562353;0.000107599887996912 +BST;случайный;Run 2;0.02269990008790046;0.00022380007430911064;0.0001463999506086111 +BST;случайный;Run 3;0.022515299962833524;0.00019350007642060518;0.00011879997327923775 +BST;случайный;Run 4;0.02134259999729693;0.00019699998665601015;0.0001330999657511711 +BST;случайный;Run 5;0.022310999920591712;0.00020180002320557833;0.00011969998013228178 +BST;случайный;AVERAGE;0.02181545998901129;0.00019750003702938556;0.00012511995155364274 +LinkedList;сортированный;Run 1;0.0014724000357091427;0.024460599990561604;0.016624199924990535 +LinkedList;сортированный;Run 2;0.0026603000005707145;0.02619360003154725;0.015555899939499795 +LinkedList;сортированный;Run 3;0.003988999989815056;0.026726300013251603;0.016439199913293123 +LinkedList;сортированный;Run 4;0.003310499945655465;0.024290600093081594;0.016939799999818206 +LinkedList;сортированный;Run 5;0.003344499971717596;0.02642290003132075;0.016576700028963387 +LinkedList;сортированный;AVERAGE;0.002955339988693595;0.02561880003195256;0.01642715996131301 +HashTable;сортированный;Run 1;0.00349499995354563;9.34000127017498e-05;5.8999983593821526e-05 +HashTable;сортированный;Run 2;0.004315900034271181;0.00011070002801716328;5.6999968364834785e-05 +HashTable;сортированный;Run 3;0.004093199968338013;8.140003774315119e-05;4.549999721348286e-05 +HashTable;сортированный;Run 4;0.004008699906989932;8.000002708286047e-05;4.539999645203352e-05 +HashTable;сортированный;Run 5;0.004412899957969785;7.609999738633633e-05;4.290009383112192e-05 +HashTable;сортированный;AVERAGE;0.004065139964222908;8.832002058625221e-05;4.996000789105892e-05 +BST;сортированный;Run 1;8.548112499993294;0.06775930000003427;0.03638990002218634 +BST;сортированный;Run 2;8.337813499965705;0.06507849995978177;0.03630929999053478 +BST;сортированный;Run 3;8.455186700099148;0.06767350004520267;0.036670299945399165 +BST;сортированный;Run 4;8.47301429999061;0.06812409998383373;0.037254099966958165 +BST;сортированный;Run 5;8.588394599966705;0.06450700003188103;0.03623760002665222 +BST;сортированный;AVERAGE;8.480504320003092;0.0666284800041467;0.03657223999034613 diff --git a/rybakovaa/lab1/docs/data/struct_comparison.png b/rybakovaa/lab1/docs/data/struct_comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..8164813b270edc7431551b8e7b716864540a91ce GIT binary patch literal 30915 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 uqt-cTpMr!f8`0lhTu}xBd@8@4n^$ literal 0 HcmV?d00001 diff --git a/rybakovaa/lab1/docs/report.md b/rybakovaa/lab1/docs/report.md new file mode 100644 index 0000000..4b604e3 --- /dev/null +++ b/rybakovaa/lab1/docs/report.md @@ -0,0 +1,25 @@ +# Отчёт: сравнение структур данных + +N = 10000, повторов = 5 + +| Структура | Режим | Вставка (с) | Поиск (с) | Удаление (с) | +| --- | --- | --- | --- | --- | +| LinkedList | случайный | 0.002502 | 0.027736 | 0.014930 | +| HashTable | случайный | 0.004812 | 0.000085 | 0.000041 | +| BST | случайный | 0.021815 | 0.000198 | 0.000125 | +| LinkedList | сортированный | 0.002955 | 0.025619 | 0.016427 | +| HashTable | сортированный | 0.004065 | 0.000088 | 0.000050 | +| BST | сортированный | 8.480504 | 0.066628 | 0.036572 | + +## Графики + +![Сравнение](data/struct_comparison.png) + +![Порядок данных](data/order_impact.png) + +## Выводы + +- BST на отсортированных данных сильно тормозит (вырождение дерева). +- Хеш-таблица быстра на поиске и слабо зависит от порядка вставки. +- Связный список медленный при поиске. +- Для частого поиска предпочтительна хеш-таблица. diff --git a/rybakovaa/lab2/docs/data/laba2.py b/rybakovaa/lab2/docs/data/laba2.py new file mode 100644 index 0000000..efcecf6 --- /dev/null +++ b/rybakovaa/lab2/docs/data/laba2.py @@ -0,0 +1,428 @@ +from abc import ABC, abstractmethod +from collections import deque +import heapq +import time +import csv +import random +import os + +BASE = os.path.dirname(os.path.abspath(__file__)) + + +class Cell: + def __init__(self, x, y): + self.x = x + self.y = y + self.isWall = False + self.isStart = False + self.isExit = False + + def isPassable(self): + return not self.isWall + + def __eq__(self, other): + if other is None: + return False + return self.x == other.x and self.y == other.y + + def __hash__(self): + return hash((self.x, self.y)) + + def __lt__(self, other): + return (self.x, self.y) < (other.x, other.y) + + +class Maze: + def __init__(self, width, height): + self.width = width + self.height = height + self.grid = [[Cell(x, y) for y in range(height)] for x in range(width)] + self.start = None + self.exit = None + + def getCell(self, x, y): + if 0 <= x < self.width and 0 <= y < self.height: + return self.grid[x][y] + return None + + def getNeighbors(self, cell): + neighbors = [] + for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]: + n = self.getCell(cell.x + dx, cell.y + dy) + if n and n.isPassable(): + neighbors.append(n) + return neighbors + + +class MazeBuilder(ABC): + @abstractmethod + def buildFromFile(self, filename): + pass + + +class TextFileMazeBuilder(MazeBuilder): + def buildFromFile(self, filename): + with open(filename, "r", encoding="utf-8") as f: + lines = [line.rstrip("\n\r") for line in f.readlines()] + + height = len(lines) + width = len(lines[0]) if height > 0 else 0 + + for line in lines: + if len(line) != width: + raise ValueError("все строки должны быть одной длины") + + maze = Maze(width, height) + + for y in range(height): + for x in range(width): + ch = lines[y][x] + cell = maze.getCell(x, y) + if ch == "#": + cell.isWall = True + elif ch == " ": + cell.isWall = False + elif ch == "S": + cell.isWall = False + cell.isStart = True + maze.start = cell + elif ch == "E": + cell.isWall = False + cell.isExit = True + maze.exit = cell + else: + raise ValueError(f"неизвестный символ: {ch}") + + if maze.start is None: + raise ValueError("нет старта (S)") + if maze.exit is None: + raise ValueError("нет выхода (E)") + + return maze + + +class PathFindingStrategy(ABC): + @abstractmethod + def findPath(self, maze, start, exit_cell): + pass + + def _reconstruct(self, parent, exit_cell): + path = [] + curr = exit_cell + while curr is not None: + path.append(curr) + curr = parent.get(curr) + path.reverse() + return path + + +class BFSStrategy(PathFindingStrategy): + def findPath(self, maze, start, exit_cell): + if exit_cell is None: + return [] + queue = deque([start]) + visited = {start} + parent = {start: None} + + while queue: + curr = queue.popleft() + if curr == exit_cell: + return self._reconstruct(parent, exit_cell) + for n in maze.getNeighbors(curr): + if n not in visited: + visited.add(n) + parent[n] = curr + queue.append(n) + return [] + + +class DFSStrategy(PathFindingStrategy): + def findPath(self, maze, start, exit_cell): + if exit_cell is None: + return [] + stack = [start] + visited = {start} + parent = {start: None} + + while stack: + curr = stack.pop() + if curr == exit_cell: + return self._reconstruct(parent, exit_cell) + for n in maze.getNeighbors(curr): + if n not in visited: + visited.add(n) + parent[n] = curr + stack.append(n) + return [] + + +class AStarStrategy(PathFindingStrategy): + def _heuristic(self, cell, exit_cell): + return abs(cell.x - exit_cell.x) + abs(cell.y - exit_cell.y) + + def findPath(self, maze, start, exit_cell): + if exit_cell is None: + return [] + open_set = [] + heapq.heappush(open_set, (0, start)) + parent = {start: None} + g_score = {start: 0} + + while open_set: + curr = heapq.heappop(open_set)[1] + if curr == exit_cell: + return self._reconstruct(parent, exit_cell) + + for n in maze.getNeighbors(curr): + new_g = g_score[curr] + 1 + if n not in g_score or new_g < g_score[n]: + g_score[n] = new_g + parent[n] = curr + f = new_g + self._heuristic(n, exit_cell) + heapq.heappush(open_set, (f, n)) + return [] + + +class SearchStats: + def __init__(self, time_ms, visited, path_len): + self.time_ms = time_ms + self.visited_cells = visited + self.path_length = path_len + + +class MazeSolver: + def __init__(self, maze): + self.maze = maze + self.strategy = None + self.observers = [] + + def setStrategy(self, strategy): + self.strategy = strategy + + def attach(self, observer): + self.observers.append(observer) + + def notify(self, event): + for obs in self.observers: + obs.update(event) + + def solve(self): + if self.strategy is None: + raise ValueError("стратегия не выбрана") + + start_time = time.perf_counter() + path = self.strategy.findPath(self.maze, self.maze.start, self.maze.exit) + elapsed_ms = (time.perf_counter() - start_time) * 1000 + + stats = SearchStats(elapsed_ms, len(path), len(path)) + self.notify({"type": "path_found", "maze": self.maze, "path": path, "stats": stats}) + return path, stats + + +class Observer(ABC): + @abstractmethod + def update(self, event): + pass + + +class ConsoleView(Observer): + def update(self, event): + if event["type"] == "path_found": + stats = event["stats"] + print(f"длина пути {stats.path_length}, время {stats.time_ms:.2f} мс") + + +def save_maze(maze, filename): + path = os.path.join(BASE, filename) + with open(path, "w", encoding="utf-8") as f: + for y in range(maze.height): + line = "" + for x in range(maze.width): + cell = maze.getCell(x, y) + if cell == maze.start: + line += "S" + elif cell == maze.exit: + line += "E" + elif cell.isWall: + line += "#" + else: + line += " " + f.write(line + "\n") + + +def generate_with_walls(w, h, prob=0.3): + maze = Maze(w, h) + for x in range(w): + for y in range(h): + if random.random() < prob: + maze.getCell(x, y).isWall = True + maze.getCell(0, 0).isWall = False + maze.getCell(w - 1, h - 1).isWall = False + for x in range(w): + maze.getCell(x, 0).isWall = False + for y in range(h): + maze.getCell(w - 1, y).isWall = False + maze.getCell(0, 0).isStart = True + maze.start = maze.getCell(0, 0) + maze.getCell(w - 1, h - 1).isExit = True + maze.exit = maze.getCell(w - 1, h - 1) + return maze + + +def generate_empty(w, h): + maze = Maze(w, h) + for x in range(w): + for y in range(h): + maze.getCell(x, y).isWall = False + maze.getCell(0, 0).isStart = True + maze.start = maze.getCell(0, 0) + maze.getCell(w - 1, h - 1).isExit = True + maze.exit = maze.getCell(w - 1, h - 1) + return maze + + +def generate_no_exit(w, h): + maze = generate_with_walls(w, h, 0.3) + exit_cell = maze.getCell(w - 1, h - 1) + exit_cell.isWall = True + exit_cell.isExit = False + maze.exit = None + return maze + + +def run_experiment(maze, strategy_class, maze_name, repeats=5): + times = [] + path_lens = [] + + for _ in range(repeats): + solver = MazeSolver(maze) + solver.setStrategy(strategy_class()) + path, stats = solver.solve() + times.append(stats.time_ms) + path_lens.append(len(path)) + + raw = strategy_class.__name__ + strat_name = "A" if raw == "AStarStrategy" else raw.replace("Strategy", "") + return { + "лабиринт": maze_name, + "стратегия": strat_name, + "время_ср": sum(times) / repeats, + "длина_пути_ср": sum(path_lens) / repeats, + "путь_найден": any(l > 0 for l in path_lens), + } + + +def main(): + mazes = [] + + small = generate_with_walls(10, 10, 0.2) + save_maze(small, "maze_small.txt") + mazes.append(("маленький 10x10", small)) + + medium = generate_with_walls(50, 50, 0.3) + save_maze(medium, "maze_medium.txt") + mazes.append(("средний 50x50", medium)) + + large = generate_with_walls(100, 100, 0.3) + save_maze(large, "maze_large.txt") + mazes.append(("большой 100x100", large)) + + empty = generate_empty(50, 50) + save_maze(empty, "maze_empty.txt") + mazes.append(("пустой 50x50", empty)) + + no_exit = generate_no_exit(20, 20) + save_maze(no_exit, "maze_no_exit.txt") + mazes.append(("без выхода 20x20", no_exit)) + + strategies = [BFSStrategy, DFSStrategy, AStarStrategy] + results = [] + + for maze_name, maze in mazes: + print(maze_name) + for strat in strategies: + res = run_experiment(maze, strat, maze_name) + results.append(res) + print(f" {strat.__name__}: {res['время_ср']:.2f} мс") + + csv_path = os.path.join(BASE, "resultslab.csv") + with open(csv_path, "w", newline="", encoding="utf-8-sig") as f: + writer = csv.DictWriter( + f, + fieldnames=["лабиринт", "стратегия", "время_ср", "длина_пути_ср", "путь_найден"], + delimiter=";", + ) + writer.writeheader() + for row in results: + row_ru = row.copy() + row_ru["путь_найден"] = "да" if row["путь_найден"] else "нет" + writer.writerow(row_ru) + + try: + import matplotlib.pyplot as plt + + plt.rcParams["font.sans-serif"] = ["Segoe UI", "Arial", "Tahoma", "DejaVu Sans"] + plt.rcParams["axes.unicode_minus"] = False + + labyrinths = [] + for r in results: + if r["лабиринт"] not in labyrinths: + labyrinths.append(r["лабиринт"]) + + fig, axes = plt.subplots(1, len(labyrinths), figsize=(4 * len(labyrinths), 4)) + if len(labyrinths) == 1: + axes = [axes] + + for idx, lab in enumerate(labyrinths): + times = [] + for s in ["BFS", "DFS", "A"]: + for r in results: + if r["лабиринт"] == lab and r["стратегия"] == s: + times.append(r["время_ср"]) + break + axes[idx].bar(["BFS", "DFS", "A"], times, color=["#1a5632", "#0e5fb4", "#e67e22"]) + axes[idx].set_title(lab) + axes[idx].set_ylabel("мс") + + plt.tight_layout() + plt.savefig(os.path.join(BASE, "maze_time_comparison.png")) + plt.close() + except ImportError: + pass + + report_path = os.path.join(os.path.dirname(BASE), "report.md") + with open(report_path, "w", encoding="utf-8-sig") as f: + f.write("# Отчёт: поиск пути в лабиринте\n\n") + f.write("Паттерны: Builder, Strategy, Observer\n\n") + f.write("```mermaid\nclassDiagram\n") + f.write("class MazeBuilder\nclass TextFileMazeBuilder\n") + f.write("class PathFindingStrategy\nclass BFSStrategy\n") + f.write("class DFSStrategy\nclass AStarStrategy\n") + f.write("class MazeSolver\nclass Observer\nclass ConsoleView\n") + f.write("MazeBuilder <|-- TextFileMazeBuilder\n") + f.write("PathFindingStrategy <|-- BFSStrategy\n") + f.write("PathFindingStrategy <|-- DFSStrategy\n") + f.write("PathFindingStrategy <|-- AStarStrategy\n") + f.write("Observer <|-- ConsoleView\n") + f.write("MazeSolver --> PathFindingStrategy\n") + f.write("```\n\n") + f.write("| Лабиринт | Стратегия | Время (мс) | Длина пути | Найден |\n") + f.write("| --- | --- | --- | --- | --- |\n") + for r in results: + found = "да" if r["путь_найден"] else "нет" + f.write( + f"| {r['лабиринт']} | {r['стратегия']} | {r['время_ср']:.2f} | " + f"{r['длина_пути_ср']:.0f} | {found} |\n" + ) + f.write("\n![График](data/maze_time_comparison.png)\n\n") + f.write("## Выводы\n\n") + f.write("- BFS и A* находят кратчайший путь.\n") + f.write("- DFS путь может быть длиннее.\n") + f.write("- На пустом лабиринте алгоритмы работают быстрее всего.\n") + f.write("- Без выхода все стратегии возвращают пустой путь.\n") + + print("Готово:", report_path) + + +if __name__ == "__main__": + main() diff --git a/rybakovaa/lab2/docs/data/maze_empty.txt b/rybakovaa/lab2/docs/data/maze_empty.txt new file mode 100644 index 0000000..a92cf1d --- /dev/null +++ b/rybakovaa/lab2/docs/data/maze_empty.txt @@ -0,0 +1,50 @@ +S + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + E diff --git a/rybakovaa/lab2/docs/data/maze_large.txt b/rybakovaa/lab2/docs/data/maze_large.txt new file mode 100644 index 0000000..5742515 --- /dev/null +++ b/rybakovaa/lab2/docs/data/maze_large.txt @@ -0,0 +1,100 @@ +S + # # # ## # # # # # # # # # ## # # # # ### # ## #### + ## # # # # # # # # ## # # # ### ## ## # ## # # #### +# # # # # # # # # # # # # # # # # # ## # ## # # + # # ## # # ## # # # ## # ## # ## # ## ## # + ### ## # ### ### # # # ## # # # ## ## # ### ## # # + ### # # # #### ## # # # # # ## # # # # # # +### # ## # # ## # # # ## # ## # # #### # # # ### # # # ## # + # # ## # # ## # # # # # ##### #### # #### # ## # # + ## # # # # # # ## # ## # ## # # # ## # # # # + # # ## # # ## # # ### # # # # # # # ### # # ## +# # # # # ## # # # ## # ## # # ### # # # # # # # ## # + # # # ### ## ## ## # # # # # # # # # # # # # ## # ## + # ## ## # # # # # # ## ## # ## # # ## # # # ### + # ## # # # # ## # # # # # # # # # # # ### # ## +# # # # # # # # #### ### # # ## # ## ## # # + # ### # # # # # ## # # #### # # # # ### # # # # # # ## +# # # # ## # # # # # ## # # # # ## ## ### # + # # ### # ## ## # # # # # # # # # # # # # + ## ## # # # # # ## # ## # # ## ## # ## # # # # # + #### ## # ### # # # # ## # # ## # # ## # # # # # # # # ## +## # ### # # # ## # # # ## # # # # # # ### ## ## # ### + ### #### # # # # # ## ## ### ### ## ## # ## # # ### ## # # # +# #### ## # # # ### # # # # # # # ## # # ##### # ## # ## + ## ### # ## ## # # ## # # # ## # # ## # # #### ### ## ## # + ## ## # # # # # # # # # ## ###### # ## ## ### #### # + # # ## # # # ## # # # # ### # ### # # ## # # # # ## # + # ## ## # # # # # ## # # ## # # ## # # # #### # # # # + # #### # ### # # # # #### # ## # # ## ### # # # # # # #### + ## # # # # # # # ### # ## # ## # # ## # # # ## ## # # +## # # # # # ## # # # # # # # # ## # # # # # # ### +# ## # # # # #### # # ## ## ## # ## # # ### # # ## # # # # + # # # # # # ## # # ## ### ## # # # ## ## # ## # # ## # ## # ## +# # ## ## # ## # ## # ### # ### ## ## ## ## # ## # # + # # # # # # ## # ###### # ## # # ## # # ## ## + ## ## # # # # # ## ## # # # #### ## ## # # # ## ## + ### # # ## # # # # ## # # # # # # ## # ## ## ## + ## # # # # # ## # # # # # ### # ## ### ## # ## # # # # # # ## +# ### # # # # ### ## # # # ## ## ### # ## # # # # + ##### ### # # # ###### # # ## # # # # ## # # # # ##### # + # # # # # # ## # #### # ### # ## #### # # # # # +# ### # # # # # # # # # #### # # ## # # # # # # # # # +## # ### # # # # # ## # # # # ### # # # # # # # # ## # # # # # + # # # # # # #### # # # ## ### # # # ## # ### # # ### +# # ## # ## # # # # # # ## # # # ## # # # # # ## ## + # # # # # # # # ## # # # ### # # ###### # # # # ## # + # # # # # ## # #### # # ## # ## ## # ## # # ## # + ### ## # # # ### # # # ## # # ### ### # # # # # ## + ## # # ### # # # ## # ## # # ####### # # #### # # # # # ## + # ## # # # ### # ## # # ## # # # # # ## ## ### # + ## ### # # ## # # # ## # ## # ## # ## # ## # ### + # # # # ## # # # # # # # # ## ##### # ## ### # ### # ### # # # # +## # # # # # # ##### ## # ### # ## ### # # # ## +## ## ## # # # # # # # # ## # ### ## # # # # # + ## # # # # # # # ## # #### # # # # # # # # # # # # ### + # # # # # # # ## ### # # ##### # # # # # # ## ## # ## # # # + # # # # # # # # # # # # ## # # # # + # # ## # ## # ## # # ## ##### # # # # # # ## # # # + # ### # ## # ### ## # # # # # ## # # ### ## # # # # + ### # # # ## ## # # # # # #### # ## # # # # ### ## + # # ## ## # ## # ## ### # # # # # # # # # ## # # # # + ## # # ## # # # ## ### # # # # ### # # # # # # # # # +# # ## ### ### # ## # # # # # # # # # # # # # # # # ### # + # # # ## # # ## # # # # # # # ## # + # # # ## ## # # # # # ## ## # # # ## ### # # # # # ### +## # ### # # ## # ## # # # # # # # # # # # # +# # ## # # # # # # # # # # # # # ## # # # # + ## # # # # ## # # # ### # # ## # # ## # ### # + # ## # # # ## # # ## ## # # # # ## # ## # # # # + # # # # # # ## # ## # ### ## # ## # # ## # # # # # +### # # # # # # # # ##### # ## # # # # # # # ## # ### # # # # +# # ## # # # ## # ## # # ### # # ## # # # # # # # # # + # # # ## # ## # # # # # ### ## # # # # # ## # + # ### # ## # # ## # # # # ## # ## ## # # # +# # # # # # # ### # # # ## # # ### # # #### # # +## ### # # # ## # # # # ## # # # # # # # ### # # # # ## # # # +# ## # # # # # # # # # # # # # # # # ### + # # # # ### # # # # # # # # # # ### # ## # ### # # # + # # ## # # # # # # # # ## # ## # # ### # # # # # + # # ## ## # # # # # # # # ## # ## # ## # ## ## # # # # # + # ## # # ## # ## # # # ### # # ## #### ### # # # +## # # # # ### # # ## # # ## # # # ## # # # # # ## # # + ## # ## # ### # ### # # # # # ## ## # # # # # ### # # # +## ### # # # # ### # # # # # # ## # # # ## ## # # ## # # ### ### + # ## # # # # ## # # # # # ### # # # # # # # # ### + ## ### # ## # # ## # # ## # ## # # # ### # # # # ## + # # # ## ##### # ## # ## # # # ### # ## # ## # ## ## # # ### + # # ## # ### # # # ## ## # # # # # # # # # # +# # # ### # # # # # ## # ## # #### ### # # # # # ### # ## # # + # # # # # # # # # # ## ## # # ## # # # # ## ## ## # # +# # # # # # ## # # # ##### # # ## ## # # ## # ## # # + # ### ## ## # #### ### # # ### # ### # # # ## ### #### ## ## ## ### + # # # # # # # ## # # # # # # # # # ## +# # # # ## # ## # # # # # # # # ## ## # # # +# # ## # # # # # ## # # # # ## ## # # # # ## + ## # # # # # # ## # # ### ## ### # ## # + # # # # # # # # # # # # # # ## ## # # # # + ## # # # ### # ### # # # # # ## ## # # # # # ## # # # # + # # ## # # ## # ### # # # # ### # # ## ### + # # # # # # # # # ## # # # # # # # ## # # # ## ## E diff --git a/rybakovaa/lab2/docs/data/maze_medium.txt b/rybakovaa/lab2/docs/data/maze_medium.txt new file mode 100644 index 0000000..6c46068 --- /dev/null +++ b/rybakovaa/lab2/docs/data/maze_medium.txt @@ -0,0 +1,50 @@ +S + # # # #### # # # # + ### # # # # # # ## ## ### # + # ## # # # # ## # #### # + ## ## # # # # ## # +# ## # # ### ## ## ### ## ## #### # + ##### # # # # # ## ## # # # ### + ### ## ## ## # # ## ### # + ## # ### # ### # ## # # # # ### ### + ### # # # # ## # ### # # + # ## # # # # # # # # + # # ### # ## # ## # # +# # # ## # # # # # # ### +## ### ### ## ## ## # # # + # # ## ## # # ## # ## ## ## # + # # # # ## # # # ## # # ## + # ## # # # ## # # +## # # # ## # # # #### # ##### # ## # +# # ## # # # # ##### ## # # + # # ## ## # # ## # # + # # ## ### # # # # # ### # + ## # # # ### # # ## # ## +# # # # ## # # # ## # # ## # ## + # # ## ## # #### # +# # # ## ### # ## # # # +# # ### # # ## # # ### # # ## # +# # # ## # ## # # # # # # # + # ## # # # # # # # # +# ## # #### # # # # ## # + # # ## # ### # # # ### ## ## # +# # # ### ## # # # # ## # +## # # ### ## # # # +### # # ## ## # # # # + # # # # # # # # # ## # # + # # ## ## # # ## # #### # # + # # # # ## # # # ## ## ## +# # # ## # ### # ### + # # ## ## # # # # # ## + # # # # # # # # ## # # # + ### ##### ## ## # # ### # # ## # # + ## # ### ## # # # #### # # + # # # # # # # ## ## ## + # # ## # # # ## ### ## ## # + ## # # ### # # ## ### +## # # # # # # # # # ## # # #### ## + # # # # # ## # ## ## # +## # # # # # # ## # # # ## # # +# ## # ### # # ## # # ### ## +## # # # ## # # # # # + # # # ### # ## # # ## E diff --git a/rybakovaa/lab2/docs/data/maze_no_exit.txt b/rybakovaa/lab2/docs/data/maze_no_exit.txt new file mode 100644 index 0000000..5d1c300 --- /dev/null +++ b/rybakovaa/lab2/docs/data/maze_no_exit.txt @@ -0,0 +1,20 @@ +S +# # # # ### + # # + # # # ## # + ## # ## # + # # ## + # ## + # ## # # + # # + ## # # + ### # # + # # # # ### + # ## +# # ## ## + # # #### + # # # # # + # # # + # ## ## + ## ## # # # +# # # ## diff --git a/rybakovaa/lab2/docs/data/maze_small.txt b/rybakovaa/lab2/docs/data/maze_small.txt new file mode 100644 index 0000000..dc8788d --- /dev/null +++ b/rybakovaa/lab2/docs/data/maze_small.txt @@ -0,0 +1,10 @@ +S + + # # +## # # +## # + # +# ## + +# # # + ### E diff --git a/rybakovaa/lab2/docs/data/maze_time_comparison.png b/rybakovaa/lab2/docs/data/maze_time_comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..d9621675489b652be383b06db1fe4eb8de5cfe2d GIT binary patch literal 29436 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 literal 0 HcmV?d00001 diff --git a/rybakovaa/lab2/docs/data/resultslab.csv b/rybakovaa/lab2/docs/data/resultslab.csv new file mode 100644 index 0000000..763fd2f --- /dev/null +++ b/rybakovaa/lab2/docs/data/resultslab.csv @@ -0,0 +1,16 @@ +лабиринт;стратегия;время_ср;длина_пути_ср;путь_найден +маленький 10x10;BFS;0.14045997522771358;19.0;да +маленький 10x10;DFS;0.08256000000983477;37.0;да +маленький 10x10;A;0.2506999997422099;19.0;да +средний 50x50;BFS;2.8775800252333283;99.0;да +средний 50x50;DFS;1.9064400112256408;283.0;да +средний 50x50;A;2.429639990441501;99.0;да +большой 100x100;BFS;12.2316999360919;199.0;да +большой 100x100;DFS;8.781959977932274;1643.0;да +большой 100x100;A;8.597399992868304;199.0;да +пустой 50x50;BFS;4.875819990411401;99.0;да +пустой 50x50;DFS;3.1325000105425715;1275.0;да +пустой 50x50;A;11.547920037992299;99.0;да +без выхода 20x20;BFS;0.0002400018274784088;0.0;нет +без выхода 20x20;DFS;0.0002400018274784088;0.0;нет +без выхода 20x20;A;0.0001600012183189392;0.0;нет diff --git a/rybakovaa/lab2/docs/report.md b/rybakovaa/lab2/docs/report.md new file mode 100644 index 0000000..93f0071 --- /dev/null +++ b/rybakovaa/lab2/docs/report.md @@ -0,0 +1,49 @@ +# Отчёт: поиск пути в лабиринте + +Паттерны: Builder, Strategy, Observer + +```mermaid +classDiagram +class MazeBuilder +class TextFileMazeBuilder +class PathFindingStrategy +class BFSStrategy +class DFSStrategy +class AStarStrategy +class MazeSolver +class Observer +class ConsoleView +MazeBuilder <|-- TextFileMazeBuilder +PathFindingStrategy <|-- BFSStrategy +PathFindingStrategy <|-- DFSStrategy +PathFindingStrategy <|-- AStarStrategy +Observer <|-- ConsoleView +MazeSolver --> PathFindingStrategy +``` + +| Лабиринт | Стратегия | Время (мс) | Длина пути | Найден | +| --- | --- | --- | --- | --- | +| маленький 10x10 | BFS | 0.14 | 19 | да | +| маленький 10x10 | DFS | 0.08 | 37 | да | +| маленький 10x10 | A | 0.25 | 19 | да | +| средний 50x50 | BFS | 2.88 | 99 | да | +| средний 50x50 | DFS | 1.91 | 283 | да | +| средний 50x50 | A | 2.43 | 99 | да | +| большой 100x100 | BFS | 12.23 | 199 | да | +| большой 100x100 | DFS | 8.78 | 1643 | да | +| большой 100x100 | A | 8.60 | 199 | да | +| пустой 50x50 | BFS | 4.88 | 99 | да | +| пустой 50x50 | DFS | 3.13 | 1275 | да | +| пустой 50x50 | A | 11.55 | 99 | да | +| без выхода 20x20 | BFS | 0.00 | 0 | нет | +| без выхода 20x20 | DFS | 0.00 | 0 | нет | +| без выхода 20x20 | A | 0.00 | 0 | нет | + +![График](data/maze_time_comparison.png) + +## Выводы + +- BFS и A* находят кратчайший путь. +- DFS путь может быть длиннее. +- На пустом лабиринте алгоритмы работают быстрее всего. +- Без выхода все стратегии возвращают пустой путь.