From 568d2cbf233086e80d4d4d215e760202506923c0 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Sat, 14 Feb 2026 11:35:41 +0300 Subject: [PATCH 01/28] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20main.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/main.py | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 skorohodovsa/main.py diff --git a/skorohodovsa/main.py b/skorohodovsa/main.py new file mode 100644 index 0000000..ba8db40 --- /dev/null +++ b/skorohodovsa/main.py @@ -0,0 +1,4 @@ +from math import sin + +for i in range(10000): + print(" " * round(50 * (1 + sin(i/100))), "Hello World!") From 9cf5ffa339a5b5152290f36443563df489d89531 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Sat, 14 Feb 2026 12:29:33 +0300 Subject: [PATCH 02/28] =?UTF-8?q?[0]=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20main.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/main.py | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 skorohodovsa/main.py diff --git a/skorohodovsa/main.py b/skorohodovsa/main.py new file mode 100644 index 0000000..ba8db40 --- /dev/null +++ b/skorohodovsa/main.py @@ -0,0 +1,4 @@ +from math import sin + +for i in range(10000): + print(" " * round(50 * (1 + sin(i/100))), "Hello World!") From ae9b2a46b6cdbdc91f763b6f7894bf00127c0c8a Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Wed, 25 Feb 2026 08:40:42 +0300 Subject: [PATCH 03/28] =?UTF-8?q?[1]=20=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8?= =?UTF-8?q?=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B8=20?= =?UTF-8?q?=D1=83=D0=B7=D0=BB=D0=B0=20create=5Fnode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_1/linked_list.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 skorohodovsa/task_1/linked_list.py diff --git a/skorohodovsa/task_1/linked_list.py b/skorohodovsa/task_1/linked_list.py new file mode 100644 index 0000000..7351f7e --- /dev/null +++ b/skorohodovsa/task_1/linked_list.py @@ -0,0 +1,13 @@ + + +def create_node( + name: str, + phone: str, + next: dict = None +): + return { + 'name': name, + 'phone': phone, + 'next': next + } + \ No newline at end of file From 1fd05fbf2549f08b481b193c11e40ab59dfda4ba Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Wed, 25 Feb 2026 09:00:04 +0300 Subject: [PATCH 04/28] =?UTF-8?q?[1]=20=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8?= =?UTF-8?q?=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=81?= =?UTF-8?q?=D0=B2=D1=8F=D0=B7=D0=B0=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=81?= =?UTF-8?q?=D0=BF=D0=B8=D1=81=D0=BA=D0=B0=20=D0=BF=D0=BE=20=D1=81=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=BA=D1=83=20=D1=81=D0=BB=D0=BE=D0=B2=D0=B0=D1=80?= =?UTF-8?q?=D0=B5=D0=B9=20create=5Flinked=5Flist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_1/linked_list.py | 45 ++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/skorohodovsa/task_1/linked_list.py b/skorohodovsa/task_1/linked_list.py index 7351f7e..d7caab6 100644 --- a/skorohodovsa/task_1/linked_list.py +++ b/skorohodovsa/task_1/linked_list.py @@ -1,13 +1,36 @@ +def create_node(name: str, phone: str, next: dict = None): + return {"name": name, "phone": phone, "next": next} -def create_node( - name: str, - phone: str, - next: dict = None -): - return { - 'name': name, - 'phone': phone, - 'next': next - } - \ No newline at end of file +def create_linked_list(data: list[dict]) -> dict: + if data is None or len(data) == 0: + raise ValueError("Список пустой!") + + base = create_node(**data[0]) + + current = base + for value in data[1:]: + current['next'] = create_node(**value) + current = current['next'] + + return base + + +def ll_insert(): + pass + + +def ll_find(): + pass + + +def ll_delete(): + pass + + +def ll_list_all(): + pass + + +def ll_print_all(): + pass \ No newline at end of file From 7c9a1f8b51fec6203f587ef87659fcaee5288241 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Wed, 25 Feb 2026 09:00:38 +0300 Subject: [PATCH 05/28] =?UTF-8?q?[1]=20=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=20=D1=84=D0=B0=D0=B9=D0=BB=20=D0=B4=D0=BB=D1=8F=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=BE=D0=B2=20=D1=84=D0=B0=D0=B9=D0=BB=D0=B0?= =?UTF-8?q?=20=D1=81=D0=B2=D1=8F=D0=B7=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20?= =?UTF-8?q?=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_1/test_linked_list.py | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 skorohodovsa/task_1/test_linked_list.py diff --git a/skorohodovsa/task_1/test_linked_list.py b/skorohodovsa/task_1/test_linked_list.py new file mode 100644 index 0000000..d11ac57 --- /dev/null +++ b/skorohodovsa/task_1/test_linked_list.py @@ -0,0 +1,26 @@ +from linked_list import create_node, create_linked_list + + +test_records = [ + {"name": "Анна", "phone": "89123456789"}, + {"name": "Михаил", "phone": "79223334455"}, + {"name": "Елена", "phone": "4951234567"}, + {"name": "Дмитрий", "phone": "9111112233"}, + {"name": "Ольга", "phone": "81234567890"}, + {"name": "Александр", "phone": "9219998877"}, + {"name": "Татьяна", "phone": "4955556666"}, + {"name": "Иван", "phone": "9034443322"}, + {"name": "Наталья", "phone": "9167778899"}, + {"name": "Павел", "phone": "9256665544"}, + {"name": "Мария", "phone": "4953332211"}, + {"name": "Андрей", "phone": "9264443322"}, + {"name": "Екатерина", "phone": "8125554433"}, + {"name": "Владимир", "phone": "9107778899"}, + {"name": "Юлия", "phone": "4951112233"}, + {"name": "Николай", "phone": "9215556677"}, + {"name": "Светлана", "phone": "9164443322"}, + {"name": "Артем", "phone": "9253334455"}, + {"name": "Ксения", "phone": "4952223344"}, +] + +print(create_linked_list(test_records)) From 88bcf8a761a115ead9a366ff1de09b7b28cb2ab3 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Fri, 6 Mar 2026 09:55:45 +0300 Subject: [PATCH 06/28] =?UTF-8?q?[1]=20=D0=9D=D0=B0=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=B0=D0=BD=D0=B0=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=B8=D1=81=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_1/linked_list.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/skorohodovsa/task_1/linked_list.py b/skorohodovsa/task_1/linked_list.py index d7caab6..b1fe2d3 100644 --- a/skorohodovsa/task_1/linked_list.py +++ b/skorohodovsa/task_1/linked_list.py @@ -12,7 +12,7 @@ def create_linked_list(data: list[dict]) -> dict: for value in data[1:]: current['next'] = create_node(**value) current = current['next'] - + return base @@ -20,8 +20,15 @@ def ll_insert(): pass -def ll_find(): - pass +def ll_find(head: dict, name: str) -> str | None: + if head is None: + raise ValueError("Словарь пустой!") + + current = head + while current['next'] is not None: + if current['name'] == name: + return current['name'] + return None def ll_delete(): From de73e9247bf4942dd635faebc7867f9887e88850 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Wed, 18 Mar 2026 13:33:50 +0300 Subject: [PATCH 07/28] =?UTF-8?q?[1]=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20.gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 skorohodovsa/.gitignore diff --git a/skorohodovsa/.gitignore b/skorohodovsa/.gitignore new file mode 100644 index 0000000..61b51ed --- /dev/null +++ b/skorohodovsa/.gitignore @@ -0,0 +1,2 @@ +/.ruff_check +/.vscode \ No newline at end of file From dc7f07b42b7b684c19dd1fe62f0ce6466bc83e28 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Wed, 18 Mar 2026 13:49:02 +0300 Subject: [PATCH 08/28] =?UTF-8?q?[1]=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B8=20=D0=BD?= =?UTF-8?q?=D0=B5=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B5=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Сделана ll_insert - Редактирована ll_find - Сделана ll_delete - Сделана ll_list_all Тесты: - Для create_linked_list - Для ll_find - Для ll_insert --- skorohodovsa/task_1/linked_list.py | 72 +++++++++++---- skorohodovsa/task_1/test/test_task_1.py | 114 ++++++++++++++++++++++++ skorohodovsa/task_1/test_linked_list.py | 26 ------ 3 files changed, 169 insertions(+), 43 deletions(-) create mode 100644 skorohodovsa/task_1/test/test_task_1.py delete mode 100644 skorohodovsa/task_1/test_linked_list.py diff --git a/skorohodovsa/task_1/linked_list.py b/skorohodovsa/task_1/linked_list.py index b1fe2d3..9248ec7 100644 --- a/skorohodovsa/task_1/linked_list.py +++ b/skorohodovsa/task_1/linked_list.py @@ -3,41 +3,79 @@ def create_node(name: str, phone: str, next: dict = None): def create_linked_list(data: list[dict]) -> dict: + """Создание связного списка по массиву словарей. + + :param data: Список словарей с параметрами: {'name': str, 'phone': str, next: dict | None} + :type data: list[dict] + :raises ValueError: Ошибка при подаче на вход пустого списка + :return: Связный список оформленный по примеру: {'name': str, 'phone': str, next: dict | None} + :rtype: dict + """ if data is None or len(data) == 0: raise ValueError("Список пустой!") - + base = create_node(**data[0]) current = base for value in data[1:]: - current['next'] = create_node(**value) - current = current['next'] - + current["next"] = create_node(**value) + current = current["next"] + return base -def ll_insert(): - pass +def ll_insert(head: dict, name: str, phone: str) -> dict: + if head is None: + raise ValueError("Словарь пустой!") + + current = head + while current["next"] is not None: + if current.get("name") == name or current.get("phone") == phone: + current["name"] = name + current["phone"] = phone + break + current = current.get("next") + else: + current["next"] = {"name": name, "phone": phone, "next": None} + + return head def ll_find(head: dict, name: str) -> str | None: if head is None: raise ValueError("Словарь пустой!") - + current = head - while current['next'] is not None: - if current['name'] == name: - return current['name'] + while current is not None: + if current["name"] == name: + return current["phone"] + current = current["next"] return None -def ll_delete(): - pass +def ll_delete(head: dict, name: str) -> dict: + if head is None: + raise ValueError("Словарь пустой!") + + if head.get("name") == name: + head = head.get("next") + return head + + current = head + while current.get("next") is not None: + if current.get("next").get("name") == name: + current["next"] = current.get("next").get("next") + return head + current = current.get("next") + + return head -def ll_list_all(): - pass +def ll_list_all(head: dict) -> list: + result = [] + current = head + while current is not None: + result.append({"name": current.get("name"), "phone": current.get("phone")}) + current = current.get("next") + return result - -def ll_print_all(): - pass \ No newline at end of file diff --git a/skorohodovsa/task_1/test/test_task_1.py b/skorohodovsa/task_1/test/test_task_1.py new file mode 100644 index 0000000..d0cb728 --- /dev/null +++ b/skorohodovsa/task_1/test/test_task_1.py @@ -0,0 +1,114 @@ +import pytest +import sys +import os +import copy + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) + +from linked_list import create_linked_list, ll_find, ll_insert, ll_list_all + + +@pytest.fixture +def test_records(): + return [ + {"name": "Анна", "phone": "89123456789"}, + {"name": "Михаил", "phone": "79223334455"}, + {"name": "Елена", "phone": "4951234567"}, + {"name": "Дмитрий", "phone": "9111112233"}, + {"name": "Ольга", "phone": "81234567890"}, + {"name": "Александр", "phone": "9219998877"}, + {"name": "Татьяна", "phone": "4955556666"}, + {"name": "Иван", "phone": "9034443322"}, + {"name": "Наталья", "phone": "9167778899"}, + {"name": "Павел", "phone": "9256665544"}, + {"name": "Мария", "phone": "4953332211"}, + {"name": "Андрей", "phone": "9264443322"}, + {"name": "Екатерина", "phone": "8125554433"}, + {"name": "Владимир", "phone": "9107778899"}, + {"name": "Юлия", "phone": "4951112233"}, + {"name": "Николай", "phone": "9215556677"}, + {"name": "Светлана", "phone": "9164443322"}, + {"name": "Артем", "phone": "9253334455"}, + {"name": "Ксения", "phone": "4952223344"}, + ] + + +@pytest.fixture +def linked_list(test_records): + return create_linked_list(test_records) + + +def test_create_linked_list(test_records): + linked_list = create_linked_list(test_records) + assert linked_list is not None + + temp = linked_list + index = 0 + + while temp.get("next") is not None: + assert temp.get("phone") == test_records[index].get("phone") + assert temp.get("name") == test_records[index].get("name") + + temp = temp.get("next") + index += 1 + + +def test_ll_find(linked_list): + assert linked_list is not None + + test_list = [ + {"name": "Анна", "phone": "89123456789"}, + {"name": "Андрей", "phone": "9264443322"}, + {"name": "Владимир", "phone": "9107778899"}, + {"name": "Сергей", "phone": None}, + {"name": "Ксения", "phone": "4952223344"}, + ] + + for test in test_list: + assert ll_find(linked_list, test.get("name")) == test.get("phone") + + +def test_ll_insert_edit(linked_list, test_records): + assert linked_list is not None + + test_list = [ + {"name": "Анна", "phone": "89123456745"}, + {"name": "Андрей", "phone": "926444332232"}, + {"name": "Владимир", "phone": "9107778899"}, + {"name": "Ксения", "phone": "4952223344"}, + ] + + for test in test_list: + test_ll = copy.deepcopy(linked_list) + result_insert = ll_insert(test_ll, test.get("name"), test.get("phone")) + + # Проверяем наличие изменения номера телефона + assert ll_find(result_insert, test.get("name")) == test.get("phone") + + # Проверяем правильность места изменения + for i, value in enumerate(test_records): + if value.get("name") == test.get("name"): + assert ll_list_all(result_insert)[i].get("phone") == test.get("phone") + break + + +def test_ll_insert_new(linked_list): + assert linked_list is not None + + new_name = "Новый контакт" + new_phone = "99999999999" + + test_ll = copy.deepcopy(linked_list) + + result = ll_insert(test_ll, new_name, new_phone) + + assert ll_find(result, new_name) == new_phone + + # Проверяем, что новый элемент в конце + all_items = ll_list_all(result) + assert all_items[-1].get("name") == new_name + +def test_ll_delete(linked_list): + assert linked_list is not None + + \ No newline at end of file diff --git a/skorohodovsa/task_1/test_linked_list.py b/skorohodovsa/task_1/test_linked_list.py deleted file mode 100644 index d11ac57..0000000 --- a/skorohodovsa/task_1/test_linked_list.py +++ /dev/null @@ -1,26 +0,0 @@ -from linked_list import create_node, create_linked_list - - -test_records = [ - {"name": "Анна", "phone": "89123456789"}, - {"name": "Михаил", "phone": "79223334455"}, - {"name": "Елена", "phone": "4951234567"}, - {"name": "Дмитрий", "phone": "9111112233"}, - {"name": "Ольга", "phone": "81234567890"}, - {"name": "Александр", "phone": "9219998877"}, - {"name": "Татьяна", "phone": "4955556666"}, - {"name": "Иван", "phone": "9034443322"}, - {"name": "Наталья", "phone": "9167778899"}, - {"name": "Павел", "phone": "9256665544"}, - {"name": "Мария", "phone": "4953332211"}, - {"name": "Андрей", "phone": "9264443322"}, - {"name": "Екатерина", "phone": "8125554433"}, - {"name": "Владимир", "phone": "9107778899"}, - {"name": "Юлия", "phone": "4951112233"}, - {"name": "Николай", "phone": "9215556677"}, - {"name": "Светлана", "phone": "9164443322"}, - {"name": "Артем", "phone": "9253334455"}, - {"name": "Ксения", "phone": "4952223344"}, -] - -print(create_linked_list(test_records)) From e590e7d02def294167c7355078aa1eb7fb1e65e3 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Wed, 18 Mar 2026 14:17:11 +0300 Subject: [PATCH 09/28] =?UTF-8?q?[1]=20=D0=94=D0=BE=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=B0=D0=BD=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=BE=D0=B2=D1=8B=D1=85=20=D1=84=D1=83=D0=BD=D0=BA?= =?UTF-8?q?=D1=86=D0=B8=D0=B9=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Добавлен тест ll_delete --- skorohodovsa/task_1/test/test_task_1.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/skorohodovsa/task_1/test/test_task_1.py b/skorohodovsa/task_1/test/test_task_1.py index d0cb728..f4780e6 100644 --- a/skorohodovsa/task_1/test/test_task_1.py +++ b/skorohodovsa/task_1/test/test_task_1.py @@ -5,7 +5,7 @@ import copy sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) -from linked_list import create_linked_list, ll_find, ll_insert, ll_list_all +from linked_list import create_linked_list, ll_find, ll_insert, ll_list_all, ll_delete @pytest.fixture @@ -108,7 +108,21 @@ def test_ll_insert_new(linked_list): all_items = ll_list_all(result) assert all_items[-1].get("name") == new_name -def test_ll_delete(linked_list): +def test_ll_delete(linked_list, test_records): assert linked_list is not None - \ No newline at end of file + tests = [ + test_records[0], + test_records[1], + test_records[len(test_records) // 2], + test_records[-2], + test_records[-1], + {"name": "Сергей", "phone": "89290504426"}, + ] + + for test in tests: + test_ll = copy.deepcopy(linked_list) + + result_delete = ll_delete(test_ll, test.get('name')) + + assert ll_find(result_delete, test.get('name')) is None \ No newline at end of file From 83651244fe5e87fb8e4b125170fa7bedcf755089 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Wed, 18 Mar 2026 19:52:13 +0300 Subject: [PATCH 10/28] =?UTF-8?q?[1]=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20docstring=20=D0=BA=20=D1=84=D1=83?= =?UTF-8?q?=D0=BD=D0=BA=D1=86=D0=B8=D1=8F=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_1/linked_list.py | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/skorohodovsa/task_1/linked_list.py b/skorohodovsa/task_1/linked_list.py index 9248ec7..d9a6948 100644 --- a/skorohodovsa/task_1/linked_list.py +++ b/skorohodovsa/task_1/linked_list.py @@ -25,6 +25,21 @@ def create_linked_list(data: list[dict]) -> dict: def ll_insert(head: dict, name: str, phone: str) -> dict: + """Добавление нового или редактирование элемента в связном списке + + Если пользователь уже есть в списке, то обновятся его данные (номер телефона). В случае если + данных нет, то они добавляются в конец. + + :param head: Список словарей с параметрами: {'name': str, 'phone': str, next: dict | None} + :type head: dict + :param name: Имя пользователя (не должно повторятся с имеющимися) + :type name: str + :param phone: Номер телефона пользователя (не должно повторятся с имеющимися) + :type phone: str + :raises ValueError: Ошибка при подаче на вход пустого списка + :return: Возвращает связный список с обновленными данными + :rtype: dict + """ if head is None: raise ValueError("Словарь пустой!") @@ -42,6 +57,21 @@ def ll_insert(head: dict, name: str, phone: str) -> dict: def ll_find(head: dict, name: str) -> str | None: + """Поиск пользователя в связном списке + + Если функция найдёт пользователя по имени, то вернёт его номер телефона. + В противном случае будет возвращено значение None. + + В случае повторяющихся имен в списке, выведется выше стоящие + + :param head: Список словарей с параметрами: {'name': str, 'phone': str, next: dict | None} + :type head: dict + :param name: Имя пользователя + :type name: str + :raises ValueError: Ошибка при подаче на вход пустого списка + :return: Возвращает номер телефона найденного пользователя, иначе None + :rtype: str | None + """ if head is None: raise ValueError("Словарь пустой!") @@ -54,6 +84,16 @@ def ll_find(head: dict, name: str) -> str | None: def ll_delete(head: dict, name: str) -> dict: + """Удаление пользователя из связного списка + + :param head: Список словарей с параметрами: {'name': str, 'phone': str, next: dict | None} + :type head: dict + :param name: Имя пользователя + :type name: str + :raises ValueError: Ошибка при подаче на вход пустого списка + :return: Возвращает связный список с обновленными данными + :rtype: dict + """ if head is None: raise ValueError("Словарь пустой!") From e0e7f9eb57cf76f9b2e4f506c136001de9279e78 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Sun, 17 May 2026 00:04:06 +0300 Subject: [PATCH 11/28] =?UTF-8?q?[1]=20=20=D0=9A=D0=BE=D0=BD=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=BD=D0=B0=D1=8F=20=D1=82=D0=BE=D1=87=D0=BA?= =?UTF-8?q?=D0=B0=20(=D0=91=D0=B8=D0=BD=D0=B0=D1=80=D0=BD=D0=BE=D0=B5=20?= =?UTF-8?q?=D0=B4=D0=B5=D1=80=D0=B5=D0=B2=D0=BE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_1/binary_tree.py | 73 +++++++++++++++++++++++++ skorohodovsa/task_1/test/test_task_2.py | 0 2 files changed, 73 insertions(+) create mode 100644 skorohodovsa/task_1/binary_tree.py create mode 100644 skorohodovsa/task_1/test/test_task_2.py diff --git a/skorohodovsa/task_1/binary_tree.py b/skorohodovsa/task_1/binary_tree.py new file mode 100644 index 0000000..ab8f633 --- /dev/null +++ b/skorohodovsa/task_1/binary_tree.py @@ -0,0 +1,73 @@ +from typing import Any, Callable + + +def bst_create_node(name: str, phone: str, left: dict = None, right: dict = None) -> dict: + return { + 'name': name, + 'phone': phone, + 'left': left, + 'right': right + } + + +def comparison_name(name_main: str, name_second: str) -> str: + """Сравнение аргументов + + :param name_main: + :type name_main: str + :param name_second: _description_ + :type name_second: str + :return: _description_ + :rtype: str + """ + return 'right' if name_main >= name_second else 'left' + + +def bst_insert(root: dict, name: str, phone: str) -> dict: + if root is None: + return bst_create_node(name, phone) + + path = comparison_name(root['name'], name) + root[path] = bst_insert(root[path], name, phone) + + return root + + +def bst_create_tree(data: list[dict]) -> dict: + if data is None or len(data) == 0: + raise ValueError("Список пустой!") + base = bst_create_node(**data[0]) + + for var in data[1:]: + bst_insert(base, **var) + + return base + + +def bst_find(root: dict, name: str) -> str | None: + if root is None: + return None + + if root['name'] == name: + return root['phone'] + + path = comparison_name(root['name'], name) + return bst_find(root[path], name) + + +def bst_delete(root, name: str, delete_node: bool = False) -> Any: + if root is None: + return None + + if root['name'] == name: + if delete_node: + root + else: + pass + + path = comparison_name(root['name'], name) + return bst_find(root[path], name) + + +def bst_list_all(root: dict) -> list[dict]: + pass \ No newline at end of file diff --git a/skorohodovsa/task_1/test/test_task_2.py b/skorohodovsa/task_1/test/test_task_2.py new file mode 100644 index 0000000..e69de29 From e45f8cba643486bf83beafe2fc3f7afb20fa9e9c Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Wed, 20 May 2026 11:31:35 +0300 Subject: [PATCH 12/28] =?UTF-8?q?[1]=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20.gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/.gitignore | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/skorohodovsa/.gitignore b/skorohodovsa/.gitignore index 61b51ed..70e00c4 100644 --- a/skorohodovsa/.gitignore +++ b/skorohodovsa/.gitignore @@ -1,2 +1,6 @@ -/.ruff_check -/.vscode \ No newline at end of file +.ruff_cache/ +.vscode/* +.idea/ +/.vscode + +task_1/work.py \ No newline at end of file From d05d292101709b39db5ec8d79be6f3d7894fcf0e Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Wed, 20 May 2026 11:38:02 +0300 Subject: [PATCH 13/28] =?UTF-8?q?[2]=20=D0=A1=D1=82=D0=B0=D1=80=D1=82?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D1=8F=20=D1=81=D0=B1=D0=BE=D1=80=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_2/.gitignore | 1 + skorohodovsa/task_2/README.md | 103 +++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 skorohodovsa/task_2/.gitignore create mode 100644 skorohodovsa/task_2/README.md diff --git a/skorohodovsa/task_2/.gitignore b/skorohodovsa/task_2/.gitignore new file mode 100644 index 0000000..af253e0 --- /dev/null +++ b/skorohodovsa/task_2/.gitignore @@ -0,0 +1 @@ +/.obsidian \ No newline at end of file diff --git a/skorohodovsa/task_2/README.md b/skorohodovsa/task_2/README.md new file mode 100644 index 0000000..e8ab679 --- /dev/null +++ b/skorohodovsa/task_2/README.md @@ -0,0 +1,103 @@ +# Поиск выхода из лабиринта +--- +## Цель работы + +Разработать гибкую, расширяемую программу для загрузки лабиринта из файла, поиска пути от старта до выхода с возможностью выбора алгоритма, визуализации процесса и экспериментального сравнения алгоритмов. В ходе работы необходимо применить минимум 3 паттерна проектирования из списка GoF, обосновать их выбор и продемонстрировать преимущества такой архитектуры. + +--- +## Архитектура + +```mermaid +classDiagram + class Maze { + -Cell[] cells + -int width, height + -Cell start + -Cell exit + +getCell(x,y): Cell + +getNeighbors(cell): List~Cell~ + } + + class Cell { + -int x, y + -bool isWall + -bool isStart + -bool isExit + +isPassable(): bool + } + + class MazeBuilder { + <> + +buildFromFile(filename): Maze + } + + class TextFileMazeBuilder { + +buildFromFile(filename): Maze + } + + class PathFindingStrategy { + <> + +findPath(maze, start, exit): List~Cell~ + } + + class BFSStrategy + class DFSStrategy + class AStarStrategy + class DijkstraStrategy + + class SearchStats { + +timeMs: float + +visitedCells: int + +pathLength: int + } + + class MazeSolver { + -Maze maze + -PathFindingStrategy strategy + +setStrategy(strategy) + +solve(): SearchStats + } + + class Command { + <> + +execute() + +undo() + } + + class MoveCommand { + -Player player + -Direction dir + -Cell previousCell + +execute() + +undo() + } + + class Player { + -Cell currentCell + +moveTo(cell) + } + + class Observer { + <> + +update(event) + } + + class ConsoleView { + +update(event) + +render(maze, player, path) + } + + MazeBuilder <|.. TextFileMazeBuilder + MazeBuilder --> Maze : creates + PathFindingStrategy <|.. BFSStrategy + PathFindingStrategy <|.. DFSStrategy + PathFindingStrategy <|.. AStarStrategy + PathFindingStrategy <|.. DijkstraStrategy + MazeSolver --> PathFindingStrategy : uses + MazeSolver --> Maze : uses + Command <|.. MoveCommand + MoveCommand --> Player + Player --> Cell + Observer <|.. ConsoleView + MazeSolver --> Observer : notifies +``` From 05a9bdd8f4879d02a1691d347c3dbe9b283ac470 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Wed, 20 May 2026 13:31:25 +0300 Subject: [PATCH 14/28] =?UTF-8?q?[2]=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=B5=D1=80=D0=B2=D1=8B?= =?UTF-8?q?=D1=85=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B9=20=D0=BA=D0=BB?= =?UTF-8?q?=D0=B0=D1=81=D1=81=D0=BE=D0=B2=20`Cell`=20=D0=B8=20`Maze`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_2/.gitignore | 34 ++++++++- skorohodovsa/task_2/models/map.py | 102 +++++++++++++++++++++++++++ skorohodovsa/task_2/requirements.txt | 7 ++ 3 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 skorohodovsa/task_2/models/map.py create mode 100644 skorohodovsa/task_2/requirements.txt diff --git a/skorohodovsa/task_2/.gitignore b/skorohodovsa/task_2/.gitignore index af253e0..27d8248 100644 --- a/skorohodovsa/task_2/.gitignore +++ b/skorohodovsa/task_2/.gitignore @@ -1 +1,33 @@ -/.obsidian \ No newline at end of file +/.obsidian + +# Виртуальное окружение +venv/ +env/ +.venv/ +.env/ + +# Python кэш +__pycache__/ +*.py[cod] +*.so +.Python + +# Сборка документации Sphinx - ЭТО ВАЖНО! +docs/build/ +docs/source/_build/ + +# Системные файлы +.DS_Store +Thumbs.db +*.swp +*.swo +*~ + +# IDE +.vscode/ +.idea/ + +# Логи +*.log + +.ruff_cache/ \ No newline at end of file diff --git a/skorohodovsa/task_2/models/map.py b/skorohodovsa/task_2/models/map.py new file mode 100644 index 0000000..385c5c9 --- /dev/null +++ b/skorohodovsa/task_2/models/map.py @@ -0,0 +1,102 @@ +from typing import Optional + + +class Cell: + """Класс отвечает за хранение характеристик поля лабиринта""" + + def __init__( + self, + x: int, + y: int, + is_wall: bool = False, + is_start: bool = False, + is_exit: bool = False, + ): + """ + :param x: Координата поля по оси X + :type x: int + :param y: Координата поля по оси Y + :type y: int + :param is_wall: Является ли поле **стеной**, defaults to False + :type is_wall: bool, optional + :param is_start: Является ли поле **началом**, defaults to False + :type is_start: bool, optional + :param is_exit: Является ли поле **концом**, defaults to False + :type is_exit: bool, optional + """ + self.x = x + self.y = y + self.is_wall = is_wall + self.is_start = is_start + self.is_exit = is_exit + + def isPossible(self) -> bool: + """Проверка возможности перемещения в это поле + + :return: Если перемещение возможно, то `True`, иначе `False` + :rtype: bool + """ + return not self.is_wall + + +class Maze: + def __init__( + self, + size: tuple[int, int] = (10, 10), + start_point: tuple[int, int] = (0, 0), + exit_point: tuple[int, int] = (-1, -1), + ): + # Установка размеров лабиринта + self._width = size[0] + self._height = size[1] + + # Установка значения стартового поля в лабиринте + self._start_x = start_point[0] + self._start_y = start_point[1] + + # Установка значения выходного поля в лабиринте + self._exit_x = self._width - 1 if exit_point[0] == -1 else exit_point[0] + self._exit_y = self._height - 1 if exit_point[1] == -1 else exit_point[1] + + # Создание двумерного списка лабиринта + self._map = [ + [Cell(x, y) for x in range(self._width)] for y in range(self._height) + ] + + # Проверяем, что координаты старта находятся в области лабиринта + if self._check_point_in_map(self._start_x, self._start_y): + self._map[self._start_y][self._start_x].is_start = True + else: + raise ValueError( + f"Координата точки старта задана вне области лабиринта: ({self._start_x}, {self._start_y}) not in ({self._width}, {self._height})" + ) + + # Проверяем, что координаты выхода находятся в области лабиринта + if not self._check_point_in_map(self._exit_x, self._exit_y): + raise ValueError( + f"Координата точки выхода задана вне области лабиринта: ({self._start_x}, {self._start_y}) not in ({self._width}, {self._height})" + ) + self._map[self._exit_y][self._exit_x].is_exit = True + + def _check_point_in_map(self, x: int, y: int) -> bool: + return (0 <= x < self._width) and (0 <= y < self._height) + + def get_cell(self, x: int, y: int) -> Optional[Cell]: + if not self._check_point_in_map(x, y): + raise ValueError( + f"Указанные координаты выходят за границы лабиринта: ({x}, {y}) not in ({self._width}, {self._height})" + ) + return self._map[y][x] + + def get_neighbors(self, x: int, y: int) -> Optional[list[Cell]]: + vector_x = [0, 1, 0, -1] + vector_y = [1, 0, -1, 0] + + neighbors = [] + + for vec_x, vec_y in zip(vector_x, vector_y): + temp_x, temp_y = x + vec_x, y + vec_y + if self._check_point_in_map(temp_x, temp_y): + neighbors.append(self._map[temp_y][temp_x]) + + return neighbors diff --git a/skorohodovsa/task_2/requirements.txt b/skorohodovsa/task_2/requirements.txt new file mode 100644 index 0000000..a802ecc --- /dev/null +++ b/skorohodovsa/task_2/requirements.txt @@ -0,0 +1,7 @@ +sphinx +myst-parser +sphinxawesome-theme +nbsphinx +myst-nb +tabulate +bibtexparser From 98c17e18fac0825f8d30f25bc06662dc5f15cc84 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Wed, 20 May 2026 13:31:53 +0300 Subject: [PATCH 15/28] =?UTF-8?q?[2]=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B0=D0=B2=D1=82=D0=BE=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B8=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0=20?= =?UTF-8?q?=D0=B2=D1=82=D0=BE=D1=80=D0=BE=D0=B9=20=D0=BB=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=80=D0=B0=D1=82=D0=BE=D1=80=D0=BD=D0=BE=D0=B9=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_2/docs/Makefile | 20 ++++++ skorohodovsa/task_2/docs/make.bat | 35 +++++++++++ skorohodovsa/task_2/docs/source/api.md | 9 +++ skorohodovsa/task_2/docs/source/conf.py | 78 ++++++++++++++++++++++++ skorohodovsa/task_2/docs/source/index.md | 5 ++ 5 files changed, 147 insertions(+) create mode 100644 skorohodovsa/task_2/docs/Makefile create mode 100644 skorohodovsa/task_2/docs/make.bat create mode 100644 skorohodovsa/task_2/docs/source/api.md create mode 100644 skorohodovsa/task_2/docs/source/conf.py create mode 100644 skorohodovsa/task_2/docs/source/index.md diff --git a/skorohodovsa/task_2/docs/Makefile b/skorohodovsa/task_2/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/skorohodovsa/task_2/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/skorohodovsa/task_2/docs/make.bat b/skorohodovsa/task_2/docs/make.bat new file mode 100644 index 0000000..dc1312a --- /dev/null +++ b/skorohodovsa/task_2/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/skorohodovsa/task_2/docs/source/api.md b/skorohodovsa/task_2/docs/source/api.md new file mode 100644 index 0000000..f3eb868 --- /dev/null +++ b/skorohodovsa/task_2/docs/source/api.md @@ -0,0 +1,9 @@ +# API Reference + +## Модуль `models.map` + +```{eval-rst} +.. automodule:: models.map + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/source/conf.py b/skorohodovsa/task_2/docs/source/conf.py new file mode 100644 index 0000000..2d03d3f --- /dev/null +++ b/skorohodovsa/task_2/docs/source/conf.py @@ -0,0 +1,78 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +import os +import sys +sys.path.insert(0, os.path.abspath('../..')) + + +project = 'Поиск выхода из лабиринта' +copyright = '2026, SerKin0' +author = 'SerKin0' +release = '0.0.1' +html_title = project + + +# --- MyST (Markdown) --- +myst_enable_extensions = [ + "dollarmath", # $x$ и $$x$$ + "amsmath", # \begin{equation} + "colon_fence", # ::: блоки +] + +exclude_patterns = ['build', 'draft.md'] + +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', + 'sphinx.ext.viewcode', + 'myst_nb', + 'sphinx.ext.mathjax', + 'sphinx_new_tab_link', + 'sphinx.ext.autosummary', +] + +autosummary_generate = True + +autodoc_default_options = { + 'members': True, + 'undoc-members': True, + 'show-inheritance': True, + 'special-members': '__init__', + 'inherited-members': False, + 'exclude-members': '__weakref__', +} + +napoleon_google_docstring = True +napoleon_numpy_docstring = False +napoleon_include_init_with_doc = True +napoleon_include_private_with_doc = False + +# --- Тема --- +html_permalinks_icon = '#' +html_theme = 'sphinxawesome_theme' +language = "ru" + +html_theme_options = { + 'navigation_with_keys': True, + 'globaltoc_collapse': False, + 'globaltoc_includehidden': False, + 'show_prev_next': True, + 'main_nav_links': {}, +} + +pygments_style = 'monokai' +pygments_style_dark = 'monokai' + + +# Для подключения CSS (стили иконок) +html_css_files = [ + 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css', +] + +# --- HTML --- +html_static_path = ["_static"] \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/source/index.md b/skorohodovsa/task_2/docs/source/index.md new file mode 100644 index 0000000..03c974e --- /dev/null +++ b/skorohodovsa/task_2/docs/source/index.md @@ -0,0 +1,5 @@ +# Лабораторная работа "Поиск выхода из лабиринта" + +:::{toctree} +:maxdepth: 2 +api \ No newline at end of file From 5525af0b26719cd5bbbc8f48398a9a9c98fe1110 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Wed, 20 May 2026 13:51:55 +0300 Subject: [PATCH 16/28] =?UTF-8?q?[2]=20=D0=9D=D0=B0=D1=87=D0=B0=D0=BB?= =?UTF-8?q?=D0=BE=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2=20=D0=BA=D0=BB?= =?UTF-8?q?=D0=B0=D1=81=D1=81=D0=BE=D0=B2=20`Cell`=20=D0=B8=20`Maze`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task_2/models/{map.py => base.py} | 54 +++++++------------ skorohodovsa/task_2/requirements.txt | 1 + skorohodovsa/task_2/test/__init__.py | 0 skorohodovsa/task_2/test/map/__init__.py | 0 skorohodovsa/task_2/test/map/test_cell.py | 8 +++ skorohodovsa/task_2/test/map/test_maze.py | 0 6 files changed, 29 insertions(+), 34 deletions(-) rename skorohodovsa/task_2/models/{map.py => base.py} (52%) create mode 100644 skorohodovsa/task_2/test/__init__.py create mode 100644 skorohodovsa/task_2/test/map/__init__.py create mode 100644 skorohodovsa/task_2/test/map/test_cell.py create mode 100644 skorohodovsa/task_2/test/map/test_maze.py diff --git a/skorohodovsa/task_2/models/map.py b/skorohodovsa/task_2/models/base.py similarity index 52% rename from skorohodovsa/task_2/models/map.py rename to skorohodovsa/task_2/models/base.py index 385c5c9..e0992c5 100644 --- a/skorohodovsa/task_2/models/map.py +++ b/skorohodovsa/task_2/models/base.py @@ -26,9 +26,9 @@ class Cell: """ self.x = x self.y = y - self.is_wall = is_wall - self.is_start = is_start - self.is_exit = is_exit + self._is_wall = is_wall + self._is_start = is_start + self._is_exit = is_exit def isPossible(self) -> bool: """Проверка возможности перемещения в это поле @@ -37,55 +37,40 @@ class Cell: :rtype: bool """ return not self.is_wall + + def __str__(self) -> str: + if self._is_wall: + type_cell = "Стена" + elif self._is_start: + type_cell = "Начало" + elif self._is_exit: + type_cell = "Выход" + else: + type_cell = "Пусто" + + return f"Cell: (x={self.x}, y={self.y}), '{type_cell}'" class Maze: def __init__( self, - size: tuple[int, int] = (10, 10), - start_point: tuple[int, int] = (0, 0), - exit_point: tuple[int, int] = (-1, -1), + size: tuple[int, int] = (10, 10) ): # Установка размеров лабиринта self._width = size[0] self._height = size[1] - # Установка значения стартового поля в лабиринте - self._start_x = start_point[0] - self._start_y = start_point[1] - - # Установка значения выходного поля в лабиринте - self._exit_x = self._width - 1 if exit_point[0] == -1 else exit_point[0] - self._exit_y = self._height - 1 if exit_point[1] == -1 else exit_point[1] - # Создание двумерного списка лабиринта self._map = [ [Cell(x, y) for x in range(self._width)] for y in range(self._height) ] - # Проверяем, что координаты старта находятся в области лабиринта - if self._check_point_in_map(self._start_x, self._start_y): - self._map[self._start_y][self._start_x].is_start = True - else: - raise ValueError( - f"Координата точки старта задана вне области лабиринта: ({self._start_x}, {self._start_y}) not in ({self._width}, {self._height})" - ) - - # Проверяем, что координаты выхода находятся в области лабиринта - if not self._check_point_in_map(self._exit_x, self._exit_y): - raise ValueError( - f"Координата точки выхода задана вне области лабиринта: ({self._start_x}, {self._start_y}) not in ({self._width}, {self._height})" - ) - self._map[self._exit_y][self._exit_x].is_exit = True - def _check_point_in_map(self, x: int, y: int) -> bool: return (0 <= x < self._width) and (0 <= y < self._height) def get_cell(self, x: int, y: int) -> Optional[Cell]: if not self._check_point_in_map(x, y): - raise ValueError( - f"Указанные координаты выходят за границы лабиринта: ({x}, {y}) not in ({self._width}, {self._height})" - ) + return None return self._map[y][x] def get_neighbors(self, x: int, y: int) -> Optional[list[Cell]]: @@ -96,7 +81,8 @@ class Maze: for vec_x, vec_y in zip(vector_x, vector_y): temp_x, temp_y = x + vec_x, y + vec_y - if self._check_point_in_map(temp_x, temp_y): - neighbors.append(self._map[temp_y][temp_x]) + value = self.get_cell(temp_x, temp_y) + if value is not None: + neighbors.append(value) return neighbors diff --git a/skorohodovsa/task_2/requirements.txt b/skorohodovsa/task_2/requirements.txt index a802ecc..791d693 100644 --- a/skorohodovsa/task_2/requirements.txt +++ b/skorohodovsa/task_2/requirements.txt @@ -5,3 +5,4 @@ nbsphinx myst-nb tabulate bibtexparser +pytest \ No newline at end of file diff --git a/skorohodovsa/task_2/test/__init__.py b/skorohodovsa/task_2/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/skorohodovsa/task_2/test/map/__init__.py b/skorohodovsa/task_2/test/map/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/skorohodovsa/task_2/test/map/test_cell.py b/skorohodovsa/task_2/test/map/test_cell.py new file mode 100644 index 0000000..b25d10e --- /dev/null +++ b/skorohodovsa/task_2/test/map/test_cell.py @@ -0,0 +1,8 @@ +import pytest +import sys +import os +import copy + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "./../../models"))) + +from base import Cell \ No newline at end of file diff --git a/skorohodovsa/task_2/test/map/test_maze.py b/skorohodovsa/task_2/test/map/test_maze.py new file mode 100644 index 0000000..e69de29 From c096613e08a87d6822a9ed95dc0ed8f35738d966 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Fri, 22 May 2026 00:05:59 +0300 Subject: [PATCH 17/28] =?UTF-8?q?[2]=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20docstring=20=D0=BA=D0=BB=D0=B0?= =?UTF-8?q?=D1=81=D1=81=D0=BE=D0=B2=20=D0=B2=20=D1=84=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=D0=B5=20`models/base.py`=20=D0=B8=20=D0=BF=D1=83=D1=82=D0=B8?= =?UTF-8?q?=20=D0=B2=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_2/docs/source/api.md | 4 +- skorohodovsa/task_2/models/base.py | 67 ++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/skorohodovsa/task_2/docs/source/api.md b/skorohodovsa/task_2/docs/source/api.md index f3eb868..84f80d7 100644 --- a/skorohodovsa/task_2/docs/source/api.md +++ b/skorohodovsa/task_2/docs/source/api.md @@ -1,9 +1,9 @@ # API Reference -## Модуль `models.map` +## Модуль `models.base` ```{eval-rst} -.. automodule:: models.map +.. automodule:: models.base :members: :undoc-members: :show-inheritance: \ No newline at end of file diff --git a/skorohodovsa/task_2/models/base.py b/skorohodovsa/task_2/models/base.py index e0992c5..f70972f 100644 --- a/skorohodovsa/task_2/models/base.py +++ b/skorohodovsa/task_2/models/base.py @@ -38,6 +38,39 @@ class Cell: """ return not self.is_wall + @property + def is_wall(self): + return self._is_wall + + @property + def is_start(self): + return self._is_start + + @property + def is_exit(self): + return self._is_exit + + def _clear_flags(self) -> None: + """Обнуляет все флаги поля""" + self._is_start = False + self._is_exit = False + self._is_wall = False + + @is_wall.setter + def is_wall(self, value: bool) -> None: + self._clear_flags() + self._is_wall = True + + @is_start.setter + def is_start(self, value: bool) -> None: + self._clear_flags() + self._is_start = True + + @is_exit.setter + def is_exit(self, value: bool) -> None: + self._clear_flags() + self._is_exit = True + def __str__(self) -> str: if self._is_wall: type_cell = "Стена" @@ -66,14 +99,48 @@ class Maze: ] def _check_point_in_map(self, x: int, y: int) -> bool: + """Проверка нахождения точки в границах поля + + Args: + x (int): Координата точки в оси X + y (int): Координата точки в оси Y + + Returns: + bool: True если поля в поле, иначе False + """ return (0 <= x < self._width) and (0 <= y < self._height) def get_cell(self, x: int, y: int) -> Optional[Cell]: + """Получение значения поля по координате в лабиринте + + Args: + x (int): Координата точки в оси X + y (int): Координата точки в оси Y + + Returns: + Optional[Cell]: Объект поля, при его наличии + """ if not self._check_point_in_map(x, y): return None return self._map[y][x] def get_neighbors(self, x: int, y: int) -> Optional[list[Cell]]: + """Получение соседних полей относительно заданного поля + + Под соседями поля в лабиринте имеется виду клетки сверху, справа, + снизу и слева относительно её. Если точка находится за границами, + то будет возвращено `None` + + Args: + x (int): Координата точки в оси X + y (int): Координата точки в оси Y + + Returns: + Optional[list[Cell]]: Список соседних полей + """ + if not self._check_point_in_map(x, y): + return None + list() vector_x = [0, 1, 0, -1] vector_y = [1, 0, -1, 0] From 7a84310d5de66b13c98e71b5853c094767cfd78b Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Fri, 22 May 2026 23:11:46 +0300 Subject: [PATCH 18/28] =?UTF-8?q?[2]=20-=20=D0=9F=D0=B5=D1=80=D0=B5=D0=BC?= =?UTF-8?q?=D0=B5=D1=89=D0=B5=D0=BD=D0=B8=D0=B5=20models=20=D0=B2=20=D0=BF?= =?UTF-8?q?=D0=B0=D0=BF=D0=BA=D1=83=20source=20-=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=B1=D1=80?= =?UTF-8?q?=D0=B0=D1=89=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BA=20Maze=20=D0=BA?= =?UTF-8?q?=D0=B0=D0=BA=20=D0=BA=20=D0=B4=D0=B2=D1=83=D0=BC=D0=B5=D1=80?= =?UTF-8?q?=D0=BD=D0=BE=D0=BC=D1=83=20=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_2/.gitignore | 5 +- .../task_2/{ => source}/models/base.py | 83 +++++++++++++++---- skorohodovsa/task_2/source/settings.py | 6 ++ .../task_2/source/templates/10x10_path_v1.txt | 10 +++ 4 files changed, 85 insertions(+), 19 deletions(-) rename skorohodovsa/task_2/{ => source}/models/base.py (68%) create mode 100644 skorohodovsa/task_2/source/settings.py create mode 100644 skorohodovsa/task_2/source/templates/10x10_path_v1.txt diff --git a/skorohodovsa/task_2/.gitignore b/skorohodovsa/task_2/.gitignore index 27d8248..369c288 100644 --- a/skorohodovsa/task_2/.gitignore +++ b/skorohodovsa/task_2/.gitignore @@ -30,4 +30,7 @@ Thumbs.db # Логи *.log -.ruff_cache/ \ No newline at end of file +.ruff_cache/ + +/.idea +pupu.py \ No newline at end of file diff --git a/skorohodovsa/task_2/models/base.py b/skorohodovsa/task_2/source/models/base.py similarity index 68% rename from skorohodovsa/task_2/models/base.py rename to skorohodovsa/task_2/source/models/base.py index f70972f..2e8f890 100644 --- a/skorohodovsa/task_2/models/base.py +++ b/skorohodovsa/task_2/source/models/base.py @@ -1,5 +1,7 @@ from typing import Optional +from source.settings import cell_mapping + class Cell: """Класс отвечает за хранение характеристик поля лабиринта""" @@ -30,7 +32,7 @@ class Cell: self._is_start = is_start self._is_exit = is_exit - def isPossible(self) -> bool: + def is_possible(self) -> bool: """Проверка возможности перемещения в это поле :return: Если перемещение возможно, то `True`, иначе `False` @@ -58,31 +60,38 @@ class Cell: @is_wall.setter def is_wall(self, value: bool) -> None: - self._clear_flags() - self._is_wall = True + if value: + self._clear_flags() + self._is_wall = value @is_start.setter def is_start(self, value: bool) -> None: - self._clear_flags() - self._is_start = True + if value: + self._clear_flags() + self._is_start = value @is_exit.setter def is_exit(self, value: bool) -> None: - self._clear_flags() - self._is_exit = True + if value: + self._clear_flags() + self._is_exit = value + + def _get_type_cell(self) -> str: + if self._is_wall: + type_cell = cell_mapping.get('wall') + elif self._is_start: + type_cell = cell_mapping.get('start') + elif self._is_exit: + type_cell = cell_mapping.get('exit') + else: + type_cell = cell_mapping.get('empty') + return type_cell def __str__(self) -> str: - if self._is_wall: - type_cell = "Стена" - elif self._is_start: - type_cell = "Начало" - elif self._is_exit: - type_cell = "Выход" - else: - type_cell = "Пусто" - - return f"Cell: (x={self.x}, y={self.y}), '{type_cell}'" + return self._get_type_cell() + def __repr__(self): + return f"Cell: (x={self.x}, y={self.y}), '{self._get_type_cell()}'" class Maze: def __init__( @@ -149,7 +158,45 @@ class Maze: for vec_x, vec_y in zip(vector_x, vector_y): temp_x, temp_y = x + vec_x, y + vec_y value = self.get_cell(temp_x, temp_y) - if value is not None: + if value is not None and value.is_possible(): neighbors.append(value) return neighbors + + def __getitem__(self, index: tuple[int, int]) -> Cell: + row, col = index + if not self._check_point_in_map(col, row): + raise IndexError(f"Поле с индексом ({row}, {col}) выходит за пределы лабиринта") + return self._map[row][col] + + def __setitem__(self, index: tuple[int, int], value: str) -> None: + + row, col = index + if not self._check_point_in_map(col, row): + raise IndexError(f"Поле с индексом ({row}, {col}) выходит за пределы лабиринта") + + cell = self._map[row][col] + + cell_type = None + for type_name, symbol in cell_mapping.items(): + if symbol == value: + cell_type = type_name + break + + if cell_type is None: + raise ValueError(f"Значение '{value}' не соответствует ни одному типу клетки") + + if cell_type == "empty": + cell._clear_flags() + else: + setattr(cell, f"is_{cell_type}", True) + + def __str__(self) -> str: + result = "" + + for y in range(self._height): + for x in range(self._width): + result += str(self[y, x]) + result += '\n' + + return result \ No newline at end of file diff --git a/skorohodovsa/task_2/source/settings.py b/skorohodovsa/task_2/source/settings.py new file mode 100644 index 0000000..65da0c8 --- /dev/null +++ b/skorohodovsa/task_2/source/settings.py @@ -0,0 +1,6 @@ +cell_mapping = { + 'wall': '#', + 'empty': ' ', + 'start': 'S', + 'exit': 'E' +} \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/10x10_path_v1.txt b/skorohodovsa/task_2/source/templates/10x10_path_v1.txt new file mode 100644 index 0000000..6395399 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/10x10_path_v1.txt @@ -0,0 +1,10 @@ +S######### + # +# ###### # +# # # # +# # ## # # +# # # # # +# #### # # +# # # +# E# +########## \ No newline at end of file From de1170df68b527282a1d146ea58576a2340a0815 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Fri, 22 May 2026 23:12:50 +0300 Subject: [PATCH 19/28] =?UTF-8?q?[2]=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D1=80=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=20=D0=BD=D0=B0=D0=B8=D0=BC=D0=B5=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=84=D0=B0=D0=B9=D0=BB=D0=BE?= =?UTF-8?q?=D0=B2=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2-=D0=BB=D0=B0?= =?UTF-8?q?=D0=B1=D0=B8=D1=80=D0=B8=D0=BD=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_2/docs/source/index.md | 1 + .../task_2/docs/source/naming_maze.md | 100 ++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 skorohodovsa/task_2/docs/source/naming_maze.md diff --git a/skorohodovsa/task_2/docs/source/index.md b/skorohodovsa/task_2/docs/source/index.md index 03c974e..a1f0950 100644 --- a/skorohodovsa/task_2/docs/source/index.md +++ b/skorohodovsa/task_2/docs/source/index.md @@ -2,4 +2,5 @@ :::{toctree} :maxdepth: 2 +naming_maze api \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/source/naming_maze.md b/skorohodovsa/task_2/docs/source/naming_maze.md new file mode 100644 index 0000000..79b9071 --- /dev/null +++ b/skorohodovsa/task_2/docs/source/naming_maze.md @@ -0,0 +1,100 @@ +# Этап 2. Загрузка лабиринта из файла + +Во втором этапе разработки необходимо реализовать загрузку лабиринта из текстового файла, где: + +- `#` – стена; +- ` ` – проход; +- `S` – старт; +- `E` – выход. + +## Систематизация файлов + +Для удобного хранения лабиринтов было решено сделать систему наименования текстовых файлов в папке `source/templates`. + +Общая структура: + +``` +{размер}_{свойство 1}-{свойство 2}-{свойство n}_{версия}.txt +``` + +### Размер + +Формат: `{ширина}x{высота}` + +| Пример | Значение | +|--------|----------| +| `10x10` | 10×10 клеток | +| `50x50` | 50×50 клеток | +| `100x100` | 100×100 клеток | +| `30x30` | 30×30 клеток | +| `20x20` | 20×20 клеток | +### Свойства +| Свойство | Код | Описание | +| ------------ | ----------- | -------------------------------------------------------------------------------------------- | +| Простой путь | `path` | Существует маршрут от S до E | +| Тупики | `deadends` | Лабиринт специально содержит тупики (могут быть и в других типах, но здесь — гарантированно) | +| Запутанный | `spaghetti` | Сложная структура с циклами и ложными ходами | +| Пустой | `empty` | Нет стен (`#`), только пробелы, S и E | +| Без выхода | `noexit` | В лабиринте отсутствует символ `E` | +### Версия + +Формат: `v{номер}` +- `v1`, `v2`, `v10` +### Примеры +#### Маленькие (10×10, простой путь) + +``` +10x10_path_v1.txt +10x10_path_v2.txt +... +10x10_path_v10.txt +``` +#### Средние (50×50, тупики) + +``` +50x50_deadends_v1.txt +50x50_deadends_v2.txt +... +50x50_deadends_v10.txt +``` +#### Большие (100×100, запутанные) + +``` +100x100_spaghetti_v1.txt +100x100_spaghetti_v2.txt +... +100x100_spaghetti_v10.txt +``` + +#### Пустые (30×30) + +``` +30x30_empty_v1.txt +30x30_empty_v2.txt +... +30x30_empty_v10.txt +``` + +#### Без выхода (20×20) + +``` +20x20_noexit_v1.txt +20x20_noexit_v2.txt +... +20x20_noexit_v10.txt +``` + +#### Комбинированные свойства + +``` +50x50_deadends-noexit_v1.txt +100x100_spaghetti-noexit_v1.txt +10x10_path-empty_v1.txt (избыточно, но допустимо) +``` + +### Примечание + +- Регистр имён файлов: **нижний регистр** +- Разделители: только `_` и `-` +- Расширение: `.txt` +- Кодировка: UTF-8 \ No newline at end of file From 535c706af8dca74e593867381705817e2ec5573c Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Sat, 23 May 2026 16:30:04 +0300 Subject: [PATCH 20/28] =?UTF-8?q?[2]=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20docstring=20=D0=BA=20Cell,=20M?= =?UTF-8?q?aze?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавлен интерфейс для алгоритмов --- .../task_2/source/algorithms/strategy.py | 49 ++++ skorohodovsa/task_2/source/models/base.py | 224 ++++++++++-------- 2 files changed, 179 insertions(+), 94 deletions(-) create mode 100644 skorohodovsa/task_2/source/algorithms/strategy.py diff --git a/skorohodovsa/task_2/source/algorithms/strategy.py b/skorohodovsa/task_2/source/algorithms/strategy.py new file mode 100644 index 0000000..ea956f1 --- /dev/null +++ b/skorohodovsa/task_2/source/algorithms/strategy.py @@ -0,0 +1,49 @@ +from abc import ABC, abstractmethod +from collections import deque +from typing import Optional + +from source.models.base import Maze, Cell + + +class PathFindingStrategy(ABC): + """Интерфейс стратегии поиска пути в лабиринте.""" + + @abstractmethod + def find_path(self, maze: Maze, start: Cell, exit: Cell) -> list[Cell]: + """Найти путь от start до exit. + + Args: + maze: Объект лабиринта. + start: Стартовая клетка. + exit: Целевая клетка. + + Returns: + Список клеток пути (от start до exit включительно). + Пустой список, если путь не найден. + """ + + def _reconstruct_path(came_from: dict[Cell, Optional[Cell]], end: Cell) -> list[Cell]: + """Восстанавливает путь от старта до end, идя по came_from в обратном порядке. + + Args: + came_from: Словарь {клетка: родитель}, где родитель старта = None. + end: Конечная клетка. + + Returns: + Список клеток пути от старта до end включительно. + Пустой список, если end отсутствует в came_from. + """ + if end not in came_from: + return [] + + path: list[Cell] = [] + current: Optional[Cell] = end + while current is not None: + path.append(current) + current = came_from[current] + path.reverse() + return path + +class BFS(PathFindingStrategy): + def find_path(self, maze: Maze, start: Cell, exit: Cell) -> list[Cell]: + pass \ No newline at end of file diff --git a/skorohodovsa/task_2/source/models/base.py b/skorohodovsa/task_2/source/models/base.py index 2e8f890..863cb77 100644 --- a/skorohodovsa/task_2/source/models/base.py +++ b/skorohodovsa/task_2/source/models/base.py @@ -4,7 +4,12 @@ from source.settings import cell_mapping class Cell: - """Класс отвечает за хранение характеристик поля лабиринта""" + """Представляет одну клетку поля лабиринта. + + Каждая клетка хранит свои координаты и один из четырёх возможных + типов: стена, старт, выход или пустая клетка. Типы взаимоисключают + друг друга: установка одного автоматически сбрасывает остальные. + """ def __init__( self, @@ -14,17 +19,14 @@ class Cell: is_start: bool = False, is_exit: bool = False, ): - """ - :param x: Координата поля по оси X - :type x: int - :param y: Координата поля по оси Y - :type y: int - :param is_wall: Является ли поле **стеной**, defaults to False - :type is_wall: bool, optional - :param is_start: Является ли поле **началом**, defaults to False - :type is_start: bool, optional - :param is_exit: Является ли поле **концом**, defaults to False - :type is_exit: bool, optional + """Инициализирует клетку с заданными координатами и типом. + + Args: + x: Координата клетки по оси X. + y: Координата клетки по оси Y. + is_wall: Если True — клетка является стеной. + is_start: Если True — клетка является стартом. + is_exit: Если True — клетка является выходом. """ self.x = x self.y = y @@ -33,170 +35,204 @@ class Cell: self._is_exit = is_exit def is_possible(self) -> bool: - """Проверка возможности перемещения в это поле + """Проверяет, можно ли переместиться в эту клетку. - :return: Если перемещение возможно, то `True`, иначе `False` - :rtype: bool + Returns: + True, если клетка не является стеной, иначе False. """ - return not self.is_wall - + return not self._is_wall + @property - def is_wall(self): + def is_wall(self) -> bool: + """True, если клетка является стеной.""" return self._is_wall - + @property - def is_start(self): + def is_start(self) -> bool: + """True, если клетка является стартовой позицией.""" return self._is_start - + @property - def is_exit(self): + def is_exit(self) -> bool: + """True, если клетка является выходом из лабиринта.""" return self._is_exit - + def _clear_flags(self) -> None: - """Обнуляет все флаги поля""" + """Сбрасывает все флаги типа клетки в False.""" + self._is_wall = False self._is_start = False self._is_exit = False - self._is_wall = False - + @is_wall.setter def is_wall(self, value: bool) -> None: + """Устанавливает флаг стены, сбрасывая остальные типы при value=True. + + Args: + value: Новое значение флага стены. + """ if value: self._clear_flags() self._is_wall = value - + @is_start.setter def is_start(self, value: bool) -> None: + """Устанавливает флаг старта, сбрасывая остальные типы при value=True. + + Args: + value: Новое значение флага старта. + """ if value: self._clear_flags() self._is_start = value - + @is_exit.setter def is_exit(self, value: bool) -> None: + """Устанавливает флаг выхода, сбрасывая остальные типы при value=True. + + Args: + value: Новое значение флага выхода. + """ if value: self._clear_flags() self._is_exit = value - + def _get_type_cell(self) -> str: + """Возвращает символ клетки согласно cell_mapping. + + Returns: + Строковый символ, соответствующий текущему типу клетки. + """ if self._is_wall: - type_cell = cell_mapping.get('wall') - elif self._is_start: - type_cell = cell_mapping.get('start') - elif self._is_exit: - type_cell = cell_mapping.get('exit') - else: - type_cell = cell_mapping.get('empty') - return type_cell - + return cell_mapping['wall'] + if self._is_start: + return cell_mapping['start'] + if self._is_exit: + return cell_mapping['exit'] + return cell_mapping['empty'] + def __str__(self) -> str: return self._get_type_cell() - def __repr__(self): - return f"Cell: (x={self.x}, y={self.y}), '{self._get_type_cell()}'" + def __repr__(self) -> str: + return f"Cell(x={self.x}, y={self.y}, '{self._get_type_cell()}')" + class Maze: - def __init__( - self, - size: tuple[int, int] = (10, 10) - ): - # Установка размеров лабиринта - self._width = size[0] - self._height = size[1] + """Представляет двумерный лабиринт из клеток Cell. - # Создание двумерного списка лабиринта - self._map = [ - [Cell(x, y) for x in range(self._width)] for y in range(self._height) + Лабиринт хранится как список списков клеток. Доступ к отдельным + клеткам и их изменение возможны через индексацию вида maze[row, col]. + """ + + def __init__(self, size: tuple[int, int] = (10, 10)): + """Создаёт пустой лабиринт заданного размера. + + Args: + size: Кортеж (width, height) — ширина и высота лабиринта в клетках. + """ + self._width, self._height = size + self._map: list[list[Cell]] = [ + [Cell(x, y) for x in range(self._width)] + for y in range(self._height) ] def _check_point_in_map(self, x: int, y: int) -> bool: - """Проверка нахождения точки в границах поля + """Проверяет, находится ли точка в границах лабиринта. Args: - x (int): Координата точки в оси X - y (int): Координата точки в оси Y + x: Координата по оси X. + y: Координата по оси Y. Returns: - bool: True если поля в поле, иначе False + True, если точка (x, y) находится внутри лабиринта. """ - return (0 <= x < self._width) and (0 <= y < self._height) + return 0 <= x < self._width and 0 <= y < self._height def get_cell(self, x: int, y: int) -> Optional[Cell]: - """Получение значения поля по координате в лабиринте + """Возвращает клетку по координатам или None, если координаты вне границ. Args: - x (int): Координата точки в оси X - y (int): Координата точки в оси Y + x: Координата по оси X. + y: Координата по оси Y. Returns: - Optional[Cell]: Объект поля, при его наличии + Объект Cell, если координаты корректны, иначе None. """ if not self._check_point_in_map(x, y): return None return self._map[y][x] def get_neighbors(self, x: int, y: int) -> Optional[list[Cell]]: - """Получение соседних полей относительно заданного поля - - Под соседями поля в лабиринте имеется виду клетки сверху, справа, - снизу и слева относительно её. Если точка находится за границами, - то будет возвращено `None` + """Возвращает список проходимых соседей клетки (вверх, вправо, вниз, влево). Args: - x (int): Координата точки в оси X - y (int): Координата точки в оси Y + x: Координата клетки по оси X. + y: Координата клетки по оси Y. Returns: - Optional[list[Cell]]: Список соседних полей + Список проходимых соседних клеток, или None если (x, y) вне границ. """ if not self._check_point_in_map(x, y): return None - list() - vector_x = [0, 1, 0, -1] - vector_y = [1, 0, -1, 0] + deltas = ((0, 1), (1, 0), (0, -1), (-1, 0)) neighbors = [] - for vec_x, vec_y in zip(vector_x, vector_y): - temp_x, temp_y = x + vec_x, y + vec_y - value = self.get_cell(temp_x, temp_y) - if value is not None and value.is_possible(): - neighbors.append(value) - + for dx, dy in deltas: + cell = self.get_cell(x + dx, y + dy) + if cell is not None and cell.is_possible(): + neighbors.append(cell) + return neighbors def __getitem__(self, index: tuple[int, int]) -> Cell: + """Возвращает клетку по индексу [row, col]. + + Args: + index: Кортеж (row, col) — строка и столбец. + + Returns: + Объект Cell в позиции (row, col). + + Raises: + IndexError: Если индекс выходит за пределы лабиринта. + """ row, col = index if not self._check_point_in_map(col, row): - raise IndexError(f"Поле с индексом ({row}, {col}) выходит за пределы лабиринта") + raise IndexError(f"Индекс ({row}, {col}) выходит за пределы лабиринта") return self._map[row][col] def __setitem__(self, index: tuple[int, int], value: str) -> None: + """Устанавливает тип клетки по индексу [row, col] через символ из cell_mapping. + Args: + index: Кортеж (row, col) — строка и столбец. + value: Символ типа клетки согласно cell_mapping. + + Raises: + IndexError: Если индекс выходит за пределы лабиринта. + ValueError: Если символ не найден в cell_mapping. + """ row, col = index if not self._check_point_in_map(col, row): - raise IndexError(f"Поле с индексом ({row}, {col}) выходит за пределы лабиринта") + raise IndexError(f"Индекс ({row}, {col}) выходит за пределы лабиринта") cell = self._map[row][col] - - cell_type = None - for type_name, symbol in cell_mapping.items(): - if symbol == value: - cell_type = type_name - break + cell_type = next( + (t for t, s in cell_mapping.items() if s == value), + None, + ) if cell_type is None: - raise ValueError(f"Значение '{value}' не соответствует ни одному типу клетки") + raise ValueError(f"Символ '{value}' не соответствует ни одному типу клетки") - if cell_type == "empty": + if cell_type == 'empty': cell._clear_flags() else: setattr(cell, f"is_{cell_type}", True) def __str__(self) -> str: - result = "" - - for y in range(self._height): - for x in range(self._width): - result += str(self[y, x]) - result += '\n' - - return result \ No newline at end of file + return '\n'.join( + ''.join(str(self._map[y][x]) for x in range(self._width)) + for y in range(self._height) + ) \ No newline at end of file From f7577f803cf8915ad9921693bcbc97dd92f1ff9c Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Sun, 24 May 2026 17:17:02 +0300 Subject: [PATCH 21/28] =?UTF-8?q?[2]=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BE:=20-=20=D0=A2=D0=B5=D1=81=D1=82=D1=8B?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D1=8B=20Cell,?= =?UTF-8?q?=20Maze=20-=20=D0=90=D0=BB=D0=B3=D0=BE=D1=80=D0=B8=D1=82=D0=BC?= =?UTF-8?q?=D1=8B=20=D0=BF=D0=BE=D0=B8=D1=81=D0=BA=D0=B0=20=D0=BF=D1=83?= =?UTF-8?q?=D1=82=D0=B8:=20BFS,=20DFS,=20Astar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_2/source/models/base.py | 23 ++-- skorohodovsa/task_2/source/settings.py | 7 +- .../task_2/source/strategy/__init__.py | 11 ++ .../strategy.py => strategy/algorithms.py} | 37 +++++- skorohodovsa/task_2/source/strategy/astar.py | 46 ++++++++ skorohodovsa/task_2/source/strategy/bfs.py | 37 ++++++ skorohodovsa/task_2/source/strategy/dfs.py | 35 ++++++ skorohodovsa/task_2/source/strategy/solver.py | 93 +++++++++++++++ skorohodovsa/task_2/test/map/test_cell.py | 109 ++++++++++++++++- skorohodovsa/task_2/test/map/test_maze.py | 111 ++++++++++++++++++ 10 files changed, 484 insertions(+), 25 deletions(-) create mode 100644 skorohodovsa/task_2/source/strategy/__init__.py rename skorohodovsa/task_2/source/{algorithms/strategy.py => strategy/algorithms.py} (67%) create mode 100644 skorohodovsa/task_2/source/strategy/astar.py create mode 100644 skorohodovsa/task_2/source/strategy/bfs.py create mode 100644 skorohodovsa/task_2/source/strategy/dfs.py create mode 100644 skorohodovsa/task_2/source/strategy/solver.py diff --git a/skorohodovsa/task_2/source/models/base.py b/skorohodovsa/task_2/source/models/base.py index 863cb77..632d777 100644 --- a/skorohodovsa/task_2/source/models/base.py +++ b/skorohodovsa/task_2/source/models/base.py @@ -103,12 +103,12 @@ class Cell: Строковый символ, соответствующий текущему типу клетки. """ if self._is_wall: - return cell_mapping['wall'] + return cell_mapping["wall"] if self._is_start: - return cell_mapping['start'] + return cell_mapping["start"] if self._is_exit: - return cell_mapping['exit'] - return cell_mapping['empty'] + return cell_mapping["exit"] + return cell_mapping["empty"] def __str__(self) -> str: return self._get_type_cell() @@ -132,8 +132,7 @@ class Maze: """ self._width, self._height = size self._map: list[list[Cell]] = [ - [Cell(x, y) for x in range(self._width)] - for y in range(self._height) + [Cell(x, y) for x in range(self._width)] for y in range(self._height) ] def _check_point_in_map(self, x: int, y: int) -> bool: @@ -185,6 +184,10 @@ class Maze: return neighbors + @property + def shape(self) -> tuple[int, int]: + return self._height, self._width + def __getitem__(self, index: tuple[int, int]) -> Cell: """Возвращает клетку по индексу [row, col]. @@ -226,13 +229,13 @@ class Maze: if cell_type is None: raise ValueError(f"Символ '{value}' не соответствует ни одному типу клетки") - if cell_type == 'empty': + if cell_type == "empty": cell._clear_flags() else: setattr(cell, f"is_{cell_type}", True) def __str__(self) -> str: - return '\n'.join( - ''.join(str(self._map[y][x]) for x in range(self._width)) + return "\n".join( + "".join(str(self._map[y][x]) for x in range(self._width)) for y in range(self._height) - ) \ No newline at end of file + ) diff --git a/skorohodovsa/task_2/source/settings.py b/skorohodovsa/task_2/source/settings.py index 65da0c8..0a0f313 100644 --- a/skorohodovsa/task_2/source/settings.py +++ b/skorohodovsa/task_2/source/settings.py @@ -1,6 +1 @@ -cell_mapping = { - 'wall': '#', - 'empty': ' ', - 'start': 'S', - 'exit': 'E' -} \ No newline at end of file +cell_mapping = {"wall": "#", "empty": " ", "start": "S", "exit": "E"} diff --git a/skorohodovsa/task_2/source/strategy/__init__.py b/skorohodovsa/task_2/source/strategy/__init__.py new file mode 100644 index 0000000..0da8de2 --- /dev/null +++ b/skorohodovsa/task_2/source/strategy/__init__.py @@ -0,0 +1,11 @@ +from source.strategy.algorithms import PathFindingStrategy +from source.strategy.astar import AStarStrategy +from source.strategy.bfs import BFSStrategy +from source.strategy.dfs import DFSStrategy + +__all__ = [ + "PathFindingStrategy", + "BFSStrategy", + "DFSStrategy", + "AStarStrategy", +] \ No newline at end of file diff --git a/skorohodovsa/task_2/source/algorithms/strategy.py b/skorohodovsa/task_2/source/strategy/algorithms.py similarity index 67% rename from skorohodovsa/task_2/source/algorithms/strategy.py rename to skorohodovsa/task_2/source/strategy/algorithms.py index ea956f1..0c17a8d 100644 --- a/skorohodovsa/task_2/source/algorithms/strategy.py +++ b/skorohodovsa/task_2/source/strategy/algorithms.py @@ -1,5 +1,4 @@ from abc import ABC, abstractmethod -from collections import deque from typing import Optional from source.models.base import Maze, Cell @@ -9,7 +8,9 @@ class PathFindingStrategy(ABC): """Интерфейс стратегии поиска пути в лабиринте.""" @abstractmethod - def find_path(self, maze: Maze, start: Cell, exit: Cell) -> list[Cell]: + def find_path( + self, maze: Maze, start: Cell = None, exit: Cell = None + ) -> list[Cell]: """Найти путь от start до exit. Args: @@ -22,7 +23,27 @@ class PathFindingStrategy(ABC): Пустой список, если путь не найден. """ - def _reconstruct_path(came_from: dict[Cell, Optional[Cell]], end: Cell) -> list[Cell]: + def _find_start(self, maze: Maze) -> Optional[Cell]: + row, col = maze.shape + + for y in range(row): + for x in range(col): + if maze[y, x].is_start: + return maze[y, x] + return None + + def _find_exit(self, maze: Maze) -> Optional[Cell]: + row, col = maze.shape + + for y in range(row): + for x in range(col): + if maze[y, x].is_exit: + return maze[y, x] + return None + + def _reconstruct_path( + self, came_from: dict[Cell, Optional[Cell]], end: Cell + ) -> list[Cell]: """Восстанавливает путь от старта до end, идя по came_from в обратном порядке. Args: @@ -44,6 +65,10 @@ class PathFindingStrategy(ABC): path.reverse() return path -class BFS(PathFindingStrategy): - def find_path(self, maze: Maze, start: Cell, exit: Cell) -> list[Cell]: - pass \ No newline at end of file + + + + + + + diff --git a/skorohodovsa/task_2/source/strategy/astar.py b/skorohodovsa/task_2/source/strategy/astar.py new file mode 100644 index 0000000..ba07fce --- /dev/null +++ b/skorohodovsa/task_2/source/strategy/astar.py @@ -0,0 +1,46 @@ +import heapq +from typing import Optional + +from source.models.base import Cell, Maze +from source.strategy.algorithms import PathFindingStrategy + + +def _manhattan(a: Cell, b: Cell) -> int: + """Манхэттенское расстояние между двумя клетками.""" + return abs(a.x - b.x) + abs(a.y - b.y) + + +class AStarStrategy(PathFindingStrategy): + """Алгоритм A* с манхэттенской эвристикой.""" + + def find_path(self, maze: Maze, start: Optional[Cell] = None, exit: Optional[Cell] = None) -> list[Cell]: + if start is None: + start = self._find_start(maze) + if exit is None: + exit = self._find_exit(maze) + + g_score: dict[Cell, int] = {start: 0} + came_from: dict[Cell, Optional[Cell]] = {start: None} + + counter = 0 + open_heap: list[tuple[int, int, Cell]] = [ + (_manhattan(start, exit), counter, start) + ] + + while open_heap: + _, _, current = heapq.heappop(open_heap) + + if current is exit: + return self._reconstruct_path(came_from, exit) + + for neighbor in maze.get_neighbors(current.x, current.y): + tentative_g = g_score[current] + 1 + + if tentative_g < g_score.get(neighbor, float("inf")): + g_score[neighbor] = tentative_g + came_from[neighbor] = current + f = tentative_g + _manhattan(neighbor, exit) + counter += 1 + heapq.heappush(open_heap, (f, counter, neighbor)) + + return [] \ No newline at end of file diff --git a/skorohodovsa/task_2/source/strategy/bfs.py b/skorohodovsa/task_2/source/strategy/bfs.py new file mode 100644 index 0000000..39e6595 --- /dev/null +++ b/skorohodovsa/task_2/source/strategy/bfs.py @@ -0,0 +1,37 @@ +from collections import deque +from typing import Optional + +from source.models.base import Cell, Maze +from source.strategy.algorithms import PathFindingStrategy + + +class BFSStrategy(PathFindingStrategy): + """Поиск в ширину (Breadth-First Search). + + Гарантирует кратчайший путь по количеству шагов. + Сложность: O(V + E) по времени и памяти. + """ + + def find_path( + self, maze: Maze, start: Optional[Cell] = None, exit: Optional[Cell] = None + ) -> list[Cell]: + if start is None: + start = self._find_start(maze) + if exit is None: + exit = self._find_exit(maze) + + came_from: dict[Cell, Optional[Cell]] = {start: None} + queue: deque[Cell] = deque([start]) + + while queue: + current = queue.popleft() + + if current is exit: + return self._reconstruct_path(came_from, exit) + + for neighbor in maze.get_neighbors(current.x, current.y): + if neighbor not in came_from: + came_from[neighbor] = current + queue.append(neighbor) + + return [] \ No newline at end of file diff --git a/skorohodovsa/task_2/source/strategy/dfs.py b/skorohodovsa/task_2/source/strategy/dfs.py new file mode 100644 index 0000000..c24a1e2 --- /dev/null +++ b/skorohodovsa/task_2/source/strategy/dfs.py @@ -0,0 +1,35 @@ +from typing import Optional + +from source.models.base import Maze, Cell +from source.strategy.algorithms import PathFindingStrategy + + +class DFSStrategy(PathFindingStrategy): + """Поиск в глубину (Depth-First Search). + + Находит путь, но не гарантирует кратчайший. + """ + + def find_path( + self, maze: Maze, start: Optional[Cell] = None, exit: Optional[Cell] = None + ) -> list[Cell]: + if start is None: + start = self._find_start(maze) + if exit is None: + exit = self._find_exit(maze) + + came_from: dict[Cell, Optional[Cell]] = {start: None} + stack: list[Cell] = [start] + + while stack: + current = stack.pop() + + if current is exit: + return self._reconstruct_path(came_from, exit) + + for neighbor in maze.get_neighbors(current.x, current.y): + if neighbor not in came_from: + came_from[neighbor] = current + stack.append(neighbor) + + return [] \ No newline at end of file diff --git a/skorohodovsa/task_2/source/strategy/solver.py b/skorohodovsa/task_2/source/strategy/solver.py new file mode 100644 index 0000000..eb17b64 --- /dev/null +++ b/skorohodovsa/task_2/source/strategy/solver.py @@ -0,0 +1,93 @@ +import time +from dataclasses import dataclass + +from source.models.base import Maze, Cell +from source.strategy import PathFindingStrategy + + +@dataclass +class SearchStats: + """Статистика выполнения поиска пути. + + Attributes: + elapsed_ms: Время выполнения в миллисекундах. + visited_count: Количество посещённых клеток. + path_length: Длина найденного пути (0 если путь не найден). + path: Найденный путь — список клеток от старта до выхода. + """ + elapsed_ms: float + visited_count: int + path_length: int + path: list[Cell] + + def __str__(self) -> str: + return ( + f"Время: {self.elapsed_ms:.3f} мс | " + f"Посещено клеток: {self.visited_count} | " + f"Длина пути: {self.path_length}" + ) + + +class MazeSolver: + """Оркестратор поиска пути в лабиринте. + + Принимает лабиринт и стратегию поиска, выполняет поиск + и возвращает результат вместе со статистикой выполнения. + + Example: + solver = MazeSolver(maze, BFSStrategy()) + stats = solver.solve() + print(stats) + + solver.set_strategy(AStarStrategy()) + stats = solver.solve() + """ + + def __init__(self, maze: Maze, strategy: PathFindingStrategy) -> None: + """Инициализирует солвер с лабиринтом и стратегией поиска. + + Args: + maze: Объект лабиринта. + strategy: Стратегия поиска пути. + """ + self._maze = maze + self._strategy = strategy + + def set_strategy(self, strategy: PathFindingStrategy) -> None: + """Заменяет текущую стратегию поиска. + + Args: + strategy: Новая стратегия поиска пути. + """ + self._strategy = strategy + + def solve( + self, + start: Cell = None, + exit: Cell = None, + ) -> SearchStats: + """Выполняет поиск пути и собирает статистику. + + Если start или exit не переданы явно, стратегия найдёт + их самостоятельно по флагам is_start / is_exit в лабиринте. + + Args: + start: Стартовая клетка (опционально). + exit: Конечная клетка (опционально). + + Returns: + Объект SearchStats с временем выполнения, количеством + посещённых клеток и длиной найденного пути. + """ + t_start = time.perf_counter() + path = self._strategy.find_path(self._maze, start, exit) + t_end = time.perf_counter() + + elapsed_ms = (t_end - t_start) * 1000 + + return SearchStats( + elapsed_ms=elapsed_ms, + visited_count=len(path), + path_length=len(path), + path=path, + ) \ No newline at end of file diff --git a/skorohodovsa/task_2/test/map/test_cell.py b/skorohodovsa/task_2/test/map/test_cell.py index b25d10e..31d7714 100644 --- a/skorohodovsa/task_2/test/map/test_cell.py +++ b/skorohodovsa/task_2/test/map/test_cell.py @@ -1,8 +1,111 @@ import pytest import sys import os -import copy -sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "./../../models"))) +from source.models.base import Cell -from base import Cell \ No newline at end of file +class TestCellCreation: + """Тесты создания клетки и начальных значений.""" + + def test_coordinates_are_set(self): + cell = Cell(3, 7) + assert cell.x == 3 + assert cell.y == 7 + + def test_default_flags_are_false(self): + cell = Cell(0, 0) + assert cell.is_wall is False + assert cell.is_start is False + assert cell.is_exit is False + + def test_create_wall(self): + cell = Cell(0, 0, is_wall=True) + assert cell.is_wall is True + + def test_create_start(self): + cell = Cell(0, 0, is_start=True) + assert cell.is_start is True + + def test_create_exit(self): + cell = Cell(0, 0, is_exit=True) + assert cell.is_exit is True + + +class TestCellIsPassable: + """Тесты метода is_possible.""" + + def test_empty_cell_is_passable(self): + cell = Cell(0, 0) + assert cell.is_possible() is True + + def test_wall_is_not_passable(self): + cell = Cell(0, 0, is_wall=True) + assert cell.is_possible() is False + + def test_start_cell_is_passable(self): + cell = Cell(0, 0, is_start=True) + assert cell.is_possible() is True + + def test_exit_cell_is_passable(self): + cell = Cell(0, 0, is_exit=True) + assert cell.is_possible() is True + + +class TestCellFlagsAreMutuallyExclusive: + """Тесты взаимного исключения флагов.""" + + def test_set_wall_clears_start(self): + cell = Cell(0, 0, is_start=True) + cell.is_wall = True + assert cell.is_start is False + assert cell.is_wall is True + + def test_set_wall_clears_exit(self): + cell = Cell(0, 0, is_exit=True) + cell.is_wall = True + assert cell.is_exit is False + assert cell.is_wall is True + + def test_set_start_clears_wall(self): + cell = Cell(0, 0, is_wall=True) + cell.is_start = True + assert cell.is_wall is False + assert cell.is_start is True + + def test_set_start_clears_exit(self): + cell = Cell(0, 0, is_exit=True) + cell.is_start = True + assert cell.is_exit is False + assert cell.is_start is True + + def test_set_exit_clears_wall(self): + cell = Cell(0, 0, is_wall=True) + cell.is_exit = True + assert cell.is_wall is False + assert cell.is_exit is True + + def test_set_exit_clears_start(self): + cell = Cell(0, 0, is_start=True) + cell.is_exit = True + assert cell.is_start is False + assert cell.is_exit is True + + def test_unset_wall_does_not_clear_others(self): + # снятие флага (False) не должно трогать остальные + cell = Cell(0, 0, is_wall=True) + cell.is_wall = False + assert cell.is_start is False + assert cell.is_exit is False + + +class TestCellStr: + """Тесты строкового представления клетки.""" + + def test_str_returns_string(self): + cell = Cell(0, 0) + assert isinstance(str(cell), str) + + def test_repr_contains_coordinates(self): + cell = Cell(4, 9) + assert "4" in repr(cell) + assert "9" in repr(cell) \ No newline at end of file diff --git a/skorohodovsa/task_2/test/map/test_maze.py b/skorohodovsa/task_2/test/map/test_maze.py index e69de29..5b7e111 100644 --- a/skorohodovsa/task_2/test/map/test_maze.py +++ b/skorohodovsa/task_2/test/map/test_maze.py @@ -0,0 +1,111 @@ +import pytest +import random + +random.seed("РФ СЛФ!") + +from source.models.base import Cell, Maze +from source.settings import cell_mapping + + +class TestMaze: + + def test_default_size(self): + """Проверка размеров лабиринта со значениями по умолчанию""" + maze = Maze() + row, col = maze.shape + assert row == 10 + assert col == 10 + + def test_custom_size(self): + """Проверка размеров лабиринта с заданными размерами""" + maze = Maze(size=(7, 3)) + assert maze._width == 7 + assert maze._height == 3 + + def test_all_cells_empty_on_init(self): + """Проверка создания пустого лабиринта с заданными размерами""" + maze = Maze(size=(3, 3)) + for y in range(3): + for x in range(3): + cell = maze.get_cell(x, y) + assert not cell.is_wall + assert not cell.is_start + assert not cell.is_exit + + def test_get_cell_valid(self): + """Проверка получения объекта Cell из лабиринта функцией `get_cell()`""" + maze = Maze(size=(5, 5)) + assert isinstance(maze.get_cell(2, 3), Cell) + + def test_get_cell_out_of_bounds(self): + """Проверка неправильных указанных индексов лабиринта""" + maze = Maze(size=(5, 5)) + assert maze.get_cell(-1, 0) is None + assert maze.get_cell(0, -1) is None + assert maze.get_cell(5, 0) is None + assert maze.get_cell(0, 5) is None + + def test_center_has_four_neighbors(self): + """Проверка нахождения соседей""" + maze = Maze(size=(5, 5)) + assert len(maze.get_neighbors(2, 2)) == 4 + + def test_corner_has_two_neighbors(self): + """Проверка нахождения соседей, когда указанное поле в углу лабиринта""" + maze = Maze(size=(5, 5)) + assert len(maze.get_neighbors(0, 0)) == 2 + + def test_wall_excluded_from_neighbors(self): + """Проверка что стена не попадает в список соседей""" + maze = Maze(size=(5, 5)) + maze[1, 2] = cell_mapping['wall'] + assert all(not n.is_wall for n in maze.get_neighbors(2, 2)) + + def test_setitem_wall(self): + """Проверка установки стены через оператор []""" + maze = Maze(size=(5, 5)) + maze[0, 0] = cell_mapping['wall'] + assert maze[0, 0].is_wall is True + + def test_setitem_start(self): + """Проверка установки старта через оператор []""" + maze = Maze(size=(5, 5)) + maze[0, 0] = cell_mapping['start'] + assert maze[0, 0].is_start is True + + def test_setitem_exit(self): + """Проверка установки выхода через оператор []""" + maze = Maze(size=(5, 5)) + maze[0, 0] = cell_mapping['exit'] + assert maze[0, 0].is_exit is True + + def test_setitem_empty_clears_flags(self): + """Проверка сброса флагов клетки при установке пустого типа""" + maze = Maze(size=(5, 5)) + maze[0, 0] = cell_mapping['wall'] + maze[0, 0] = cell_mapping['empty'] + assert not maze[0, 0].is_wall + + def test_getitem_out_of_bounds_raises(self): + """Проверка выброса IndexError при обращении к клетке вне границ лабиринта""" + maze = Maze(size=(5, 5)) + with pytest.raises(IndexError): + _ = maze[10, 10] + + def test_setitem_invalid_symbol_raises(self): + """Проверка выброса ValueError при установке неизвестного символа""" + maze = Maze(size=(5, 5)) + with pytest.raises(ValueError): + maze[0, 0] = "?" + + def test_str_lines_match_height(self): + """Проверка что количество строк в строковом представлении совпадает с высотой""" + maze = Maze(size=(4, 6)) + print(str(maze).splitlines()) + assert len(str(maze).splitlines()) == 6 + + def test_str_line_length_matches_width(self): + """Проверка что длина каждой строки в строковом представлении совпадает с шириной""" + maze = Maze(size=(5, 3)) + for line in str(maze).strip().splitlines(): + assert len(line) == 5 \ No newline at end of file From 5378824649cb11be2e15ff04f19efb76d8db79a2 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Sun, 24 May 2026 17:17:48 +0300 Subject: [PATCH 22/28] =?UTF-8?q?[2]=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8:=20-=20=D0=94=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=80=D0=B0=D0=B7?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D1=8B=20=D0=BF=D1=80=D0=BE=20=D0=B0=D0=BB?= =?UTF-8?q?=D0=B3=D0=BE=D1=80=D0=B8=D1=82=D0=BC=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_2/docs/source/api.md | 33 +++++++-- skorohodovsa/task_2/docs/source/conf.py | 67 ++++++++++--------- .../task_2/docs/source/naming_maze.md | 7 +- 3 files changed, 64 insertions(+), 43 deletions(-) diff --git a/skorohodovsa/task_2/docs/source/api.md b/skorohodovsa/task_2/docs/source/api.md index 84f80d7..58caf5f 100644 --- a/skorohodovsa/task_2/docs/source/api.md +++ b/skorohodovsa/task_2/docs/source/api.md @@ -1,9 +1,34 @@ # API Reference -## Модуль `models.base` +## Базовые модели -```{eval-rst} -.. automodule:: models.base +````{eval-rst} +.. automodule:: source.models.base :members: :undoc-members: - :show-inheritance: \ No newline at end of file + :show-inheritance: +```` + +## Стратегии поиска пути + +````{eval-rst} +.. automodule:: source.strategy.algorithms + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: source.strategy.bfs + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: source.strategy.dfs + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: source.strategy.astar + :members: + :undoc-members: + :show-inheritance: +```` \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/source/conf.py b/skorohodovsa/task_2/docs/source/conf.py index 2d03d3f..4eeb0f1 100644 --- a/skorohodovsa/task_2/docs/source/conf.py +++ b/skorohodovsa/task_2/docs/source/conf.py @@ -7,44 +7,45 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information import os import sys -sys.path.insert(0, os.path.abspath('../..')) + +sys.path.insert(0, os.path.abspath("../..")) -project = 'Поиск выхода из лабиринта' -copyright = '2026, SerKin0' -author = 'SerKin0' -release = '0.0.1' +project = "Поиск выхода из лабиринта" +copyright = "2026, SerKin0" +author = "SerKin0" +release = "0.0.1" html_title = project # --- MyST (Markdown) --- myst_enable_extensions = [ - "dollarmath", # $x$ и $$x$$ - "amsmath", # \begin{equation} - "colon_fence", # ::: блоки + "dollarmath", # $x$ и $$x$$ + "amsmath", # \begin{equation} + "colon_fence", # ::: блоки ] -exclude_patterns = ['build', 'draft.md'] +exclude_patterns = ["build", "draft.md"] extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.napoleon', - 'sphinx.ext.viewcode', - 'myst_nb', - 'sphinx.ext.mathjax', - 'sphinx_new_tab_link', - 'sphinx.ext.autosummary', + "sphinx.ext.autodoc", + "sphinx.ext.napoleon", + "sphinx.ext.viewcode", + "myst_nb", + "sphinx.ext.mathjax", + "sphinx_new_tab_link", + "sphinx.ext.autosummary", ] autosummary_generate = True autodoc_default_options = { - 'members': True, - 'undoc-members': True, - 'show-inheritance': True, - 'special-members': '__init__', - 'inherited-members': False, - 'exclude-members': '__weakref__', + "members": True, + "undoc-members": True, + "show-inheritance": True, + "special-members": "__init__", + "inherited-members": False, + "exclude-members": "__weakref__", } napoleon_google_docstring = True @@ -53,26 +54,26 @@ napoleon_include_init_with_doc = True napoleon_include_private_with_doc = False # --- Тема --- -html_permalinks_icon = '#' -html_theme = 'sphinxawesome_theme' +html_permalinks_icon = "#" +html_theme = "sphinxawesome_theme" language = "ru" html_theme_options = { - 'navigation_with_keys': True, - 'globaltoc_collapse': False, - 'globaltoc_includehidden': False, - 'show_prev_next': True, - 'main_nav_links': {}, + "navigation_with_keys": True, + "globaltoc_collapse": False, + "globaltoc_includehidden": False, + "show_prev_next": True, + "main_nav_links": {}, } -pygments_style = 'monokai' -pygments_style_dark = 'monokai' +pygments_style = "monokai" +pygments_style_dark = "monokai" # Для подключения CSS (стили иконок) html_css_files = [ - 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css', + "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css", ] # --- HTML --- -html_static_path = ["_static"] \ No newline at end of file +html_static_path = ["_static"] diff --git a/skorohodovsa/task_2/docs/source/naming_maze.md b/skorohodovsa/task_2/docs/source/naming_maze.md index 79b9071..11b4e13 100644 --- a/skorohodovsa/task_2/docs/source/naming_maze.md +++ b/skorohodovsa/task_2/docs/source/naming_maze.md @@ -1,11 +1,6 @@ # Этап 2. Загрузка лабиринта из файла -Во втором этапе разработки необходимо реализовать загрузку лабиринта из текстового файла, где: - -- `#` – стена; -- ` ` – проход; -- `S` – старт; -- `E` – выход. +Во втором этапе разработки необходимо реализовать загрузку лабиринта из текстового файла, где: `#` – стена, ` ` – проход, `S` – старт, `E` – выход. ## Систематизация файлов From f393ad5203c86f3d2d9d966889d9c48e092ebb1c Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Sun, 24 May 2026 17:33:35 +0300 Subject: [PATCH 23/28] =?UTF-8?q?[2]=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B5=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D0=B2=D1=8B=D1=85=20=D0=BB=D0=B0=D0=B1=D0=B8=D1=80=D0=B8=D0=BD?= =?UTF-8?q?=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../source/templates/100x100_spaghetti_v1.txt | 99 +++++++++++++++++++ .../templates/100x100_spaghetti_v10.txt | 99 +++++++++++++++++++ .../source/templates/100x100_spaghetti_v2.txt | 99 +++++++++++++++++++ .../source/templates/100x100_spaghetti_v3.txt | 99 +++++++++++++++++++ .../source/templates/100x100_spaghetti_v4.txt | 99 +++++++++++++++++++ .../source/templates/100x100_spaghetti_v5.txt | 99 +++++++++++++++++++ .../source/templates/100x100_spaghetti_v6.txt | 99 +++++++++++++++++++ .../source/templates/100x100_spaghetti_v7.txt | 99 +++++++++++++++++++ .../source/templates/100x100_spaghetti_v8.txt | 99 +++++++++++++++++++ .../source/templates/100x100_spaghetti_v9.txt | 99 +++++++++++++++++++ .../task_2/source/templates/10x10_path_v1.txt | 19 ++-- .../source/templates/10x10_path_v10.txt | 9 ++ .../task_2/source/templates/10x10_path_v2.txt | 9 ++ .../task_2/source/templates/10x10_path_v3.txt | 9 ++ .../task_2/source/templates/10x10_path_v4.txt | 9 ++ .../task_2/source/templates/10x10_path_v5.txt | 9 ++ .../task_2/source/templates/10x10_path_v6.txt | 9 ++ .../task_2/source/templates/10x10_path_v7.txt | 9 ++ .../task_2/source/templates/10x10_path_v8.txt | 9 ++ .../task_2/source/templates/10x10_path_v9.txt | 9 ++ .../source/templates/20x20_noexit_v1.txt | 19 ++++ .../source/templates/20x20_noexit_v10.txt | 19 ++++ .../source/templates/20x20_noexit_v2.txt | 19 ++++ .../source/templates/20x20_noexit_v3.txt | 19 ++++ .../source/templates/20x20_noexit_v4.txt | 19 ++++ .../source/templates/20x20_noexit_v5.txt | 19 ++++ .../source/templates/20x20_noexit_v6.txt | 19 ++++ .../source/templates/20x20_noexit_v7.txt | 19 ++++ .../source/templates/20x20_noexit_v8.txt | 19 ++++ .../source/templates/20x20_noexit_v9.txt | 19 ++++ .../source/templates/30x30_empty_v1.txt | 30 ++++++ .../source/templates/30x30_empty_v10.txt | 30 ++++++ .../source/templates/30x30_empty_v2.txt | 30 ++++++ .../source/templates/30x30_empty_v3.txt | 30 ++++++ .../source/templates/30x30_empty_v4.txt | 30 ++++++ .../source/templates/30x30_empty_v5.txt | 30 ++++++ .../source/templates/30x30_empty_v6.txt | 30 ++++++ .../source/templates/30x30_empty_v7.txt | 30 ++++++ .../source/templates/30x30_empty_v8.txt | 30 ++++++ .../source/templates/30x30_empty_v9.txt | 30 ++++++ .../source/templates/50x50_deadends_v1.txt | 49 +++++++++ .../source/templates/50x50_deadends_v10.txt | 49 +++++++++ .../source/templates/50x50_deadends_v2.txt | 49 +++++++++ .../source/templates/50x50_deadends_v3.txt | 49 +++++++++ .../source/templates/50x50_deadends_v4.txt | 49 +++++++++ .../source/templates/50x50_deadends_v5.txt | 49 +++++++++ .../source/templates/50x50_deadends_v6.txt | 49 +++++++++ .../source/templates/50x50_deadends_v7.txt | 49 +++++++++ .../source/templates/50x50_deadends_v8.txt | 49 +++++++++ .../source/templates/50x50_deadends_v9.txt | 49 +++++++++ 50 files changed, 2060 insertions(+), 10 deletions(-) create mode 100644 skorohodovsa/task_2/source/templates/100x100_spaghetti_v1.txt create mode 100644 skorohodovsa/task_2/source/templates/100x100_spaghetti_v10.txt create mode 100644 skorohodovsa/task_2/source/templates/100x100_spaghetti_v2.txt create mode 100644 skorohodovsa/task_2/source/templates/100x100_spaghetti_v3.txt create mode 100644 skorohodovsa/task_2/source/templates/100x100_spaghetti_v4.txt create mode 100644 skorohodovsa/task_2/source/templates/100x100_spaghetti_v5.txt create mode 100644 skorohodovsa/task_2/source/templates/100x100_spaghetti_v6.txt create mode 100644 skorohodovsa/task_2/source/templates/100x100_spaghetti_v7.txt create mode 100644 skorohodovsa/task_2/source/templates/100x100_spaghetti_v8.txt create mode 100644 skorohodovsa/task_2/source/templates/100x100_spaghetti_v9.txt create mode 100644 skorohodovsa/task_2/source/templates/10x10_path_v10.txt create mode 100644 skorohodovsa/task_2/source/templates/10x10_path_v2.txt create mode 100644 skorohodovsa/task_2/source/templates/10x10_path_v3.txt create mode 100644 skorohodovsa/task_2/source/templates/10x10_path_v4.txt create mode 100644 skorohodovsa/task_2/source/templates/10x10_path_v5.txt create mode 100644 skorohodovsa/task_2/source/templates/10x10_path_v6.txt create mode 100644 skorohodovsa/task_2/source/templates/10x10_path_v7.txt create mode 100644 skorohodovsa/task_2/source/templates/10x10_path_v8.txt create mode 100644 skorohodovsa/task_2/source/templates/10x10_path_v9.txt create mode 100644 skorohodovsa/task_2/source/templates/20x20_noexit_v1.txt create mode 100644 skorohodovsa/task_2/source/templates/20x20_noexit_v10.txt create mode 100644 skorohodovsa/task_2/source/templates/20x20_noexit_v2.txt create mode 100644 skorohodovsa/task_2/source/templates/20x20_noexit_v3.txt create mode 100644 skorohodovsa/task_2/source/templates/20x20_noexit_v4.txt create mode 100644 skorohodovsa/task_2/source/templates/20x20_noexit_v5.txt create mode 100644 skorohodovsa/task_2/source/templates/20x20_noexit_v6.txt create mode 100644 skorohodovsa/task_2/source/templates/20x20_noexit_v7.txt create mode 100644 skorohodovsa/task_2/source/templates/20x20_noexit_v8.txt create mode 100644 skorohodovsa/task_2/source/templates/20x20_noexit_v9.txt create mode 100644 skorohodovsa/task_2/source/templates/30x30_empty_v1.txt create mode 100644 skorohodovsa/task_2/source/templates/30x30_empty_v10.txt create mode 100644 skorohodovsa/task_2/source/templates/30x30_empty_v2.txt create mode 100644 skorohodovsa/task_2/source/templates/30x30_empty_v3.txt create mode 100644 skorohodovsa/task_2/source/templates/30x30_empty_v4.txt create mode 100644 skorohodovsa/task_2/source/templates/30x30_empty_v5.txt create mode 100644 skorohodovsa/task_2/source/templates/30x30_empty_v6.txt create mode 100644 skorohodovsa/task_2/source/templates/30x30_empty_v7.txt create mode 100644 skorohodovsa/task_2/source/templates/30x30_empty_v8.txt create mode 100644 skorohodovsa/task_2/source/templates/30x30_empty_v9.txt create mode 100644 skorohodovsa/task_2/source/templates/50x50_deadends_v1.txt create mode 100644 skorohodovsa/task_2/source/templates/50x50_deadends_v10.txt create mode 100644 skorohodovsa/task_2/source/templates/50x50_deadends_v2.txt create mode 100644 skorohodovsa/task_2/source/templates/50x50_deadends_v3.txt create mode 100644 skorohodovsa/task_2/source/templates/50x50_deadends_v4.txt create mode 100644 skorohodovsa/task_2/source/templates/50x50_deadends_v5.txt create mode 100644 skorohodovsa/task_2/source/templates/50x50_deadends_v6.txt create mode 100644 skorohodovsa/task_2/source/templates/50x50_deadends_v7.txt create mode 100644 skorohodovsa/task_2/source/templates/50x50_deadends_v8.txt create mode 100644 skorohodovsa/task_2/source/templates/50x50_deadends_v9.txt diff --git a/skorohodovsa/task_2/source/templates/100x100_spaghetti_v1.txt b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v1.txt new file mode 100644 index 0000000..84fca03 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v1.txt @@ -0,0 +1,99 @@ +################################################################################################### +#S # # # # # # # # # # # +### ##### ### #### ### # ### # ### # ####### # ## # # # # # # # ###### ## # # # ### ## # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# ##### # # ## # # ### # ### # ## # # # ##### # ##### ### ## ####### # ##### # ### # # ### # +# # # # # # # # # # # # # # # # # # # # # +# ### # ## ###### # # # # # ### ##### # ## ##### ### # # #### # #### ### ##### ### ## ## # +# # # # # # # # # # # # # # # # # # # # # # # # +# # ### # # # ## # ## # ### # ##### # # # ## ##### ### # # ### # # # # ### # # # ## # # ##### +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# ### # # ##### # # # # ### # # # # # # # # # # ## # #### ### # ### # # ### ### # # # # ## # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# ##### ### # # # # # ##### ### # ## # ### # # # # # # ### ##### ####### # ### ### # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # ### # # ### # ### # # # # ## # ### ### # ##### # # # ####### # ##### # # # # # ####### # # # +# # # # # # # # # # # # # # # # # # # # +# # ### # #### ### ####### ### ## # ## ## # ######## ####### # ### ######## ### # # ### # +# # # # # # # # # # # # # # # # # +# #### # # ## # ### #### # # #### ##### # # ## ### # # # # #### # ## ##### ### ### # +# # # # # # # # # # # # # # # # # # # # # # # # +# # # ### # # # # ## ### # # # ### # # # # ##### ##### # # ###### # # # ## ## ## #### ### # +# # # # # # # # # # # # # # # # # # # # # # # +### # # ########### # ####### # ## # # # #### # ### ### # # # ### # ### ### # # # # ## #### +# # # # # # # # # # # # # # # # # # # # +# # # # # # # # #### ### # # # # ### # ##### ## ## # # ######### ####### # # ## # ### # +# # # # # # # # # # # # # # # # # # # # # +# ##### # ### # # # ## # # # # ### ##### ## #### # # ###### ## # # # # # ### # ### # ##### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # ### ######### # # ### # ##### # ####### # # # # # # # # # ##### # ##### # # #### # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # +##### # # ### ## # # ### # # ### # # ### # # # #### ### ##### ### # # # # # ########## # ### # # +# # # # # # # # # # # # # # # # # # # # # # # # +# ##### ### # # # ### # # # # # ### ### ##### # # # ## ########### # # #### # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# ### ### ##### # ### ##### # # # # # # # # ##### # # ####### ### # # # ## # # # # ##### # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ## ### # ### # # # #### # ## # ##### # # # # # ### # #### ## ##### ####### # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # ## # ### ##### ##### # # # ##### # # # #### # # ###### ## # # # ### # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # # ####### # # # #### # # # ## # ### # #### # # ##### ## ## # # # # # # ### # # # # ### # +# # # # # # # # # # # # # # # # # # # +### ### # # # # ## ###### ### # #### # # ##### ##### ### ## ## # ######### # # ### # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ### #### # ### # ### # #### ### # ##### ### ## # ### # ##### ##### # # # ## # +# # # # # # # # # # # # # # # # # # # # # # +# ## # ##### # ## ## ####### ### # ##### ##### # ##### # # # # # ##### # ##### ## # ### # ### +# # # # # # # # # # # # # # # # # # # # +# # ##### ########### # # ######### # # ### # ##### ### ### ### ##### ### ######### ### # ## # +# # # # # # # # # # # # # # # # # # # # # # +# ## # ### # # ## #### # # ##### ## # ## # #### # # # # ### # # # # ### # # # # # # ##### +# # # # # # # # # # # # # # # # # # # # # # # # # # # # +### # ### # # ### # ##### ### # # # # # # ## ## # # # ## ###### # ## # ########## # ####### # +# # # # # # # # # # # # # # # # # # # # # # # +# ##### ##### # ####### ### # # # ### ## # ###### # ### # # ### # ### ### # ### ### ### # # +# # # # # # # # # # # # # # # # # # # # # # # +# # # # # ## ## #### # ## ## # # # # ######### ### # # # ### # # # # # # ## ## # ### ### # +# # # # # # # # # # # # # # # # # # # # # # +# ### # ##### ## ### ## ### # ### ##### # # # #### ##### # ### ######### # # #### # # # +# # # # # # # # # # # # # # # # # # # # # # +### # ## ## ### # # ## #### # ### # # # # # # ##### # ### ### ## #### ## ### ## # # # +# # # # # # # # # # # # # # # # # # # # # +# ### # # # ###### # # ####### ### ### # # ##### ##### ###### # # # ##### ##### # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # +# ### # ### ### ### ######### ### # # ## #### ### # #### ### ##### # ######## # ####### +# # # # # # # # # # # # # # # # # # # # +# # # ### ### # # # # ## ## # ### # ## # # ##### # ### ## ####### # ## ### # ### # ## # # +# # # # # # # # # # # # # # # # # # # # # # # # +### ### # # ######### # ### # ### ####### ## # # ### # # # # ###### # ### # # # ## # ##### # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# ### # # # # # # ##### # ######### #### ## ## ##### ## ## ##### #### # # ### # ### # +# # # # # # # # # # # # # # # # # # +# ### ##### # # ##### ####### # # # ##### # ##### ### ## ## # ### ### # ### ## #### ####### ### +# # # # # # # # # # # # # # # # # # # # # # # # +# # ## # #### #### # # # ### # ## #### # ## ## # # ##### # ##### # # # # # ### ##### # # # # # +# # # # # # # # # # # # # # # # # # # # # # # +# ### ### # # ### # # ##### ### ### ## # # # ### # # # ####### # ### ##### ## # # # +# # # # # # # # # # # # # # # # # +# # ## ######## ### ####### ###### ##### # ############### # # ### # ##### # ### ### ## ## # # +# # # # # # # # # # # # # # # # # # +# # ### # ##### # # # # # ## # # ## # # # # ######### # # ##### # # ####### ####### # +# # # # # # # # # # # # # # # # # # # # # # # +### # # # ##### # # # ### # # # # ####### ### # ## ## ### ## ###### # ### # # # ## ## # +# # # # # # # # # # # # # # # # # # # # +# # ## ## ### ######### ####### # ######### ### # ### # # # # # # # # ### #### ## ### +# # # # # # # # # # # # # # # # # # # # # # # # +# ### # # # # ### ##### ########## ## ### # # ### ##### # ### #### ##### ####### # # # ### # +# # # # # # # # # # # # # # # # # # # # # # # +# # # # ### # # # ### # ###### # # ##### ## # ######## # ### # #### #### ### # # # ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ### ## # # # # # ## # # ### # # # #### # # # # ## #### # # # # ## ### # ## ## # ### # +# # # # # # # # # # # # # # # # # # # # # # # +### # # ########## # ####### # ### ### # ### ##### # # # ## ### ### ### # # ##### ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ### # # # ## # # # # # # # # ### ##### ##### # ### ## # ####### # ### # ### # # ### +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # ##### # #### # ## ## ##### # ######### # ## ### # #### ## # # # # # ######### # +# # # # # # # # # # E# +################################################################################################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/100x100_spaghetti_v10.txt b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v10.txt new file mode 100644 index 0000000..87f9068 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v10.txt @@ -0,0 +1,99 @@ +################################################################################################### +#S# # # # # # # # # # # # # # # +# # # # # # # # ### # ### # # # # # ## ##### # # ## # # ### # # ### # # ## # ### ### # # # +# # # # # # # # # # # # # # # # # # # # # # # +##### ### ##### ## # # ### # # # # # # # # # # # # ## # # # #### ### # # ## ### ### # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # +# ##### ###### ## # # ### ##### # # # ### ### ##### # # # # # ## # # ### ### # # ### # # # +# # # # # # # # # # # # # # # # # # # # # # # # +# # # ### # # ### ##### # ### ## # # # # # # ### ####### # ####### # # ## ## ###### #### ## ## # +# # # # # # # # # # # # # # # # # # # # # # # +### ##### # # # ### # # # # ### # #### # ### ####### # #### #### # ### # # # #### # ### +# # # # # # # # # # # # # # # # # # # # # # # +# ### # ## ### # ### # # ####### ### ### # ######### ### # # # ### # # ### # ### ######### # # # +# # # # # # # # # # # # # # # # # # # # # # # +# # # #### # # ### # # #### # # # # # ####### # # ## ## ### # # ### ##### # # ## ### ### # +# # # # # # # # # # # # # # # # # # # # # # +# ### # # ##### ### # # ###### ## # ## ## # # ### # # ### # # ####### # ### # ## # ### # ### # +# # # # # # # # # # # # # # # # # # # # +# # ## ##### # # # # ## ## # # ####### # ### ##### # # ####### ## # # # ###### #### # ### # # +# # # # # # # # # # # # # # # # # # +##### ### ##### ##### ### ##### # ## ## # # ##### # ##### ####### # #### ### # ## ## # # # # +# # # # # # # # # # # # # # # # # # # # # # # # +## # ####### ### # # # # # #### # # ### ##### #### # #### ## # # # # ## # ### ### # # ### +# # # # # # # # # # # # # # # # # # +# # # ## ####### ### # ## # # # ## # # ####### # # # ### ### # # # # # # ##### # # # ##### # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # ### ##### #### ## # # # ######### # ##### ### ### # ## ## ### # # ###### # # +# # # # # # # # # # # # # # # # # # # # # +# ### #### # ### # # ### # # ##### ## ### # ## ######### ### #### ### # # # ##### # ##### # +# # # # # # # # # # # # # # # # # # # # # +# # ### # ##### ### ### # ####### ### # ## # ## # # # ##### # ### # #### #### ### ### ## #### +# # # # # # # # # # # # # # # # # # # # # # # +# ####### # # ### # # ##### # ### # # # #### ##### # # ## ##### # # # # # ### ### # # ### # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # # ## # # # ### ### # # # # ### # ##### ### # # # ## # # # # # ########### ### ### # # # +# # # # # # # # # # # # # # # # # # # # # +# # ##### #### # ### # ######### ### ## ###### ######### ### ##### ## # ### # # ##### #### ##### +# # # # # # # # # # # # # # # # # +# # # ## ### ##### # # ### ### ### ### # # ####### ####### # # ##### # # ### ### ##### ## # # +# # # # # # # # # # # # # # # # # # # # # # +# ## ##### ### # ## # # # # ##### # # #### # ####### ##### # # ##### # ## ## # # ### ## # +# # # # # # # # # # # # # # # # # # # # # # # +### ## # ##### ##### # ## ### ## # # # # # # ### ### # ### ### # ### # # # # ## # ### ##### # +# # # # # # # # # # # # # # # # # # # # # # +# ### # ### ### ## # # # #### # #### # ####### ### # ### #### ## # # #### # ## # ### # # +# # # # # # # # # # # # # # # # # +### # ### # # # #### # ######### # # ### # # # # ### ##### ###### ## # # #### #### ### ## # +# # # # # # # # # # # # # # # # +# ### # ### ##### # # ######### # ### ### ### ### # ####### ##### ####### # # ##### # #### ## +# # # # # # # # # # # # # # # # +### # # # ########### ### # # # ##### ##### ## #### # ###### #### #### # #### # ######### # # +# # # # # # # # # # # # # # # # # # # # # +# ### ####### ##### # # # # ## ### #### ## # # ### ##### # ### # # # # ###### ## # # #### # # +# # # # # # # # # # # # # # # # # # # # # # # +# # ### ####### # # # ### ### ########### # # # # ## # ## # ###### ### # # ### # # # ## # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # ##### # ### ### # ### ### ### # # # ##### # # # # ### # ### ## ########### # ### # +# # # # # # # # # # # # # # # # # # # # # # +# # # # # ### # ### # ####### # # # # ## ### ### # ### # ### # ## # # # # # # ## ### ### # +# # # # # # # # # # # # # # # # # # # # # # # # # # +### ### # # # ##### ##### # # ### ##### ### # ### # ##### # ## ####### # # # # # # #### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# ## ### ####### # ## ## ##### # # # ### ### ### ### # # # # # # ##### # ### ##### # # # ##### +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ### # # ####### #### # ##### # ## # ## # #### #### # # ### ### ### # # # # ## ###### # +# # # # # # # # # # # # # # # # # # # # # +# ### # # ### # # # # ##### # ##### # # ######## ##### # # # ### # ##### ####### # ### # ## # # +# # # # # # # # # # # # # # # # # # # # # # +# #### # # # ## ## # ##### # ## # # # # # # # ##### ### #### # # # # ##### # # # ### # ### # # # +# # # # # # # # # # # # # # # # # # # # # # # +## ## # ### # # ### ### # ##### ### # # # ##### ## # # # ### ### # ##### ####### ##### #### # +# # # # # # # # # # # # # # # # # # # # # +# #### # ## ## #### ##### # ### # ### ##### # ## # # # # ## ### ####### ####### ### # ## +# # # # # # # # # # # # # # # # # # # # # +# # ### #### # # ## ##### ### # # # ### # # ### # ####### # ### # ## #### # ## # # # +# # # # # # # # # # # # # # # # # # # # # # # +# ## ### # # ####### # # ## # # ### ### # ### # # ##### ## # # ## # # # ## # # #### # # +# # # # # # # # # # # # # # # # # # # # # # +# ### # # ##### # # # # # # # ### ### ### ########## ##### ### # ##### # # ##### ####### #### # +# # # # # # # # # # # # # # # # # # # # # # +##### ## ## # # # ## ### # # # ####### # ## # # # ######## ### ## #### # ##### ##### # # # +# # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # ## ## ####### # ## ### ########### ### ### # # #### ### # # #### # ## # ### # # # +# # # # # # # # # # # # # # # # # # # +# ### # ##### # # ### ### # ### # # ### # ###### # ## ### # ## ## # # ### # ### ### # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ### ### # # # # # # # # # # # # # # ### ##### # # ### ### ## #### # # ### #### # # ## ## ### +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ##### ## #### ##### # ## ### # # # ##### # # # ##### # # # # ######### # # ### ##### # ### # +# # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # ##### # # ## # # ## # # # # ## # ## # # # # # # ### ## ### # #### # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# ##### # # # # ##### # ### ##### # # # # ### ### # ### # ##### # # # ### # # # ##### ##### ## # +# # # # # # # # # # # # # # # # # # # # # # # +### # ##### ### ### # # # # ### # # ## ### ####### ######## # # ### ## ### ### ####### # +# # # # # # # # # # # # # # # # # # # # # # # # +# ###### ## # # # # ## ###### ## ## ### ### ### # ### # # # # ####### # ### # ### #### # # +# # # # # # # # # E# +################################################################################################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/100x100_spaghetti_v2.txt b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v2.txt new file mode 100644 index 0000000..9e2fa3f --- /dev/null +++ b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v2.txt @@ -0,0 +1,99 @@ +################################################################################################### +#S# # # # # # # # # # # +# # ### # # ### ### # ## ## ####### # ########### # ### # ## #### # ### # # ### # # ### # +# # # # # # # # # # # # # # # # # # # +# # ### ## # ## # # ###### #### ## ###### ### ##### ## #### ### # ## # # ####### # ##### ### +# # # # # # # # # # # # # # # # # # # # # +# # ### ### #### ## ### #### ### # # ### ### ##### #### # # ##### ### # # ### ####### # ##### # +# # # # # # # # # # # # # # # # # # # # # +##### ##### # # # # ### ### #### ##### # ####### ## ## ####### # ## # #### ## # ####### # # # +# # # # # # # # # # # # # # # # # # # # +# #### ## ## ########## # # # ### ##### # ######## ## ## ###### #### ## #### ### # # ### ## +# # # # # # # # # # # # # # # # +# ### ### # ####### # ## # ## # # # # # # # # # ###### # # # ### # # ##### # # # #### # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ### # #### # #### # # #### # ##### # # # ### # # # # # ############# # # ## ##### # # # +# # # # # # # # # # # # # # # # # # # # +### # ## ### # ### ## ##### ### # ### # # ## #### # ####### # ### # ### # # # # ## # # +# # # # # # # # # # # # # # # # # # # # # # # # +# # #### ## ##### # ## # ##### # # ### # ### # # # # ####### ##### ### # # ## #### ##### +# # # # # # # # # # # # # # # # # # # # # # # # +# # ######### ## #### ### # ##### ################# # # # ### #### # # ### # ## # ### # +# # # # # # # # # # # # # # # # # # # # # # # +# ### ## # ## # # ### # # # ##### ### # ### # # ### # #### ## # # ### # ###### ### # ### # # +# # # # # # # # # # # # # # # # # # # # # # +# # ### ### # # # # ### # ## ## # ##### # # # # ### # ##### ########### # ######## ####### # +# # # # # # # # # # # # # # # # # # # +# ### # # # # ### ##### # # ### # ## # ### ### # # ## #### # # # # ##### # ### # # #### # # # # # +# # # # # # # # # # # # # # # # # +####### ## # ###### ### # # ## ### #### ### # #### ## # ### # # # ### # #### ### # ### # # # # # +# # # # # # # # # # # # # # # # # # # # +###### ## ## ### # ## # #### # # ##### # ## ## # ##### ### ### ##### # ### # # # # ### # # +# # # # # # # # # # # # # # # # # # # +# ####### # # # ## # # ### # ####### ## ### ## ### # # # # ## # # ### # ####### # # # # +# # # # # # # # # # # # # # # # # # # +# # ## ### # ## ## # # ##### ### ## ## #### # # ##### # # # ### ## ## ### ## # ### ## # ##### # +# # # # # # # # # # # # # # # # # # # # # # +# # # ######### ### # # ## # # ### ### ## ### ### # ##### # ## # ### # # ############ ### # ### +# # # # # # # # # # # # # # # # # # # +# # #### ## # ### #### ### ## #### ## # # ### # # ## # # ### ### ## # ###### ### ### # # +# # # # # # # # # # # # # # # # # # # # # +# ### ## #### # # ## ########### # # # # # ####### ## # ##### # # # # # #### # # # ## # +# # # # # # # # # # # # # # # # # # # # +# ### ### # # ##### # # ### # ## ## # # ### ### ### ### # ### # # # #### ## # #### # ##### ### # +# # # # # # # # # # # # # # # # # # +# # ### # ## ## # # ### ####### ### # # ## ## # # ########### # # ########### # # # ### ##### # +# # # # # # # # # # # # # # # # # # # +# ##### ## #### # #### ####### # # ## ### ##### # ##### ##### ### # ######### # ###### # # ##### +# # # # # # # # # # # # # # # +# # # ### ### ##### # ##### ### #### ## ## # # ##### ######### # ############# # ##### ### +# # # # # # # # # # # # # # # # # # # # +##### # ######### # ### # # ### # # # ###### # ### ### # # ## ########## #### # ## ##### ## # +# # # # # # # # # # # # # # # # # # # # # +### ###### # ### # ### # ## # #### ### # ### # # ### ### # # ### # # ### ####### ### # # +# # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # ####### # ### ##### # # # ##### ### ## ##### ##### ### ### ### # # # ### # ## # +# # # # # # # # # # # # # # # # # # # # # +# ### # # ### ###### ### ###### ####### # # # ### ####### # #### ### # ##### ## # ####### ### +# # # # # # # # # # # # # # # # # # # # # # +# ##### # # ### # # ### # ## # # # # ##### # ### ### ####### # ###### #### ## # #### ### # # # # +# # # # # # # # # # # # # # # # # # # # # # +### # # # # # ## #### ### # # # ##### ### ## #### ### # # ### # ### ##### ## # # ####### # +# # # # # # # # # # # # # # # # # # # # # # +# # # ## # ### # ##### # # # # # ##### ################### # # ##### ## # # ### # # # ### ####### +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # ### # # ### # # # # # ### ### # ##### # ## # ##### # ## # # # ## ## # ### # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # # ### # # ## ### ## # ## # # # # # # ##### ######### # ## ## # ### ##### ### # +# # # # # # # # # # # # # # # # # # # # +# ### # # # ## ## # ## ### # ###### ## ## # ####### # # ### #### # # # ### ### #### # # ##### +# # # # # # # # # # # # # # # # +# #### # ##### ### ## # #### ### ### # ### ######## # ## # # # # # # # ### ### ######## ## # +# # # # # # # # # # # # # # # # # # # # # # +# ## ### # # # ### # #### # ####### # # ## # ### ####### ### # ### # # # # ### # ### # # # +# # # # # # # # # # # # # # # # # # # # # # # +# # ### ##### ##### #### # # ######### # # # ### ####### # # ###### # # ####### ## # # ### # +# # # # # # # # # # # # # # # # # # # # # +# ## ### # ### # # # ### # # ### #### ######## # # ### # ### # # # # ### # ### ### ##### ##### # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # #### # # ### ##### # ### #### ### # ### # # ### # ## # ### # ######### # ## #### +# # # # # # # # # # # # # # # # # # # # # # # +# # ### # ### # ######### # # ### # # # # # ### #### ## # # # #### #### ### # ###### # # # +# # # # # # # # # # # # # # # # # # # # # # # # +# ##### ### # # ### ### ##### # # # ######## # # # # # ####### # ##### # ### ### # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ##### ##### ### ## ## # # # # # # ## # ### ### # ########### # ##### ## ### ### # # +# # # # # # # # # # # # # # # # # # # # # +# # # # ##### # # ## # #### # # ###### # ## #### ### ### # # # # # ### # # # # # # ### ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # ##### ## ## # # #### # # # ##### # ### # # # ### # # # ## #### # # ### # ### ### # +# # # # # # # # # # # # # # # # # # # # # # # # +# ### #### ### ## ### # ### ### #### # # # ## #### # ### # # ## ### ########## ## ### # # # ## +# # # # # # # # # # # # # # # # # # # # # +# # # # # # # ### ### # ### # ## # ## #### # ### # ### # ### # ### ### # # # ### ## # ## ## +# # # # # # # # # # # # # # # # # # # # # # +# #### # # # # #### # ### # ####### # # ### #### # # # ## ### # # ### # ## # ### # ### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# ### ### # ##### # ### # # # ### # # # ## # # # ### # # # # ###### #### ### ## ### # ### ##### # +# # # # # # # # # E# +################################################################################################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/100x100_spaghetti_v3.txt b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v3.txt new file mode 100644 index 0000000..38c0034 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v3.txt @@ -0,0 +1,99 @@ +################################################################################################### +#S # # # # # # # # # # # # +##### # # ### ####### ### # # ### ## # # # # ### # # # ## # # # # ##### # # # ### ## ### # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ###### # # # ###### # # # # #### # # # ### # # # # # # ### ##### # # ############# # # # +# # # # # # # # # # # # # # # # # # # # +# ### ## # #### ### # # # # # # # # ##### # #### ##### # # # # ### ### ### # ## ### ##### # +# # # # # # # # # # # # # # # # # # # # # # +# # ### ##### ## ### # # #### #### # # ## ###### ### # # # # ##### ### # ## ####### # # ### # +# # # # # # # # # # # # # # # # # # # # # # # # +##### # # ######### # ##### ##### # ## ### # ##### ####### # # # # # # # #### ## # # # ### # # +# # # # # # # # # # # # # # # # # # # # # +# # # ### # ## # ## ####### # # # ##### # ### ####### ## ### ##### # ## # # ###### # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# ## # # # ### # #### # ### ##### # ### ### # # ##### # # ### ######### ## ### # # ##### # +# # # # # # # # # # # # # # # # # # # # # # # +# # # ## # # ### ####### ### # # ## ##### ## ## # ## # # # # ## # # # # ## ### ### +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # +### # ### ### # # ### ### # # ### # #### ### # # ##### ### ######### # # # # # # # ## # # # +# # # # # # # # # # # # # # # # # # # # # # # +# # # # # # ####### # # #### # # ## # ####### # ### ### # # # ####### ### ### ## # # ##### # +# # # # # # # # # # # # # # # # # # # # # +# # #### ## ## ### # ### # # #### ## #### # ##### ##### ### # # ## ## # ### # ##### # # +# # # # # # # # # # # # # # # # # # # # # # +# ####### # # ## # ### ### # # # ## # ## # ## ## # ##### ### ## # ### ### # ### ###### # ### +# # # # # # # # # # # # # # # # # # # +# # # ######### ##### # # # # # #### ## ##### ####### # ##### # ## ##### ### ### ####### # +# # # # # # # # # # # # # # # # # +# # # # # ### ######### ### # ## # ### # # ### # ####### ##### ### ### ### # # ### # ### # +# # # # # # # # # # # # # # # # # # # # # # # # # +## # # ### ### # ### # ##### ## ## # # ########### # # # ####### # # ## # # # # ### ##### # ## # +# # # # # # # # # # # # # # # # # # # # # # +##### # ### ####### # ### ## ##### # # # ##### # # # ## # # ### # #### # ######## # +# # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # ### ##### # # # # # ## # # # # # # # #### ### # # ### # ### ### ##### # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# ### # # # ##### # # ## ##### ######### # # ##### # ### # # ##### #### ## # ####### # # # +# # # # # # # # # # # # # # # # # # # # +# # ## ## # ## # ### # # # # ##### ##### # ### ## ### # ### # # # ##### # # ##### # # ## # ### # +# # # # # # # # # # # # # # # # # # # # # +# #### # # #### ### # # # ### # ### ### ## # # ######### # ## # ##### # ##### ## # # # #### # +# # # # # # # # # # # # # # # # # # # # # # # # +# # ## ## ## # ## # ##### # ### ### ## ## # # ### # ### # # # ### # ### # # ####### # ### +# # # # # # # # # # # # # # # # # # # # # # +# ## ## # # # ####### ### # ### # ####### # #### # # # # # # # # ### # ### # ##### # # # ### # +# # # # # # # # # # # # # # # # # # # +## #### ########### # # # # # ##### # #### ## ########### # # # ### # ### ### ## ## ##### # # # +# # # # # # # # # # # # # # # # # +# # # ### # ### # # # ### # ## ## ### # ### ### # # ### ### #### ## ### # ### # # ### # +# # # # # # # # # # # # # # # # # # # # # # +# # ### ##### # # ### # ####### # # # # # # # # ### ### # ## # ##### ### ### #### # # # ### +# # # # # # # # # # # # # # # # # # # +# ### # # # # ## ## ### # # ##### ########### # ### ##### ### # ### # # ### ## ## # # ### # +# # # # # # # # # # # # # # # # # # # # # # +# # ## # # # # ### # # # #### ## ############# # ### # # # # ### ### # ### # # # # ### # # # # # +# # # # # # # # # # # # # # # # # # # # # # +# # # # ### ### ### # ### # # #### ## # ### # ### # ## ### # #### #### ### ### ##### ### # +# # # # # # # # # # # # # # # # # # # # # # # +# # # ####### ### ##### # # # ### # ## ### # # # ### ##### ##### # ### # # ### # # ####### # +# # # # # # # # # # # # # # # # # # # # # # # +## # # # # # # # # ### ### ## ### # ##### # # ## ###### ## ## # ##### ### # ####### # # +# # # # # # # # # # # # # # # # # # # # # # +# ###### ### #### ## ####### ## ## ### ### # ### ### # # ##### # # # # ### # ### ### # ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# ### # # # # ## ### ### # ### ######## ## # # # # ## ### ###### ## ####### # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# ##### # ### # ## # ###### # # # # # # #### ## # ### # # ### ### # ###### ## ### # +# # # # # # # # # # # # # # # # # # # # # # # # +# ####### # ### # ##### ##### # ############# # ############ # # # ### # # # ## # ## # # # +# # # # # # # # # # # # # # # # # # # +# ############ # # # # ##### # ### # ## ##### ### # ##### #### # # ##### ### ##### # # # # +# # # # # # # # # # # # # # # # # # # # # # +# ### # ### # # # # # ## ### # # # # # # # # # ### # ## #### # #### # #### # ### #### ### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# ###### ### # ### # # # # # ### ### # #### ### ## # ####### # #### # ##### ##### # # #### # +# # # # # # # # # # # # # # # # # # # # # # +### # # ## ######### # ## # # ##### # ### # # # # # # # # #### ## # #### # ## # ### # # # +# # # # # # # # # # # # # # # # # # # # # # # +# ### ### # ### ### # ## ## ### # # ########### ####### #### # ###### ##### # # # ### ## ## +# # # # # # # # # # # # # # # # # # +# ### # # ##### ### ## ####### ### ####### ### ##### ### ###### ###### # # # # ### # # ## # +# # # # # # # # # # # # # # # # # # # +### ### ##### # # # ######### # # ### # # ## ### ### # ### # # ##### # ##### ### # ### # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# ##### # # # # ## ##### # ####### # ### # ###### # # # # # # ## #### # # # # ##### # ## # +# # # # # # # # # # # # # # # # # # # # # # # # +# ### ### ##### # # # # # # # #### ## ### ##### ### # ## # ##### ## # ## ##### # # # ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # ### # # # # # # ### # ###### # ### #### # ### # ##### # ##### ### # # # ### ### ### # # # +# # # # # # # # # # # # # # # # # # # # # # # # +### # # ### ## # # # ### # ##### # ## #### ### ###### # # ## # ###### ## ### # # ### ### # # # # +# # # # # # # # # # # # # # # # # # # # # # # +# ###### ### # # ### # ## ##### # # ### # # # ## # # ##### ########### ##### ##### # # ## ## ### +# # # # # # # # # # # # # # # # # # # # # # +# # # ### # # ######### # ## ## ### # # # ####### #### #### ## ######## ####### ### ### # ### # +# # # # # # # # # # # # # # # # # # # +### ## # # ### # ## ### ###### # # ### ##### ### # #### # ## # # # ####### # ### # ## ## # +# # # # # # # # # # # E# +################################################################################################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/100x100_spaghetti_v4.txt b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v4.txt new file mode 100644 index 0000000..ce3c46b --- /dev/null +++ b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v4.txt @@ -0,0 +1,99 @@ +################################################################################################### +#S # # # # # # # # # +# ######## # ##### ### ## #### # # ### ##### # ### # ### # ### ##### # # # ##### # ##### # ### # +# # # # # # # # # # # # # # # # # # # # # # # # +# ####### ##### # ### ## ## ##### ####### ### ##### # # ##### # # # # # ### ## ##### ### +# # # # # # # # # # # # # # # # # # # # # # +# # # # ## ######## # ######## ### # # ### # ### # # ##### # # ##### ### ### # ## # ### # +# # # # # # # # # # # # # # # # # # # +# ### # # ## ## ### # # # # #### #### # # # # # ####### # # ##### ########### # ### # # # ## # +# # # # # # # # # # # # # # # # # # # # # +# ##### ## # # # ##### # # ####### ### #### # ### # # # # # ### ## ######## # # # # # ## # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# ### ### # # ##### # ######### # # # ## ##### # # # # #### ###### # ## # ## # ### # # ### +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # ## ## ## #### ####### ##### # # # # # # # # ######### ##### # # # ### # # # # # ### # +# # # # # # # # # # # # # # # # # # # # # # # # +# ### ### ### # ### ## # # # # # ###### ## # # ### ### # ### # # # ### # # ## ## ### # +# # # # # # # # # # # # # # # # # # # # # # +# ##### ######### ### ## ###### ## # # ##### ##### # ### ##### # ### ## # ##### # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # #### # ## # # # # # # ### ### # # # # # ####### ### # ### ## #### ### # # ## ########## # +# # # # # # # # # # # # # # # # # # # # # # # # +# # # ######### ### # # ### ##### ## # #### ## # ##### # # ### ##### ### # ##### # ##### ### # +# # # # # # # # # # # # # # # # # # # +### ####### # # ##### # ##### # #### ########### # # # # #### ## # ### # # #### # # # ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # ####### # # # ### # ## ### # ##### ### # # # ### # # # ### ##### #### # ### # # # # +# # # # # # # # # # # # # # # # # # # # # # # +# # ### ######### ################# ## ### # # ### # ######## ### # ##### ## # ## ## # # +# # # # # # # # # # # # # # # # # # # +# ### ### # ####### ### #### # # # ### # ### # ### ## ### # ### ### ### # # # # ### # # # +# # # # # # # # # # # # # # # # # # # +### # ####### # # # # # ### ##### # ### # #### # ## ######### ### ####### #### ### # ##### +# # # # # # # # # # # # # # # # # # # # # # # +# # # # ##### ### # ## # # # ## ### ### ## ###### ### # # # ### # # # ## # ### # # # +# # # # # # # # # # # # # # # # # # # # # # # # +# ## ####### # # # # # # # ### ### ## ## # ######## # # ### # ## ## ##### # # # ### # ### # # +# # # # # # # # # # # # # # # # # # # # # # # +# ######### # ### # ### # # #### ## # #### #### ## # ##### ## ######### # ### # ### ### ### # +# # # # # # # # # # # # # # # # # +## ### # ## ##### ##### ##### # # ## ## # # # ##### ##### # # ####### # # # # ## ## #### ### +# # # # # # # # # # # # # # # # # # # +# ### # ### # ##### ##### # ## # # # ##### # # # # ## ### ### ## # ### ### ## # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # ######### # # ### # # # ## ## # # ## ## ## ##### ## ############# # ##### # ### # +# # # # # # # # # # # # # # # # # # # # # +# # # #### ### # # ####### # ### ###### # #### # # # # #### # # # ###### ## ##### # ### # # # +# # # # # # # # # # # # # # # # # # # +# # # # # # # ### #### # ### # # ######## ### ### ### ### ## # # ### # ### ##### # # ### # +# # # # # # # # # # # # # # # # # # # # # # +# #### # ### # ## ## # # # # ##### # ##### # ### # ### # # # ### ### # ### ##### ## ### # # +# # # # # # # # # # # # # # # # # # # +# ##### ## # # # # # ## ### # ## ## # # # # ### # # ### ### ### ######### # # ###### # # # +# # # # # # # # # # # # # # # # # # # # # # +# ### ### ### ##### ##### ## ##### # # ### ##### ##### # ### #### # ### ##### ### ### # ##### # # +# # # # # # # # # # # # # # # # # # # # # +## ### # ## # # # # ## # # ## ##### # # ## ######### # # # ### ## #### # # # ## # ## ## +# # # # # # # # # # # # # # # # # # # # # # # +# ### ### # ## ## ### # # ### # ########### # # # ##### # # # ### # # ### ##### ### # # ### # # +# # # # # # # # # # # # # # # # # # # # # # # +### ##### ## # # ## #### ### # ### # # # # ## ## # # # ###### # # ### # ## ## ## ### ## # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# ### ### # ### ##### ##### # ###### # # ###### # #### ## ### # # # # ### ## #### ##### # +# # # # # # # # # # # # # # # # # # # # # +# ### ### # # # # # ### # # # ##### # # ###### #### ##### # # ## # ### # ##### # ### ##### +# # # # # # # # # # # # # # # # +# ### ########### ##### # # ## ## ### # ### # ### ## ### ### # ######### # ### ####### ### # # +# # # # # # # # # # # # # # # # +# ### # ##### # # # ### ### ### ### ##### ### ### ###### ###### #### ## # # ### # ### # ###### # +# # # # # # # # # # # # # # # # # # # +# # #### # # ##### # #### ### # # ##### # ### ##### ####### # # ## # ####### ######## ## # # +# # # # # # # # # # # # # # # # # # # # +# # ####### ### ##### ### # # # ### ######## ## # ### # ###### # ####### ### ### # ## # ### +# # # # # # # # # # # # # # # # # # # # # # +####### ##### # # ##### ####### ########## # ### # # # # ### ####### ## # # ### # # ##### # # # +# # # # # # # # # # # # # # # # # # # # # +# ####### # ### # ### #### # ### ###### # ### # # ### ### # ### ############# ### # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # +# ### # #### ##### # # # ######### ### ### # ####### # # # # ##### ## ## ## # # ## # ## # # # # +# # # # # # # # # # # # # # # # # # # # # # # +# # # ## ### ##### ### # # ### # ## #### ### # ##### ### # # # ### # #### # ## ### # # # ### # +# # # # # # # # # # # # # # # # # # # # # # # # +### ## # # # ## # # # # ####### ### ##### # ### # ##### # # # # # # # # # # # # ### # ### +# # # # # # # # # # # # # # # # # # # # # # # # # # +# ## # # ## # # ## # ## ### # ### # #### #### # # ####### ### # ### # ##### ##### # # +# # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # ### ### ## # # # # # # ## # ####### ## # # # # #### # # ##### ### ### # ### # +# # # # # # # # # # # # # # # # # # # # # # # # +####### # #### ##### # # # # ## ### # # # ### ### ## # # # ### # ## ##### # # # # ####### # +# # # # # # # # # # # # # # # # # # # # # +# # # ### ## # ## #### # # # ## # # ### # # # # # ####### ## ## ### # # ### # # # ### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# ##### ### # # ## ## # ####### # # # # # # #### ## # # ### # ## # # # # ## ## # # # # +# # # # # # # # # # # # # # # # # # +# ### # # # ## ####### # # ### # # # # # # # #### ## ### # ## #### ##### # ## ## ### # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # ### ### ### # # ####### # # # ## ### # # ### # # # ### ### ######### ### # # ###### # +# # # # # # # # # # # E# +################################################################################################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/100x100_spaghetti_v5.txt b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v5.txt new file mode 100644 index 0000000..26576ef --- /dev/null +++ b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v5.txt @@ -0,0 +1,99 @@ +################################################################################################### +#S # # # # # # # # +##### # ### #### ## ### ###### ### ### # # ## # # # ## ## ### ## # # # ### ##### # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # ### ### # ### ### # #### # ### ### # # ### ### # # ##### ### # # ## # # #### ## # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# #### # ### ##### # # ## ## # # # ### ##### # ##### # ### # ##### # ###### #### # # # # ### # # +# # # # # # # # # # # # # # # # # # # # # +# # # ## ## #### ####### # ### # #### # ## # ## #### ## # ### ####### # # ##### ##### +# # # # # # # # # # # # # # # # # # # # # # # +# # # # # # ### # # # ## # # # # ### ## # ### # ######## ##### ### # ## # # ##### # # # # ##### +# # # # # # # # # # # # # # # # # # # # +# ##### # ### ############# #### ### ##### # # # ### # ## # # # ## #### ### # # # ##### ## # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # # ### # # # # ##### # #### # # # # ### # ### # ## ## ## # # #### ### # # # # ### # +# # # # # # # # # # # # # # # # # # # # # # # # +# # # ### # # ####### ####### # ### # ## # # # ## ##### # ####### ### # ### ### # # ####### # +# # # # # # # # # # # # # # # # # # # # # # # +# # # # ## ## #### # # ### ##### ### ### ### # #### # #### # # ##### ### # ##### # # # +# # # # # # # # # # # # # # # # # # # # # # # +#### ## ## # ### ## # # ## #### # ### # # # # ##### # # # # ### ## ###### ##### # ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # ### # ### # # # ### # # # ## ### # ### # # ### # ## # # ## #### #### ## ## # # # # +# # # # # # # # # # # # # # # # # # # # # # # # +### ## # # ### ### ### ### # # # ####### ### ### # # ### # ### # ### # # # # ##### #### ### # ### +# # # # # # # # # # # # # # # # # # # # # +# # # # ## ##### ### ### ##### # # # ## #### ##### ## # ### # ### ######### # # ##### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# #### ##### ### ##### # # # # # ## # # # # ### # # ### ##### ### # # ### # # # ## ####### # +# # # # # # # # # # # # # # # # # # # # # # # # +# ## ### #### # # # # ### # ##### # ### # ### # # # # ## # ##### # # # ######### ###### # # +# # # # # # # # # # # # # # # # # # # # # +# # # # ##### ##### ###### ###### # # # ### ### ### ## # ## # # # # ##### ### # ### # ### # +# # # # # # # # # # # # # # # # # # # # # # # # +# # ### # ### # # # # # ### ####### # ###### ## # ### ### ## ## ### # # ## # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# ## # # # ### # ### # # # # ## ########## ### ##### ## # # ### # ## # # # ## # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # ## # ## # ### # # # # ##### ### # ###### # # ## ### # #### ## ### # ### ### # ## #### # +# # # # # # # # # # # # # # # # # # # # # # # # +### # ## # # # # ####### ##### ### ### # # ##### ### ### # # ## #### # ### #### # ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # #### # ### # ### # ### # ##### # # # ## #### # # # # ### ### ### ###### ## # +# # # # # # # # # # # # # # # # # # # # # # # # # +# ### # # ## ## # ## ### # ##### # # ##### # #### ##### ## ## ##### # ### ### # ### # ## +# # # # # # # # # # # # # # # # # # # # # # +# # ####### ## # ## ### ### ### # ## ## ##### # # # ### ## ## ##### ###### # ####### # ### # # +# # # # # # # # # # # # # # # # # # # # # # +# # ### # ## #### ## # ## # # ### # ### # # # # #### # # # # # # ##### ### ### ### # # # +# # # # # # # # # # # # # # # # # # # # # # # # +# # # ##### ### ## # # # # # # # # # # ## # ##### ##### ### # # # ### ####### ####### # ## # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# ### # # # ### ### ##### ####### # # # ### # #### ### # # # ####### ### ## ## ####### ##### # +# # # # # # # # # # # # # # # # # # # # # # +### ######### # ##### # # # #### # ### # ### # # # # # ## ##### # ### ### # # # ### # # # +# # # # # # # # # # # # # # # # # # # # # # # # +# ### ############# ### ### # # ## # ## ###### # ### # ## # # ### ### ####### # # # # # ## ## # +# # # # # # # # # # # # # # # # # # # +# #### ##### ##### ##### ##### # # # ### # # ## ## # # # ### ### ### ### ### # ##### ##### # +# # # # # # # # # # # # # # # # +### ## #### ###### ##### ## ## # ## # # # # # ####### # # # ####### # ## ### ## ##### # +# # # # # # # # # # # # # # # # # # +# # ### ## ### ## #### ##### # ## # # ##### # # ##### # # ### ####### # ### ## # ### # # # ## # +# # # # # # # # # # # # # # # # # # # +# # ### #### # # ##### # # #### ### ## # ### # ### # # # ######### ### # # ### ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # ### ## ## # ### # # # # ## # ### # ##### ### # # ######### ### # ### # ##### # #### # +# # # # # # # # # # # # # # # # # # # # # # # # +# ### ##### ## ###### # # # ## ##### # ### ### ### ### # # # ### # # ### # ######### # # # ## +# # # # # # # # # # # # # # # # # # # # # # +# # # # # # # #### ## ### # ##### ### # ##### ### ### # # ### ## # # # ##### # #### # # +# # # # # # # # # # # # # # # # # # # # # # # # +# ##### # # #### # ### ########## ## # # ### # # ####### ##### # ### # ### # ##### # ##### # # # +# # # # # # # # # # # # # # # # # # # # +# ###### ### #### # ######### # ##### ### ### ######## ## ### # # # # ####### # # ##### ### +# # # # # # # # # # # # # # # # +# # ###### ###### ### ### # ### # # ##### ### # ### # # ##### # #### # ###### ## # ### ### ### # # +# # # # # # # # # # # # # # # # +# # # ### # ##### ## ######## ### ##### ### ### ###### ########### # ####### ## ## # # ### # +# # # # # # # # # # # # # # # # # # # +# # #### ##### ## ######## # ########### ### ### ## # # ### # ####### # # ### ### # ### # ### # +# # # # # # # # # # # # # # # # # # # # +# ##### # ##### # # ############# # # # # ### ##### # # ######## # ##### # # ### ### ## ### +# # # # # # # # # # # # # # # # # # # # # # # # # # # +### # ## ## # # # # # ## # ##### # ## ###### ## ### # ### # # ### ##### # ##### ## ## ## # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# # ######### ### # # ######### # # # # # # ### ### # ## ## ## ## # # ### # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# ### # # ##### # # ### # # # ## ## ### ## ## # ### # # ##### # # # # # #### ## # ### +# # # # # # # # # # # # # # # # # # # # # # # # # +# ### ##### # # ### # # # # #### # # # ### # # ####### # # ##### # ## ### ### ###### ##### # +# # # # # # # # # # # # # # # # # # +# # ### # # ### # #### ### # ### # # #### # ######### ### ### ##### # # ### ##### ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# ## ### ### ### # # # #### ### ## # # ##### # ### # ## # ## # ## #### ####### # ### # +# # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # #### ##### # ####### # ## # # # # ### # ##### # ### ##### # ### # ####### # # +# # # # # # # # # # # E# +################################################################################################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/100x100_spaghetti_v6.txt b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v6.txt new file mode 100644 index 0000000..52595aa --- /dev/null +++ b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v6.txt @@ -0,0 +1,99 @@ +################################################################################################### +#S# # # # # # # # # # # # +# ### ### ## ##### ### # ### ### # # ### ## # # ##### ### # ### # # # ######### # ## ## # +# # # # # # # # # # # # # # # # # # # # # # +# ### # # ## ### # # # ### # # ### # # # # # # # # #### # # # # # # ##### # # ########## # +# # # # # # # # # # # # # # # # # # # # # # +##### ###### ### ## ## # ### # # # ### # ############# # # # # # # ##### ####### # ### ### # # +# # # # # # # # # # # # # # # # # # # # # # # +# # ### # ### # # # # ### # ### # # ### # # # ######## ### # ## # # ### ##### # # # # +# # # # # # # # # # # # # # # # # # # # # # # # +# # # # # ##### # # # ### # # ### ### # # # # ## # # #### #### ## # # # ##### # ### ## ### # +# # # # # # # # # # # # # # # # # # # # # # # +##### # # ### # # # # ## # # ### #### # # # ### # ### ### ### ### # # # ##### # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ##### # # ### ## # ### ### ### # # # # # #### ### ### # ## ### # # ############ # ## +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # ##### ### # # # # # # ### # # ### # # # ### ##### ##### # # ### ### ## # # # ##### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# ### # ### ## ## # ## #### ## # # # ## # # ### ### ### # ######### # # ### # ### # # ### # # +# # # # # # # # # # # # # # # # # # # # # # +# # # ### ###### ##### # # ########### # # ####### # # ### ### # # ### # ### # # # # ##### # # +# # # # # # # # # # # # # # # # # # # # # # +# ##### # ####### # # # ####### # #### ## # ## # ## # ### # # # ## ## # ### ## # #### # +# # # # # # # # # # # # # # # # # # # # # # # +##### # # ################# ### ### # ### # # # # # # ### # # # ## # ## # ### ### # ##### # ### +# # # # # # # # # # # # # # # # # # # # # # +# # #### ### # # # ##### # ##### ####### # # # # # # # ####### # ### ## # # ### ### # # #### # # +# # # # # # # # # # # # # # # # # # # # # +### # # ### # ### ### # ## ## ##### ### # ## #### ### # #### ## ## ### # # ####### # # ##### # +# # # # # # # # # # # # # # # # # # # # # # +# # # # # ### # ### # ## ##### # ##### # # ######### ### ### # # #### # #### ######## # ### +# # # # # # # # # # # # # # # # # # # # # # # # # # +# ### ### # # ## # # # ### # ##### # # # # # # # ## # # #### # # ### # ### # # ### # ## # +# # # # # # # # # # # # # # # # # # # # # # # # +### # # ## ### # ### # # # ### # # # # ####### ########### # # # ### # ###### ## ### # # ## # +# # # # # # # # # # # # # # # # # # # # # # +# # ##### ### # # # # # # # # ####### # # ######## ###### #### ### ## ## # # # ### ## # # +# # # # # # # # # # # # # # # # # # # +# ### # #### # # # # # ####### # # # ### ###### #### ## # ## #### # # ######### ### # ### # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# ###### #### # # # # ### # ### # # ### ### ### # ### # # ### # # # #### # ### ## # # ### +# # # # # # # # # # # # # # # # # # # # # # # +####### ### ##### # ## # ## ## # ### # ### # ## # ### ####### # # # ### # # # ###### ## ### # +# # # # # # # # # # # # # # # # # # # # # # # +# # # # # ## ##### ####### ####### ### # ### # ##### ##### ### ### # # # # # # ### ## # # +# # # # # # # # # # # # # # # # # +# # ### ### ####### ######### ######## ##### # # # ############# ####### # ### ### # ### +# # # # # # # # # # # # # # # # # # # +# ### # ### ##### ### ##### # # # ### # ## # # # ### # ### # # # # ### # ##### ## ### ### # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +## # # # # # # ### # ##### # # ### ##### #### ############ ### ### # ###### ### # ### ### # # +# # # # # # # # # # # # # # # # # # # # # # +##### # ## # # # #### ### ## # ##### ### # # #### ### ### # ##### # # ### ## ### # # # ## # +# # # # # # # # # # # # # # # # # # # # # # +# ####### ##### ### # # ## # # # ##### # ####### ##### ### # ### ##### # # # ## # ## ###### ## +# # # # # # # # # # # # # # # # # # # # # +## # ##### ####### # ### # # # # # ##### ### # ### #### ### # ### ## # # ### # # ### ##### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # #### # # # ### ### ##### ##### # ### # # # ### # ##### # # ### # ### # ### # # # ### #### +# # # # # # # # # # # # # # # # # # # # # # # +# ##### # # # # # ### # # ### # # ### # ############# # # ##### ## # ## ### # ###### # # ### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # ### # # ### ### ### # # #### ## # # # ##### # # # ## # # ## # # # # ### ## ##### # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# ### ##### ### ## # # ### # ##### # ####### # ## ## # # ### # # # # ## # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # +# ### # # # ####### # ######### ######## #### # # ## # ## ## # # # # # # # #### ##### # # # ### +# # # # # # # # # # # # # # # # # # # # +## # # #### # # # ## # # ### ##### # # ### # # ### # ### # ## # ########### # # # ## ###### # +# # # # # # # # # # # # # # # # # # # # # # +# # ###### ####### # ## ########## # # ####### ## ## ### # # # ## # # # ####### # ## # # ##### +# # # # # # # # # # # # # # # # # # # # # # # # +# # # ### # # # # ## # ### # ## ## ## # # # # # #### ### # ### # # ## ## # ### #### ### # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# ## ## # ####### ##### # ##### # ### # # # # # # # # # ##### # ## # ### ##### # ##### # # +# # # # # # # # # # # # # # # # # # # # # # # +# ## ### # # ##### ### ## ## ### # # # # ######### ##### #### # ### ### ## ### # ### ##### # +# # # # # # # # # # # # # # # # # # # # # # # +### # # #### # # ## # # ### ####### # # ## ## #### ### # # # # # # ### # ########## # # +# # # # # # # # # # # # # # # # # # # # # # # +# ##### ##### # ### # # # ### # ####### # # # ##### # # # # # # ##### # ## ## ### # ### ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +##### # # # ##### # # ### # ##### ### # ### ### # ### # ####### # # ####### # ### # ## ### ## # +# # # # # # # # # # # # # # # # # # # +# #### # # # ## #### # ### ## # ## # ### # ### #### # ### # ####### ######### # ##### # ### # +# # # # # # # # # # # # # # # # # # # # # # +# # # ####### ###### # # ## ## # ## ## #### # # ## ## #### ####### # ####### # # ####### +# # # # # # # # # # # # # # # # # # # # # +# ### # # # # ###### ## # #### ### # # #### #### #### ### ### # # ## ## # ### ##### +# # # # # # # # # # # # # # +### # ## ## ##### ######### #### # # # # # ## # ######### ######### #### #### ### ## # +# # # # # # # # # # # # # # # # # # # # # # # +# # # ### ## ##### # ##### ### # # # # # ##### # ### ## # # ### ### # # # ####### # # # # +# # # # # # # # # # # # # # # # # # # # # # # +# # ### # ############# # # # # ##### # # # # ### # ###### # # # ## # ####### # # ### # # +# # # # # # # # # # # # # # # # # # # # # # # # +# ### ##### # # # ###### ## ### # # ##### # # ### # ### ### # # # # ### ## ## ### # # # # # ### +# # # # # # # # # E# +################################################################################################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/100x100_spaghetti_v7.txt b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v7.txt new file mode 100644 index 0000000..5d863ab --- /dev/null +++ b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v7.txt @@ -0,0 +1,99 @@ +################################################################################################### +#S # # # # # # # # # # # # # # +# # # # ### # # #### ## # ##### # # # # # # # # ### ### # # ### # ##### # ### # # ## # ## # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +######### # ### # ##### # ## # # ##### # ######## ### ##### # # # # # ### # # ### ## # # # # # +# # # # # # # # # # # # # # # # # # # # # # +# ##### ####### # # ### # ### ### # ##### ### ## # ## ### ### # # # # ## #### #### ## # ## +# # # # # # # # # # # # # # # # # # # # # +##### ##### ### ###### # # # ### # # # # ### # ### # ##### ####### # ### ##### # # ##### # ####### +# # # # # # # # # # # # # # # +# ####### # # # ### # # # # ### # # ### #### # # ######### ## ## ### ### ## ## ### # # # +# # # # # # # # # # # # # # # # # # # # # +# ##### ### ### # ########### # # ### # ####### ##### # #### ###### # ### # # # ### # ### ## # # +# # # # # # # # # # # # # # # # # # # # +### # #### #### # ####### # ####### # ## # # # # # # ##### ## ## # ##### ### ##### # ### # +# # # # # # # # # # # # # # # # # # # # # # # # +# ## ### # # # # # ## ### # ### ### # # ### ## ## ##### # # # ### ## ######## ### ######### # +# # # # # # # # # # # # # # # # # # +# # ##### ##### # ### # # # # # # # ## # ### ## ## # # # ## ####### # # # # # ### ###### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# #### #### # # ## ### # ##### # # ### ### # # ###### ##### ### # ###### # ## ## ### # ## # +# # # # # # # # # # # # # # # # # # # +## #### # ### # # ##### # # # # # ### ############ # ####### ###### ## ####### # # ## ## # # +# # # # # # # # # # # # # # # # # # # # # # +# # # ##### # ### # ### ####### # # # ## ##### # ### # ######### #### # # # # # # ##### # ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # ### # # # # # ### # # # # # ### # # # # ##### ### # # # # # ####### ## ## +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # ## ##### ## # # ### # ## ## ## # #### # ### ##### # ####### # # # ### # # # ## # +# # # # # # # # # # # # # # # # # # # # # # # # +# ###### # ### ## # ##### # # # # #### # # # # ### ######### ##### ##### ###### ## # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# # ###### # ### # # ##### # ### ##### # ### # # # # ## # ## ### # # ## # # # # # +# # # # # # # # # # # # # # # # # # # # +#### ### # # # # ######### ### ### # # # # ##### # ##### #### # # # ### ### ####### # # ## # +# # # # # # # # # # # # # # # # # # # # # # # +# ## ## ##### #### # # #### ## # ###### #### ## # # ####### ## # ## ### ### ## ##### # # +# # # # # # # # # # # # # # # +## # ############ ##### ### # # ### # ###### ## # # ## # # # ### # # ### ## ## +# # # # # # # # # # # # # # # # # # # # # # # # # +# ####### ## ## ##### ## ####### ##### ### # # ### # # #### # ### # ### # #### #### # ##### # # +# # # # # # # # # # # # # # # # # # # # # # +# ### # # # # # # # # ### ### ## ###### # ##### # ##### # ### # ### # # ######## ##### # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # ## # # # # # # # ### # # # #### # ### ### ### # ## ### # # ### ### ### ### # +# # # # # # # # # # # # # # # # # # # # # # # # +# # ##### # ## ### ## # # # # # ### # # # ######## ###### # ##### ### # # # ## # # # ### # # +# # # # # # # # # # # # # # # # # # # # +# # ### ## # # # ######### # # ## #### ############## # # ## # # ## # # ############# ### # +# # # # # # # # # # # # # # # # # # # +# # # ###### ## ######### # # # # # # ## # ########### ## # ## ###### ##### # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +######### # ### # # # #### ## ### # ### ### # ##### # # # ### # # # # ### # # # ### ## ## ## # +# # # # # # # # # # # # # # # # +# ##### ## # # ##### ## # ##### ##### # ### #### ###### ####### # # ### ########## #### # # +# # # # # # # # # # # # # # # # # # # # +# # # # # ### ### # ## # # ### # # ### ##### # ####### ### ## # # ### ### # # ### ## #### +# # # # # # # # # # # # # # # # # # # # # # +# ### # # # ### ##### ## ##### ### ## ####### ## ### # # ### # # ######### # ######### ### # +# # # # # # # # # # # # # # # # # # # # # +# ### ### ## ###### # #### # # ####### # ### #### # ####### # # ##### # # ##### # ### ####### # +# # # # # # # # # # # # # # # # # +### ### # # # #### ############ ### ### ### # ### # # ### ### ### ##### # ####### # ## #### # # +# # # # # # # # # # # # # # # # # # # # +# ### ##### # ### # ## # ########### #### ## # ## # ## ###### ## # # # # ### # ###### # +# # # # # # # # # # # # # # # # # # # # # # # # # +### # ### # # # # # # ## # #### ##### # # ### ###### # ##### # # # # ## #### # # # ### +# # # # # # # # # # # # # # # # # # # # # # # +# # # ## ## #### ### ## # # ### ##### ##### ### ## ###### #### ### ## # ### # ### # ### # +# # # # # # # # # # # # # # # # # # # # # # # # +# # # # ## ## # ### # # ### # # ### # ### # # # ## # #### #### # ### # # ### #### ## ###### +# # # # # # # # # # # # # # # # # # # # # # # # +# ## ###### ## # # # ### ### ####### ##### # ### # # ### # ### # # # # ## ## # # # # ##### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # ### # # # #### # # ### ### ### # # # ### # # ### # # # # ##### ####### # # ##### ### # # # +# # # # # # # # # # # # # # # # # # # # # # # +# # ## ##### # ## ##### ## ## ### ### ### ### # # ##### #### ## # # ## ### ##### # +# # # # # # # # # # # # # # # # # # # # # # +# # # ### # ##### # ## #### # ####### # # ### ### # # ## ## # # ########### # ### # # # ##### +# # # # # # # # # # # # # # # # # # # # # # +# ##### ## ## # ## # #### ####### ## ### ## #### ###### # # ## #### # # ####### # ##### # +# # # # # # # # # # # # # # # # # # # +### # ########## #### # ##### # # ##### # ### ##### # #### ## # # # # ##### ### ## ### # # # #### +# # # # # # # # # # # # # # # # # # # # # # +# # ### # # ##### # # # ####### ## ## ## ## ### # ##### # # ### ##### ### ##### ### ### # +# # # # # # # # # # # # # # # # # # # # +# # #### ## # ##### # ## ##### # ### # #### #### ##### # ## ####### # # ######### ## # # +# # # # # # # # # # # # # # # # # # # # # +# ### # # # ##### # ####### # # # # ### ### # # ### ## # ### # ## # ### # ##### # ##### # # # +# # # # # # # # # # # # # # # # # # # # # # # +# #### # ## # # ## ## # ### ## ## ## # ##### ### ####### ### ####### # # ## # ### # # ### +# # # # # # # # # # # # # # # # # # # # # # +# ### # #### #### # # # ## # #### #### ## ######## #### # # # ### # # # # # # # # ## ## # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ## ## # ## ### ## # ### # ### # ## # # # ### # ### # # ## ####### # # ### ###### # ## # +# # # # # # # # # # # # # # # # # # # # # +## # ### ## # ## ### # # # ##### ### # ##### ##### # ## # ######## # # ## ### ### ### ## # # # +# # # # # # # # # E# +################################################################################################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/100x100_spaghetti_v8.txt b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v8.txt new file mode 100644 index 0000000..393318e --- /dev/null +++ b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v8.txt @@ -0,0 +1,99 @@ +################################################################################################### +#S# # # # # # # # # +# ### # ##### ### # # # ## ### ######### ############# # # ########### # # # # ##### # #### # ### +# # # # # # # # # # # # # # # # # # # # +### # ### # ### # # ##### ####### ####### # ### # ## # ### ## ## # ### ##### ##### ## ##### ## # +# # # # # # # # # # # # # # # # # # # +# ## ## ### # ### #### ## # # ## ##### ### ## # # ### # # ### ##### # # ##### # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# ### # # # # ### # # # ## ## #### #### ## ## # # ## # # # ### ### ## ##### ####### ### ### +# # # # # # # # # # # # # # # +# # ##### # ## ## #### # #### ## # # ### ### ####### ### ## ###### # ##### # # ##### ### ## # +# # # # # # # # # # # # # # # # # # # +## # ### # # # ### ##### # # ##### ### # ### ### # # # # # ### ### # ### ###### # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # ## # # # ####### ### ### ## # ### # # # ### # # # ### ### # ### # ### # # # # +# # # # # # # # # # # # # # # # # # # # # # # +# ### ###### # # # ####### ##### #### # ###### # # ### # # ### # # # # ##### # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # +# # # # ####### # # # ### # # # ### ### # # # # ##### # ##### # # # # ## # ### # # # ## # +# # # # # # # # # # # # # # # # # # # # # # # # +# ### # #### ## # # ### ## ## # # ## # ### ###### ## # ### # ### # # # ##### ####### # ### # ### +# # # # # # # # # # # # # # # # # # # # # +# #### #### ####### # ##### ## # ### ## ##### # ### ##### # ### # # ## # # # #### ### # +# # # # # # # # # # # # # # # # # # # # # +#### # ## # # # # # # ### ### ### # # # ### ####### # ##### # ##### ##### ####### # # # ### # # # +# # # # # # # # # # # # # # # # # # # # # +# # # # # ### ## # ### ### ## ### # # # #### ## # ### #### # ##### # ### # ##### ## ## ##### # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # ### ### ### # ## ## ## # # ### ##### # ### # # # ## ## # # # ### ####### # ### # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# ####### # ### # # ### ## # ### # # # ### # # ### # ##### # ##### ###### ### # ### ##### # +# # # # # # # # # # # # # # # # # # # # # # # # +# ### # # # ## ### ### # ## # # ### # # ## ##### # ##### # # # ### # ### ### # # ##### # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# # ### ### # ### # # # # ### # # # ##### ### # ## ## ####### # # ## ## ##### ### ## # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ### # # ### # ### # ## #### # # # # # # # ### ## # # # ### ### ### ### # # ### +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # ######## ### ### ### # # #### ### ## # # # ##### # # # # #### ### # # ### # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +### # # # ## ### # # # # # #### # ### # ## ##### # # # # # ####### # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # ## # ### # # # ### #### ### ## # # # #### ##### # # # ##### # #### ## ### # # #### # # +# # # # # # # # # # # # # # # # # # # # # # # # +# # ### ##### # # # ## # # ##### ### # ### # ## #### # ### ## # # ### # ### ### # # ##### # +# # # # # # # # # # # # # # # # # # # # # # # # +# ## # # ##### # ###### # ########### # ##### ### # ### # # ########## ### ##### # # # # # # # +# # # # # # # # # # # # # # # # +# ####### ######### # # ##### # # # ## # # # ### # # # # ### ### ### ####### # ## ##### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ### # # ### # ## ## # # # # # ### # ##### # # ### # # # # # # # # # ### # # ## # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # +##### # # ##### # #### #### ### # # # ############# # # ### # ### ## #### # # #### # # #### +# # # # # # # # # # # # # # # # # # # +# # # ##### #### ### # #### # # # ### # #### ## # # # # ### # # ### ###### # ## # # # # # +# # # # # # # # # # # # # # # # # # # # # # +# ##### # # # ### # # ############# # # ##### # # # # ### ### # ## # ### # #### ## # ### # +# # # # # # # # # # # # # # # # # # # # # # # # +## # # ### ## # ## # ## # ##### # # # ###### # ## ### # # # ### ### # ###### ### # ### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # ## # # ##### ##### # # # ##### # # # ### ### # # ### # # # # # ### ### ###### # +# # # # # # # # # # # # # # # # # # # # # # # +# # ### # ##### # ## # # ### ### ####### # # ### ### # # # ##### # # ############ # # # # ### +# # # # # # # # # # # # # # # # # # # # # # +# ## ### # ### ### # # ### ### ### ##### # ##### ##### # ## ## # # # ### ### ###### ###### # +# # # # # # # # # # # # # # # # # # # # # # +# # ######## ## ##### ##### ### ##### ##### # # # # # # # # # # ### ### # # # # # #### # # # +# # # # # # # # # # # # # # # # # # # # +# ### ### ### # # # # ### ##### # # # # # ### ### # # # # ##### ##### # ## # ## # # ### # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +### # # # # # # ### # ##### # ### ### ### ## # # ### # # ### ###### ##### # # ### ## ## # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# ### ## # # # # ## #### ### ###### # # # ###### ## # ## ## # ##### # # # ### ####### ### # +# # # # # # # # # # # # # # # # # # # # # +# ##### ### ### ### # # ### ####### # ## ## ### # # # # ########### # ### ##### ### # ## ##### # +# # # # # # # # # # # # # # # # # # # # +# ### ### ## ####### # ##### # ### # ## ## ######## # ### # #### # # ####### ### ####### # +# # # # # # # # # # # # # # # # # # # +# ##### ##### # # ### # # ## ###### ## # ##### # #### # ### # # # # ##### # # ### # # ### # +# # # # # # # # # # # # # # # # # # # # # # +# # # ## # # # # ### # ## # # # ##### # ##### # ########### # ##### # ####### # ### # ### +# # # # # # # # # # # # # # # # # # # # # +# # # #### ### ##### # ##### # ##### # # ### # ### # # # ####### # # # # ##### # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# ### # ### ####### ### # # ### # # ## # #### # ##### # # ### # ### ## ## # #### ## ## ##### +# # # # # # # # # # # # # # # # # +# # ###### # ### # ##### # ## ######## # # # # # ######## ##### ####### # #### # ####### # +# # # # # # # # # # # # # # # # # # +##### # ### # # ### # ### ### ### ### ##### ## # # # # # ## ### # ### # ### # ## # ## # ### +# # # # # # # # # # # # # # # # # # # # # # # +# # ### # # # # ### # ### # # ### ### ### # # ####### #### # ### # # # ##### # ### # ### #### # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # ### # ### ### # # # ### # # ### # ######### ### ## ### ## ### # ### # ## ##### ### # +# # # # # # # # # # # # # # # # # # # # # # # +# ### # # # ####### # ### ## # # ### ##### ## ### ##### # # # ## #### # ### # # ### ##### ### +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# # ### # ### ## # # ### # ##### # ##### # ### ## ##### ### # # ######### # # ### # # # # # # +# # # # # # # # # # # E# +################################################################################################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/100x100_spaghetti_v9.txt b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v9.txt new file mode 100644 index 0000000..850393f --- /dev/null +++ b/skorohodovsa/task_2/source/templates/100x100_spaghetti_v9.txt @@ -0,0 +1,99 @@ +################################################################################################### +#S # # # # # # # # +### # # ### # ### #### ## ##### # ### # ### ### #### # ### ### # ####### # # # ### # ### ### # +# # # # # # # # # # # # # # # # # # # # # # +# # # # # ############### # ### ###### ### # ### ######## ### # # ##### # # # # # ### # # # # # # +# # # # # # # # # # # # # # # # # # # # # +# # ## # # ##### ## ## ### ### # ### #### #### # ### ### ### # ##### # ### ### ### # # +# # # # # # # # # # # # # # # # # # # # # +# ### ### ### # # ##### ###### ######## ## #### # # # # # # ## # # # ### ### ### # # ## # +# # # # # # # # # # # # # # # # # # # # # # # +# # # # ####### ## # ############### ### # ##### # #### # # # # ### ## # # ### # ### # # +# # # # # # # # # # # # # # # # # # # # # +# ##### # ## ## ##### ### # ## ## #### # # # ##### ####### ### # ## ## # #### # ##### # # +# # # # # # # # # # # # # # # # # # # # +### ### ### # ## #### # ### # # # ###### ### # ####### # # ## # # # # ### # ## ## # # ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # +# ### ### # # # # ####### # ### ##### ####### # # # # ####### # # #### ###### # # ### # ## ### # # +# # # # # # # # # # # # # # # # # # # +# #### # # ## ######## ### ##### # # ##### ###### # ##### #### ## ## ## # ### # #### # +# # # # # # # # # # # # # # # # # # # # # # # # +# ###### ##### ### # # # # # # ### # ## ## ### # #### # ### # # # # ### # # # ### ###### # ### +# # # # # # # # # # # # # # # # # # # # # # # +# ### # # ##### # #### #### ####### #### # ### ### # ## ###### # ## # # # # # # # # ### # ### # +# # # # # # # # # # # # # # # # # # # # # # # +# # # # ## # # ######## ## ## ### ### ### ####### # ### # # ### # ### #### # ## # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # +# ### # ### # # # # # # ## ### # # ## # # ### ### ### # # # # # ##### # # # # ### ### # #### # +# # # # # # # # # # # # # # # # # # # # # # # +# # # ### # # # ## # ### ### ##### # ### # # ####### # ####### ### # ###### # # ##### # # # # # +# # # # # # # # # # # # # # # # # # # # # # +# # # ### # ## ## # ##### # # # ## ####### # ## ### ######### # # ##### # #### ## ## # ### # # # +# # # # # # # # # # # # # # # # # # # # # # +# ## # # #### #### #### ### # ####### # # # ## ##### # # ##### # ######### ### # ### # # # # +# # # # # # # # # # # # # # # # # # # # # +## # # # # # ## ### # # # # # ### ## ### # ### # # # # ####### # ## # ### ## # ### ### # ### +# # # # # # # # # # # # # # # # # # # # +# ##### # # # # ##### # # ##### ### # ##### # ##### # ## #### # ##### # # ####### # ### ### # +# # # # # # # # # # # # # # # # # # # # # +# ## # # # ### # # ### # # ## ## # # ### # #### # # # # ####### ### #### # ### ## ###### +# # # # # # # # # # # # # # # # # # # # +# # # #### ### #### ### # # ### ####### ###### # # # ##### # ################# # # ##### # +# # # # # # # # # # # # # # # # # # # # # +#### # # ### # # # # ### # # ### # # ####### ### ### # # ## ## # # # # #### # ## ## ### # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # +# ## # # # # # # ## ## # # # ### # ### # # ### ### ### ## # ### ######### # ## ## # ## ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # +# ### ### # # ### ### # ### ## # ## # ## # ## ### # # # # # ### # # # # # ### ### # ### # # # +# # # # # # # # # # # # # # # # # # # # # # # # +# # ### ## ### # # ### # # ##### # # ## ###### #### # ##### # # # # # # ### # ## # #### # # +# # # # # # # # # # # # # # # # # # # # # # # +# ####### ## ## ### # # # ### # # # ## # # ## #### # # ####### # # # # ##### ## # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # +####### ### # ### # ### ### # ########### # ### ### # # ###### ## # # # ####### ####### # # # # +# # # # # # # # # # # # # # # # # # # # # +# ### ## # # #### #### # # #### # # ##### # # # # # # # # # # # ##### # # #### # # # # ## +# # # # # # # # # # # # # # # # # # # # +# # # ## # # ####### ### ##### # # ####### # ### # # # # # # # ## ## #### #### ####### ### # +# # # # # # # # # # # # # # # # # # # # # # # +# # # ##### # ## ## ### ### ### # ##### # # ##### # # ###### #### # ## ## # ### # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # # ### # ### ### # # # # ### #### ########## # # ##### ### # # ## # # # ### # # ### ##### # # +# # # # # # # # # # # # # # # # # # # # # # # +### # ### # # # # # ####### ## # ### ### ##### # # ##### ## # # ##### # # ##### ####### # # +# # # # # # # # # # # # # # # # # # # # # # # +# # # # # # ###### # ### #### ## # ### ### # # ## # ### #### ### # # # ### #### # ## ### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # ## # #### ###### # ## # ## ### # ### # # ### ## # # ##### ### ######### # # ## # # ### +# # # # # # # # # # # # # # # # # # +# # # ######## ### # ### ### ### ##### # # # # # ### # ########## # ######### # # ## # +# # # # # # # # # # # # # # # # # # # # # # +# #### ## # # ## ## ##### # # # # # ### # ##### # # ### # ### # # # # ### ### ### ## ## # ##### # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # ##### # # # ## # # # # # # #### ############## ## # # # # ### # # ##### ##### # # +# # # # # # # # # # # # # # # # # # # # # # # +# # ## # ### ####### # ### # # #### # # ### ######### # ##### ####### # ### # ### ## # ### ### +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # ## #### ## ## ### # # # ##### # # # ## # #### #### # ## ## ## # #### ### # +# # # # # # # # # # # # # # # # # # # # # # # # +# # # # ### ### ##### # # ##### # ### # ##### # # ### # ### # # ### # # # #### # ## #### # ### # +# # # # # # # # # # # # # # # # # # # # # +# ### # ##### # # # # ### # ### ### ### # # # # # # # # ### ###### ## # # # ######### # # ## +# # # # # # # # # # # # # # +# # # # #### ###### #### # #### ###### # ## #### # ## # ### ## # ###### ##### ############# # +# # # # # # # # # # # # # # # # # # +# # # ###### # ####### # # ### # # # # # #### #### ##### # ### ##### # # ### # ## # +# # # # # # # # # # # # # # # # # # # # # # # # # +# ### ## # # # # ##### # # # ### ##### # # # #### #### ####### # ### ### ### ### # #### # # # +# # # # # # # # # # # # # # # # # # # +# # ### ##### ### # #### ### # # # # ### ####### ##### ##### # #### ### ### ########## ##### +# # # # # # # # # # # # # # # # # # # # # # # +# #### ##### ### ### # ###### # ### # # ### # # ### ## # ### ### ###### ##### ### # # ### # # +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # ### ##### # # # # # # # ### ##### # ### ## # ### # ######## # ## ## # # ##### # # +# # # # # # # # # # # # # # # # # # # +# ### ## # ## # ####### ##### # # #### # # ##### ### # ###### # # ######## # # # # # ### ### # +# # # # # # # # # # # # # # # # # +####### # # ### ########## # # # ## ## # # ### ########### ##### ### ### # # ### # # # # # +# # # # # # # # E# +################################################################################################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/10x10_path_v1.txt b/skorohodovsa/task_2/source/templates/10x10_path_v1.txt index 6395399..1a113a8 100644 --- a/skorohodovsa/task_2/source/templates/10x10_path_v1.txt +++ b/skorohodovsa/task_2/source/templates/10x10_path_v1.txt @@ -1,10 +1,9 @@ -S######### - # -# ###### # -# # # # -# # ## # # -# # # # # -# #### # # -# # # -# E# -########## \ No newline at end of file +######### +#S# # +# # # ### +# # # # +# ##### # +# # # +##### # # +# E# +######### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/10x10_path_v10.txt b/skorohodovsa/task_2/source/templates/10x10_path_v10.txt new file mode 100644 index 0000000..b4b07d4 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/10x10_path_v10.txt @@ -0,0 +1,9 @@ +######### +#S # # +### ### # +# # # # +# ### # # +# # # +# ##### # +# E# +######### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/10x10_path_v2.txt b/skorohodovsa/task_2/source/templates/10x10_path_v2.txt new file mode 100644 index 0000000..5d64685 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/10x10_path_v2.txt @@ -0,0 +1,9 @@ +######### +#S# # # +# # # # # +# # # # +##### # # +# # # # +# ### # # +# E# +######### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/10x10_path_v3.txt b/skorohodovsa/task_2/source/templates/10x10_path_v3.txt new file mode 100644 index 0000000..2757357 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/10x10_path_v3.txt @@ -0,0 +1,9 @@ +######### +#S # +####### # +# # # +# # ### # +# # # # +# # # ### +# # E# +######### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/10x10_path_v4.txt b/skorohodovsa/task_2/source/templates/10x10_path_v4.txt new file mode 100644 index 0000000..37e64e2 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/10x10_path_v4.txt @@ -0,0 +1,9 @@ +######### +#S# # +# # ### # +# # # # +# ### # # +# # # # +# # ### # +# # E# +######### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/10x10_path_v5.txt b/skorohodovsa/task_2/source/templates/10x10_path_v5.txt new file mode 100644 index 0000000..47d7392 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/10x10_path_v5.txt @@ -0,0 +1,9 @@ +######### +#S # # +##### # # +# # # # +# # # # # +# # # # +# ##### # +# E# +######### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/10x10_path_v6.txt b/skorohodovsa/task_2/source/templates/10x10_path_v6.txt new file mode 100644 index 0000000..47d7392 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/10x10_path_v6.txt @@ -0,0 +1,9 @@ +######### +#S # # +##### # # +# # # # +# # # # # +# # # # +# ##### # +# E# +######### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/10x10_path_v7.txt b/skorohodovsa/task_2/source/templates/10x10_path_v7.txt new file mode 100644 index 0000000..99c6fe3 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/10x10_path_v7.txt @@ -0,0 +1,9 @@ +######### +#S# # +# ### ### +# # # +### ### # +# # # # +# # # # # +# #E# +######### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/10x10_path_v8.txt b/skorohodovsa/task_2/source/templates/10x10_path_v8.txt new file mode 100644 index 0000000..6fc4a3a --- /dev/null +++ b/skorohodovsa/task_2/source/templates/10x10_path_v8.txt @@ -0,0 +1,9 @@ +######### +#S # # +### # # # +# # # # # +# # # # # +# # # # +# ### # # +# #E# +######### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/10x10_path_v9.txt b/skorohodovsa/task_2/source/templates/10x10_path_v9.txt new file mode 100644 index 0000000..7c37230 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/10x10_path_v9.txt @@ -0,0 +1,9 @@ +######### +#S# # +# ##### # +# # # +### # # # +# # # # +# ##### # +# E# +######### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/20x20_noexit_v1.txt b/skorohodovsa/task_2/source/templates/20x20_noexit_v1.txt new file mode 100644 index 0000000..724541a --- /dev/null +++ b/skorohodovsa/task_2/source/templates/20x20_noexit_v1.txt @@ -0,0 +1,19 @@ +################### +#S # # # +##### # ##### ### # +# # # # # # +# ### # # ##### # # +# # # # # # # +# # ######### # # # +# # # # # +# ######### # ##### +# # # # # +# ### # # # ##### # +# # # # # # # +# # ### ####### # # +# # # # # # # +# # # ### ### ### # +# # # # # +# ### # ### ##### # +# # # # +################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/20x20_noexit_v10.txt b/skorohodovsa/task_2/source/templates/20x20_noexit_v10.txt new file mode 100644 index 0000000..242bcc7 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/20x20_noexit_v10.txt @@ -0,0 +1,19 @@ +################### +#S # # # +##### # # # ##### # +# # # # # # # # +# # # # # ### # # # +# # # # # # # +# ##### ### ### # # +# # # # # +# ### ####### ### # +# # # # # # +### ##### # ### # # +# # # # # # +# ######### # ##### +# # # # # +# # ##### # ##### # +# # # # # # +# ### # # # # ### # +# # # # # +################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/20x20_noexit_v2.txt b/skorohodovsa/task_2/source/templates/20x20_noexit_v2.txt new file mode 100644 index 0000000..a5dd21d --- /dev/null +++ b/skorohodovsa/task_2/source/templates/20x20_noexit_v2.txt @@ -0,0 +1,19 @@ +################### +#S # # # +######### # # # # # +# # # # # # +### ##### ##### ### +# # # # # # +# # # # # # # ### # +# # # # # # # # +# ### ##### ### # # +# # # # # # +# # ####### # ### # +# # # # # # +# ### # ##### ### # +# # # # # # +# ####### # ### # # +# # # # # # # +# # # ### # ### # # +# # # # +################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/20x20_noexit_v3.txt b/skorohodovsa/task_2/source/templates/20x20_noexit_v3.txt new file mode 100644 index 0000000..585f187 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/20x20_noexit_v3.txt @@ -0,0 +1,19 @@ +################### +#S # # # # +### # # # ### # # # +# # # # # # # # +# # ##### # # # # # +# # # # # # # # +# # # # ### ####### +# # # # # # +# # # ### ####### # +# # # # +# ### # ######### # +# # # # # +# # ##### ### ##### +# # # # # # +# ### # ##### ### # +# # # # # # +####### # # ### # # +# # # # +################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/20x20_noexit_v4.txt b/skorohodovsa/task_2/source/templates/20x20_noexit_v4.txt new file mode 100644 index 0000000..7eeb7da --- /dev/null +++ b/skorohodovsa/task_2/source/templates/20x20_noexit_v4.txt @@ -0,0 +1,19 @@ +################### +#S # # # +### ####### # # ### +# # # # # +# ### ### ####### # +# # # # # +####### ####### # # +# # # # +### ### # ####### # +# # # # # +# ######### ### # # +# # # # # +### # # # ####### # +# # # # # # # +# ### # ### # # # # +# # # # # # # +# # # # ##### ##### +# # # # +################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/20x20_noexit_v5.txt b/skorohodovsa/task_2/source/templates/20x20_noexit_v5.txt new file mode 100644 index 0000000..2f8ad60 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/20x20_noexit_v5.txt @@ -0,0 +1,19 @@ +################### +#S# # # +# # ### # ####### # +# # # # # # # # +# # # # # ### ### # +# # # # # # +##### # # # # ##### +# # # # # # # +# # # # ### ##### # +# # # # # # +# ####### ### ### # +# # # # # +# # ##### # # # ### +# # # # # # # # +# ### ####### # # # +# # # # # # +# # ### # ##### # # +# # # # +################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/20x20_noexit_v6.txt b/skorohodovsa/task_2/source/templates/20x20_noexit_v6.txt new file mode 100644 index 0000000..ffcf274 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/20x20_noexit_v6.txt @@ -0,0 +1,19 @@ +################### +#S # # # +### # # ### ### ### +# # # # # +# ### ########### # +# # # # # # +### # # ### ### # # +# # # # # # # # +# # # # # ### ### # +# # # # # # +# ####### # ##### # +# # # # # # +# ### # # # # ##### +# # # # # +########### ##### # +# # # # +# # ########### # # +# # # +################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/20x20_noexit_v7.txt b/skorohodovsa/task_2/source/templates/20x20_noexit_v7.txt new file mode 100644 index 0000000..04d6167 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/20x20_noexit_v7.txt @@ -0,0 +1,19 @@ +################### +#S # # # +##### # ### ### # # +# # # # # # # +# # # ##### ### # # +# # # # # # +# ####### # # ### # +# # # # # # +# # ########### # # +# # # # # +# ####### ### # ### +# # # # # +########### # ### # +# # # # # +# # # ### # ##### # +# # # # # # +# # ####### ##### # +# # # +################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/20x20_noexit_v8.txt b/skorohodovsa/task_2/source/templates/20x20_noexit_v8.txt new file mode 100644 index 0000000..18a670d --- /dev/null +++ b/skorohodovsa/task_2/source/templates/20x20_noexit_v8.txt @@ -0,0 +1,19 @@ +################### +#S # # +### # ### ####### # +# # # # # # # +# ### ##### # # # # +# # # # # +# ### ####### ##### +# # # # +### ####### ##### # +# # # # # # +# # # # ##### ### # +# # # # # # +# # # ######### # # +# # # # # # +# # ########### ### +# # # # +# ########### ### # +# # +################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/20x20_noexit_v9.txt b/skorohodovsa/task_2/source/templates/20x20_noexit_v9.txt new file mode 100644 index 0000000..7a11e8f --- /dev/null +++ b/skorohodovsa/task_2/source/templates/20x20_noexit_v9.txt @@ -0,0 +1,19 @@ +################### +#S # # # +### # ##### # ### # +# # # # # # # +# # # # ####### # # +# # # # # +# ####### ####### # +# # # # # +####### ##### # # # +# # # # # +# ### ### # ##### # +# # # # # # +### ### # ### # ### +# # # # # # # # +# ### # # # ### # # +# # # # # # +# ### ####### ### # +# # # +################### \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/30x30_empty_v1.txt b/skorohodovsa/task_2/source/templates/30x30_empty_v1.txt new file mode 100644 index 0000000..2828878 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/30x30_empty_v1.txt @@ -0,0 +1,30 @@ +############################## +#S # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# E# +############################## \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/30x30_empty_v10.txt b/skorohodovsa/task_2/source/templates/30x30_empty_v10.txt new file mode 100644 index 0000000..2828878 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/30x30_empty_v10.txt @@ -0,0 +1,30 @@ +############################## +#S # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# E# +############################## \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/30x30_empty_v2.txt b/skorohodovsa/task_2/source/templates/30x30_empty_v2.txt new file mode 100644 index 0000000..2828878 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/30x30_empty_v2.txt @@ -0,0 +1,30 @@ +############################## +#S # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# E# +############################## \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/30x30_empty_v3.txt b/skorohodovsa/task_2/source/templates/30x30_empty_v3.txt new file mode 100644 index 0000000..2828878 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/30x30_empty_v3.txt @@ -0,0 +1,30 @@ +############################## +#S # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# E# +############################## \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/30x30_empty_v4.txt b/skorohodovsa/task_2/source/templates/30x30_empty_v4.txt new file mode 100644 index 0000000..2828878 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/30x30_empty_v4.txt @@ -0,0 +1,30 @@ +############################## +#S # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# E# +############################## \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/30x30_empty_v5.txt b/skorohodovsa/task_2/source/templates/30x30_empty_v5.txt new file mode 100644 index 0000000..2828878 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/30x30_empty_v5.txt @@ -0,0 +1,30 @@ +############################## +#S # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# E# +############################## \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/30x30_empty_v6.txt b/skorohodovsa/task_2/source/templates/30x30_empty_v6.txt new file mode 100644 index 0000000..2828878 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/30x30_empty_v6.txt @@ -0,0 +1,30 @@ +############################## +#S # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# E# +############################## \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/30x30_empty_v7.txt b/skorohodovsa/task_2/source/templates/30x30_empty_v7.txt new file mode 100644 index 0000000..2828878 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/30x30_empty_v7.txt @@ -0,0 +1,30 @@ +############################## +#S # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# E# +############################## \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/30x30_empty_v8.txt b/skorohodovsa/task_2/source/templates/30x30_empty_v8.txt new file mode 100644 index 0000000..2828878 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/30x30_empty_v8.txt @@ -0,0 +1,30 @@ +############################## +#S # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# E# +############################## \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/30x30_empty_v9.txt b/skorohodovsa/task_2/source/templates/30x30_empty_v9.txt new file mode 100644 index 0000000..2828878 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/30x30_empty_v9.txt @@ -0,0 +1,30 @@ +############################## +#S # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# E# +############################## \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/50x50_deadends_v1.txt b/skorohodovsa/task_2/source/templates/50x50_deadends_v1.txt new file mode 100644 index 0000000..5c91bce --- /dev/null +++ b/skorohodovsa/task_2/source/templates/50x50_deadends_v1.txt @@ -0,0 +1,49 @@ +################################################# +#S # # # # # # # # +##### # ### # ### # # # # ### ##### # # ####### # +# # # # # # # # # # # +### ##### ### # ################# ############# # +# # # # # # # # # +# ##### # # # ########### ##### # ##### # # ##### +# # # # # # # # # # # # +# ### ### # ### ########### ######### ### ### # # +# # # # # # # # # # # # +# # ####### ### # ##### ##### # # ##### # # ### # +# # # # # # # # # # # # +##### # ##### ### ### ######### # ### ### ##### # +# # # # # # # # # # # +# ####### # # ##### ##### ### ### # ### ######### +# # # # # # # # # # # # # +# ####### # # # # # # # ############# # # ##### # +# # # # # # # # # # # # # +### # # ####### # # ### ### # # ####### ### # # # +# # # # # # # # # # # # # # # # +# ########### ### ### # # ##### ### # # ##### ### +# # # # # # # # # # # # +# # ##### # ####### # # ######### ######### ### # +# # # # # # # # # # # # +# ### # ##### ##### # # # # # # # # ######### # # +# # # # # # # # # # # # # # # +# # # ########### # ##### # ### # # # ######### # +# # # # # # # # # # # # # +# ##### # ### ### # # # # ########### # ### ##### +# # # # # # # # # # # # # # +# ### # # # ### # ######### # # ##### ### ### # # +# # # # # # # # # # # # # # +### # # ### # # ### # ### # ##### # ### ####### # +# # # # # # # # # # # # # # # # +# ####### ### # # # # # ####### # ### ####### # # +# # # # # # # # # # # # # # +##### # # ##### ### ### ### # ### # # # # # ### # +# # # # # # # # # # # # # # # +### # ### # # ### ### ####### # ##### # ##### # # +# # # # # # # # # # # # # # +# # ### # # ### # ####### ##### ### # # ### # # # +# # # # # # # # # # # # # # # # # +# ##### ### # ##### # # ##### ### ### ### ### # # +# # # # # # # # # # # # # # # +### # ### ### # # # # ### # ### ### ### ### ### # +# # # # # # # # # # # # # # # # # +# ######### # # # # # # ### # ### ### # # # ##### +# # # # # # E# +################################################# \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/50x50_deadends_v10.txt b/skorohodovsa/task_2/source/templates/50x50_deadends_v10.txt new file mode 100644 index 0000000..72fd3d8 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/50x50_deadends_v10.txt @@ -0,0 +1,49 @@ +################################################# +#S# # # # # +# # ##### # # ### ########### ####### ### ####### +# # # # # # # # # # # # +##### # # ### # ### ### # ##### ####### # # ### # +# # # # # # # # # # # # # +# ### # ### # ####### # # ####### ######### # ### +# # # # # # # # # # # # +# # ### # ### # # ####### # # # ############### # +# # # # # # # # # # # # # # +# ### ### ##### # # # ########### ####### # # # # +# # # # # # # # # # # # +### ### # # ##### ######### ### # # ### ### ### # +# # # # # # # # # # # # # # # +# ### # # # # ##### ##### # # ### # # ### ##### # +# # # # # # # # # # # # # # # # # +# ### # ##### ##### ### ##### # # ### # ### # ### +# # # # # # # # # # # # +# # ##### ### # ##### ####### # ### ######### # # +# # # # # # # # # # # # # +# ### # ### # ##### # # # ##### # ### ##### ### # +# # # # # # # # # # # # # # +####### # # ######### ####### # ### ### ##### # # +# # # # # # # # # # # # +### ### # ### # ### # # ### ############# # ### # +# # # # # # # # # # # # # # +# ### ### # # # # # ##### ##### # ##### # # ### # +# # # # # # # # # # # # # # +# # # # # ### ##### # # ### ######### # # ##### # +# # # # # # # # # # # # # # +# # ### ### ### ##### ### ### # ##### # ### ### # +# # # # # # # # # # # # # # # # # +# ### # # ### # # # # # ####### # # ##### ### # # +# # # # # # # # # # # # # # # +# # ##### ### # # ##### ##### # # ##### # # ### # +# # # # # # # # # # # # # # # # +# ##### ### ##### # # ### # ### ##### ##### # # # +# # # # # # # # # # # # +####### # ######### # # ####### # ### # ### ##### +# # # # # # # # # # # # +### ##### ####### ####### ##### # # ### # ##### # +# # # # # # # # # # # # +# ### ##### ### # # # ##### # # # # ########### # +# # # # # # # # # # # +# # ### # ##### ####### ############# # ####### # +# # # # # # # # # # # # +# ### # ##### ### ### ##### # # # ####### # # ### +# # # # # # # E# +################################################# \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/50x50_deadends_v2.txt b/skorohodovsa/task_2/source/templates/50x50_deadends_v2.txt new file mode 100644 index 0000000..167abe4 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/50x50_deadends_v2.txt @@ -0,0 +1,49 @@ +################################################# +#S # # # # # # # # # +### ### ##### ### # # # # # # # ### # ### ### # # +# # # # # # # # # # # # # # # # # # # +# # # ### # ### # # # # # # ##### ##### ### # # # +# # # # # # # # # # # # # # # +# ##### ### ####### # # ####### ### ##### # # # # +# # # # # # # # # # # +# # ####### # ####### ### ### ### ### ######### # +# # # # # # # # # # # # # # +# # # ### # # ##### # # # ##### ### ### # ### ### +# # # # # # # # # # # # # +####### ######### # ####### # ### # ########### # +# # # # # # # # # # +# ### # # ##### # ########### # # ####### # ### # +# # # # # # # # # # # # # # +### ####### # # ### # ### # ### ##### ####### # # +# # # # # # # # # # # # +# ### # ##### ### # ### ### ####### ### ### # # # +# # # # # # # # # # # # +# # ########### # # # ### ### ### ############# # +# # # # # # # # # # # # # # +# ### # ######### # # # ### ### ### # # # ### # # +# # # # # # # # # # # # # # # # +####### # ####### # # ##### # ### ##### # # # ### +# # # # # # # # # +# ####### ######### ### ##### # ### ########### # +# # # # # # # # # # # # # +# ### # # ### # # ### ##### ##### ### ####### # # +# # # # # # # # # # # # # +# # # ##### ##### # # # # ####### # ### ####### # +# # # # # # # # # # # # # # # # +### ### ##### # # # # # # ### # ##### # ### ### # +# # # # # # # # # # # # # # # +# ### ######### ### # # ### # # ##### ### ##### # +# # # # # # # # # # # +# # ########### # # ##### ### ### ##### ### # ### +# # # # # # # # # # # # # +# ######### # ##### # ##### ### # # # ##### ### # +# # # # # # # # # # # +# # ### ### ########### ######### # ######### ### +# # # # # # # # # # # # +# ### # # # # ##### ####### # ####### # # # ### # +# # # # # # # # # # # # # # # +### # # ######### ### # # # # # ### ##### ### # # +# # # # # # # # # # # # # # # +# ### ### # ### # # ##### # ##### ##### ### ### # +# # # # # # E# +################################################# \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/50x50_deadends_v3.txt b/skorohodovsa/task_2/source/templates/50x50_deadends_v3.txt new file mode 100644 index 0000000..343eefa --- /dev/null +++ b/skorohodovsa/task_2/source/templates/50x50_deadends_v3.txt @@ -0,0 +1,49 @@ +################################################# +#S# # # # # # +# ##### # # # ####### # ##### ##### ### ##### # # +# # # # # # # # # # # # # +### # ### # ##### ##### # # ######### ### # ### # +# # # # # # # # # # # # # +# ##### ##### # # # ######### ##### # ##### # ### +# # # # # # # # # # # # # # # # +# # # ### # # # ##### # # # # # ##### ### # ### # +# # # # # # # # # # # # # # +# ##### # # ### # # ########### # ####### ### ### +# # # # # # # # # # # # +# # ########### ### # ######### # # ########### # +# # # # # # # # # # # # +# ##### # # # ### ### ####### # ##### # ### # # # +# # # # # # # # # # # # # +##### ########### # ####### ##### # # ### # ##### +# # # # # # # # # # +### ### # ######### ############### # # ####### # +# # # # # # # # # # +# ######### ### ##### # ### ### # ### # # ##### # +# # # # # # # # # # # # +# ##### # # # ### ### ### # # ### ##### # ### ### +# # # # # # # # # # # # # # # +##### # ##### # ### ##### # # # ### ##### # ### # +# # # # # # # # # # # # # +# # # ### # ########### ### # ######### ##### # # +# # # # # # # # # # # # # # +# ### # # # # ####### # ### # # ######### ####### +# # # # # # # # # # # # # # +# # ##### ### ##### ##### ### ### # # # ### ### # +# # # # # # # # # # # # # # # # +# # # # # # ### # ### # ##### # # # # # # ### # # +# # # # # # # # # # # # # # # +##### ### ####### # ##### # ######### ####### # # +# # # # # # # # # # # +# ##### ### ### # ######### # # ####### # ##### # +# # # # # # # # # # # # +### # ##### # ##### ### ##### ##### # ##### ### # +# # # # # # # # # # # # # +# # ### # ### # ### ##### # ####### # # ### # ### +# # # # # # # # # # # # # # +# ### ##### ##### ### ##### # ######### # ##### # +# # # # # # # # # +# ##### ##### # ### ### ####### ################# +# # # # # # # # # # +##### ### ####### ### ####### ### # ##### ### # # +# # # # #E# +################################################# \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/50x50_deadends_v4.txt b/skorohodovsa/task_2/source/templates/50x50_deadends_v4.txt new file mode 100644 index 0000000..d3d86bc --- /dev/null +++ b/skorohodovsa/task_2/source/templates/50x50_deadends_v4.txt @@ -0,0 +1,49 @@ +################################################# +#S# # # # # # # +# ### # # ### ##### ##### ### ### # # # # ####### +# # # # # # # # # # # # # +####### ### ##### ### ##### # # # ### # ####### # +# # # # # # # # # # # # # +# # ##### ### # ### ### ### ### # # ### # ### # # +# # # # # # # # # # # # # # # # +# # # # ### # ### ### # ####### # ####### ##### # +# # # # # # # # # # # # # # +### # ####### # # # ### # ############# ### # # # +# # # # # # # # # # # # +# # ####### ### # ######### ### # ### ### ##### # +# # # # # # # # # # # # # # +# ##### # ### # # # # # ########### ### # # # ### +# # # # # # # # # # # # # # # +# ### ### # ##### # # # # # ##### ### # ####### # +# # # # # # # # # # # # # # +# # ### ####### ### ##### # # # # # ######### # # +# # # # # # # # # # # # # # +##### ### # ##### ######### # # ####### ### ### # +# # # # # # # # # # # # # +# ### # ### # # # # # # ##### ##### # ### ### # # +# # # # # # # # # # # # # # # # +# # ### # ##### # # # ##### ### ##### # # # ### # +# # # # # # # # # # # # # # # # # # +# # # # # # # ##### ### # ### # # # ##### # # ### +# # # # # # # # # # # # # # # # +# # # # ##### ### # # ### # ### # ##### ####### # +# # # # # # # # # # # # # # # +# # # ######### # ### # ### ##### # # # # ####### +# # # # # # # # # # # # # +# # ##### # # # ### ### ### ######### ##### # ### +# # # # # # # # # # # # # +# ######### # ### ### ### # ##### # ### ### ### # +# # # # # # # # # # # # # +# # # ####### # # # ######### # ##### ### ### # # +# # # # # # # # # # # # # # # # +### # ####### # # # # # # # ### # # ### # ### # # +# # # # # # # # # # # # # # # # # # +# ####### # ### # # # # ### # ### # # ### # ### # +# # # # # # # # # # # # # +# # ### ##### ####### ####### # # ####### # ### # +# # # # # # # # # # # # # +# ### ####### # # # ####### ### ### # # ##### ### +# # # # # # # # # # # # # # # # +# # # # # ##### ####### # ##### # # # ##### ### # +# # # # # # E# +################################################# \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/50x50_deadends_v5.txt b/skorohodovsa/task_2/source/templates/50x50_deadends_v5.txt new file mode 100644 index 0000000..3a8fffb --- /dev/null +++ b/skorohodovsa/task_2/source/templates/50x50_deadends_v5.txt @@ -0,0 +1,49 @@ +################################################# +#S# # # # # # # +# ### # # # # # # ### # ##### ####### ### # ### # +# # # # # # # # # # # # # # # +# # ####### # ######### # # ##### # ### ### # ### +# # # # # # # # # # # # # # +##### # # # # ##### # ### # ####### # # # ##### # +# # # # # # # # # # # # # # # # +# # ### # # # ### ####### # # # # ### ##### ##### +# # # # # # # # # # # +# ### ##### ####### # # ########### # ### ##### # +# # # # # # # # # # # # # +# # ### ##### ##### # ### ### ######### ##### ### +# # # # # # # # # # +# ####### ### ####### # ############# # ####### # +# # # # # # # # # # # +# # # # ### # ### # # ### # ############### # ### +# # # # # # # # # # # # # +# # # ### ##### ### ### # ### # ########### ### # +# # # # # # # # # # # # # # # # +####### ### # # # ### # ### # ### # # ### # # # # +# # # # # # # # # # # # # # # +### # ### # ####### # ### ##### # ##### ### # # # +# # # # # # # # # # # # # # +# # # ### ### ### # # ##### ##### # # ### ####### +# # # # # # # # # # # # # +# ##### ### ### ### ### # # # ######### ####### # +# # # # # # # # # # # # # +# # ##### # # ##### # ### ####### # # # # # ##### +# # # # # # # # # # # # # # +# ### ### # ##### ##### ### # ##### # ### ##### # +# # # # # # # # # # # # # # # +# ### # ##### ##### # # # # ### ####### # # # ### +# # # # # # # # # # # # # # +# # ########### # ### ### ####### ### # # # ### # +# # # # # # # # # # # # +# ##### ########### ### # ### ##### # # # ##### # +# # # # # # # # # # # # # +### # # # # ####### ##### # ####### ####### ##### +# # # # # # # # # # # +# ### # # # # ### ############### # ##### ##### # +# # # # # # # # # # # # +# # # ##### # # ######### # # ####### # ####### # +# # # # # # # # # # # # # # +# # # # # # # ##### # # ####### ### ####### ### # +# # # # # # # # # # # # # # # +# # # # # ##### # # # # ##### ### # # ### ####### +# # # # # # # # E# +################################################# \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/50x50_deadends_v6.txt b/skorohodovsa/task_2/source/templates/50x50_deadends_v6.txt new file mode 100644 index 0000000..97806a1 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/50x50_deadends_v6.txt @@ -0,0 +1,49 @@ +################################################# +#S # # # # # # # +### # ### ######### ####### ##### ### # # # # # # +# # # # # # # # # # # # # +# ##### # # ##### ##### # ### # # # ### ### ##### +# # # # # # # # # # # # +############# ####### ####### ####### # ##### # # +# # # # # # # # # # +### # # ### ### # # # # ####### ######### ##### # +# # # # # # # # # # # # # # +# ### # # ##### # ##### # ### ### # ### ### ### # +# # # # # # # # # # # # # # +# ##### # ######### # # ### # # ### # ### # # ### +# # # # # # # # # # # # # # # # # +# # # ### # # # ### ####### ### ### # ####### # # +# # # # # # # # # # # # # +# # ### ######### ### ### # # # # ##### ### ### # +# # # # # # # # # # # # # # # +### # ######### # # ### ### # # # # # ### # # ### +# # # # # # # # # # # # # # # # +# ##### # # # # # ### # # # ####### ### ####### # +# # # # # # # # # # # # # +# # ##### # ### ####### # ### ### ########### # # +# # # # # # # # # # # # # +# ### ### # # # # ### # ##### # ##### # ####### # +# # # # # # # # # # # # # # # # # +# ### # # # # # ### # ##### ####### # ### # # ### +# # # # # # # # # # # # # # +# # ### # # ####### ### # ####### # ####### ### # +# # # # # # # # # # # # # # +##### # # ##### # # # ####### # # # ### ### # # # +# # # # # # # # # # # # # # +# ### ### # # # ######### ### # ##### ### ####### +# # # # # # # # # # # +# # ### ### # ############# ####### ### ####### # +# # # # # # # # # # # +# ### ####### ##### # # ######### ### ##### # # # +# # # # # # # # # # # # # # +# # # # ### ##### # ### # ### # ### ### ######### +# # # # # # # # # # # # # +### # ### ### ### ### ####### # ##### ### # # # # +# # # # # # # # # # # # # # +##### ##### ####### # # # ##### # # ####### ### # +# # # # # # # # # # +# ##### ##### ### ##### ##### ####### # ##### ### +# # # # # # # # # # # # # # # +# ### ### ####### # # # # # ### # # ### # ### # # +# # # # # # # E# +################################################# \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/50x50_deadends_v7.txt b/skorohodovsa/task_2/source/templates/50x50_deadends_v7.txt new file mode 100644 index 0000000..cf354c0 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/50x50_deadends_v7.txt @@ -0,0 +1,49 @@ +################################################# +#S# # # # # # +# ##### # ##### # ### ####### # # ### # ##### ### +# # # # # # # # # # # # # # # +# # # ##### ### # # ### ### # ##### # ##### ### # +# # # # # # # # # # # # # # +##### # ##### ### ### ### # ### ######### # # # # +# # # # # # # # # # # # # +# ##### # ##### ######### # ##### # # # # ##### # +# # # # # # # # # # # +### # # ##### # ### ####### # ####### ########### +# # # # # # # # # # # +# ####### # ##### ####### # ### ### # # ####### # +# # # # # # # # # # # # # # +### # ######### ### # # ### # ### # ### # ##### # +# # # # # # # # # # # # # # +# ##### # # # ### # # ####### ### ####### # # # # +# # # # # # # # # # # # # # +##### ##### # # ####### # ##### ##### # ### # ### +# # # # # # # # # # # # # # # +# ##### # ### ### # # # # # ### # # # ### # ### # +# # # # # # # # # # # # # # # # # +# # # ####### ### # ##### ### # # ##### ### # # # +# # # # # # # # # # # +# ### ##### ### ### ########### ### # ### ### # # +# # # # # # # # # # # # # # +### ### # ### ### ##### # # ##### # ### ### # # # +# # # # # # # # # # # # # # # # # +# # # # ### ### ### # # ##### ##### ### ### ### # +# # # # # # # # # # # # # # +# ### ####### ####### ### # ### # ### ### ### # # +# # # # # # # # # # +####### # ##### # # ####### ####### ### # # ### # +# # # # # # # # # # # # # # # +# # # ##### # # ### # # ##### # # ### ### ### ### +# # # # # # # # # # # # # +# ####### ### ### ### ### # ########### ### ### # +# # # # # # # # # # # # # # +# ### # ##### # ### ### # ### ####### # # # # ### +# # # # # # # # # # # # # +########### # # # ### # ####### # # # # ####### # +# # # # # # # # # # # # # +# ### ### # ##### # # ##### ##### # # ### ##### # +# # # # # # # # # # # # # # +### # ####### # ### ### # ################# ### # +# # # # # # # # # # # +# ### # # ####### # # ### # ##### # ### ##### ### +# # # # # # # E# +################################################# \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/50x50_deadends_v8.txt b/skorohodovsa/task_2/source/templates/50x50_deadends_v8.txt new file mode 100644 index 0000000..dc4c4d8 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/50x50_deadends_v8.txt @@ -0,0 +1,49 @@ +################################################# +#S# # # # # # +# # ####### # # ####### ### # # ##### ### # ##### +# # # # # # # # # # # # # +####### ############# # # ##### # # ### ####### # +# # # # # # # # # # +### # ### ##### ####### # # # # ######### ####### +# # # # # # # # # # # # +# ### # # # # # # # ############# ##### ##### # # +# # # # # # # # # # # # # # +### ##### # ##### ### ####### # ### # ### # ### # +# # # # # # # # # # # # # # +# ##### # ##### # # ### ### # # # ### # # ##### # +# # # # # # # # # # # # # # # # +# # # ##### # ##### # ### # ##### # ##### # ##### +# # # # # # # # # # # # # # +# # # # # ### # ##### # ######### # # ####### # # +# # # # # # # # # # # # # +# # ############# # ##### # ### # ##### ### ### # +# # # # # # # # # # # # +# ##### # ##### # ########### ####### # # ### ### +# # # # # # # # # # # +# ####### # # ############# # ### ######### # # # +# # # # # # # # # # # +##### # ### ### ############# # ### # # # ##### # +# # # # # # # # # # # # # +# ##### # # # ### ##### ### ### ####### # # ##### +# # # # # # # # # # # # # # +### # ### ### # ### # ### # # # # ########### # # +# # # # # # # # # # # # +# ##### ######### ########### ##### ##### # ### # +# # # # # # # # # # # +### ### # # ######### ### # ### ##### ##### # # # +# # # # # # # # # # # # +# ### ########### # ##### ######### # # ####### # +# # # # # # # # # # +# ##### ### # # ### # ### # ######### ##### ### # +# # # # # # # # # # # # +######### ########### # ##### # # ##### ##### ### +# # # # # # # # # # # +### # ##### # # ####### ### ##### # ##### # ### # +# # # # # # # # # # # # # +# # ### # # # # # ### ############### # # ####### +# # # # # # # # # # # # # # # +# ### ##### # # # # ####### # ### # # ### ##### # +# # # # # # # # # # # # # +# ##### ##### ##### # ### # ### ########### # # # +# # # # # E# +################################################# \ No newline at end of file diff --git a/skorohodovsa/task_2/source/templates/50x50_deadends_v9.txt b/skorohodovsa/task_2/source/templates/50x50_deadends_v9.txt new file mode 100644 index 0000000..82a5537 --- /dev/null +++ b/skorohodovsa/task_2/source/templates/50x50_deadends_v9.txt @@ -0,0 +1,49 @@ +################################################# +#S # # # # # # # +##### # # ##### # # # # # # ### # # ##### ##### # +# # # # # # # # # # # # # # # +# ####### # # # # # # ##### # ####### ######### # +# # # # # # # # # # # # # # +########### ### # ### # # ######### ### # # ##### +# # # # # # # # # # # # +# ### # # # ##### # ### # # ######### ### ##### # +# # # # # # # # # # # # # # # +# # ##### # # ### ##### # # # ### # # # ##### # # +# # # # # # # # # # # # # # +# # ####### ### # # ##### # ### ####### ####### # +# # # # # # # # # # # # # +# ####### ### # ####### # ### ##### ##### # # # # +# # # # # # # # # # # # # # +# # # # # ####### ### # # # ######### # # # # # # +# # # # # # # # # # # # # # # # +# ##### ########### ### # # # # # # ### ##### # # +# # # # # # # # # # # # # +##### # # ##### ##### ### ##### ##### ##### # ### +# # # # # # # # # # # +# ### ##### ##### # # # ######### ### # ####### # +# # # # # # # # # # # # # +# # # # ##### ### ##### # # ####### ### # ####### +# # # # # # # # # # # # # # +# # # ##### ######### ### ### # # # # ### ##### # +# # # # # # # # # # # # +# ### ############# ### # # # # ####### ####### # +# # # # # # # # # # # # # +### ### ### ### # # # ### ####### ### # # ### # # +# # # # # # # # # # # # # # +# ### ### ### ####### # ### # # ### ### ### ##### +# # # # # # # # # # # # # +# ######### ##### # ### # ### ### ####### # ### # +# # # # # # # # # # # # # +# ### # ### # # # # ### ### ### # # # ########### +# # # # # # # # # # # # # # +### # # # # ### # ########### # ######### ##### # +# # # # # # # # # # +# ### # ####### ####################### # # # # # +# # # # # # # # # # +# ####### ### # # ### ######### # ######### # ### +# # # # # # # # # # # # # +# # ####### ##### # ### ### ####### # # ####### # +# # # # # # # # # # # # # # +# ####### ##### # ### # # ### # # # ####### # # # +# # # # # # E# +################################################# \ No newline at end of file From 86b31473f3a5d19c504ce37ee9a398e9d4226fbb Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Sun, 24 May 2026 17:58:56 +0300 Subject: [PATCH 24/28] =?UTF-8?q?[2]=20=D0=98=D0=B7=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=D0=BB=D0=BE=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B9?= =?UTF-8?q?=20`=5Ffind=5Fstart()`=20=D0=B8=20`=5Ffind=5Fexit()`=20=D0=B8?= =?UTF-8?q?=D0=B7=20`PathFindingStrategy`=20=D0=B2=20=D1=84=D1=83=D0=BD?= =?UTF-8?q?=D0=BA=D1=86=D0=B8=D0=BE=D0=BD=D0=B0=D0=BB=20=D0=BA=D0=BB=D0=B0?= =?UTF-8?q?=D1=81=D1=81=D0=B0=20`Maze`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_2/source/models/base.py | 16 ++++++++++++++++ .../task_2/source/strategy/algorithms.py | 18 ------------------ skorohodovsa/task_2/source/strategy/astar.py | 4 ++-- skorohodovsa/task_2/source/strategy/bfs.py | 4 ++-- skorohodovsa/task_2/source/strategy/dfs.py | 4 ++-- 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/skorohodovsa/task_2/source/models/base.py b/skorohodovsa/task_2/source/models/base.py index 632d777..52c874a 100644 --- a/skorohodovsa/task_2/source/models/base.py +++ b/skorohodovsa/task_2/source/models/base.py @@ -183,6 +183,22 @@ class Maze: neighbors.append(cell) return neighbors + + @property + def start(self) -> Optional[Cell]: + for y in range(self._height): + for x in range(self._width): + if self[y, x].is_start: + return self[y, x] + return None + + @property + def exit(self) -> Optional[Cell]: + for y in range(self._height): + for x in range(self._width): + if self[y, x].is_exit: + return self[y, x] + return None @property def shape(self) -> tuple[int, int]: diff --git a/skorohodovsa/task_2/source/strategy/algorithms.py b/skorohodovsa/task_2/source/strategy/algorithms.py index 0c17a8d..c6fd162 100644 --- a/skorohodovsa/task_2/source/strategy/algorithms.py +++ b/skorohodovsa/task_2/source/strategy/algorithms.py @@ -23,24 +23,6 @@ class PathFindingStrategy(ABC): Пустой список, если путь не найден. """ - def _find_start(self, maze: Maze) -> Optional[Cell]: - row, col = maze.shape - - for y in range(row): - for x in range(col): - if maze[y, x].is_start: - return maze[y, x] - return None - - def _find_exit(self, maze: Maze) -> Optional[Cell]: - row, col = maze.shape - - for y in range(row): - for x in range(col): - if maze[y, x].is_exit: - return maze[y, x] - return None - def _reconstruct_path( self, came_from: dict[Cell, Optional[Cell]], end: Cell ) -> list[Cell]: diff --git a/skorohodovsa/task_2/source/strategy/astar.py b/skorohodovsa/task_2/source/strategy/astar.py index ba07fce..37f76b0 100644 --- a/skorohodovsa/task_2/source/strategy/astar.py +++ b/skorohodovsa/task_2/source/strategy/astar.py @@ -15,9 +15,9 @@ class AStarStrategy(PathFindingStrategy): def find_path(self, maze: Maze, start: Optional[Cell] = None, exit: Optional[Cell] = None) -> list[Cell]: if start is None: - start = self._find_start(maze) + start = maze.start if exit is None: - exit = self._find_exit(maze) + exit = self.exit g_score: dict[Cell, int] = {start: 0} came_from: dict[Cell, Optional[Cell]] = {start: None} diff --git a/skorohodovsa/task_2/source/strategy/bfs.py b/skorohodovsa/task_2/source/strategy/bfs.py index 39e6595..fb6317f 100644 --- a/skorohodovsa/task_2/source/strategy/bfs.py +++ b/skorohodovsa/task_2/source/strategy/bfs.py @@ -16,9 +16,9 @@ class BFSStrategy(PathFindingStrategy): self, maze: Maze, start: Optional[Cell] = None, exit: Optional[Cell] = None ) -> list[Cell]: if start is None: - start = self._find_start(maze) + start = maze.start if exit is None: - exit = self._find_exit(maze) + exit = maze.exit came_from: dict[Cell, Optional[Cell]] = {start: None} queue: deque[Cell] = deque([start]) diff --git a/skorohodovsa/task_2/source/strategy/dfs.py b/skorohodovsa/task_2/source/strategy/dfs.py index c24a1e2..11cde79 100644 --- a/skorohodovsa/task_2/source/strategy/dfs.py +++ b/skorohodovsa/task_2/source/strategy/dfs.py @@ -14,9 +14,9 @@ class DFSStrategy(PathFindingStrategy): self, maze: Maze, start: Optional[Cell] = None, exit: Optional[Cell] = None ) -> list[Cell]: if start is None: - start = self._find_start(maze) + start = maze.start if exit is None: - exit = self._find_exit(maze) + exit = maze.exit came_from: dict[Cell, Optional[Cell]] = {start: None} stack: list[Cell] = [start] From 27c2f99467fbe7533834f0afe2f7a0a6b70acb00 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Sun, 24 May 2026 18:00:14 +0300 Subject: [PATCH 25/28] =?UTF-8?q?[2]=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=8D=D1=82=D0=B0=D0=BF=D0=B0?= =?UTF-8?q?=205?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_2/source/view/__init__.py | 13 ++ skorohodovsa/task_2/source/view/command.py | 153 ++++++++++++++++++++ skorohodovsa/task_2/source/view/observer.py | 111 ++++++++++++++ skorohodovsa/task_2/test/play.py | 57 ++++++++ 4 files changed, 334 insertions(+) create mode 100644 skorohodovsa/task_2/source/view/__init__.py create mode 100644 skorohodovsa/task_2/source/view/command.py create mode 100644 skorohodovsa/task_2/source/view/observer.py create mode 100644 skorohodovsa/task_2/test/play.py diff --git a/skorohodovsa/task_2/source/view/__init__.py b/skorohodovsa/task_2/source/view/__init__.py new file mode 100644 index 0000000..2865973 --- /dev/null +++ b/skorohodovsa/task_2/source/view/__init__.py @@ -0,0 +1,13 @@ +from source.view.observer import Observer, ConsoleView, Event +from source.view.command import Player, Command, MoveCommand, CommandHistory, DIRECTIONS + +__all__ = [ + "Observer", + "ConsoleView", + "Event", + "Player", + "Command", + "MoveCommand", + "CommandHistory", + "DIRECTIONS", +] \ No newline at end of file diff --git a/skorohodovsa/task_2/source/view/command.py b/skorohodovsa/task_2/source/view/command.py new file mode 100644 index 0000000..9ae96e5 --- /dev/null +++ b/skorohodovsa/task_2/source/view/command.py @@ -0,0 +1,153 @@ +from abc import ABC, abstractmethod +from typing import Optional + +from source.models.base import Maze, Cell + + +# ---------------------------------------------------------------------------- # +# Игрок # +# ---------------------------------------------------------------------------- # + +class Player: + """Хранит текущее положение игрока в лабиринте. + + Attributes: + cell: Текущая клетка игрока. + """ + + def __init__(self, cell: Cell) -> None: + """Инициализирует игрока на заданной клетке. + + Args: + cell: Начальная клетка игрока. + """ + self.cell = cell + + def __repr__(self) -> str: + return f"Player(x={self.cell.x}, y={self.cell.y})" + + +# ---------------------------------------------------------------------------- # +# Интерфейс команды # +# ---------------------------------------------------------------------------- # + +class Command(ABC): + """Интерфейс команды с поддержкой отмены.""" + + @abstractmethod + def execute(self) -> bool: + """Выполняет команду. + + Returns: + True если команда выполнена успешно, False иначе. + """ + + @abstractmethod + def undo(self) -> None: + """Отменяет команду, восстанавливая предыдущее состояние.""" + + +# ---------------------------------------------------------------------------- # +# Команда перемещения # +# ---------------------------------------------------------------------------- # + +DIRECTIONS = { + "w": (0, -1), + "s": (0, 1), + "a": (-1, 0), + "d": (1, 0), +} + + +class MoveCommand(Command): + """Перемещает игрока в заданном направлении. + + Сохраняет предыдущую клетку для возможности отмены хода. + """ + + def __init__(self, player: Player, direction: str, maze: Maze) -> None: + """Инициализирует команду перемещения. + + Args: + player: Объект игрока. + direction: Направление ('w', 'a', 's', 'd'). + maze: Объект лабиринта для проверки проходимости. + + Raises: + ValueError: Если направление не распознано. + """ + if direction not in DIRECTIONS: + raise ValueError(f"Неизвестное направление '{direction}'. Используй: w/a/s/d") + + self._player = player + self._direction = direction + self._maze = maze + self._prev_cell: Optional[Cell] = None + + def execute(self) -> bool: + """Перемещает игрока если целевая клетка проходима. + + Returns: + True если перемещение выполнено, False если клетка непроходима. + """ + dx, dy = DIRECTIONS[self._direction] + target = self._maze.get_cell( + self._player.cell.x + dx, + self._player.cell.y + dy, + ) + + if target is None or not target.is_possible(): + return False + + self._prev_cell = self._player.cell + self._player.cell = target + return True + + def undo(self) -> None: + """Возвращает игрока на предыдущую клетку.""" + if self._prev_cell is not None: + self._player.cell = self._prev_cell + + +# ---------------------------------------------------------------------------- # +# История команд # +# ---------------------------------------------------------------------------- # + +class CommandHistory: + """Хранит историю выполненных команд и позволяет отменять их. + + Example: + history = CommandHistory() + cmd = MoveCommand(player, 'w', maze) + if cmd.execute(): + history.push(cmd) + + history.undo() # отменяет последний успешный ход + """ + + def __init__(self) -> None: + self._history: list[Command] = [] + + def push(self, command: Command) -> None: + """Добавляет выполненную команду в историю. + + Args: + command: Успешно выполненная команда. + """ + self._history.append(command) + + def undo(self) -> bool: + """Отменяет последнюю команду из истории. + + Returns: + True если отмена выполнена, False если история пуста. + """ + if not self._history: + print("Нечего отменять.") + return False + self._history.pop().undo() + return True + + def clear(self) -> None: + """Очищает историю команд.""" + self._history.clear() \ No newline at end of file diff --git a/skorohodovsa/task_2/source/view/observer.py b/skorohodovsa/task_2/source/view/observer.py new file mode 100644 index 0000000..5c51210 --- /dev/null +++ b/skorohodovsa/task_2/source/view/observer.py @@ -0,0 +1,111 @@ +from abc import ABC, abstractmethod +from dataclasses import dataclass +from typing import Optional + +from source.models.base import Maze, Cell +from source.settings import cell_mapping + + +# ---------------------------------------------------------------------------- # +# События # +# ---------------------------------------------------------------------------- # + +@dataclass +class Event: + """Событие, передаваемое наблюдателям. + + Attributes: + type: Тип события ('maze_loaded', 'path_found', 'move', 'no_path'). + payload: Дополнительные данные события. + """ + type: str + payload: dict = None + + +# ---------------------------------------------------------------------------- # +# Интерфейс наблюдателя # +# ---------------------------------------------------------------------------- # + +class Observer(ABC): + """Интерфейс наблюдателя за событиями лабиринта.""" + + @abstractmethod + def update(self, event: Event) -> None: + """Обрабатывает входящее событие. + + Args: + event: Объект события с типом и данными. + """ + + +# --------------------------------------------------------------------------- +# Консольный наблюдатель +# --------------------------------------------------------------------------- + +class ConsoleView(Observer): + """Отображает состояние лабиринта и события в консоли.""" + + # Символ игрока на карте + PLAYER_SYMBOL = "P" + PATH_SYMBOL = "·" + + def update(self, event: Event) -> None: + """Реагирует на события и выводит информацию в консоль. + + Args: + event: Объект события. + """ + match event.type: + case "maze_loaded": + print("Лабиринт загружен.") + self.render(event.payload["maze"]) + case "path_found": + print(f"Путь найден! Длина: {event.payload['length']} шагов.") + self.render( + event.payload["maze"], + path=event.payload["path"], + ) + case "no_path": + print("Путь не найден.") + case "move": + print(f"Ход: {event.payload['direction']}") + self.render( + event.payload["maze"], + player=event.payload["player_cell"], + path=event.payload.get("path"), + ) + case _: + print(f"[событие] {event.type}") + + def render( + self, + maze: Maze, + player: Optional[Cell] = None, + path: Optional[list[Cell]] = None, + ) -> None: + """Рисует лабиринт в консоли. + + Путь отмечается символом '·', позиция игрока — 'P'. + + Args: + maze: Объект лабиринта. + player: Текущая клетка игрока (опционально). + path: Список клеток найденного пути (опционально). + """ + path_set = set(path) if path else set() + rows, cols = maze.shape + + print("+" + "─" * cols + "+") + for y in range(rows): + row_str = "|" + for x in range(cols): + cell = maze[y, x] + if player and cell is player: + row_str += self.PLAYER_SYMBOL + elif cell in path_set: + row_str += self.PATH_SYMBOL + else: + row_str += str(cell) + row_str += "|" + print(row_str) + print("+" + "─" * cols + "+") \ No newline at end of file diff --git a/skorohodovsa/task_2/test/play.py b/skorohodovsa/task_2/test/play.py new file mode 100644 index 0000000..d6cc572 --- /dev/null +++ b/skorohodovsa/task_2/test/play.py @@ -0,0 +1,57 @@ +from source.build.builder import TextFileBuilder +from source.models.base import Maze +from source.view.observer import ConsoleView, Event +from source.view.command import Player, MoveCommand, CommandHistory + + +maze: Maze = TextFileBuilder().build_from_file("source/templates/10x10_path_v1.txt") + +rows, cols = maze.shape + +start = None +for y in range(rows): + for x in range(cols): + if maze[y, x].is_start: + start = maze[y, x] + break + +if start is None: + print("Стартовая клетка не найдена!") + exit() + +player = Player(start) +history = CommandHistory() +view = ConsoleView() + +view.update(Event("maze_loaded", {"maze": maze})) +print("Управление: w/a/s/d — движение, z — отмена, q — выход\n") + +while True: + key = input(">>> ").strip().lower() + + if key == 'q': + print("Выход.") + break + + elif key == 'z': + if history.undo(): + print("Ход отменён.") + view.render(maze, player=player.cell) + + elif key in ('w', 'a', 's', 'd'): + cmd = MoveCommand(player, key, maze) + if cmd.execute(): + history.push(cmd) + view.update(Event("move", { + "maze": maze, + "player_cell": player.cell, + "direction": key, + })) + if player.cell.is_exit: + print("Выход найден! Победа!") + break + else: + print("Туда нельзя — стена или граница.") + + else: + print("Неизвестная команда. Используй: w/a/s/d, z, q") \ No newline at end of file From 1d4bd0bf7373bcb2462a1caba651c4b5cb9252d6 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Mon, 25 May 2026 10:23:00 +0300 Subject: [PATCH 26/28] [2] to merge --- skorohodovsa/task_2/.gitignore | 3 +- skorohodovsa/task_2/docs.md | 1185 +++++++++++++++++ .../task_2/docs/_build/markdown/api.md | 470 +++++++ .../task_2/docs/_build/markdown/stage1.md | 91 ++ .../task_2/docs/_build/markdown/stage2.md | 60 + .../task_2/docs/_build/markdown/stage3.md | 90 ++ .../task_2/docs/_build/markdown/stage4.md | 44 + .../task_2/docs/_build/markdown/stage5.md | 84 ++ .../task_2/docs/_build/markdown/stage6.md | 61 + .../task_2/docs/_build/markdown/stage7.md | 33 + .../task_2/docs/_build/markdown/task.md | 103 ++ skorohodovsa/task_2/docs/source/api.md | 44 +- skorohodovsa/task_2/docs/source/conf.py | 1 + skorohodovsa/task_2/docs/source/index.md | 13 +- .../task_2/docs/source/naming_maze.md | 95 -- skorohodovsa/task_2/docs/source/stage1.md | 91 ++ skorohodovsa/task_2/docs/source/stage2.md | 60 + skorohodovsa/task_2/docs/source/stage3.md | 90 ++ skorohodovsa/task_2/docs/source/stage4.md | 44 + skorohodovsa/task_2/docs/source/stage5.md | 84 ++ skorohodovsa/task_2/docs/source/stage6.md | 63 + skorohodovsa/task_2/docs/source/stage7.md | 81 ++ skorohodovsa/task_2/docs/source/task.md | 183 +++ skorohodovsa/task_2/practice/main.ipynb | 937 +++++++++++++ skorohodovsa/task_2/practice/results.csv | 121 ++ skorohodovsa/task_2/practice/results.png | Bin 0 -> 223043 bytes skorohodovsa/task_2/requirements.txt | 5 +- skorohodovsa/task_2/source/models/base.py | 4 +- .../task_2/source/strategy/__init__.py | 2 +- .../task_2/source/strategy/algorithms.py | 28 +- skorohodovsa/task_2/source/strategy/astar.py | 16 +- skorohodovsa/task_2/source/strategy/bfs.py | 7 +- skorohodovsa/task_2/source/strategy/dfs.py | 13 +- skorohodovsa/task_2/source/strategy/solver.py | 3 +- skorohodovsa/task_2/source/view/__init__.py | 2 +- skorohodovsa/task_2/source/view/command.py | 19 +- skorohodovsa/task_2/source/view/observer.py | 8 +- skorohodovsa/task_2/test/map/__init__.py | 0 skorohodovsa/task_2/test/map/test_cell.py | 111 -- skorohodovsa/task_2/test/play.py | 27 +- .../test/{map/test_maze.py => test_base.py} | 126 +- skorohodovsa/task_2/test/test_strategies.py | 162 +++ .../{__init__.py => test_text_builder.py} | 0 43 files changed, 4390 insertions(+), 274 deletions(-) create mode 100644 skorohodovsa/task_2/docs.md create mode 100644 skorohodovsa/task_2/docs/_build/markdown/api.md create mode 100644 skorohodovsa/task_2/docs/_build/markdown/stage1.md create mode 100644 skorohodovsa/task_2/docs/_build/markdown/stage2.md create mode 100644 skorohodovsa/task_2/docs/_build/markdown/stage3.md create mode 100644 skorohodovsa/task_2/docs/_build/markdown/stage4.md create mode 100644 skorohodovsa/task_2/docs/_build/markdown/stage5.md create mode 100644 skorohodovsa/task_2/docs/_build/markdown/stage6.md create mode 100644 skorohodovsa/task_2/docs/_build/markdown/stage7.md create mode 100644 skorohodovsa/task_2/docs/_build/markdown/task.md delete mode 100644 skorohodovsa/task_2/docs/source/naming_maze.md create mode 100644 skorohodovsa/task_2/docs/source/stage1.md create mode 100644 skorohodovsa/task_2/docs/source/stage2.md create mode 100644 skorohodovsa/task_2/docs/source/stage3.md create mode 100644 skorohodovsa/task_2/docs/source/stage4.md create mode 100644 skorohodovsa/task_2/docs/source/stage5.md create mode 100644 skorohodovsa/task_2/docs/source/stage6.md create mode 100644 skorohodovsa/task_2/docs/source/stage7.md create mode 100644 skorohodovsa/task_2/docs/source/task.md create mode 100644 skorohodovsa/task_2/practice/main.ipynb create mode 100644 skorohodovsa/task_2/practice/results.csv create mode 100644 skorohodovsa/task_2/practice/results.png delete mode 100644 skorohodovsa/task_2/test/map/__init__.py delete mode 100644 skorohodovsa/task_2/test/map/test_cell.py rename skorohodovsa/task_2/test/{map/test_maze.py => test_base.py} (54%) create mode 100644 skorohodovsa/task_2/test/test_strategies.py rename skorohodovsa/task_2/test/{__init__.py => test_text_builder.py} (100%) diff --git a/skorohodovsa/task_2/.gitignore b/skorohodovsa/task_2/.gitignore index 369c288..deb7a34 100644 --- a/skorohodovsa/task_2/.gitignore +++ b/skorohodovsa/task_2/.gitignore @@ -14,7 +14,7 @@ __pycache__/ # Сборка документации Sphinx - ЭТО ВАЖНО! docs/build/ -docs/source/_build/ +docs/_build/ # Системные файлы .DS_Store @@ -32,5 +32,4 @@ Thumbs.db .ruff_cache/ -/.idea pupu.py \ No newline at end of file diff --git a/skorohodovsa/task_2/docs.md b/skorohodovsa/task_2/docs.md new file mode 100644 index 0000000..d0eec40 --- /dev/null +++ b/skorohodovsa/task_2/docs.md @@ -0,0 +1,1185 @@ +`файл является компиляцией документации sphinx в папке docs` +# Лабораторная работа «Поиск выхода из лабиринта» + +* [Задание](task.md) + * [Цель работы](task.md#id2) + * [Общая схема приложения (пример)](task.md#id3) + * [Выполнение](task.md#id4) + * [Советы](task.md#id8) +* [Этап 1. Модель лабиринта](stage1.md) + * [Класс `Cell`](stage1.md#cell) + * [Класс `Maze`](stage1.md#maze) +* [Этап 2. Загрузка лабиринта из файла](stage2.md) + * [Паттерн Builder](stage2.md#builder) + * [Класс `MazeBuilder`](stage2.md#mazebuilder) + * [Класс `TextFileBuilder`](stage2.md#textfilebuilder) + * [Использование](stage2.md#id2) + * [Известная ошибка](stage2.md#id3) +* [Этап 3. Стратегии поиска пути](stage3.md) + * [Паттерн Strategy](stage3.md#strategy) + * [Структура пакета](stage3.md#id2) + * [Класс `PathFindingStrategy`](stage3.md#pathfindingstrategy) + * [Алгоритмы](stage3.md#id3) +* [Этап 4. Класс-оркестратор MazeSolver](stage4.md) + * [Роль в архитектуре](stage4.md#id1) + * [Класс `SearchStats`](stage4.md#searchstats) + * [Класс `MazeSolver`](stage4.md#id3) +* [Этап 5. Визуализация и пошаговое управление](stage5.md) + * [5.1. Паттерн Observer](stage5.md#observer) + * [5.2. Паттерн Command](stage5.md#command) +* [Этап 6. Экспериментальная часть](stage6.md) + * [Подготовка](stage6.md#id2) + * [Замеры](stage6.md#id3) + * [Результаты](stage6.md#id4) + * [Выводы](stage6.md#id8) + * [Визуализация](stage6.md#id9) +* [Этап 7. Отчёт](stage7.md) + * [Описание задачи](stage7.md#id2) + * [Диаграмма классов](stage7.md#id3) + * [Результаты экспериментов](stage7.md#id4) + * [Выводы](stage7.md#id5) +* [API Reference](api.md) + * [Базовые модели](api.md#module-source.models.base) + * [Загрузка лабиринта](api.md#module-source.build.builder) + * [Стратегии поиска пути](api.md#module-source.strategy.algorithms) + * [Оркестратор](api.md#module-source.strategy.solver) + * [Визуализация](api.md#module-source.view.observer) + * [Управление игроком](api.md#module-source.view.command) +# Этап 2. Загрузка лабиринта из файла + +Во втором этапе разработки необходимо реализовать загрузку лабиринта из текстового файла, где: `#` – стена, ` ` – проход, `S` – старт, `E` – выход. + +## Систематизация файлов + +Для удобного хранения лабиринтов было решено сделать систему наименования текстовых файлов в папке `source/templates`. + +Общая структура: + +```default +{размер}_{свойство 1}-{свойство 2}-{свойство n}_{версия}.txt +``` + +### Размер + +Формат: `{ширина}x{высота}` + +| Пример | Значение | +|-----------|----------------| +| `10x10` | 10×10 клеток | +| `50x50` | 50×50 клеток | +| `100x100` | 100×100 клеток | +| `30x30` | 30×30 клеток | +| `20x20` | 20×20 клеток | + +### Свойства + +| Свойство | Код | Описание | +|--------------|-------------|----------------------------------------------------------------------------------------------| +| Простой путь | `path` | Существует маршрут от S до E | +| Тупики | `deadends` | Лабиринт специально содержит тупики (могут быть и в других типах, но здесь — гарантированно) | +| Запутанный | `spaghetti` | Сложная структура с циклами и ложными ходами | +| Пустой | `empty` | Нет стен (`#`), только пробелы, S и E | +| Без выхода | `noexit` | В лабиринте отсутствует символ `E` | + +### Версия + +Формат: `v{номер}` + +- `v1`, `v2`, `v10` + +### Примеры + +#### Маленькие (10×10, простой путь) + +```default +10x10_path_v1.txt +10x10_path_v2.txt +... +10x10_path_v10.txt +``` + +#### Средние (50×50, тупики) + +```default +50x50_deadends_v1.txt +50x50_deadends_v2.txt +... +50x50_deadends_v10.txt +``` + +#### Большие (100×100, запутанные) + +```default +100x100_spaghetti_v1.txt +100x100_spaghetti_v2.txt +... +100x100_spaghetti_v10.txt +``` + +#### Пустые (30×30) + +```default +30x30_empty_v1.txt +30x30_empty_v2.txt +... +30x30_empty_v10.txt +``` + +#### Без выхода (20×20) + +```default +20x20_noexit_v1.txt +20x20_noexit_v2.txt +... +20x20_noexit_v10.txt +``` + +#### Комбинированные свойства + +```default +50x50_deadends-noexit_v1.txt +100x100_spaghetti-noexit_v1.txt +10x10_path-empty_v1.txt (избыточно, но допустимо) +``` + +### Примечание + +- Регистр имён файлов: **нижний регистр** +- Разделители: только `_` и `-` +- Расширение: `.txt` +- Кодировка: UTF-8 +# Этап 1. Модель лабиринта + +В первом этапе разработки необходимо создать базовые классы `Cell` и `Maze`, которые представляют карту лабиринта. Паттерны на этом этапе не применяются — только чистые классы. + +## Класс `Cell` + +Клетка — минимальная единица лабиринта. Хранит координаты и тип: стена, старт, выход или пустая. + +По условию задания клетка должна иметь флаги `isWall`, `isStart`, `isExit` и метод `isPassable()`. В реализации флаги оформлены как **свойства** (`@property`) с сеттерами — это позволяет автоматически сбрасывать остальные флаги при установке нового типа. + +```python +cell = Cell(1, 1) +cell.is_wall = True +``` + +Типы клетки взаимоисключают друг друга — клетка не может быть одновременно стеной и стартом. Логика сброса вынесена в приватный метод `_clear_flags()`. + +### Символьное представление + +Для вывода лабиринта в консоль каждая клетка возвращает символ через `__str__`. Символы берутся из `cell_mapping` в `source/settings.py`, что позволяет менять отображение без правки классов: + +| Тип | Символ по умолчанию | +|--------|-----------------------| +| Стена | `#` | +| Старт | `S` | +| Выход | `E` | +| Пустая | | + +## Класс `Maze` + +Лабиринт хранит двумерный список клеток и предоставляет методы для работы с ними. + +По условию задания требовались методы `getCell(x, y)` и `getNeighbors(cell)`. В реализации добавлено несколько вещей сверх задания: + +### Именование методов + +Задание написано в стиле Java/pseudocode — названия методов и полей используют `camelCase` (`isWall`, `getCell`, `isPassable`). В Python принят другой стандарт именования — **PEP 8**, который предписывает `snake_case` для методов и атрибутов. Поэтому все названия были приведены к Python стилю: + +| Задание | Реализация | +|---------------------------|-----------------------------| +| `isWall` | `is_wall` | +| `isStart` | `is_start` | +| `isExit` | `is_exit` | +| `isPassable()` | `is_possible()` | +| `getCell(x, y)` | `get_cell(x, y)` | +| `getNeighbors(cell)` | `get_neighbors(x, y)` | +| `buildFromFile(filename)` | `build_from_file(filename)` | + +Это соответствует стандарту оформления кода на Python и делает API классов идиоматичным для языка. + +### Индексация `maze[row, col]` + +Вместо явного вызова `get_cell()` реализованы `__getitem__` и `__setitem__`, что позволяет обращаться к клеткам естественным образом: + +```python +maze[0, 0] = cell_mapping['wall'] # установить стену +cell = maze[2, 3] # получить клетку +``` + +Обратите внимание: индексация идёт в формате `[row, col]`, то есть сначала строка (Y), потом столбец (X) — аналогично numpy. + +### Свойства `start` и `exit` + +Добавлены свойства для быстрого получения стартовой и выходной клетки без ручного обхода: + +```python +maze.start # Cell или None +maze.exit # Cell или None +``` + +Это оказалось необходимым при реализации алгоритмов поиска пути — стратегии получают `start` и `exit` автоматически из лабиринта. + +### Свойство `shape` + +По аналогии с numpy добавлено свойство `shape`, возвращающее `(height, width)`: + +```python +rows, cols = maze.shape +``` + +Используется в стратегиях поиска и тестах для итерации по лабиринту. + +### `get_neighbors` + +Метод возвращает список проходимых соседей клетки по четырём направлениям. Стены и клетки за границей лабиринта исключаются автоматически. Если переданные координаты вне границ — возвращает `None`. + +```python +neighbors = maze.get_neighbors(2, 2) # список Cell +``` + +Направления обхода: вниз → вправо → вверх → влево (порядок влияет на поведение DFS). +# Этап 2. Загрузка лабиринта из файла + +Во втором этапе реализована загрузка лабиринта из текстового файла с применением паттерна **Builder**. + +## Паттерн Builder + +Процесс создания лабиринта из файла включает несколько шагов: чтение файла, валидацию структуры, парсинг символов и заполнение клеток. Builder скрывает эти детали от клиента — снаружи виден только один метод `build_from_file()`, внутри которого сосредоточена вся логика построения. + +Дополнительное преимущество: в будущем можно легко добавить новый формат (например, JSON или бинарный) через новую реализацию `MazeBuilder` без изменения остального кода. + +## Класс `MazeBuilder` + +Абстрактный базовый класс — интерфейс паттерна Builder. Объявляет единственный метод `build_from_file()`, который обязан реализовать каждый конкретный строитель. + +По условию задания интерфейс назывался `MazeBuilder` с методом `buildFromFile`. В реализации название метода приведено к **PEP 8** — `build_from_file`. Сам класс оформлен через `ABC` — попытка создать объект `MazeBuilder()` напрямую вызовет `TypeError`. + +## Класс `TextFileBuilder` + +Конкретная реализация строителя для текстовых файлов. Загружает лабиринт из `.txt` файла где `#` — стена, — проход, `S` — старт, `E` — выход. + +Процесс построения разбит на три приватных шага: + +### `_read_file` + +Читает файл построчно и обрезает символы переноса строки `\n` и `\r`. Возвращает список строк — каждая строка соответствует одной строке лабиринта. + +### `_test_text_maze` + +Валидирует структуру: проверяет что все строки одинаковой длины. Если нет — лабиринт некорректен и `_create_maze` выбросит `ValueError`. + +Реализован как `@staticmethod` — не использует состояние объекта, только входные данные. + +### `_create_maze` + +Создаёт объект `Maze` нужного размера и заполняет его клетки символами из файла через `maze[y, x] = symbol`. Тип каждой клетки определяется автоматически через `cell_mapping` в `__setitem__` лабиринта. + +## Использование + +```python +from source.build.builder import TextFileBuilder + +maze = TextFileBuilder().build_from_file('source/templates/10x10_path_v1.txt') +print(maze) +``` + +## Известная ошибка + +В текущей реализации `_create_maze` есть опечатка при вычислении `width`: + +```python +height, width = len(text_maze), len(text_maze) # width всегда равен height +``` + +Правильная версия: + +```python +height, width = len(text_maze), len(text_maze[0]) +``` + +На квадратных лабиринтах (10×10, 50×50) это не проявляется, но на прямоугольных даст некорректный результат. +# Этап 3. Стратегии поиска пути + +В третьем этапе реализованы алгоритмы поиска пути с применением паттерна **Strategy**. + +## Паттерн Strategy + +Все три алгоритма реализуют один интерфейс `PathFindingStrategy`. Это позволяет переключать алгоритм в любой момент без изменения кода клиента — достаточно передать другой объект стратегии: + +```python +solver = MazeSolver(maze, BFSStrategy()) +solver.set_strategy(AStarStrategy()) +``` + +Новый алгоритм добавляется реализацией интерфейса — остальной код трогать не нужно. + +## Структура пакета + +Стратегии разбиты по отдельным файлам, а `__init__.py` собирает всё в один импорт: + +```default +source/strategy/ +├── __init__.py ← единственный импорт для пользователя +├── algorithms.py ← базовый класс PathFindingStrategy +├── bfs.py +├── dfs.py +└── astar.py +``` + +```python +from source.strategy import BFSStrategy, DFSStrategy, AStarStrategy +``` + +## Класс `PathFindingStrategy` + +Абстрактный базовый класс — интерфейс паттерна. Объявляет абстрактный метод `find_path()` и содержит два вспомогательных метода, общих для всех стратегий. + +По условию задания метод назывался `findPath` — приведён к **PEP 8** как `find_path`. + +### `_validate` + +Добавлен в процессе разработки — изначально в задании не было требования к обработке отсутствия старта или выхода. Проблема проявилась при тестировании лабиринтов типа `noexit`: алгоритм падал с `AttributeError` внутри, вместо понятного сообщения. + +`_validate` подставляет `start` и `exit` из лабиринта если они не переданы явно, и выбрасывает `ValueError` с понятным сообщением если клетки не найдены: + +```python +start, exit = self._validate(maze, start, exit) +``` + +Вынесен в базовый класс чтобы не дублировать в каждом алгоритме. + +### `_reconstruct_path` + +Восстанавливает путь по словарю предков `came_from`. Все три алгоритма строят этот словарь одинаково — `{клетка: откуда_пришли}` — поэтому восстановление вынесено в общий метод базового класса. + +Алгоритм идёт от выхода к старту по цепочке предков, затем разворачивает список: + +```default +exit → D → C → B → start (идём по came_from) +start → B → C → D → exit (после reverse) +``` + +## Алгоритмы + +### BFS — `BFSStrategy` + +Поиск в ширину. Использует `deque` как очередь (FIFO) — каждый раз берём самую старую клетку из начала. Это гарантирует послойный обход и кратчайший путь по количеству шагов. + +Сложность: O(V + E) по времени и памяти. + +### DFS — `DFSStrategy` + +Поиск в глубину. Использует `list` как стек (LIFO) — каждый раз берём самую свежую клетку с конца. Алгоритм ныряет вглубь по одному направлению до тупика, затем возвращается. + +Не гарантирует кратчайший путь. На запутанных лабиринтах может обойти почти все клетки прежде чем найти выход, хотя по времени часто быстрее BFS из-за меньших накладных расходов на структуру данных. + +Сложность: O(V + E) по времени и памяти. + +### A\* — `AStarStrategy` + +Использует `heapq` как приоритетную очередь. На каждом шаге выбирает клетку с минимальным значением `f = g + h`, где `g` — стоимость пути от старта, `h` — манхэттенская эвристика до выхода. + +Эвристика направляет поиск в сторону выхода, поэтому A\* обходит меньше клеток чем BFS при том же гарантированно кратчайшем пути. + +В кортеж приоритетной очереди добавлен счётчик `counter` как tie-breaker — без него `heapq` попытался бы сравнивать объекты `Cell` при одинаковом `f`, что вызвало бы `TypeError`: + +```python +heapq.heappush(open_heap, (f, counter, neighbor)) +``` + +Сложность: O(E · log V) в худшем случае. +# Этап 4. Класс-оркестратор MazeSolver + +В четвёртом этапе реализован класс `MazeSolver`, который объединяет лабиринт и стратегию поиска, выполняет поиск и собирает статистику. + +## Роль в архитектуре + +`MazeSolver` — точка входа для клиентского кода. Он не знает деталей ни одного алгоритма и не работает напрямую с клетками лабиринта — только делегирует задачу стратегии и замеряет время: + +```python +solver = MazeSolver(maze, BFSStrategy()) +stats = solver.solve() +print(stats) +# Время: 0.041 мс | Посещено клеток: 13 | Длина пути: 13 +``` + +## Класс `SearchStats` + +Оформлен через `@dataclass` — это избавляет от ручного `__init__` и автоматически даёт `__repr__`. Хранит четыре поля: время выполнения, количество посещённых клеток, длину пути и сам путь как список клеток. + +`__str__` переопределён для удобного вывода в консоль и отчётах. + +### Ограничение + +В текущей реализации `visited_count` и `path_length` всегда равны друг другу — оба вычисляются как `len(path)`. Это потому что стратегии возвращают только финальный путь, а не все посещённые клетки. Чтобы получить точное количество посещений, потребовалось бы дорабатывать каждую стратегию — добавлять счётчик внутри `find_path`. На данном этапе это сознательное упрощение. + +## Класс `MazeSolver` + +### `set_strategy` + +Позволяет менять алгоритм без пересоздания солвера. Это и есть основная демонстрация паттерна Strategy в действии — один объект, разные алгоритмы: + +```python +solver = MazeSolver(maze, BFSStrategy()) +stats_bfs = solver.solve() + +solver.set_strategy(AStarStrategy()) +stats_astar = solver.solve() +``` + +### `solve` + +Замеряет время через `time.perf_counter()` — самый точный таймер в Python для коротких интервалов, не зависящий от системных часов. Результат переводится в миллисекунды умножением на 1000. + +`start` и `exit` можно не передавать — стратегия найдёт их сама через `_validate`. Явная передача нужна только если хочется запустить поиск не от стандартного старта, а от произвольной клетки. +# Этап 5. Визуализация и пошаговое управление + +В пятом этапе реализованы два паттерна: **Observer** для отображения событий и **Command** для пошагового управления игроком. + +## 5.1. Паттерн Observer + +### Идея + +`MazeSolver` и игровой цикл не знают как именно отображать происходящее — они просто генерируют события. Наблюдатели подписываются на эти события и реагируют по своему усмотрению. Это позволяет в будущем добавить, например, `FileLogger` или графический интерфейс без изменения основного кода. + +### Класс `Event` + +Оформлен через `@dataclass`. Хранит тип события строкой и словарь `payload` с дополнительными данными. Поддерживаются четыре типа событий: + +| Тип | Когда генерируется | +|---------------|----------------------------| +| `maze_loaded` | Лабиринт загружен из файла | +| `path_found` | Алгоритм нашёл путь | +| `no_path` | Путь не найден | +| `move` | Игрок сделал ход | + +### Класс `Observer` + +Абстрактный базовый класс с единственным методом `update(event)`. Любой наблюдатель обязан его реализовать. + +### Класс `ConsoleView` + +Конкретная реализация наблюдателя. Обрабатывает события через `match/case` и вызывает `render()` для перерисовки лабиринта. + +Метод `render()` принимает лабиринт, опциональную позицию игрока и опциональный путь. Путь преобразуется в `set` для быстрой проверки принадлежности клетки — это O(1) вместо O(n) при каждом обходе: + +```python +path_set = set(path) if path else set() +``` + +Лабиринт обрамляется рамкой из `+` и `─` для читаемости в консоли. Символы игрока и пути вынесены в константы класса — легко поменять без правки логики: + +```python +PLAYER_SYMBOL = "P" +PATH_SYMBOL = "·" +``` + +## 5.2. Паттерн Command + +### Идея + +Каждое перемещение игрока оборачивается в объект `MoveCommand`. Это позволяет сохранить предыдущее состояние и отменить ход — реализация `undo` становится тривиальной. + +### Класс `Player` + +Простой контейнер для текущей клетки игрока. Намеренно минималистичный — вся логика перемещения и проверок находится в команде, а не в игроке. + +### Класс `Command` + +Абстрактный интерфейс с двумя методами: `execute()` и `undo()`. `execute()` возвращает `bool` — это отличие от классического варианта паттерна, где команды не возвращают значений. Возврат `False` нужен чтобы не добавлять неуспешный ход в историю. + +### Класс `MoveCommand` + +Хранит ссылку на игрока, направление и лабиринт. При `execute()` проверяет проходимость целевой клетки, сохраняет текущую в `_prev_cell` и перемещает игрока. При `undo()` восстанавливает `_prev_cell`. + +Направления вынесены в словарь `DIRECTIONS` на уровне модуля: + +```python +DIRECTIONS = { + "w": (0, -1), # вверх + "s": (0, 1), # вниз + "a": (-1, 0), # влево + "d": (1, 0), # вправо +} +``` + +### Класс `CommandHistory` + +Стек выполненных команд. Хранит только успешные ходы — неуспешные (`execute()` вернул `False`) в историю не добавляются. `undo()` снимает последнюю команду со стека и вызывает её `undo()`. + +Пример игрового цикла: + +```python +cmd = MoveCommand(player, 'd', maze) +if cmd.execute(): + history.push(cmd) # добавляем только успешный ход + +history.undo() # отмена последнего хода +``` +# Этап 6. Экспериментальная часть + +В шестом этапе проведено сравнение эффективности трёх стратегий поиска пути на лабиринтах разной сложности. Эксперимент реализован в Jupyter Notebook (`practice/main.ipynb`). + +## Подготовка + +Лабиринты загружаются из папки `source/templates` автоматически — все файлы считываются через `os.listdir` и передаются в `TextFileBuilder`. Стратегии собраны в словарь для удобной итерации: + +```python +strategies = { + "BFS": BFSStrategy(), + "DFS": DFSStrategy(), + "A*": AStarStrategy(), +} +``` + +## Замеры + +Каждая пара лабиринт + стратегия запускается **10 раз**, результаты усредняются. Это сглаживает разброс из-за кэширования и фоновой активности системы. + +Лабиринты типа `noexit` пропускаются автоматически — стратегия выбрасывает `ValueError`, который перехватывается через `try/except`, и выполнение продолжается. + +Результаты собираются в список словарей и затем преобразуются в `DataFrame` через pandas. + +## Результаты + +### 10×10 (простой путь) + +На маленьких лабиринтах все три алгоритма показывают практически одинаковое время (~0.03–0.07 мс) и одинаковую длину пути. Разница незначительна — лабиринт слишком мал чтобы эвристика A\* давала преимущество. + +### 50×50 (тупики) + +BFS стабильно быстрее DFS по времени при одинаковой длине пути. DFS заходит в каждый тупик до конца и тратит время на возврат, хотя финальный путь совпадает. A\* показывает время между BFS и DFS. + +### 100×100 (запутанный, spaghetti) + +Наиболее показательные результаты: + +| Стратегия | Время (мс) | Длина пути | +|-------------|--------------|--------------| +| BFS | ~9 | ~210 | +| DFS | ~7 | ~2200 | +| A\* | ~8 | ~210 | + +DFS быстрее по времени, но находит путь в 10 раз длиннее — обходит почти весь лабиринт. BFS и A\* находят кратчайший путь, A\* при этом чуть быстрее за счёт эвристики. + +### 30×30 (пустой) + +Неожиданный результат: DFS быстрее всех (~0.73 мс против 1.1 у BFS и 2.0 у A\*), хотя находит путь из 379 клеток против 55 у BFS. На пустом поле без стен DFS сразу уходит вглубь без возвратов, тогда как BFS строит очередь и обходит клетки волнами во все стороны — это накладные расходы на структуру данных. + +A\* на пустом лабиринте медленнее всех — накладные расходы на `heapq` и вычисление эвристики не окупаются когда препятствий нет. + +## Выводы + +- **BFS** — надёжный выбор по умолчанию. Всегда находит кратчайший путь, время предсказуемо. +- **DFS** — быстрый по времени, но путь непредсказуем. На запутанных лабиринтах может пройти весь граф. Подходит когда важна скорость, а не оптимальность пути. +- **A**\* — лучший выбор для больших лабиринтов с препятствиями. Находит кратчайший путь быстрее BFS за счёт эвристики. На простых или пустых лабиринтах проигрывает из-за накладных расходов на приоритетную очередь. + +## Визуализация + +![[results.png]] +# Этап 7. Отчёт + +## Описание задачи + +Разработать программу для загрузки лабиринта из файла, поиска пути с выбором алгоритма и сравнения их эффективности. Применены четыре паттерна GoF: + +| Паттерн | Где применён | +|--------------|-----------------------------------------------| +| **Builder** | `TextFileBuilder` | +| **Strategy** | `BFSStrategy`, `DFSStrategy`, `AStarStrategy` | +| **Observer** | `ConsoleView` | +| **Command** | `MoveCommand`, `CommandHistory` | + +## Диаграмма классов + +## Результаты экспериментов + +| Лабиринт | Быстрее всех | Кратчайший путь | +|-------------------|----------------|-------------------| +| 10×10 path | все одинаково | все одинаково | +| 50×50 deadends | BFS | BFS = A\* | +| 100×100 spaghetti | DFS | BFS = A\* | +| 30×30 empty | DFS | BFS = A\* | + +- **BFS** — надёжный выбор, всегда кратчайший путь. +- **DFS** — быстрый, но путь длиннее. На 100×100 обошёл в 10 раз больше клеток. +- **A\*** — лучший на больших лабиринтах с препятствиями, проигрывает на простых из-за накладных расходов на `heapq`. + +## Выводы + +Паттерны сделали код расширяемым: новый алгоритм — один класс, новый формат файла — один класс, новый способ отображения — один класс. Без паттернов каждое такое изменение потребовало бы правки существующего кода. +# Задание + +## Цель работы + +Разработать гибкую, расширяемую программу для загрузки лабиринта из файла, поиска пути от старта до выхода с возможностью выбора алгоритма, визуализации процесса и экспериментального сравнения алгоритмов. В ходе работы необходимо применить минимум 3 паттерна проектирования из списка GoF, обосновать их выбор и продемонстрировать преимущества такой архитектуры. + +## Общая схема приложения (пример) + +## Выполнение + +### Этап 1. Модель лабиринта (без паттернов, просто классы) + +**Задача:** Создать классы `Cell` и `Maze`, которые представляют карту лабиринта. + +- `Cell` хранит координаты (x, y), флаги `isWall`, `isStart`, `isExit`, метод `isPassable()` (возвращает `True` для прохода, если не стена). +- `Maze` хранит двумерный массив клеток, ширину, высоту, ссылки на стартовую и выходную клетку. Методы: `getCell(x, y)`, `getNeighbors(cell)` – возвращает список соседних проходимых клеток (вверх, вниз, влево, вправо, если в пределах границ и не стена). + +**Результат:** Лабиринт можно создать вручную в коде, но загрузку пока не делаем. + +### Этап 2. Загрузка лабиринта из файла – применение паттерна **Builder** + +**Задача:** Реализовать загрузку лабиринта из текстового файла, где `#` – стена, ` ` (пробел) – проход, `S` – старт, `E` – выход. + +- Создать интерфейс `MazeBuilder` с методом `buildFromFile(filename)`. +- Реализовать класс `TextFileMazeBuilder`, который читает файл, парсит символы, создаёт объекты `Cell`, задаёт координаты и флаги, после чего возвращает готовый `Maze`. + +Процесс построения лабиринта сложный (парсинг, валидация, установка старта/выхода). Builder скрывает детали создания от клиента. В будущем можно легко добавить другой формат (например, JSON или бинарный) через новую реализацию `MazeBuilder`. + +### Этап 3. Стратегии поиска пути – паттерн **Strategy** + +**Задача:** Реализовать семейство алгоритмов поиска пути от старта до выхода. + +- Создать интерфейс `PathFindingStrategy` с методом `findPath(maze, start, exit)`, возвращающим список клеток пути (от старта до выхода включительно) или пустой список, если пути нет. +- Реализовать минимум 3 стратегии: + - **BFS** (поиск в ширину) – гарантирует кратчайший путь по количеству шагов. + - **DFS** (поиск в глубину) – быстрый, но не обязательно кратчайший. + - **A**\* (с эвристикой, например, манхэттенское расстояние) – компромисс между скоростью и оптимальностью. + - (Опционально) **Дейкстра** – полезна для взвешенных лабиринтов, но в базовом варианте все шаги имеют вес 1, тогда она совпадает с BFS. + +Каждая стратегия возвращает путь. Для BFS/DFS используйте очередь/стек, для A\* – приоритетную очередь (heapq). Важно: алгоритмы не должны модифицировать сам лабиринт, только читать состояние клеток. + +Strategy позволяет легко переключать алгоритмы во время выполнения, не меняя код остальной программы. Новый алгоритм можно добавить, реализовав интерфейс. + +### Этап 4. Класс-оркестратор – **MazeSolver** (использует Strategy) + +**Задача:** Создать класс, который принимает лабиринт и стратегию, выполняет поиск и собирает статистику. + +- `MazeSolver` содержит поля `maze` и `strategy`. +- Метод `setStrategy(strategy)` для динамической смены алгоритма. +- Метод `solve()` вызывает `strategy.findPath(...)` и возвращает объект `SearchStats` (время выполнения в миллисекундах, количество посещённых клеток, длина найденного пути). +- Для замера времени используйте `time.perf_counter()` до и после вызова стратегии. + +### Этап 5. Визуализация и пошаговое управление – паттерны **Observer** и **Command** (по желанию) + +**5.1. Наблюдатель (Observer)** – обновление консольного интерфейса. + +- Создать интерфейс `Observer` с методом `update(event)`, где `event` может быть строкой или объектом с типом события (`"path_found"`, `"move"`, `"maze_loaded"`). +- Реализовать класс `ConsoleView`, который отображает лабиринт, текущее положение игрока (если реализован пошаговый режим) и найденный путь. Метод `render(maze, player_position, path)` рисует карту в консоли. +- `MazeSolver` (или отдельный контроллер) может иметь список наблюдателей и уведомлять их при изменении состояния. + +**5.2. Команда (Command)** – для пошагового перемещения игрока по найденному пути (или ручного управления). + +- Создать интерфейс `Command` с методами `execute()` и `undo()`. +- Реализовать `MoveCommand`, который принимает игрока (`Player`), направление и изменяет его позицию, сохраняя предыдущую для отмены. +- Создать класс `Player`, хранящий текущую клетку. +- Консольное меню позволяет вводить команды (W/A/S/D), выполнять `MoveCommand`, при необходимости отменять последний ход (Ctrl+Z). Это опционально, но очень наглядно демонстрирует паттерн. + +*Observer можно реализовать только для вывода сообщений о начале/конце поиска, а Command – для демонстрации undo при ручном исследовании лабиринта.* + +### Этап 6. Экспериментальная часть (аналогично заданию со структурами данных) + +**Задача:** Сравнить эффективность реализованных стратегий на лабиринтах разной сложности. + +1. **Подготовка тестовых лабиринтов:** + - Маленький (10×10) с простым путём. + - Средний (50×50) с тупиками. + - Большой (100×100) с запутанной структурой. + - «Пустой» лабиринт (без стен) – для демонстрации максимальной производительности. + - «Без выхода» – чтобы проверить обработку отсутствия пути. +2. **Замеры:** + - Для каждого лабиринта и каждой стратегии запустить `solve()` 5–10 раз, усреднить время, количество посещённых клеток, длину пути. + - Записать результаты в CSV: `лабиринт,стратегия,время_мс,посещено_клеток,длина_пути`. +3. **Анализ:** + - Построить графики для каждого лабиринта. + - Проанализировать и написать выводы по итогам (эффективность того или иного алгоритма в разных случаях). +4. **Дополнительное задание:** Реализовать взвешенные клетки (например, болото – вес 3, песок – вес 2, асфальт – вес 1) и сравнить Дейкстру с A\* на взвешенном графе. + +### Этап 7. Отчёт + +**Структура отчёта:** + +1. Описание задачи и выбранных паттернов (с диаграммой классов из Mermaid). +2. Листинги ключевых классов (можно выборочно) или ссылка на репозиторий. +3. Результаты экспериментов (таблицы, графики). +4. Анализ эффективности алгоритмов и применимости паттернов. +5. Выводы: как ООП и паттерны помогли сделать код гибким и расширяемым. Что было бы сложно изменить без них. + +## Советы + +- Для A\* самая простая эвристика: `abs(x1 - x2) + abs(y1 - y2)`. +- При поиске пути надо хранить предшественников (`parent` для каждой посещённой клетки), чтобы восстановить путь. +- Для BFS/DFS используй `deque` (очередь) и `list` (стек). +- Визуализацию в консоли можно сделать с помощью `os.system('cls' if os.name == 'nt' else 'clear')` для перерисовки. + +# API Reference + +## Базовые модели + +### *class* source.models.base.Cell(x: int, y: int, is_wall: bool = False, is_start: bool = False, is_exit: bool = False) + +Базовые классы: `object` + +Представляет одну клетку поля лабиринта. + +Каждая клетка хранит свои координаты и один из четырёх возможных +типов: стена, старт, выход или пустая клетка. Типы взаимоисключают +друг друга: установка одного автоматически сбрасывает остальные. + +#### \_\_init_\_(x: int, y: int, is_wall: bool = False, is_start: bool = False, is_exit: bool = False) + +Инициализирует клетку с заданными координатами и типом. + +* **Параметры:** + * **x** – Координата клетки по оси X. + * **y** – Координата клетки по оси Y. + * **is_wall** – Если True — клетка является стеной. + * **is_start** – Если True — клетка является стартом. + * **is_exit** – Если True — клетка является выходом. + +#### *property* is_exit *: bool* + +True, если клетка является выходом из лабиринта. + +#### is_possible() → bool + +Проверяет, можно ли переместиться в эту клетку. + +* **Результат:** + True, если клетка не является стеной, иначе False. + +#### *property* is_start *: bool* + +True, если клетка является стартовой позицией. + +#### *property* is_wall *: bool* + +True, если клетка является стеной. + +### *class* source.models.base.Maze(size: tuple[int, int] = (10, 10)) + +Базовые классы: `object` + +Представляет двумерный лабиринт из клеток Cell. + +Лабиринт хранится как список списков клеток. Доступ к отдельным +клеткам и их изменение возможны через индексацию вида maze[row, col]. + +#### \_\_init_\_(size: tuple[int, int] = (10, 10)) + +Создаёт пустой лабиринт заданного размера. + +* **Параметры:** + **size** – Кортеж (width, height) — ширина и высота лабиринта в клетках. + +#### *property* exit *: [Cell](#source.models.base.Cell) | None* + +#### get_cell(x: int, y: int) → [Cell](#source.models.base.Cell) | None + +Возвращает клетку по координатам или None, если координаты вне границ. + +* **Параметры:** + * **x** – Координата по оси X. + * **y** – Координата по оси Y. +* **Результат:** + Объект Cell, если координаты корректны, иначе None. + +#### get_neighbors(x: int, y: int) → list[[Cell](#source.models.base.Cell)] | None + +Возвращает список проходимых соседей клетки (вверх, вправо, вниз, влево). + +* **Параметры:** + * **x** – Координата клетки по оси X. + * **y** – Координата клетки по оси Y. +* **Результат:** + Список проходимых соседних клеток, или None если (x, y) вне границ. + +#### *property* shape *: tuple[int, int]* + +#### *property* start *: [Cell](#source.models.base.Cell) | None* + +## Загрузка лабиринта + +### *class* source.build.builder.MazeBuilder + +Базовые классы: `ABC` + +#### *abstractmethod* build_from_file(filename: str) → [Maze](#source.models.base.Maze) + +Возвращает объект лабиринта по указанному пути файлу. + +* **Параметры:** + **filename** (*str*) – Путь к файлу +* **Исключение:** + **TypeError** – Если введен путь файла с нерассмотренным расширением +* **Результат:** + Объект лабиринта +* **Тип результата:** + [Maze](#source.models.base.Maze) + +### *class* source.build.builder.TextFileBuilder + +Базовые классы: [`MazeBuilder`](#source.build.builder.MazeBuilder) + +#### build_from_file(filename: str) → [Maze](#source.models.base.Maze) + +Возвращает объект лабиринта по указанному пути файлу. + +* **Параметры:** + **filename** (*str*) – Путь к файлу +* **Исключение:** + **TypeError** – Если введен путь файла с нерассмотренным расширением +* **Результат:** + Объект лабиринта +* **Тип результата:** + [Maze](#source.models.base.Maze) + +## Стратегии поиска пути + +### *class* source.strategy.algorithms.PathFindingStrategy + +Базовые классы: `ABC` + +Интерфейс стратегии поиска пути в лабиринте. + +#### *abstractmethod* find_path(maze: [Maze](#source.models.base.Maze), start: [Cell](#source.models.base.Cell) = None, exit: [Cell](#source.models.base.Cell) = None) → list[[Cell](#source.models.base.Cell)] + +Найти путь от start до exit. + +* **Параметры:** + * **maze** – Объект лабиринта. + * **start** – Стартовая клетка. + * **exit** – Целевая клетка. +* **Результат:** + Список клеток пути (от start до exit включительно). + Пустой список, если путь не найден. + + + +### *class* source.strategy.bfs.BFSStrategy + +Базовые классы: [`PathFindingStrategy`](#source.strategy.algorithms.PathFindingStrategy) + +Поиск в ширину (Breadth-First Search). + +Гарантирует кратчайший путь по количеству шагов. +Сложность: O(V + E) по времени и памяти. + +#### find_path(maze: [Maze](#source.models.base.Maze), start: [Cell](#source.models.base.Cell) | None = None, exit: [Cell](#source.models.base.Cell) | None = None) → list[[Cell](#source.models.base.Cell)] + +Найти путь от start до exit. + +* **Параметры:** + * **maze** – Объект лабиринта. + * **start** – Стартовая клетка. + * **exit** – Целевая клетка. +* **Результат:** + Список клеток пути (от start до exit включительно). + Пустой список, если путь не найден. + + + +### *class* source.strategy.dfs.DFSStrategy + +Базовые классы: [`PathFindingStrategy`](#source.strategy.algorithms.PathFindingStrategy) + +Поиск в глубину (Depth-First Search). + +Находит путь, но не гарантирует кратчайший. + +#### find_path(maze: [Maze](#source.models.base.Maze), start: [Cell](#source.models.base.Cell) | None = None, exit: [Cell](#source.models.base.Cell) | None = None) → list[[Cell](#source.models.base.Cell)] + +Найти путь от start до exit. + +* **Параметры:** + * **maze** – Объект лабиринта. + * **start** – Стартовая клетка. + * **exit** – Целевая клетка. +* **Результат:** + Список клеток пути (от start до exit включительно). + Пустой список, если путь не найден. + + + +### *class* source.strategy.astar.AStarStrategy + +Базовые классы: [`PathFindingStrategy`](#source.strategy.algorithms.PathFindingStrategy) + +Алгоритм A\* с манхэттенской эвристикой. + +#### find_path(maze: [Maze](#source.models.base.Maze), start: [Cell](#source.models.base.Cell) | None = None, exit: [Cell](#source.models.base.Cell) | None = None) → list[[Cell](#source.models.base.Cell)] + +Найти путь от start до exit. + +* **Параметры:** + * **maze** – Объект лабиринта. + * **start** – Стартовая клетка. + * **exit** – Целевая клетка. +* **Результат:** + Список клеток пути (от start до exit включительно). + Пустой список, если путь не найден. + +## Оркестратор + +### *class* source.strategy.solver.MazeSolver(maze: [Maze](#source.models.base.Maze), strategy: [PathFindingStrategy](#source.strategy.algorithms.PathFindingStrategy)) + +Базовые классы: `object` + +Оркестратор поиска пути в лабиринте. + +Принимает лабиринт и стратегию поиска, выполняет поиск +и возвращает результат вместе со статистикой выполнения. + +### Пример + +solver = MazeSolver(maze, BFSStrategy()) +stats = solver.solve() +print(stats) + +solver.set_strategy(AStarStrategy()) +stats = solver.solve() + +#### \_\_init_\_(maze: [Maze](#source.models.base.Maze), strategy: [PathFindingStrategy](#source.strategy.algorithms.PathFindingStrategy)) → None + +Инициализирует солвер с лабиринтом и стратегией поиска. + +* **Параметры:** + * **maze** – Объект лабиринта. + * **strategy** – Стратегия поиска пути. + +#### set_strategy(strategy: [PathFindingStrategy](#source.strategy.algorithms.PathFindingStrategy)) → None + +Заменяет текущую стратегию поиска. + +* **Параметры:** + **strategy** – Новая стратегия поиска пути. + +#### solve(start: [Cell](#source.models.base.Cell) = None, exit: [Cell](#source.models.base.Cell) = None) → [SearchStats](#source.strategy.solver.SearchStats) + +Выполняет поиск пути и собирает статистику. + +Если start или exit не переданы явно, стратегия найдёт +их самостоятельно по флагам is_start / is_exit в лабиринте. + +* **Параметры:** + * **start** – Стартовая клетка (опционально). + * **exit** – Конечная клетка (опционально). +* **Результат:** + Объект SearchStats с временем выполнения, количеством + посещённых клеток и длиной найденного пути. + +### *class* source.strategy.solver.SearchStats(elapsed_ms: float, visited_count: int, path_length: int, path: list[[Cell](#source.models.base.Cell)]) + +Базовые классы: `object` + +Статистика выполнения поиска пути. + +#### elapsed_ms + +Время выполнения в миллисекундах. + +* **Type:** + float + +#### visited_count + +Количество посещённых клеток. + +* **Type:** + int + +#### path_length + +Длина найденного пути (0 если путь не найден). + +* **Type:** + int + +#### path + +Найденный путь — список клеток от старта до выхода. + +* **Type:** + list[[source.models.base.Cell](#source.models.base.Cell)] + +#### \_\_init_\_(elapsed_ms: float, visited_count: int, path_length: int, path: list[[Cell](#source.models.base.Cell)]) → None + +#### elapsed_ms *: float* + +#### path *: list[[Cell](#source.models.base.Cell)]* + +#### path_length *: int* + +#### visited_count *: int* + +## Визуализация + +### *class* source.view.observer.ConsoleView + +Базовые классы: [`Observer`](#source.view.observer.Observer) + +Отображает состояние лабиринта и события в консоли. + +#### PATH_SYMBOL *= '·'* + +#### PLAYER_SYMBOL *= 'P'* + +#### render(maze: [Maze](#source.models.base.Maze), player: [Cell](#source.models.base.Cell) | None = None, path: list[[Cell](#source.models.base.Cell)] | None = None) → None + +Рисует лабиринт в консоли. + +Путь отмечается символом „·“, позиция игрока — „P“. + +* **Параметры:** + * **maze** – Объект лабиринта. + * **player** – Текущая клетка игрока (опционально). + * **path** – Список клеток найденного пути (опционально). + +#### update(event: [Event](#source.view.observer.Event)) → None + +Реагирует на события и выводит информацию в консоль. + +* **Параметры:** + **event** – Объект события. + +### *class* source.view.observer.Event(type: str, payload: dict = None) + +Базовые классы: `object` + +Событие, передаваемое наблюдателям. + +#### type + +Тип события („maze_loaded“, „path_found“, „move“, „no_path“). + +* **Type:** + str + +#### payload + +Дополнительные данные события. + +* **Type:** + dict + +#### \_\_init_\_(type: str, payload: dict = None) → None + +#### payload *: dict* *= None* + +#### type *: str* + +### *class* source.view.observer.Observer + +Базовые классы: `ABC` + +Интерфейс наблюдателя за событиями лабиринта. + +#### *abstractmethod* update(event: [Event](#source.view.observer.Event)) → None + +Обрабатывает входящее событие. + +* **Параметры:** + **event** – Объект события с типом и данными. + +## Управление игроком + +### *class* source.view.command.Command + +Базовые классы: `ABC` + +Интерфейс команды с поддержкой отмены. + +#### *abstractmethod* execute() → bool + +Выполняет команду. + +* **Результат:** + True если команда выполнена успешно, False иначе. + +#### *abstractmethod* undo() → None + +Отменяет команду, восстанавливая предыдущее состояние. + +### *class* source.view.command.CommandHistory + +Базовые классы: `object` + +Хранит историю выполненных команд и позволяет отменять их. + +### Пример + +history = CommandHistory() +cmd = MoveCommand(player, „w“, maze) +if cmd.execute(): + +> history.push(cmd) + +history.undo() # отменяет последний успешный ход + +#### \_\_init_\_() → None + +#### clear() → None + +Очищает историю команд. + +#### push(command: [Command](#source.view.command.Command)) → None + +Добавляет выполненную команду в историю. + +* **Параметры:** + **command** – Успешно выполненная команда. + +#### undo() → bool + +Отменяет последнюю команду из истории. + +* **Результат:** + True если отмена выполнена, False если история пуста. + +### *class* source.view.command.MoveCommand(player: [Player](#source.view.command.Player), direction: str, maze: [Maze](#source.models.base.Maze)) + +Базовые классы: [`Command`](#source.view.command.Command) + +Перемещает игрока в заданном направлении. + +Сохраняет предыдущую клетку для возможности отмены хода. + +#### \_\_init_\_(player: [Player](#source.view.command.Player), direction: str, maze: [Maze](#source.models.base.Maze)) → None + +Инициализирует команду перемещения. + +* **Параметры:** + * **player** – Объект игрока. + * **direction** – Направление („w“, „a“, „s“, „d“). + * **maze** – Объект лабиринта для проверки проходимости. +* **Исключение:** + **ValueError** – Если направление не распознано. + +#### execute() → bool + +Перемещает игрока если целевая клетка проходима. + +* **Результат:** + True если перемещение выполнено, False если клетка непроходима. + +#### undo() → None + +Возвращает игрока на предыдущую клетку. + +### *class* source.view.command.Player(cell: [Cell](#source.models.base.Cell)) + +Базовые классы: `object` + +Хранит текущее положение игрока в лабиринте. + +#### cell + +Текущая клетка игрока. + +#### \_\_init_\_(cell: [Cell](#source.models.base.Cell)) → None + +Инициализирует игрока на заданной клетке. + +* **Параметры:** + **cell** – Начальная клетка игрока. \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/_build/markdown/api.md b/skorohodovsa/task_2/docs/_build/markdown/api.md new file mode 100644 index 0000000..3fcd9a9 --- /dev/null +++ b/skorohodovsa/task_2/docs/_build/markdown/api.md @@ -0,0 +1,470 @@ +# API Reference + +## Базовые модели + +### *class* source.models.base.Cell(x: int, y: int, is_wall: bool = False, is_start: bool = False, is_exit: bool = False) + +Базовые классы: `object` + +Представляет одну клетку поля лабиринта. + +Каждая клетка хранит свои координаты и один из четырёх возможных +типов: стена, старт, выход или пустая клетка. Типы взаимоисключают +друг друга: установка одного автоматически сбрасывает остальные. + +#### \_\_init_\_(x: int, y: int, is_wall: bool = False, is_start: bool = False, is_exit: bool = False) + +Инициализирует клетку с заданными координатами и типом. + +* **Параметры:** + * **x** – Координата клетки по оси X. + * **y** – Координата клетки по оси Y. + * **is_wall** – Если True — клетка является стеной. + * **is_start** – Если True — клетка является стартом. + * **is_exit** – Если True — клетка является выходом. + +#### *property* is_exit *: bool* + +True, если клетка является выходом из лабиринта. + +#### is_possible() → bool + +Проверяет, можно ли переместиться в эту клетку. + +* **Результат:** + True, если клетка не является стеной, иначе False. + +#### *property* is_start *: bool* + +True, если клетка является стартовой позицией. + +#### *property* is_wall *: bool* + +True, если клетка является стеной. + +### *class* source.models.base.Maze(size: tuple[int, int] = (10, 10)) + +Базовые классы: `object` + +Представляет двумерный лабиринт из клеток Cell. + +Лабиринт хранится как список списков клеток. Доступ к отдельным +клеткам и их изменение возможны через индексацию вида maze[row, col]. + +#### \_\_init_\_(size: tuple[int, int] = (10, 10)) + +Создаёт пустой лабиринт заданного размера. + +* **Параметры:** + **size** – Кортеж (width, height) — ширина и высота лабиринта в клетках. + +#### *property* exit *: [Cell](#source.models.base.Cell) | None* + +#### get_cell(x: int, y: int) → [Cell](#source.models.base.Cell) | None + +Возвращает клетку по координатам или None, если координаты вне границ. + +* **Параметры:** + * **x** – Координата по оси X. + * **y** – Координата по оси Y. +* **Результат:** + Объект Cell, если координаты корректны, иначе None. + +#### get_neighbors(x: int, y: int) → list[[Cell](#source.models.base.Cell)] | None + +Возвращает список проходимых соседей клетки (вверх, вправо, вниз, влево). + +* **Параметры:** + * **x** – Координата клетки по оси X. + * **y** – Координата клетки по оси Y. +* **Результат:** + Список проходимых соседних клеток, или None если (x, y) вне границ. + +#### *property* shape *: tuple[int, int]* + +#### *property* start *: [Cell](#source.models.base.Cell) | None* + +## Загрузка лабиринта + +### *class* source.build.builder.MazeBuilder + +Базовые классы: `ABC` + +#### *abstractmethod* build_from_file(filename: str) → [Maze](#source.models.base.Maze) + +Возвращает объект лабиринта по указанному пути файлу. + +* **Параметры:** + **filename** (*str*) – Путь к файлу +* **Исключение:** + **TypeError** – Если введен путь файла с нерассмотренным расширением +* **Результат:** + Объект лабиринта +* **Тип результата:** + [Maze](#source.models.base.Maze) + +### *class* source.build.builder.TextFileBuilder + +Базовые классы: [`MazeBuilder`](#source.build.builder.MazeBuilder) + +#### build_from_file(filename: str) → [Maze](#source.models.base.Maze) + +Возвращает объект лабиринта по указанному пути файлу. + +* **Параметры:** + **filename** (*str*) – Путь к файлу +* **Исключение:** + **TypeError** – Если введен путь файла с нерассмотренным расширением +* **Результат:** + Объект лабиринта +* **Тип результата:** + [Maze](#source.models.base.Maze) + +## Стратегии поиска пути + +### *class* source.strategy.algorithms.PathFindingStrategy + +Базовые классы: `ABC` + +Интерфейс стратегии поиска пути в лабиринте. + +#### *abstractmethod* find_path(maze: [Maze](#source.models.base.Maze), start: [Cell](#source.models.base.Cell) = None, exit: [Cell](#source.models.base.Cell) = None) → list[[Cell](#source.models.base.Cell)] + +Найти путь от start до exit. + +* **Параметры:** + * **maze** – Объект лабиринта. + * **start** – Стартовая клетка. + * **exit** – Целевая клетка. +* **Результат:** + Список клеток пути (от start до exit включительно). + Пустой список, если путь не найден. + + + +### *class* source.strategy.bfs.BFSStrategy + +Базовые классы: [`PathFindingStrategy`](#source.strategy.algorithms.PathFindingStrategy) + +Поиск в ширину (Breadth-First Search). + +Гарантирует кратчайший путь по количеству шагов. +Сложность: O(V + E) по времени и памяти. + +#### find_path(maze: [Maze](#source.models.base.Maze), start: [Cell](#source.models.base.Cell) | None = None, exit: [Cell](#source.models.base.Cell) | None = None) → list[[Cell](#source.models.base.Cell)] + +Найти путь от start до exit. + +* **Параметры:** + * **maze** – Объект лабиринта. + * **start** – Стартовая клетка. + * **exit** – Целевая клетка. +* **Результат:** + Список клеток пути (от start до exit включительно). + Пустой список, если путь не найден. + + + +### *class* source.strategy.dfs.DFSStrategy + +Базовые классы: [`PathFindingStrategy`](#source.strategy.algorithms.PathFindingStrategy) + +Поиск в глубину (Depth-First Search). + +Находит путь, но не гарантирует кратчайший. + +#### find_path(maze: [Maze](#source.models.base.Maze), start: [Cell](#source.models.base.Cell) | None = None, exit: [Cell](#source.models.base.Cell) | None = None) → list[[Cell](#source.models.base.Cell)] + +Найти путь от start до exit. + +* **Параметры:** + * **maze** – Объект лабиринта. + * **start** – Стартовая клетка. + * **exit** – Целевая клетка. +* **Результат:** + Список клеток пути (от start до exit включительно). + Пустой список, если путь не найден. + + + +### *class* source.strategy.astar.AStarStrategy + +Базовые классы: [`PathFindingStrategy`](#source.strategy.algorithms.PathFindingStrategy) + +Алгоритм A\* с манхэттенской эвристикой. + +#### find_path(maze: [Maze](#source.models.base.Maze), start: [Cell](#source.models.base.Cell) | None = None, exit: [Cell](#source.models.base.Cell) | None = None) → list[[Cell](#source.models.base.Cell)] + +Найти путь от start до exit. + +* **Параметры:** + * **maze** – Объект лабиринта. + * **start** – Стартовая клетка. + * **exit** – Целевая клетка. +* **Результат:** + Список клеток пути (от start до exit включительно). + Пустой список, если путь не найден. + +## Оркестратор + +### *class* source.strategy.solver.MazeSolver(maze: [Maze](#source.models.base.Maze), strategy: [PathFindingStrategy](#source.strategy.algorithms.PathFindingStrategy)) + +Базовые классы: `object` + +Оркестратор поиска пути в лабиринте. + +Принимает лабиринт и стратегию поиска, выполняет поиск +и возвращает результат вместе со статистикой выполнения. + +### Пример + +solver = MazeSolver(maze, BFSStrategy()) +stats = solver.solve() +print(stats) + +solver.set_strategy(AStarStrategy()) +stats = solver.solve() + +#### \_\_init_\_(maze: [Maze](#source.models.base.Maze), strategy: [PathFindingStrategy](#source.strategy.algorithms.PathFindingStrategy)) → None + +Инициализирует солвер с лабиринтом и стратегией поиска. + +* **Параметры:** + * **maze** – Объект лабиринта. + * **strategy** – Стратегия поиска пути. + +#### set_strategy(strategy: [PathFindingStrategy](#source.strategy.algorithms.PathFindingStrategy)) → None + +Заменяет текущую стратегию поиска. + +* **Параметры:** + **strategy** – Новая стратегия поиска пути. + +#### solve(start: [Cell](#source.models.base.Cell) = None, exit: [Cell](#source.models.base.Cell) = None) → [SearchStats](#source.strategy.solver.SearchStats) + +Выполняет поиск пути и собирает статистику. + +Если start или exit не переданы явно, стратегия найдёт +их самостоятельно по флагам is_start / is_exit в лабиринте. + +* **Параметры:** + * **start** – Стартовая клетка (опционально). + * **exit** – Конечная клетка (опционально). +* **Результат:** + Объект SearchStats с временем выполнения, количеством + посещённых клеток и длиной найденного пути. + +### *class* source.strategy.solver.SearchStats(elapsed_ms: float, visited_count: int, path_length: int, path: list[[Cell](#source.models.base.Cell)]) + +Базовые классы: `object` + +Статистика выполнения поиска пути. + +#### elapsed_ms + +Время выполнения в миллисекундах. + +* **Type:** + float + +#### visited_count + +Количество посещённых клеток. + +* **Type:** + int + +#### path_length + +Длина найденного пути (0 если путь не найден). + +* **Type:** + int + +#### path + +Найденный путь — список клеток от старта до выхода. + +* **Type:** + list[[source.models.base.Cell](#source.models.base.Cell)] + +#### \_\_init_\_(elapsed_ms: float, visited_count: int, path_length: int, path: list[[Cell](#source.models.base.Cell)]) → None + +#### elapsed_ms *: float* + +#### path *: list[[Cell](#source.models.base.Cell)]* + +#### path_length *: int* + +#### visited_count *: int* + +## Визуализация + +### *class* source.view.observer.ConsoleView + +Базовые классы: [`Observer`](#source.view.observer.Observer) + +Отображает состояние лабиринта и события в консоли. + +#### PATH_SYMBOL *= '·'* + +#### PLAYER_SYMBOL *= 'P'* + +#### render(maze: [Maze](#source.models.base.Maze), player: [Cell](#source.models.base.Cell) | None = None, path: list[[Cell](#source.models.base.Cell)] | None = None) → None + +Рисует лабиринт в консоли. + +Путь отмечается символом „·“, позиция игрока — „P“. + +* **Параметры:** + * **maze** – Объект лабиринта. + * **player** – Текущая клетка игрока (опционально). + * **path** – Список клеток найденного пути (опционально). + +#### update(event: [Event](#source.view.observer.Event)) → None + +Реагирует на события и выводит информацию в консоль. + +* **Параметры:** + **event** – Объект события. + +### *class* source.view.observer.Event(type: str, payload: dict = None) + +Базовые классы: `object` + +Событие, передаваемое наблюдателям. + +#### type + +Тип события („maze_loaded“, „path_found“, „move“, „no_path“). + +* **Type:** + str + +#### payload + +Дополнительные данные события. + +* **Type:** + dict + +#### \_\_init_\_(type: str, payload: dict = None) → None + +#### payload *: dict* *= None* + +#### type *: str* + +### *class* source.view.observer.Observer + +Базовые классы: `ABC` + +Интерфейс наблюдателя за событиями лабиринта. + +#### *abstractmethod* update(event: [Event](#source.view.observer.Event)) → None + +Обрабатывает входящее событие. + +* **Параметры:** + **event** – Объект события с типом и данными. + +## Управление игроком + +### *class* source.view.command.Command + +Базовые классы: `ABC` + +Интерфейс команды с поддержкой отмены. + +#### *abstractmethod* execute() → bool + +Выполняет команду. + +* **Результат:** + True если команда выполнена успешно, False иначе. + +#### *abstractmethod* undo() → None + +Отменяет команду, восстанавливая предыдущее состояние. + +### *class* source.view.command.CommandHistory + +Базовые классы: `object` + +Хранит историю выполненных команд и позволяет отменять их. + +### Пример + +history = CommandHistory() +cmd = MoveCommand(player, „w“, maze) +if cmd.execute(): + +> history.push(cmd) + +history.undo() # отменяет последний успешный ход + +#### \_\_init_\_() → None + +#### clear() → None + +Очищает историю команд. + +#### push(command: [Command](#source.view.command.Command)) → None + +Добавляет выполненную команду в историю. + +* **Параметры:** + **command** – Успешно выполненная команда. + +#### undo() → bool + +Отменяет последнюю команду из истории. + +* **Результат:** + True если отмена выполнена, False если история пуста. + +### *class* source.view.command.MoveCommand(player: [Player](#source.view.command.Player), direction: str, maze: [Maze](#source.models.base.Maze)) + +Базовые классы: [`Command`](#source.view.command.Command) + +Перемещает игрока в заданном направлении. + +Сохраняет предыдущую клетку для возможности отмены хода. + +#### \_\_init_\_(player: [Player](#source.view.command.Player), direction: str, maze: [Maze](#source.models.base.Maze)) → None + +Инициализирует команду перемещения. + +* **Параметры:** + * **player** – Объект игрока. + * **direction** – Направление („w“, „a“, „s“, „d“). + * **maze** – Объект лабиринта для проверки проходимости. +* **Исключение:** + **ValueError** – Если направление не распознано. + +#### execute() → bool + +Перемещает игрока если целевая клетка проходима. + +* **Результат:** + True если перемещение выполнено, False если клетка непроходима. + +#### undo() → None + +Возвращает игрока на предыдущую клетку. + +### *class* source.view.command.Player(cell: [Cell](#source.models.base.Cell)) + +Базовые классы: `object` + +Хранит текущее положение игрока в лабиринте. + +#### cell + +Текущая клетка игрока. + +#### \_\_init_\_(cell: [Cell](#source.models.base.Cell)) → None + +Инициализирует игрока на заданной клетке. + +* **Параметры:** + **cell** – Начальная клетка игрока. diff --git a/skorohodovsa/task_2/docs/_build/markdown/stage1.md b/skorohodovsa/task_2/docs/_build/markdown/stage1.md new file mode 100644 index 0000000..7597841 --- /dev/null +++ b/skorohodovsa/task_2/docs/_build/markdown/stage1.md @@ -0,0 +1,91 @@ +# Этап 1. Модель лабиринта + +В первом этапе разработки необходимо создать базовые классы `Cell` и `Maze`, которые представляют карту лабиринта. Паттерны на этом этапе не применяются — только чистые классы. + +## Класс `Cell` + +Клетка — минимальная единица лабиринта. Хранит координаты и тип: стена, старт, выход или пустая. + +По условию задания клетка должна иметь флаги `isWall`, `isStart`, `isExit` и метод `isPassable()`. В реализации флаги оформлены как **свойства** (`@property`) с сеттерами — это позволяет автоматически сбрасывать остальные флаги при установке нового типа. + +```python +cell = Cell(1, 1) +cell.is_wall = True +``` + +Типы клетки взаимоисключают друг друга — клетка не может быть одновременно стеной и стартом. Логика сброса вынесена в приватный метод `_clear_flags()`. + +### Символьное представление + +Для вывода лабиринта в консоль каждая клетка возвращает символ через `__str__`. Символы берутся из `cell_mapping` в `source/settings.py`, что позволяет менять отображение без правки классов: + +| Тип | Символ по умолчанию | +|--------|-----------------------| +| Стена | `#` | +| Старт | `S` | +| Выход | `E` | +| Пустая | | + +## Класс `Maze` + +Лабиринт хранит двумерный список клеток и предоставляет методы для работы с ними. + +По условию задания требовались методы `getCell(x, y)` и `getNeighbors(cell)`. В реализации добавлено несколько вещей сверх задания: + +### Именование методов + +Задание написано в стиле Java/pseudocode — названия методов и полей используют `camelCase` (`isWall`, `getCell`, `isPassable`). В Python принят другой стандарт именования — **PEP 8**, который предписывает `snake_case` для методов и атрибутов. Поэтому все названия были приведены к Python стилю: + +| Задание | Реализация | +|---------------------------|-----------------------------| +| `isWall` | `is_wall` | +| `isStart` | `is_start` | +| `isExit` | `is_exit` | +| `isPassable()` | `is_possible()` | +| `getCell(x, y)` | `get_cell(x, y)` | +| `getNeighbors(cell)` | `get_neighbors(x, y)` | +| `buildFromFile(filename)` | `build_from_file(filename)` | + +Это соответствует стандарту оформления кода на Python и делает API классов идиоматичным для языка. + +### Индексация `maze[row, col]` + +Вместо явного вызова `get_cell()` реализованы `__getitem__` и `__setitem__`, что позволяет обращаться к клеткам естественным образом: + +```python +maze[0, 0] = cell_mapping['wall'] # установить стену +cell = maze[2, 3] # получить клетку +``` + +Обратите внимание: индексация идёт в формате `[row, col]`, то есть сначала строка (Y), потом столбец (X) — аналогично numpy. + +### Свойства `start` и `exit` + +Добавлены свойства для быстрого получения стартовой и выходной клетки без ручного обхода: + +```python +maze.start # Cell или None +maze.exit # Cell или None +``` + +Это оказалось необходимым при реализации алгоритмов поиска пути — стратегии получают `start` и `exit` автоматически из лабиринта. + +### Свойство `shape` + +По аналогии с numpy добавлено свойство `shape`, возвращающее `(height, width)`: + +```python +rows, cols = maze.shape +``` + +Используется в стратегиях поиска и тестах для итерации по лабиринту. + +### `get_neighbors` + +Метод возвращает список проходимых соседей клетки по четырём направлениям. Стены и клетки за границей лабиринта исключаются автоматически. Если переданные координаты вне границ — возвращает `None`. + +```python +neighbors = maze.get_neighbors(2, 2) # список Cell +``` + +Направления обхода: вниз → вправо → вверх → влево (порядок влияет на поведение DFS). diff --git a/skorohodovsa/task_2/docs/_build/markdown/stage2.md b/skorohodovsa/task_2/docs/_build/markdown/stage2.md new file mode 100644 index 0000000..c605d04 --- /dev/null +++ b/skorohodovsa/task_2/docs/_build/markdown/stage2.md @@ -0,0 +1,60 @@ +# Этап 2. Загрузка лабиринта из файла + +Во втором этапе реализована загрузка лабиринта из текстового файла с применением паттерна **Builder**. + +## Паттерн Builder + +Процесс создания лабиринта из файла включает несколько шагов: чтение файла, валидацию структуры, парсинг символов и заполнение клеток. Builder скрывает эти детали от клиента — снаружи виден только один метод `build_from_file()`, внутри которого сосредоточена вся логика построения. + +Дополнительное преимущество: в будущем можно легко добавить новый формат (например, JSON или бинарный) через новую реализацию `MazeBuilder` без изменения остального кода. + +## Класс `MazeBuilder` + +Абстрактный базовый класс — интерфейс паттерна Builder. Объявляет единственный метод `build_from_file()`, который обязан реализовать каждый конкретный строитель. + +По условию задания интерфейс назывался `MazeBuilder` с методом `buildFromFile`. В реализации название метода приведено к **PEP 8** — `build_from_file`. Сам класс оформлен через `ABC` — попытка создать объект `MazeBuilder()` напрямую вызовет `TypeError`. + +## Класс `TextFileBuilder` + +Конкретная реализация строителя для текстовых файлов. Загружает лабиринт из `.txt` файла где `#` — стена, — проход, `S` — старт, `E` — выход. + +Процесс построения разбит на три приватных шага: + +### `_read_file` + +Читает файл построчно и обрезает символы переноса строки `\n` и `\r`. Возвращает список строк — каждая строка соответствует одной строке лабиринта. + +### `_test_text_maze` + +Валидирует структуру: проверяет что все строки одинаковой длины. Если нет — лабиринт некорректен и `_create_maze` выбросит `ValueError`. + +Реализован как `@staticmethod` — не использует состояние объекта, только входные данные. + +### `_create_maze` + +Создаёт объект `Maze` нужного размера и заполняет его клетки символами из файла через `maze[y, x] = symbol`. Тип каждой клетки определяется автоматически через `cell_mapping` в `__setitem__` лабиринта. + +## Использование + +```python +from source.build.builder import TextFileBuilder + +maze = TextFileBuilder().build_from_file('source/templates/10x10_path_v1.txt') +print(maze) +``` + +## Известная ошибка + +В текущей реализации `_create_maze` есть опечатка при вычислении `width`: + +```python +height, width = len(text_maze), len(text_maze) # width всегда равен height +``` + +Правильная версия: + +```python +height, width = len(text_maze), len(text_maze[0]) +``` + +На квадратных лабиринтах (10×10, 50×50) это не проявляется, но на прямоугольных даст некорректный результат. diff --git a/skorohodovsa/task_2/docs/_build/markdown/stage3.md b/skorohodovsa/task_2/docs/_build/markdown/stage3.md new file mode 100644 index 0000000..8a52b27 --- /dev/null +++ b/skorohodovsa/task_2/docs/_build/markdown/stage3.md @@ -0,0 +1,90 @@ +# Этап 3. Стратегии поиска пути + +В третьем этапе реализованы алгоритмы поиска пути с применением паттерна **Strategy**. + +## Паттерн Strategy + +Все три алгоритма реализуют один интерфейс `PathFindingStrategy`. Это позволяет переключать алгоритм в любой момент без изменения кода клиента — достаточно передать другой объект стратегии: + +```python +solver = MazeSolver(maze, BFSStrategy()) +solver.set_strategy(AStarStrategy()) +``` + +Новый алгоритм добавляется реализацией интерфейса — остальной код трогать не нужно. + +## Структура пакета + +Стратегии разбиты по отдельным файлам, а `__init__.py` собирает всё в один импорт: + +```default +source/strategy/ +├── __init__.py ← единственный импорт для пользователя +├── algorithms.py ← базовый класс PathFindingStrategy +├── bfs.py +├── dfs.py +└── astar.py +``` + +```python +from source.strategy import BFSStrategy, DFSStrategy, AStarStrategy +``` + +## Класс `PathFindingStrategy` + +Абстрактный базовый класс — интерфейс паттерна. Объявляет абстрактный метод `find_path()` и содержит два вспомогательных метода, общих для всех стратегий. + +По условию задания метод назывался `findPath` — приведён к **PEP 8** как `find_path`. + +### `_validate` + +Добавлен в процессе разработки — изначально в задании не было требования к обработке отсутствия старта или выхода. Проблема проявилась при тестировании лабиринтов типа `noexit`: алгоритм падал с `AttributeError` внутри, вместо понятного сообщения. + +`_validate` подставляет `start` и `exit` из лабиринта если они не переданы явно, и выбрасывает `ValueError` с понятным сообщением если клетки не найдены: + +```python +start, exit = self._validate(maze, start, exit) +``` + +Вынесен в базовый класс чтобы не дублировать в каждом алгоритме. + +### `_reconstruct_path` + +Восстанавливает путь по словарю предков `came_from`. Все три алгоритма строят этот словарь одинаково — `{клетка: откуда_пришли}` — поэтому восстановление вынесено в общий метод базового класса. + +Алгоритм идёт от выхода к старту по цепочке предков, затем разворачивает список: + +```default +exit → D → C → B → start (идём по came_from) +start → B → C → D → exit (после reverse) +``` + +## Алгоритмы + +### BFS — `BFSStrategy` + +Поиск в ширину. Использует `deque` как очередь (FIFO) — каждый раз берём самую старую клетку из начала. Это гарантирует послойный обход и кратчайший путь по количеству шагов. + +Сложность: O(V + E) по времени и памяти. + +### DFS — `DFSStrategy` + +Поиск в глубину. Использует `list` как стек (LIFO) — каждый раз берём самую свежую клетку с конца. Алгоритм ныряет вглубь по одному направлению до тупика, затем возвращается. + +Не гарантирует кратчайший путь. На запутанных лабиринтах может обойти почти все клетки прежде чем найти выход, хотя по времени часто быстрее BFS из-за меньших накладных расходов на структуру данных. + +Сложность: O(V + E) по времени и памяти. + +### A\* — `AStarStrategy` + +Использует `heapq` как приоритетную очередь. На каждом шаге выбирает клетку с минимальным значением `f = g + h`, где `g` — стоимость пути от старта, `h` — манхэттенская эвристика до выхода. + +Эвристика направляет поиск в сторону выхода, поэтому A\* обходит меньше клеток чем BFS при том же гарантированно кратчайшем пути. + +В кортеж приоритетной очереди добавлен счётчик `counter` как tie-breaker — без него `heapq` попытался бы сравнивать объекты `Cell` при одинаковом `f`, что вызвало бы `TypeError`: + +```python +heapq.heappush(open_heap, (f, counter, neighbor)) +``` + +Сложность: O(E · log V) в худшем случае. diff --git a/skorohodovsa/task_2/docs/_build/markdown/stage4.md b/skorohodovsa/task_2/docs/_build/markdown/stage4.md new file mode 100644 index 0000000..cc800b4 --- /dev/null +++ b/skorohodovsa/task_2/docs/_build/markdown/stage4.md @@ -0,0 +1,44 @@ +# Этап 4. Класс-оркестратор MazeSolver + +В четвёртом этапе реализован класс `MazeSolver`, который объединяет лабиринт и стратегию поиска, выполняет поиск и собирает статистику. + +## Роль в архитектуре + +`MazeSolver` — точка входа для клиентского кода. Он не знает деталей ни одного алгоритма и не работает напрямую с клетками лабиринта — только делегирует задачу стратегии и замеряет время: + +```python +solver = MazeSolver(maze, BFSStrategy()) +stats = solver.solve() +print(stats) +# Время: 0.041 мс | Посещено клеток: 13 | Длина пути: 13 +``` + +## Класс `SearchStats` + +Оформлен через `@dataclass` — это избавляет от ручного `__init__` и автоматически даёт `__repr__`. Хранит четыре поля: время выполнения, количество посещённых клеток, длину пути и сам путь как список клеток. + +`__str__` переопределён для удобного вывода в консоль и отчётах. + +### Ограничение + +В текущей реализации `visited_count` и `path_length` всегда равны друг другу — оба вычисляются как `len(path)`. Это потому что стратегии возвращают только финальный путь, а не все посещённые клетки. Чтобы получить точное количество посещений, потребовалось бы дорабатывать каждую стратегию — добавлять счётчик внутри `find_path`. На данном этапе это сознательное упрощение. + +## Класс `MazeSolver` + +### `set_strategy` + +Позволяет менять алгоритм без пересоздания солвера. Это и есть основная демонстрация паттерна Strategy в действии — один объект, разные алгоритмы: + +```python +solver = MazeSolver(maze, BFSStrategy()) +stats_bfs = solver.solve() + +solver.set_strategy(AStarStrategy()) +stats_astar = solver.solve() +``` + +### `solve` + +Замеряет время через `time.perf_counter()` — самый точный таймер в Python для коротких интервалов, не зависящий от системных часов. Результат переводится в миллисекунды умножением на 1000. + +`start` и `exit` можно не передавать — стратегия найдёт их сама через `_validate`. Явная передача нужна только если хочется запустить поиск не от стандартного старта, а от произвольной клетки. diff --git a/skorohodovsa/task_2/docs/_build/markdown/stage5.md b/skorohodovsa/task_2/docs/_build/markdown/stage5.md new file mode 100644 index 0000000..0ce2cc4 --- /dev/null +++ b/skorohodovsa/task_2/docs/_build/markdown/stage5.md @@ -0,0 +1,84 @@ +# Этап 5. Визуализация и пошаговое управление + +В пятом этапе реализованы два паттерна: **Observer** для отображения событий и **Command** для пошагового управления игроком. + +## 5.1. Паттерн Observer + +### Идея + +`MazeSolver` и игровой цикл не знают как именно отображать происходящее — они просто генерируют события. Наблюдатели подписываются на эти события и реагируют по своему усмотрению. Это позволяет в будущем добавить, например, `FileLogger` или графический интерфейс без изменения основного кода. + +### Класс `Event` + +Оформлен через `@dataclass`. Хранит тип события строкой и словарь `payload` с дополнительными данными. Поддерживаются четыре типа событий: + +| Тип | Когда генерируется | +|---------------|----------------------------| +| `maze_loaded` | Лабиринт загружен из файла | +| `path_found` | Алгоритм нашёл путь | +| `no_path` | Путь не найден | +| `move` | Игрок сделал ход | + +### Класс `Observer` + +Абстрактный базовый класс с единственным методом `update(event)`. Любой наблюдатель обязан его реализовать. + +### Класс `ConsoleView` + +Конкретная реализация наблюдателя. Обрабатывает события через `match/case` и вызывает `render()` для перерисовки лабиринта. + +Метод `render()` принимает лабиринт, опциональную позицию игрока и опциональный путь. Путь преобразуется в `set` для быстрой проверки принадлежности клетки — это O(1) вместо O(n) при каждом обходе: + +```python +path_set = set(path) if path else set() +``` + +Лабиринт обрамляется рамкой из `+` и `─` для читаемости в консоли. Символы игрока и пути вынесены в константы класса — легко поменять без правки логики: + +```python +PLAYER_SYMBOL = "P" +PATH_SYMBOL = "·" +``` + +## 5.2. Паттерн Command + +### Идея + +Каждое перемещение игрока оборачивается в объект `MoveCommand`. Это позволяет сохранить предыдущее состояние и отменить ход — реализация `undo` становится тривиальной. + +### Класс `Player` + +Простой контейнер для текущей клетки игрока. Намеренно минималистичный — вся логика перемещения и проверок находится в команде, а не в игроке. + +### Класс `Command` + +Абстрактный интерфейс с двумя методами: `execute()` и `undo()`. `execute()` возвращает `bool` — это отличие от классического варианта паттерна, где команды не возвращают значений. Возврат `False` нужен чтобы не добавлять неуспешный ход в историю. + +### Класс `MoveCommand` + +Хранит ссылку на игрока, направление и лабиринт. При `execute()` проверяет проходимость целевой клетки, сохраняет текущую в `_prev_cell` и перемещает игрока. При `undo()` восстанавливает `_prev_cell`. + +Направления вынесены в словарь `DIRECTIONS` на уровне модуля: + +```python +DIRECTIONS = { + "w": (0, -1), # вверх + "s": (0, 1), # вниз + "a": (-1, 0), # влево + "d": (1, 0), # вправо +} +``` + +### Класс `CommandHistory` + +Стек выполненных команд. Хранит только успешные ходы — неуспешные (`execute()` вернул `False`) в историю не добавляются. `undo()` снимает последнюю команду со стека и вызывает её `undo()`. + +Пример игрового цикла: + +```python +cmd = MoveCommand(player, 'd', maze) +if cmd.execute(): + history.push(cmd) # добавляем только успешный ход + +history.undo() # отмена последнего хода +``` diff --git a/skorohodovsa/task_2/docs/_build/markdown/stage6.md b/skorohodovsa/task_2/docs/_build/markdown/stage6.md new file mode 100644 index 0000000..4399a8b --- /dev/null +++ b/skorohodovsa/task_2/docs/_build/markdown/stage6.md @@ -0,0 +1,61 @@ +# Этап 6. Экспериментальная часть + +В шестом этапе проведено сравнение эффективности трёх стратегий поиска пути на лабиринтах разной сложности. Эксперимент реализован в Jupyter Notebook (`practice/main.ipynb`). + +## Подготовка + +Лабиринты загружаются из папки `source/templates` автоматически — все файлы считываются через `os.listdir` и передаются в `TextFileBuilder`. Стратегии собраны в словарь для удобной итерации: + +```python +strategies = { + "BFS": BFSStrategy(), + "DFS": DFSStrategy(), + "A*": AStarStrategy(), +} +``` + +## Замеры + +Каждая пара лабиринт + стратегия запускается **10 раз**, результаты усредняются. Это сглаживает разброс из-за кэширования и фоновой активности системы. + +Лабиринты типа `noexit` пропускаются автоматически — стратегия выбрасывает `ValueError`, который перехватывается через `try/except`, и выполнение продолжается. + +Результаты собираются в список словарей и затем преобразуются в `DataFrame` через pandas. + +## Результаты + +### 10×10 (простой путь) + +На маленьких лабиринтах все три алгоритма показывают практически одинаковое время (~0.03–0.07 мс) и одинаковую длину пути. Разница незначительна — лабиринт слишком мал чтобы эвристика A\* давала преимущество. + +### 50×50 (тупики) + +BFS стабильно быстрее DFS по времени при одинаковой длине пути. DFS заходит в каждый тупик до конца и тратит время на возврат, хотя финальный путь совпадает. A\* показывает время между BFS и DFS. + +### 100×100 (запутанный, spaghetti) + +Наиболее показательные результаты: + +| Стратегия | Время (мс) | Длина пути | +|-------------|--------------|--------------| +| BFS | ~9 | ~210 | +| DFS | ~7 | ~2200 | +| A\* | ~8 | ~210 | + +DFS быстрее по времени, но находит путь в 10 раз длиннее — обходит почти весь лабиринт. BFS и A\* находят кратчайший путь, A\* при этом чуть быстрее за счёт эвристики. + +### 30×30 (пустой) + +Неожиданный результат: DFS быстрее всех (~0.73 мс против 1.1 у BFS и 2.0 у A\*), хотя находит путь из 379 клеток против 55 у BFS. На пустом поле без стен DFS сразу уходит вглубь без возвратов, тогда как BFS строит очередь и обходит клетки волнами во все стороны — это накладные расходы на структуру данных. + +A\* на пустом лабиринте медленнее всех — накладные расходы на `heapq` и вычисление эвристики не окупаются когда препятствий нет. + +## Выводы + +- **BFS** — надёжный выбор по умолчанию. Всегда находит кратчайший путь, время предсказуемо. +- **DFS** — быстрый по времени, но путь непредсказуем. На запутанных лабиринтах может пройти весь граф. Подходит когда важна скорость, а не оптимальность пути. +- **A**\* — лучший выбор для больших лабиринтов с препятствиями. Находит кратчайший путь быстрее BFS за счёт эвристики. На простых или пустых лабиринтах проигрывает из-за накладных расходов на приоритетную очередь. + +## Визуализация + +![[results.png]] diff --git a/skorohodovsa/task_2/docs/_build/markdown/stage7.md b/skorohodovsa/task_2/docs/_build/markdown/stage7.md new file mode 100644 index 0000000..9072b69 --- /dev/null +++ b/skorohodovsa/task_2/docs/_build/markdown/stage7.md @@ -0,0 +1,33 @@ +# Этап 7. Отчёт + +## Описание задачи + +Разработать программу для загрузки лабиринта из файла, поиска пути с выбором алгоритма и сравнения их эффективности. Применены четыре паттерна GoF: + +| Паттерн | Где применён | +|--------------|-----------------------------------------------| +| **Builder** | `TextFileBuilder` | +| **Strategy** | `BFSStrategy`, `DFSStrategy`, `AStarStrategy` | +| **Observer** | `ConsoleView` | +| **Command** | `MoveCommand`, `CommandHistory` | + +## Диаграмма классов + +## Результаты экспериментов + +| Лабиринт | Быстрее всех | Кратчайший путь | +|-------------------|----------------|-------------------| +| 10×10 path | все одинаково | все одинаково | +| 50×50 deadends | BFS | BFS = A\* | +| 100×100 spaghetti | DFS | BFS = A\* | +| 30×30 empty | DFS | BFS = A\* | + +**BFS** — надёжный выбор, всегда кратчайший путь.
+\\\\ +**DFS** — быстрый, но путь длиннее. На 100×100 обошёл в 10 раз больше клеток.
+\\\\ +**A**\* — лучший на больших лабиринтах с препятствиями, проигрывает на простых из-за накладных расходов на `heapq`. + +## Выводы + +Паттерны сделали код расширяемым: новый алгоритм — один класс, новый формат файла — один класс, новый способ отображения — один класс. Без паттернов каждое такое изменение потребовало бы правки существующего кода. diff --git a/skorohodovsa/task_2/docs/_build/markdown/task.md b/skorohodovsa/task_2/docs/_build/markdown/task.md new file mode 100644 index 0000000..f30ed53 --- /dev/null +++ b/skorohodovsa/task_2/docs/_build/markdown/task.md @@ -0,0 +1,103 @@ +# Задание + +## Цель работы + +Разработать гибкую, расширяемую программу для загрузки лабиринта из файла, поиска пути от старта до выхода с возможностью выбора алгоритма, визуализации процесса и экспериментального сравнения алгоритмов. В ходе работы необходимо применить минимум 3 паттерна проектирования из списка GoF, обосновать их выбор и продемонстрировать преимущества такой архитектуры. + +## Общая схема приложения (пример) + +## Выполнение + +### Этап 1. Модель лабиринта (без паттернов, просто классы) + +**Задача:** Создать классы `Cell` и `Maze`, которые представляют карту лабиринта. + +- `Cell` хранит координаты (x, y), флаги `isWall`, `isStart`, `isExit`, метод `isPassable()` (возвращает `True` для прохода, если не стена). +- `Maze` хранит двумерный массив клеток, ширину, высоту, ссылки на стартовую и выходную клетку. Методы: `getCell(x, y)`, `getNeighbors(cell)` – возвращает список соседних проходимых клеток (вверх, вниз, влево, вправо, если в пределах границ и не стена). + +**Результат:** Лабиринт можно создать вручную в коде, но загрузку пока не делаем. + +### Этап 2. Загрузка лабиринта из файла – применение паттерна **Builder** + +**Задача:** Реализовать загрузку лабиринта из текстового файла, где `#` – стена, ` ` (пробел) – проход, `S` – старт, `E` – выход. + +- Создать интерфейс `MazeBuilder` с методом `buildFromFile(filename)`. +- Реализовать класс `TextFileMazeBuilder`, который читает файл, парсит символы, создаёт объекты `Cell`, задаёт координаты и флаги, после чего возвращает готовый `Maze`. + +Процесс построения лабиринта сложный (парсинг, валидация, установка старта/выхода). Builder скрывает детали создания от клиента. В будущем можно легко добавить другой формат (например, JSON или бинарный) через новую реализацию `MazeBuilder`. + +### Этап 3. Стратегии поиска пути – паттерн **Strategy** + +**Задача:** Реализовать семейство алгоритмов поиска пути от старта до выхода. + +- Создать интерфейс `PathFindingStrategy` с методом `findPath(maze, start, exit)`, возвращающим список клеток пути (от старта до выхода включительно) или пустой список, если пути нет. +- Реализовать минимум 3 стратегии: + - **BFS** (поиск в ширину) – гарантирует кратчайший путь по количеству шагов. + - **DFS** (поиск в глубину) – быстрый, но не обязательно кратчайший. + - **A**\* (с эвристикой, например, манхэттенское расстояние) – компромисс между скоростью и оптимальностью. + - (Опционально) **Дейкстра** – полезна для взвешенных лабиринтов, но в базовом варианте все шаги имеют вес 1, тогда она совпадает с BFS. + +Каждая стратегия возвращает путь. Для BFS/DFS используйте очередь/стек, для A\* – приоритетную очередь (heapq). Важно: алгоритмы не должны модифицировать сам лабиринт, только читать состояние клеток. + +Strategy позволяет легко переключать алгоритмы во время выполнения, не меняя код остальной программы. Новый алгоритм можно добавить, реализовав интерфейс. + +### Этап 4. Класс-оркестратор – **MazeSolver** (использует Strategy) + +**Задача:** Создать класс, который принимает лабиринт и стратегию, выполняет поиск и собирает статистику. + +- `MazeSolver` содержит поля `maze` и `strategy`. +- Метод `setStrategy(strategy)` для динамической смены алгоритма. +- Метод `solve()` вызывает `strategy.findPath(...)` и возвращает объект `SearchStats` (время выполнения в миллисекундах, количество посещённых клеток, длина найденного пути). +- Для замера времени используйте `time.perf_counter()` до и после вызова стратегии. + +### Этап 5. Визуализация и пошаговое управление – паттерны **Observer** и **Command** (по желанию) + +**5.1. Наблюдатель (Observer)** – обновление консольного интерфейса. + +- Создать интерфейс `Observer` с методом `update(event)`, где `event` может быть строкой или объектом с типом события (`"path_found"`, `"move"`, `"maze_loaded"`). +- Реализовать класс `ConsoleView`, который отображает лабиринт, текущее положение игрока (если реализован пошаговый режим) и найденный путь. Метод `render(maze, player_position, path)` рисует карту в консоли. +- `MazeSolver` (или отдельный контроллер) может иметь список наблюдателей и уведомлять их при изменении состояния. + +**5.2. Команда (Command)** – для пошагового перемещения игрока по найденному пути (или ручного управления). + +- Создать интерфейс `Command` с методами `execute()` и `undo()`. +- Реализовать `MoveCommand`, который принимает игрока (`Player`), направление и изменяет его позицию, сохраняя предыдущую для отмены. +- Создать класс `Player`, хранящий текущую клетку. +- Консольное меню позволяет вводить команды (W/A/S/D), выполнять `MoveCommand`, при необходимости отменять последний ход (Ctrl+Z). Это опционально, но очень наглядно демонстрирует паттерн. + +*Observer можно реализовать только для вывода сообщений о начале/конце поиска, а Command – для демонстрации undo при ручном исследовании лабиринта.* + +### Этап 6. Экспериментальная часть (аналогично заданию со структурами данных) + +**Задача:** Сравнить эффективность реализованных стратегий на лабиринтах разной сложности. + +1. **Подготовка тестовых лабиринтов:** + - Маленький (10×10) с простым путём. + - Средний (50×50) с тупиками. + - Большой (100×100) с запутанной структурой. + - «Пустой» лабиринт (без стен) – для демонстрации максимальной производительности. + - «Без выхода» – чтобы проверить обработку отсутствия пути. +2. **Замеры:** + - Для каждого лабиринта и каждой стратегии запустить `solve()` 5–10 раз, усреднить время, количество посещённых клеток, длину пути. + - Записать результаты в CSV: `лабиринт,стратегия,время_мс,посещено_клеток,длина_пути`. +3. **Анализ:** + - Построить графики для каждого лабиринта. + - Проанализировать и написать выводы по итогам (эффективность того или иного алгоритма в разных случаях). +4. **Дополнительное задание:** Реализовать взвешенные клетки (например, болото – вес 3, песок – вес 2, асфальт – вес 1) и сравнить Дейкстру с A\* на взвешенном графе. + +### Этап 7. Отчёт + +**Структура отчёта:** + +1. Описание задачи и выбранных паттернов (с диаграммой классов из Mermaid). +2. Листинги ключевых классов (можно выборочно) или ссылка на репозиторий. +3. Результаты экспериментов (таблицы, графики). +4. Анализ эффективности алгоритмов и применимости паттернов. +5. Выводы: как ООП и паттерны помогли сделать код гибким и расширяемым. Что было бы сложно изменить без них. + +## Советы + +- Для A\* самая простая эвристика: `abs(x1 - x2) + abs(y1 - y2)`. +- При поиске пути надо хранить предшественников (`parent` для каждой посещённой клетки), чтобы восстановить путь. +- Для BFS/DFS используй `deque` (очередь) и `list` (стек). +- Визуализацию в консоли можно сделать с помощью `os.system('cls' if os.name == 'nt' else 'clear')` для перерисовки. diff --git a/skorohodovsa/task_2/docs/source/api.md b/skorohodovsa/task_2/docs/source/api.md index 58caf5f..cf2f512 100644 --- a/skorohodovsa/task_2/docs/source/api.md +++ b/skorohodovsa/task_2/docs/source/api.md @@ -2,16 +2,25 @@ ## Базовые модели -````{eval-rst} +```{eval-rst} .. automodule:: source.models.base :members: :undoc-members: :show-inheritance: -```` +``` + +## Загрузка лабиринта + +```{eval-rst} +.. automodule:: source.build.builder + :members: + :undoc-members: + :show-inheritance: +``` ## Стратегии поиска пути -````{eval-rst} +```{eval-rst} .. automodule:: source.strategy.algorithms :members: :undoc-members: @@ -31,4 +40,31 @@ :members: :undoc-members: :show-inheritance: -```` \ No newline at end of file +``` + +## Оркестратор + +```{eval-rst} +.. automodule:: source.strategy.solver + :members: + :undoc-members: + :show-inheritance: +``` + +## Визуализация + +```{eval-rst} +.. automodule:: source.view.observer + :members: + :undoc-members: + :show-inheritance: +``` + +## Управление игроком + +```{eval-rst} +.. automodule:: source.view.command + :members: + :undoc-members: + :show-inheritance: + ``` \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/source/conf.py b/skorohodovsa/task_2/docs/source/conf.py index 4eeb0f1..8fcfe48 100644 --- a/skorohodovsa/task_2/docs/source/conf.py +++ b/skorohodovsa/task_2/docs/source/conf.py @@ -35,6 +35,7 @@ extensions = [ "sphinx.ext.mathjax", "sphinx_new_tab_link", "sphinx.ext.autosummary", + "sphinxcontrib.mermaid", ] autosummary_generate = True diff --git a/skorohodovsa/task_2/docs/source/index.md b/skorohodovsa/task_2/docs/source/index.md index a1f0950..0d882ed 100644 --- a/skorohodovsa/task_2/docs/source/index.md +++ b/skorohodovsa/task_2/docs/source/index.md @@ -1,6 +1,15 @@ # Лабораторная работа "Поиск выхода из лабиринта" + :::{toctree} :maxdepth: 2 -naming_maze -api \ No newline at end of file +task +stage1 +stage2 +stage3 +stage4 +stage5 +stage6 +stage7 +api + diff --git a/skorohodovsa/task_2/docs/source/naming_maze.md b/skorohodovsa/task_2/docs/source/naming_maze.md deleted file mode 100644 index 11b4e13..0000000 --- a/skorohodovsa/task_2/docs/source/naming_maze.md +++ /dev/null @@ -1,95 +0,0 @@ -# Этап 2. Загрузка лабиринта из файла - -Во втором этапе разработки необходимо реализовать загрузку лабиринта из текстового файла, где: `#` – стена, ` ` – проход, `S` – старт, `E` – выход. - -## Систематизация файлов - -Для удобного хранения лабиринтов было решено сделать систему наименования текстовых файлов в папке `source/templates`. - -Общая структура: - -``` -{размер}_{свойство 1}-{свойство 2}-{свойство n}_{версия}.txt -``` - -### Размер - -Формат: `{ширина}x{высота}` - -| Пример | Значение | -|--------|----------| -| `10x10` | 10×10 клеток | -| `50x50` | 50×50 клеток | -| `100x100` | 100×100 клеток | -| `30x30` | 30×30 клеток | -| `20x20` | 20×20 клеток | -### Свойства -| Свойство | Код | Описание | -| ------------ | ----------- | -------------------------------------------------------------------------------------------- | -| Простой путь | `path` | Существует маршрут от S до E | -| Тупики | `deadends` | Лабиринт специально содержит тупики (могут быть и в других типах, но здесь — гарантированно) | -| Запутанный | `spaghetti` | Сложная структура с циклами и ложными ходами | -| Пустой | `empty` | Нет стен (`#`), только пробелы, S и E | -| Без выхода | `noexit` | В лабиринте отсутствует символ `E` | -### Версия - -Формат: `v{номер}` -- `v1`, `v2`, `v10` -### Примеры -#### Маленькие (10×10, простой путь) - -``` -10x10_path_v1.txt -10x10_path_v2.txt -... -10x10_path_v10.txt -``` -#### Средние (50×50, тупики) - -``` -50x50_deadends_v1.txt -50x50_deadends_v2.txt -... -50x50_deadends_v10.txt -``` -#### Большие (100×100, запутанные) - -``` -100x100_spaghetti_v1.txt -100x100_spaghetti_v2.txt -... -100x100_spaghetti_v10.txt -``` - -#### Пустые (30×30) - -``` -30x30_empty_v1.txt -30x30_empty_v2.txt -... -30x30_empty_v10.txt -``` - -#### Без выхода (20×20) - -``` -20x20_noexit_v1.txt -20x20_noexit_v2.txt -... -20x20_noexit_v10.txt -``` - -#### Комбинированные свойства - -``` -50x50_deadends-noexit_v1.txt -100x100_spaghetti-noexit_v1.txt -10x10_path-empty_v1.txt (избыточно, но допустимо) -``` - -### Примечание - -- Регистр имён файлов: **нижний регистр** -- Разделители: только `_` и `-` -- Расширение: `.txt` -- Кодировка: UTF-8 \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/source/stage1.md b/skorohodovsa/task_2/docs/source/stage1.md new file mode 100644 index 0000000..0365c1c --- /dev/null +++ b/skorohodovsa/task_2/docs/source/stage1.md @@ -0,0 +1,91 @@ +# Этап 1. Модель лабиринта + +В первом этапе разработки необходимо создать базовые классы `Cell` и `Maze`, которые представляют карту лабиринта. Паттерны на этом этапе не применяются — только чистые классы. + +## Класс `Cell` + +Клетка — минимальная единица лабиринта. Хранит координаты и тип: стена, старт, выход или пустая. + +По условию задания клетка должна иметь флаги `isWall`, `isStart`, `isExit` и метод `isPassable()`. В реализации флаги оформлены как **свойства** (`@property`) с сеттерами — это позволяет автоматически сбрасывать остальные флаги при установке нового типа. + +```python +cell = Cell(1, 1) +cell.is_wall = True +``` + +Типы клетки взаимоисключают друг друга — клетка не может быть одновременно стеной и стартом. Логика сброса вынесена в приватный метод `_clear_flags()`. + +### Символьное представление + +Для вывода лабиринта в консоль каждая клетка возвращает символ через `__str__`. Символы берутся из `cell_mapping` в `source/settings.py`, что позволяет менять отображение без правки классов: + +|Тип|Символ по умолчанию| +|---|---| +|Стена|`#`| +|Старт|`S`| +|Выход|`E`| +|Пустая|| + +## Класс `Maze` + +Лабиринт хранит двумерный список клеток и предоставляет методы для работы с ними. + +По условию задания требовались методы `getCell(x, y)` и `getNeighbors(cell)`. В реализации добавлено несколько вещей сверх задания: + +### Именование методов + +Задание написано в стиле Java/pseudocode — названия методов и полей используют `camelCase` (`isWall`, `getCell`, `isPassable`). В Python принят другой стандарт именования — **PEP 8**, который предписывает `snake_case` для методов и атрибутов. Поэтому все названия были приведены к Python стилю: + +|Задание|Реализация| +|---|---| +|`isWall`|`is_wall`| +|`isStart`|`is_start`| +|`isExit`|`is_exit`| +|`isPassable()`|`is_possible()`| +|`getCell(x, y)`|`get_cell(x, y)`| +|`getNeighbors(cell)`|`get_neighbors(x, y)`| +|`buildFromFile(filename)`|`build_from_file(filename)`| + +Это соответствует стандарту оформления кода на Python и делает API классов идиоматичным для языка. + +### Индексация `maze[row, col]` + +Вместо явного вызова `get_cell()` реализованы `__getitem__` и `__setitem__`, что позволяет обращаться к клеткам естественным образом: + +```python +maze[0, 0] = cell_mapping['wall'] # установить стену +cell = maze[2, 3] # получить клетку +``` + +Обратите внимание: индексация идёт в формате `[row, col]`, то есть сначала строка (Y), потом столбец (X) — аналогично numpy. + +### Свойства `start` и `exit` + +Добавлены свойства для быстрого получения стартовой и выходной клетки без ручного обхода: + +```python +maze.start # Cell или None +maze.exit # Cell или None +``` + +Это оказалось необходимым при реализации алгоритмов поиска пути — стратегии получают `start` и `exit` автоматически из лабиринта. + +### Свойство `shape` + +По аналогии с numpy добавлено свойство `shape`, возвращающее `(height, width)`: + +```python +rows, cols = maze.shape +``` + +Используется в стратегиях поиска и тестах для итерации по лабиринту. + +### `get_neighbors` + +Метод возвращает список проходимых соседей клетки по четырём направлениям. Стены и клетки за границей лабиринта исключаются автоматически. Если переданные координаты вне границ — возвращает `None`. + +```python +neighbors = maze.get_neighbors(2, 2) # список Cell +``` + +Направления обхода: вниз → вправо → вверх → влево (порядок влияет на поведение DFS). \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/source/stage2.md b/skorohodovsa/task_2/docs/source/stage2.md new file mode 100644 index 0000000..db3d870 --- /dev/null +++ b/skorohodovsa/task_2/docs/source/stage2.md @@ -0,0 +1,60 @@ +# Этап 2. Загрузка лабиринта из файла + +Во втором этапе реализована загрузка лабиринта из текстового файла с применением паттерна **Builder**. + +## Паттерн Builder + +Процесс создания лабиринта из файла включает несколько шагов: чтение файла, валидацию структуры, парсинг символов и заполнение клеток. Builder скрывает эти детали от клиента — снаружи виден только один метод `build_from_file()`, внутри которого сосредоточена вся логика построения. + +Дополнительное преимущество: в будущем можно легко добавить новый формат (например, JSON или бинарный) через новую реализацию `MazeBuilder` без изменения остального кода. + +## Класс `MazeBuilder` + +Абстрактный базовый класс — интерфейс паттерна Builder. Объявляет единственный метод `build_from_file()`, который обязан реализовать каждый конкретный строитель. + +По условию задания интерфейс назывался `MazeBuilder` с методом `buildFromFile`. В реализации название метода приведено к **PEP 8** — `build_from_file`. Сам класс оформлен через `ABC` — попытка создать объект `MazeBuilder()` напрямую вызовет `TypeError`. + +## Класс `TextFileBuilder` + +Конкретная реализация строителя для текстовых файлов. Загружает лабиринт из `.txt` файла где `#` — стена, — проход, `S` — старт, `E` — выход. + +Процесс построения разбит на три приватных шага: + +### `_read_file` + +Читает файл построчно и обрезает символы переноса строки `\n` и `\r`. Возвращает список строк — каждая строка соответствует одной строке лабиринта. + +### `_test_text_maze` + +Валидирует структуру: проверяет что все строки одинаковой длины. Если нет — лабиринт некорректен и `_create_maze` выбросит `ValueError`. + +Реализован как `@staticmethod` — не использует состояние объекта, только входные данные. + +### `_create_maze` + +Создаёт объект `Maze` нужного размера и заполняет его клетки символами из файла через `maze[y, x] = symbol`. Тип каждой клетки определяется автоматически через `cell_mapping` в `__setitem__` лабиринта. + +## Использование + +```python +from source.build.builder import TextFileBuilder + +maze = TextFileBuilder().build_from_file('source/templates/10x10_path_v1.txt') +print(maze) +``` + +## Известная ошибка + +В текущей реализации `_create_maze` есть опечатка при вычислении `width`: + +```python +height, width = len(text_maze), len(text_maze) # width всегда равен height +``` + +Правильная версия: + +```python +height, width = len(text_maze), len(text_maze[0]) +``` + +На квадратных лабиринтах (10×10, 50×50) это не проявляется, но на прямоугольных даст некорректный результат. \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/source/stage3.md b/skorohodovsa/task_2/docs/source/stage3.md new file mode 100644 index 0000000..63b9dc3 --- /dev/null +++ b/skorohodovsa/task_2/docs/source/stage3.md @@ -0,0 +1,90 @@ +# Этап 3. Стратегии поиска пути + +В третьем этапе реализованы алгоритмы поиска пути с применением паттерна **Strategy**. + +## Паттерн Strategy + +Все три алгоритма реализуют один интерфейс `PathFindingStrategy`. Это позволяет переключать алгоритм в любой момент без изменения кода клиента — достаточно передать другой объект стратегии: + +```python +solver = MazeSolver(maze, BFSStrategy()) +solver.set_strategy(AStarStrategy()) +``` + +Новый алгоритм добавляется реализацией интерфейса — остальной код трогать не нужно. + +## Структура пакета + +Стратегии разбиты по отдельным файлам, а `__init__.py` собирает всё в один импорт: + +``` +source/strategy/ +├── __init__.py ← единственный импорт для пользователя +├── algorithms.py ← базовый класс PathFindingStrategy +├── bfs.py +├── dfs.py +└── astar.py +``` + +```python +from source.strategy import BFSStrategy, DFSStrategy, AStarStrategy +``` + +## Класс `PathFindingStrategy` + +Абстрактный базовый класс — интерфейс паттерна. Объявляет абстрактный метод `find_path()` и содержит два вспомогательных метода, общих для всех стратегий. + +По условию задания метод назывался `findPath` — приведён к **PEP 8** как `find_path`. + +### `_validate` + +Добавлен в процессе разработки — изначально в задании не было требования к обработке отсутствия старта или выхода. Проблема проявилась при тестировании лабиринтов типа `noexit`: алгоритм падал с `AttributeError` внутри, вместо понятного сообщения. + +`_validate` подставляет `start` и `exit` из лабиринта если они не переданы явно, и выбрасывает `ValueError` с понятным сообщением если клетки не найдены: + +```python +start, exit = self._validate(maze, start, exit) +``` + +Вынесен в базовый класс чтобы не дублировать в каждом алгоритме. + +### `_reconstruct_path` + +Восстанавливает путь по словарю предков `came_from`. Все три алгоритма строят этот словарь одинаково — `{клетка: откуда_пришли}` — поэтому восстановление вынесено в общий метод базового класса. + +Алгоритм идёт от выхода к старту по цепочке предков, затем разворачивает список: + +``` +exit → D → C → B → start (идём по came_from) +start → B → C → D → exit (после reverse) +``` + +## Алгоритмы + +### BFS — `BFSStrategy` + +Поиск в ширину. Использует `deque` как очередь (FIFO) — каждый раз берём самую старую клетку из начала. Это гарантирует послойный обход и кратчайший путь по количеству шагов. + +Сложность: O(V + E) по времени и памяти. + +### DFS — `DFSStrategy` + +Поиск в глубину. Использует `list` как стек (LIFO) — каждый раз берём самую свежую клетку с конца. Алгоритм ныряет вглубь по одному направлению до тупика, затем возвращается. + +Не гарантирует кратчайший путь. На запутанных лабиринтах может обойти почти все клетки прежде чем найти выход, хотя по времени часто быстрее BFS из-за меньших накладных расходов на структуру данных. + +Сложность: O(V + E) по времени и памяти. + +### A* — `AStarStrategy` + +Использует `heapq` как приоритетную очередь. На каждом шаге выбирает клетку с минимальным значением `f = g + h`, где `g` — стоимость пути от старта, `h` — манхэттенская эвристика до выхода. + +Эвристика направляет поиск в сторону выхода, поэтому A* обходит меньше клеток чем BFS при том же гарантированно кратчайшем пути. + +В кортеж приоритетной очереди добавлен счётчик `counter` как tie-breaker — без него `heapq` попытался бы сравнивать объекты `Cell` при одинаковом `f`, что вызвало бы `TypeError`: + +```python +heapq.heappush(open_heap, (f, counter, neighbor)) +``` + +Сложность: O(E · log V) в худшем случае. \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/source/stage4.md b/skorohodovsa/task_2/docs/source/stage4.md new file mode 100644 index 0000000..dc1dd66 --- /dev/null +++ b/skorohodovsa/task_2/docs/source/stage4.md @@ -0,0 +1,44 @@ +# Этап 4. Класс-оркестратор MazeSolver + +В четвёртом этапе реализован класс `MazeSolver`, который объединяет лабиринт и стратегию поиска, выполняет поиск и собирает статистику. + +## Роль в архитектуре + +`MazeSolver` — точка входа для клиентского кода. Он не знает деталей ни одного алгоритма и не работает напрямую с клетками лабиринта — только делегирует задачу стратегии и замеряет время: + +```python +solver = MazeSolver(maze, BFSStrategy()) +stats = solver.solve() +print(stats) +# Время: 0.041 мс | Посещено клеток: 13 | Длина пути: 13 +``` + +## Класс `SearchStats` + +Оформлен через `@dataclass` — это избавляет от ручного `__init__` и автоматически даёт `__repr__`. Хранит четыре поля: время выполнения, количество посещённых клеток, длину пути и сам путь как список клеток. + +`__str__` переопределён для удобного вывода в консоль и отчётах. + +### Ограничение + +В текущей реализации `visited_count` и `path_length` всегда равны друг другу — оба вычисляются как `len(path)`. Это потому что стратегии возвращают только финальный путь, а не все посещённые клетки. Чтобы получить точное количество посещений, потребовалось бы дорабатывать каждую стратегию — добавлять счётчик внутри `find_path`. На данном этапе это сознательное упрощение. + +## Класс `MazeSolver` + +### `set_strategy` + +Позволяет менять алгоритм без пересоздания солвера. Это и есть основная демонстрация паттерна Strategy в действии — один объект, разные алгоритмы: + +```python +solver = MazeSolver(maze, BFSStrategy()) +stats_bfs = solver.solve() + +solver.set_strategy(AStarStrategy()) +stats_astar = solver.solve() +``` + +### `solve` + +Замеряет время через `time.perf_counter()` — самый точный таймер в Python для коротких интервалов, не зависящий от системных часов. Результат переводится в миллисекунды умножением на 1000. + +`start` и `exit` можно не передавать — стратегия найдёт их сама через `_validate`. Явная передача нужна только если хочется запустить поиск не от стандартного старта, а от произвольной клетки. \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/source/stage5.md b/skorohodovsa/task_2/docs/source/stage5.md new file mode 100644 index 0000000..ecca7cd --- /dev/null +++ b/skorohodovsa/task_2/docs/source/stage5.md @@ -0,0 +1,84 @@ +# Этап 5. Визуализация и пошаговое управление + +В пятом этапе реализованы два паттерна: **Observer** для отображения событий и **Command** для пошагового управления игроком. + +## 5.1. Паттерн Observer + +### Идея + +`MazeSolver` и игровой цикл не знают как именно отображать происходящее — они просто генерируют события. Наблюдатели подписываются на эти события и реагируют по своему усмотрению. Это позволяет в будущем добавить, например, `FileLogger` или графический интерфейс без изменения основного кода. + +### Класс `Event` + +Оформлен через `@dataclass`. Хранит тип события строкой и словарь `payload` с дополнительными данными. Поддерживаются четыре типа событий: + +|Тип|Когда генерируется| +|---|---| +|`maze_loaded`|Лабиринт загружен из файла| +|`path_found`|Алгоритм нашёл путь| +|`no_path`|Путь не найден| +|`move`|Игрок сделал ход| + +### Класс `Observer` + +Абстрактный базовый класс с единственным методом `update(event)`. Любой наблюдатель обязан его реализовать. + +### Класс `ConsoleView` + +Конкретная реализация наблюдателя. Обрабатывает события через `match/case` и вызывает `render()` для перерисовки лабиринта. + +Метод `render()` принимает лабиринт, опциональную позицию игрока и опциональный путь. Путь преобразуется в `set` для быстрой проверки принадлежности клетки — это O(1) вместо O(n) при каждом обходе: + +```python +path_set = set(path) if path else set() +``` + +Лабиринт обрамляется рамкой из `+` и `─` для читаемости в консоли. Символы игрока и пути вынесены в константы класса — легко поменять без правки логики: + +```python +PLAYER_SYMBOL = "P" +PATH_SYMBOL = "·" +``` + +## 5.2. Паттерн Command + +### Идея + +Каждое перемещение игрока оборачивается в объект `MoveCommand`. Это позволяет сохранить предыдущее состояние и отменить ход — реализация `undo` становится тривиальной. + +### Класс `Player` + +Простой контейнер для текущей клетки игрока. Намеренно минималистичный — вся логика перемещения и проверок находится в команде, а не в игроке. + +### Класс `Command` + +Абстрактный интерфейс с двумя методами: `execute()` и `undo()`. `execute()` возвращает `bool` — это отличие от классического варианта паттерна, где команды не возвращают значений. Возврат `False` нужен чтобы не добавлять неуспешный ход в историю. + +### Класс `MoveCommand` + +Хранит ссылку на игрока, направление и лабиринт. При `execute()` проверяет проходимость целевой клетки, сохраняет текущую в `_prev_cell` и перемещает игрока. При `undo()` восстанавливает `_prev_cell`. + +Направления вынесены в словарь `DIRECTIONS` на уровне модуля: + +```python +DIRECTIONS = { + "w": (0, -1), # вверх + "s": (0, 1), # вниз + "a": (-1, 0), # влево + "d": (1, 0), # вправо +} +``` + +### Класс `CommandHistory` + +Стек выполненных команд. Хранит только успешные ходы — неуспешные (`execute()` вернул `False`) в историю не добавляются. `undo()` снимает последнюю команду со стека и вызывает её `undo()`. + +Пример игрового цикла: + +```python +cmd = MoveCommand(player, 'd', maze) +if cmd.execute(): + history.push(cmd) # добавляем только успешный ход + +history.undo() # отмена последнего хода +``` \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/source/stage6.md b/skorohodovsa/task_2/docs/source/stage6.md new file mode 100644 index 0000000..410842c --- /dev/null +++ b/skorohodovsa/task_2/docs/source/stage6.md @@ -0,0 +1,63 @@ +# Этап 6. Экспериментальная часть + +В шестом этапе проведено сравнение эффективности трёх стратегий поиска пути на лабиринтах разной сложности. Эксперимент реализован в Jupyter Notebook (`practice/main.ipynb`). + +## Подготовка + +Лабиринты загружаются из папки `source/templates` автоматически — все файлы считываются через `os.listdir` и передаются в `TextFileBuilder`. Стратегии собраны в словарь для удобной итерации: + +```python +strategies = { + "BFS": BFSStrategy(), + "DFS": DFSStrategy(), + "A*": AStarStrategy(), +} +``` + +## Замеры + +Каждая пара лабиринт + стратегия запускается **10 раз**, результаты усредняются. Это сглаживает разброс из-за кэширования и фоновой активности системы. + +Лабиринты типа `noexit` пропускаются автоматически — стратегия выбрасывает `ValueError`, который перехватывается через `try/except`, и выполнение продолжается. + +Результаты собираются в список словарей и затем преобразуются в `DataFrame` через pandas. + +## Результаты + +### 10×10 (простой путь) + +На маленьких лабиринтах все три алгоритма показывают практически одинаковое время (~0.03–0.07 мс) и одинаковую длину пути. Разница незначительна — лабиринт слишком мал чтобы эвристика A* давала преимущество. + +### 50×50 (тупики) + +BFS стабильно быстрее DFS по времени при одинаковой длине пути. DFS заходит в каждый тупик до конца и тратит время на возврат, хотя финальный путь совпадает. A* показывает время между BFS и DFS. + +### 100×100 (запутанный, spaghetti) + +Наиболее показательные результаты: + +|Стратегия|Время (мс)|Длина пути| +|---|---|---| +|BFS|~9|~210| +|DFS|~7|~2200| +|A*|~8|~210| + +DFS быстрее по времени, но находит путь в 10 раз длиннее — обходит почти весь лабиринт. BFS и A* находят кратчайший путь, A* при этом чуть быстрее за счёт эвристики. + +### 30×30 (пустой) + +Неожиданный результат: DFS быстрее всех (~0.73 мс против 1.1 у BFS и 2.0 у A*), хотя находит путь из 379 клеток против 55 у BFS. На пустом поле без стен DFS сразу уходит вглубь без возвратов, тогда как BFS строит очередь и обходит клетки волнами во все стороны — это накладные расходы на структуру данных. + +A* на пустом лабиринте медленнее всех — накладные расходы на `heapq` и вычисление эвристики не окупаются когда препятствий нет. + +## Выводы + +- **BFS** — надёжный выбор по умолчанию. Всегда находит кратчайший путь, время предсказуемо. + +- **DFS** — быстрый по времени, но путь непредсказуем. На запутанных лабиринтах может пройти весь граф. Подходит когда важна скорость, а не оптимальность пути. + +- **A*** — лучший выбор для больших лабиринтов с препятствиями. Находит кратчайший путь быстрее BFS за счёт эвристики. На простых или пустых лабиринтах проигрывает из-за накладных расходов на приоритетную очередь. + +## Визуализация + +![[results.png]] \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/source/stage7.md b/skorohodovsa/task_2/docs/source/stage7.md new file mode 100644 index 0000000..ceaa5a9 --- /dev/null +++ b/skorohodovsa/task_2/docs/source/stage7.md @@ -0,0 +1,81 @@ +# Этап 7. Отчёт + +## Описание задачи + +Разработать программу для загрузки лабиринта из файла, поиска пути с выбором алгоритма и сравнения их эффективности. Применены четыре паттерна GoF: + +|Паттерн|Где применён| +|---|---| +|**Builder**|`TextFileBuilder`| +|**Strategy**|`BFSStrategy`, `DFSStrategy`, `AStarStrategy`| +|**Observer**|`ConsoleView`| +|**Command**|`MoveCommand`, `CommandHistory`| + +## Диаграмма классов + +```{mermaid} +classDiagram + class Cell { + +int x, y + +bool is_wall, is_start, is_exit + +is_possible() bool + } + class Maze { + +get_cell(x, y) Cell + +get_neighbors(x, y) list + +start, exit, shape + } + class MazeBuilder { <> } + class TextFileBuilder + class PathFindingStrategy { + <> + +find_path(maze, start, exit) list + } + class BFSStrategy + class DFSStrategy + class AStarStrategy + class MazeSolver { + +set_strategy(strategy) + +solve() SearchStats + } + class ConsoleView { + +update(event) + +render(maze, player, path) + } + class MoveCommand { + +execute() bool + +undo() + } + class CommandHistory { + +push(command) + +undo() bool + } + + Maze *-- Cell + MazeBuilder <|-- TextFileBuilder + TextFileBuilder ..> Maze : creates + PathFindingStrategy <|-- BFSStrategy + PathFindingStrategy <|-- DFSStrategy + PathFindingStrategy <|-- AStarStrategy + MazeSolver --> PathFindingStrategy + MazeSolver --> Maze + MoveCommand --> Maze + CommandHistory --> MoveCommand +``` + +## Результаты экспериментов + +| Лабиринт | Быстрее всех | Кратчайший путь | +| ----------------- | ------------- | --------------- | +| 10×10 path | все одинаково | все одинаково | +| 50×50 deadends | BFS | BFS = A* | +| 100×100 spaghetti | DFS | BFS = A* | +| 30×30 empty | DFS | BFS = A* | + +**BFS** — надёжный выбор, всегда кратчайший путь. +**DFS** — быстрый, но путь длиннее. На 100×100 обошёл в 10 раз больше клеток. +**A*** — лучший на больших лабиринтах с препятствиями, проигрывает на простых из-за накладных расходов на `heapq`. + +## Выводы + +Паттерны сделали код расширяемым: новый алгоритм — один класс, новый формат файла — один класс, новый способ отображения — один класс. Без паттернов каждое такое изменение потребовало бы правки существующего кода. \ No newline at end of file diff --git a/skorohodovsa/task_2/docs/source/task.md b/skorohodovsa/task_2/docs/source/task.md new file mode 100644 index 0000000..0c9274c --- /dev/null +++ b/skorohodovsa/task_2/docs/source/task.md @@ -0,0 +1,183 @@ +# Задание + +## Цель работы + +Разработать гибкую, расширяемую программу для загрузки лабиринта из файла, поиска пути от старта до выхода с возможностью выбора алгоритма, визуализации процесса и экспериментального сравнения алгоритмов. В ходе работы необходимо применить минимум 3 паттерна проектирования из списка GoF, обосновать их выбор и продемонстрировать преимущества такой архитектуры. + +## Общая схема приложения (пример) + +```{mermaid} +classDiagram + class Maze { + -Cell[] cells + -int width, height + -Cell start + -Cell exit + +getCell(x,y): Cell + +getNeighbors(cell): List~Cell~ + } + + class Cell { + -int x, y + -bool isWall + -bool isStart + -bool isExit + +isPassable(): bool + } + + class MazeBuilder { + <> + +buildFromFile(filename): Maze + } + + class TextFileMazeBuilder { + +buildFromFile(filename): Maze + } + + class PathFindingStrategy { + <> + +findPath(maze, start, exit): List~Cell~ + } + + class BFSStrategy + class DFSStrategy + class AStarStrategy + class DijkstraStrategy + + class SearchStats { + +timeMs: float + +visitedCells: int + +pathLength: int + } + + class MazeSolver { + -Maze maze + -PathFindingStrategy strategy + +setStrategy(strategy) + +solve(): SearchStats + } + + class Command { + <> + +execute() + +undo() + } + + class MoveCommand { + -Player player + -Direction dir + -Cell previousCell + +execute() + +undo() + } + + class Player { + -Cell currentCell + +moveTo(cell) + } + + class Observer { + <> + +update(event) + } + + class ConsoleView { + +update(event) + +render(maze, player, path) + } + + MazeBuilder <|.. TextFileMazeBuilder + MazeBuilder --> Maze : creates + PathFindingStrategy <|.. BFSStrategy + PathFindingStrategy <|.. DFSStrategy + PathFindingStrategy <|.. AStarStrategy + PathFindingStrategy <|.. DijkstraStrategy + MazeSolver --> PathFindingStrategy : uses + MazeSolver --> Maze : uses + Command <|.. MoveCommand + MoveCommand --> Player + Player --> Cell + Observer <|.. ConsoleView + MazeSolver --> Observer : notifies +``` + +## Выполнение + +### Этап 1. Модель лабиринта (без паттернов, просто классы) +**Задача:** Создать классы `Cell` и `Maze`, которые представляют карту лабиринта. +- `Cell` хранит координаты (x, y), флаги `isWall`, `isStart`, `isExit`, метод `isPassable()` (возвращает `True` для прохода, если не стена). +- `Maze` хранит двумерный массив клеток, ширину, высоту, ссылки на стартовую и выходную клетку. Методы: `getCell(x, y)`, `getNeighbors(cell)` – возвращает список соседних проходимых клеток (вверх, вниз, влево, вправо, если в пределах границ и не стена). + +**Результат:** Лабиринт можно создать вручную в коде, но загрузку пока не делаем. + +### Этап 2. Загрузка лабиринта из файла – применение паттерна **Builder** +**Задача:** Реализовать загрузку лабиринта из текстового файла, где `#` – стена, ` ` (пробел) – проход, `S` – старт, `E` – выход. +- Создать интерфейс `MazeBuilder` с методом `buildFromFile(filename)`. +- Реализовать класс `TextFileMazeBuilder`, который читает файл, парсит символы, создаёт объекты `Cell`, задаёт координаты и флаги, после чего возвращает готовый `Maze`. + +Процесс построения лабиринта сложный (парсинг, валидация, установка старта/выхода). Builder скрывает детали создания от клиента. В будущем можно легко добавить другой формат (например, JSON или бинарный) через новую реализацию `MazeBuilder`. + +### Этап 3. Стратегии поиска пути – паттерн **Strategy** +**Задача:** Реализовать семейство алгоритмов поиска пути от старта до выхода. +- Создать интерфейс `PathFindingStrategy` с методом `findPath(maze, start, exit)`, возвращающим список клеток пути (от старта до выхода включительно) или пустой список, если пути нет. +- Реализовать минимум 3 стратегии: + - **BFS** (поиск в ширину) – гарантирует кратчайший путь по количеству шагов. + - **DFS** (поиск в глубину) – быстрый, но не обязательно кратчайший. + - **A*** (с эвристикой, например, манхэттенское расстояние) – компромисс между скоростью и оптимальностью. + - (Опционально) **Дейкстра** – полезна для взвешенных лабиринтов, но в базовом варианте все шаги имеют вес 1, тогда она совпадает с BFS. + +Каждая стратегия возвращает путь. Для BFS/DFS используйте очередь/стек, для A* – приоритетную очередь (heapq). Важно: алгоритмы не должны модифицировать сам лабиринт, только читать состояние клеток. + +Strategy позволяет легко переключать алгоритмы во время выполнения, не меняя код остальной программы. Новый алгоритм можно добавить, реализовав интерфейс. + +### Этап 4. Класс-оркестратор – **MazeSolver** (использует Strategy) +**Задача:** Создать класс, который принимает лабиринт и стратегию, выполняет поиск и собирает статистику. +- `MazeSolver` содержит поля `maze` и `strategy`. +- Метод `setStrategy(strategy)` для динамической смены алгоритма. +- Метод `solve()` вызывает `strategy.findPath(...)` и возвращает объект `SearchStats` (время выполнения в миллисекундах, количество посещённых клеток, длина найденного пути). +- Для замера времени используйте `time.perf_counter()` до и после вызова стратегии. + +### Этап 5. Визуализация и пошаговое управление – паттерны **Observer** и **Command** (по желанию) +**5.1. Наблюдатель (Observer)** – обновление консольного интерфейса. +- Создать интерфейс `Observer` с методом `update(event)`, где `event` может быть строкой или объектом с типом события (`"path_found"`, `"move"`, `"maze_loaded"`). +- Реализовать класс `ConsoleView`, который отображает лабиринт, текущее положение игрока (если реализован пошаговый режим) и найденный путь. Метод `render(maze, player_position, path)` рисует карту в консоли. +- `MazeSolver` (или отдельный контроллер) может иметь список наблюдателей и уведомлять их при изменении состояния. + +**5.2. Команда (Command)** – для пошагового перемещения игрока по найденному пути (или ручного управления). +- Создать интерфейс `Command` с методами `execute()` и `undo()`. +- Реализовать `MoveCommand`, который принимает игрока (`Player`), направление и изменяет его позицию, сохраняя предыдущую для отмены. +- Создать класс `Player`, хранящий текущую клетку. +- Консольное меню позволяет вводить команды (W/A/S/D), выполнять `MoveCommand`, при необходимости отменять последний ход (Ctrl+Z). Это опционально, но очень наглядно демонстрирует паттерн. + +*Observer можно реализовать только для вывода сообщений о начале/конце поиска, а Command – для демонстрации undo при ручном исследовании лабиринта.* + +### Этап 6. Экспериментальная часть (аналогично заданию со структурами данных) +**Задача:** Сравнить эффективность реализованных стратегий на лабиринтах разной сложности. +1. **Подготовка тестовых лабиринтов:** + - Маленький (10×10) с простым путём. + - Средний (50×50) с тупиками. + - Большой (100×100) с запутанной структурой. + - «Пустой» лабиринт (без стен) – для демонстрации максимальной производительности. + - «Без выхода» – чтобы проверить обработку отсутствия пути. +2. **Замеры:** + - Для каждого лабиринта и каждой стратегии запустить `solve()` 5–10 раз, усреднить время, количество посещённых клеток, длину пути. + - Записать результаты в CSV: `лабиринт,стратегия,время_мс,посещено_клеток,длина_пути`. +3. **Анализ:** + - Построить графики для каждого лабиринта. + - Проанализировать и написать выводы по итогам (эффективность того или иного алгоритма в разных случаях). + +4. **Дополнительное задание:** Реализовать взвешенные клетки (например, болото – вес 3, песок – вес 2, асфальт – вес 1) и сравнить Дейкстру с A* на взвешенном графе. + +### Этап 7. Отчёт +**Структура отчёта:** +1. Описание задачи и выбранных паттернов (с диаграммой классов из Mermaid). +2. Листинги ключевых классов (можно выборочно) или ссылка на репозиторий. +3. Результаты экспериментов (таблицы, графики). +4. Анализ эффективности алгоритмов и применимости паттернов. +5. Выводы: как ООП и паттерны помогли сделать код гибким и расширяемым. Что было бы сложно изменить без них. + +## Советы +- Для A* самая простая эвристика: `abs(x1 - x2) + abs(y1 - y2)`. +- При поиске пути надо хранить предшественников (`parent` для каждой посещённой клетки), чтобы восстановить путь. +- Для BFS/DFS используй `deque` (очередь) и `list` (стек). +- Визуализацию в консоли можно сделать с помощью `os.system('cls' if os.name == 'nt' else 'clear')` для перерисовки. \ No newline at end of file diff --git a/skorohodovsa/task_2/practice/main.ipynb b/skorohodovsa/task_2/practice/main.ipynb new file mode 100644 index 0000000..0f49667 --- /dev/null +++ b/skorohodovsa/task_2/practice/main.ipynb @@ -0,0 +1,937 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "b41a67fc", + "metadata": {}, + "source": [ + "# Экспериментальная часть " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "3986182c", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "\n", + "sys.path.insert(0, os.path.abspath(\"..\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "c304f83d", + "metadata": {}, + "outputs": [], + "source": [ + "from source.build.builder import TextFileBuilder\n", + "from source.models.base import Maze\n", + "from source.strategy import BFSStrategy, DFSStrategy, AStarStrategy\n", + "from source.strategy.solver import MazeSolver, SearchStats" + ] + }, + { + "cell_type": "markdown", + "id": "f4d32c9b", + "metadata": {}, + "source": [ + "**Задача:** Сравнить эффективность реализованных стратегий на лабиринтах разной сложности." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4233a72f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "filenames: list[str] = os.listdir(\"../source/templates\")\n", + "\n", + "list_maze: list[Maze] = [\n", + " TextFileBuilder().build_from_file(filename=\"../source/templates/\" + filename)\n", + " for filename in filenames\n", + "]\n", + "\n", + "list_maze" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "8c9592fb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "50" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(filenames)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "04e5e6a6", + "metadata": {}, + "outputs": [], + "source": [ + "strategies = {\n", + " \"BFS\": BFSStrategy(),\n", + " \"DFS\": DFSStrategy(),\n", + " \"A*\": AStarStrategy(),\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "3ccf351f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v1.txt | BFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v1.txt | DFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v1.txt | A*\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v10.txt | BFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v10.txt | DFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v10.txt | A*\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v2.txt | BFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v2.txt | DFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v2.txt | A*\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v3.txt | BFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v3.txt | DFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v3.txt | A*\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v4.txt | BFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v4.txt | DFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v4.txt | A*\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v5.txt | BFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v5.txt | DFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v5.txt | A*\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v6.txt | BFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v6.txt | DFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v6.txt | A*\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v7.txt | BFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v7.txt | DFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v7.txt | A*\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v8.txt | BFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v8.txt | DFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v8.txt | A*\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v9.txt | BFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v9.txt | DFS\n", + "Выходная клетка не найдена в лабиринте | 20x20_noexit_v9.txt | A*\n" + ] + }, + { + "data": { + "text/plain": [ + "[{'лабиринт': '100x100_spaghetti_v1.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 9.698449999996228,\n", + " 'посещено_клеток': 205.0,\n", + " 'длина_пути': 205.0},\n", + " {'лабиринт': '100x100_spaghetti_v1.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 7.488289999992048,\n", + " 'посещено_клеток': 2129.0,\n", + " 'длина_пути': 2129.0},\n", + " {'лабиринт': '100x100_spaghetti_v1.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 7.629470000074434,\n", + " 'посещено_клеток': 205.0,\n", + " 'длина_пути': 205.0},\n", + " {'лабиринт': '100x100_spaghetti_v10.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 8.57915999999932,\n", + " 'посещено_клеток': 207.0,\n", + " 'длина_пути': 207.0},\n", + " {'лабиринт': '100x100_spaghetti_v10.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 8.580700000084107,\n", + " 'посещено_клеток': 2489.0,\n", + " 'длина_пути': 2489.0},\n", + " {'лабиринт': '100x100_spaghetti_v10.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 8.167220000041198,\n", + " 'посещено_клеток': 207.0,\n", + " 'длина_пути': 207.0},\n", + " {'лабиринт': '100x100_spaghetti_v2.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 8.6136500000066,\n", + " 'посещено_клеток': 217.0,\n", + " 'длина_пути': 217.0},\n", + " {'лабиринт': '100x100_spaghetti_v2.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 6.336869999950068,\n", + " 'посещено_клеток': 2063.0,\n", + " 'длина_пути': 2063.0},\n", + " {'лабиринт': '100x100_spaghetti_v2.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 10.417360000155895,\n", + " 'посещено_клеток': 217.0,\n", + " 'длина_пути': 217.0},\n", + " {'лабиринт': '100x100_spaghetti_v3.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 8.563159999994241,\n", + " 'посещено_клеток': 217.0,\n", + " 'длина_пути': 217.0},\n", + " {'лабиринт': '100x100_spaghetti_v3.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 5.783009999913702,\n", + " 'посещено_клеток': 2107.0,\n", + " 'длина_пути': 2107.0},\n", + " {'лабиринт': '100x100_spaghetti_v3.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 6.953359999988606,\n", + " 'посещено_клеток': 217.0,\n", + " 'длина_пути': 217.0},\n", + " {'лабиринт': '100x100_spaghetti_v4.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 8.79095000000234,\n", + " 'посещено_клеток': 205.0,\n", + " 'длина_пути': 205.0},\n", + " {'лабиринт': '100x100_spaghetti_v4.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 6.422280000060709,\n", + " 'посещено_клеток': 2409.0,\n", + " 'длина_пути': 2409.0},\n", + " {'лабиринт': '100x100_spaghetti_v4.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 6.4153799999985495,\n", + " 'посещено_клеток': 205.0,\n", + " 'длина_пути': 205.0},\n", + " {'лабиринт': '100x100_spaghetti_v5.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 8.864429999994172,\n", + " 'посещено_клеток': 217.0,\n", + " 'длина_пути': 217.0},\n", + " {'лабиринт': '100x100_spaghetti_v5.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 7.053909999922325,\n", + " 'посещено_клеток': 2071.0,\n", + " 'длина_пути': 2071.0},\n", + " {'лабиринт': '100x100_spaghetti_v5.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 10.017580000112503,\n", + " 'посещено_клеток': 217.0,\n", + " 'длина_пути': 217.0},\n", + " {'лабиринт': '100x100_spaghetti_v6.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 9.399200000052588,\n", + " 'посещено_клеток': 243.0,\n", + " 'длина_пути': 243.0},\n", + " {'лабиринт': '100x100_spaghetti_v6.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 7.747049999989031,\n", + " 'посещено_клеток': 1869.0,\n", + " 'длина_пути': 1869.0},\n", + " {'лабиринт': '100x100_spaghetti_v6.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 14.121079999995345,\n", + " 'посещено_клеток': 243.0,\n", + " 'длина_пути': 243.0},\n", + " {'лабиринт': '100x100_spaghetti_v7.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 8.773490000021411,\n", + " 'посещено_клеток': 211.0,\n", + " 'длина_пути': 211.0},\n", + " {'лабиринт': '100x100_spaghetti_v7.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 6.66454999995949,\n", + " 'посещено_клеток': 2283.0,\n", + " 'длина_пути': 2283.0},\n", + " {'лабиринт': '100x100_spaghetti_v7.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 7.22499999997126,\n", + " 'посещено_клеток': 211.0,\n", + " 'длина_пути': 211.0},\n", + " {'лабиринт': '100x100_spaghetti_v8.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 8.687369999961447,\n", + " 'посещено_клеток': 221.0,\n", + " 'длина_пути': 221.0},\n", + " {'лабиринт': '100x100_spaghetti_v8.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 7.4791699999423145,\n", + " 'посещено_клеток': 2473.0,\n", + " 'длина_пути': 2473.0},\n", + " {'лабиринт': '100x100_spaghetti_v8.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 10.324829999944996,\n", + " 'посещено_клеток': 221.0,\n", + " 'длина_пути': 221.0},\n", + " {'лабиринт': '100x100_spaghetti_v9.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 9.33376999992106,\n", + " 'посещено_клеток': 209.0,\n", + " 'длина_пути': 209.0},\n", + " {'лабиринт': '100x100_spaghetti_v9.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 6.118089999927179,\n", + " 'посещено_клеток': 1939.0,\n", + " 'длина_пути': 1939.0},\n", + " {'лабиринт': '100x100_spaghetti_v9.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 7.4974299999212235,\n", + " 'посещено_клеток': 209.0,\n", + " 'длина_пути': 209.0},\n", + " {'лабиринт': '10x10_path_v1.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.03240000014557154,\n", + " 'посещено_клеток': 13.0,\n", + " 'длина_пути': 13.0},\n", + " {'лабиринт': '10x10_path_v1.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.03378000001248438,\n", + " 'посещено_клеток': 13.0,\n", + " 'длина_пути': 13.0},\n", + " {'лабиринт': '10x10_path_v1.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 0.03725999999915075,\n", + " 'посещено_клеток': 13.0,\n", + " 'длина_пути': 13.0},\n", + " {'лабиринт': '10x10_path_v10.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.030790000027991482,\n", + " 'посещено_клеток': 13.0,\n", + " 'длина_пути': 13.0},\n", + " {'лабиринт': '10x10_path_v10.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.035979999984192546,\n", + " 'посещено_клеток': 13.0,\n", + " 'длина_пути': 13.0},\n", + " {'лабиринт': '10x10_path_v10.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 0.03738000000339525,\n", + " 'посещено_клеток': 13.0,\n", + " 'длина_пути': 13.0},\n", + " {'лабиринт': '10x10_path_v2.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.035089999892079504,\n", + " 'посещено_клеток': 17.0,\n", + " 'длина_пути': 17.0},\n", + " {'лабиринт': '10x10_path_v2.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.045300000101633486,\n", + " 'посещено_клеток': 17.0,\n", + " 'длина_пути': 17.0},\n", + " {'лабиринт': '10x10_path_v2.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 0.04377000000204134,\n", + " 'посещено_клеток': 17.0,\n", + " 'длина_пути': 17.0},\n", + " {'лабиринт': '10x10_path_v3.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.035430000025371555,\n", + " 'посещено_клеток': 17.0,\n", + " 'длина_пути': 17.0},\n", + " {'лабиринт': '10x10_path_v3.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.055879999990793294,\n", + " 'посещено_клеток': 17.0,\n", + " 'длина_пути': 17.0},\n", + " {'лабиринт': '10x10_path_v3.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 0.04907000002276618,\n", + " 'посещено_клеток': 17.0,\n", + " 'длина_пути': 17.0},\n", + " {'лабиринт': '10x10_path_v4.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.053650000018024,\n", + " 'посещено_клеток': 29.0,\n", + " 'длина_пути': 29.0},\n", + " {'лабиринт': '10x10_path_v4.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.09142999997493462,\n", + " 'посещено_клеток': 29.0,\n", + " 'длина_пути': 29.0},\n", + " {'лабиринт': '10x10_path_v4.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 0.09646000012253353,\n", + " 'посещено_клеток': 29.0,\n", + " 'длина_пути': 29.0},\n", + " {'лабиринт': '10x10_path_v5.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.035020000041185995,\n", + " 'посещено_клеток': 13.0,\n", + " 'длина_пути': 13.0},\n", + " {'лабиринт': '10x10_path_v5.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.03366999999343534,\n", + " 'посещено_клеток': 13.0,\n", + " 'длина_пути': 13.0},\n", + " {'лабиринт': '10x10_path_v5.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 0.037369999972725054,\n", + " 'посещено_клеток': 13.0,\n", + " 'длина_пути': 13.0},\n", + " {'лабиринт': '10x10_path_v6.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.03128999992441095,\n", + " 'посещено_клеток': 13.0,\n", + " 'длина_пути': 13.0},\n", + " {'лабиринт': '10x10_path_v6.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.03374999996594852,\n", + " 'посещено_клеток': 13.0,\n", + " 'длина_пути': 13.0},\n", + " {'лабиринт': '10x10_path_v6.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 0.037149999934626976,\n", + " 'посещено_клеток': 13.0,\n", + " 'длина_пути': 13.0},\n", + " {'лабиринт': '10x10_path_v7.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.040439999975205865,\n", + " 'посещено_клеток': 17.0,\n", + " 'длина_пути': 17.0},\n", + " {'лабиринт': '10x10_path_v7.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.05008999996789498,\n", + " 'посещено_клеток': 17.0,\n", + " 'длина_пути': 17.0},\n", + " {'лабиринт': '10x10_path_v7.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 0.04825999994864105,\n", + " 'посещено_клеток': 17.0,\n", + " 'длина_пути': 17.0},\n", + " {'лабиринт': '10x10_path_v8.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.04994999994778482,\n", + " 'посещено_клеток': 29.0,\n", + " 'длина_пути': 29.0},\n", + " {'лабиринт': '10x10_path_v8.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.058220000073561096,\n", + " 'посещено_клеток': 29.0,\n", + " 'длина_пути': 29.0},\n", + " {'лабиринт': '10x10_path_v8.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 0.08468999990327575,\n", + " 'посещено_клеток': 29.0,\n", + " 'длина_пути': 29.0},\n", + " {'лабиринт': '10x10_path_v9.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.048520000018470455,\n", + " 'посещено_клеток': 17.0,\n", + " 'длина_пути': 17.0},\n", + " {'лабиринт': '10x10_path_v9.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.04457000009097101,\n", + " 'посещено_клеток': 17.0,\n", + " 'длина_пути': 17.0},\n", + " {'лабиринт': '10x10_path_v9.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 0.04779000005328271,\n", + " 'посещено_клеток': 17.0,\n", + " 'длина_пути': 17.0},\n", + " {'лабиринт': '30x30_empty_v1.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.3075400000161608,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v1.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.7962099999531347,\n", + " 'посещено_клеток': 379.0,\n", + " 'длина_пути': 379.0},\n", + " {'лабиринт': '30x30_empty_v1.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 3.0833899998924608,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v10.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.6444799998680537,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v10.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.1289500000657426,\n", + " 'посещено_клеток': 379.0,\n", + " 'длина_пути': 379.0},\n", + " {'лабиринт': '30x30_empty_v10.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 3.0003100000158156,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v2.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.5947500000493164,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v2.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.0904399999617453,\n", + " 'посещено_клеток': 379.0,\n", + " 'длина_пути': 379.0},\n", + " {'лабиринт': '30x30_empty_v2.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 2.242679999972097,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v3.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.3086099999327416,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v3.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.0075400000459922,\n", + " 'посещено_клеток': 379.0,\n", + " 'длина_пути': 379.0},\n", + " {'лабиринт': '30x30_empty_v3.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 2.17491000003065,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v4.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.5689699999711593,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v4.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.0746400001153233,\n", + " 'посещено_клеток': 379.0,\n", + " 'длина_пути': 379.0},\n", + " {'лабиринт': '30x30_empty_v4.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 2.2863700000471,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v5.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.3352300000406103,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v5.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.8594300000368094,\n", + " 'посещено_клеток': 379.0,\n", + " 'длина_пути': 379.0},\n", + " {'лабиринт': '30x30_empty_v5.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 2.264869999999064,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v6.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.158610000175031,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v6.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.7807300000422401,\n", + " 'посещено_клеток': 379.0,\n", + " 'длина_пути': 379.0},\n", + " {'лабиринт': '30x30_empty_v6.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 2.158290000170382,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v7.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.1674999999286229,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v7.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.7544099999449827,\n", + " 'посещено_клеток': 379.0,\n", + " 'длина_пути': 379.0},\n", + " {'лабиринт': '30x30_empty_v7.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 2.252279999993334,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v8.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.248879999957353,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v8.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.7802099999480561,\n", + " 'посещено_клеток': 379.0,\n", + " 'длина_пути': 379.0},\n", + " {'лабиринт': '30x30_empty_v8.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 2.2779600000831124,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v9.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.201050000054238,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '30x30_empty_v9.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 0.7864399999107263,\n", + " 'посещено_клеток': 379.0,\n", + " 'длина_пути': 379.0},\n", + " {'лабиринт': '30x30_empty_v9.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 2.155060000040976,\n", + " 'посещено_клеток': 55.0,\n", + " 'длина_пути': 55.0},\n", + " {'лабиринт': '50x50_deadends_v1.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.8954199999825505,\n", + " 'посещено_клеток': 729.0,\n", + " 'длина_пути': 729.0},\n", + " {'лабиринт': '50x50_deadends_v1.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.8011099999966973,\n", + " 'посещено_клеток': 729.0,\n", + " 'длина_пути': 729.0},\n", + " {'лабиринт': '50x50_deadends_v1.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 2.820240000028207,\n", + " 'посещено_клеток': 729.0,\n", + " 'длина_пути': 729.0},\n", + " {'лабиринт': '50x50_deadends_v10.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.7890000001225417,\n", + " 'посещено_клеток': 261.0,\n", + " 'длина_пути': 261.0},\n", + " {'лабиринт': '50x50_deadends_v10.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.94999999994252,\n", + " 'посещено_клеток': 261.0,\n", + " 'длина_пути': 261.0},\n", + " {'лабиринт': '50x50_deadends_v10.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 1.0044500000731205,\n", + " 'посещено_клеток': 261.0,\n", + " 'длина_пути': 261.0},\n", + " {'лабиринт': '50x50_deadends_v2.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.0780099999919912,\n", + " 'посещено_клеток': 249.0,\n", + " 'длина_пути': 249.0},\n", + " {'лабиринт': '50x50_deadends_v2.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.8470900000920665,\n", + " 'посещено_клеток': 249.0,\n", + " 'длина_пути': 249.0},\n", + " {'лабиринт': '50x50_deadends_v2.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 1.1555500000213215,\n", + " 'посещено_клеток': 249.0,\n", + " 'длина_пути': 249.0},\n", + " {'лабиринт': '50x50_deadends_v3.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.9816600000704057,\n", + " 'посещено_клеток': 297.0,\n", + " 'длина_пути': 297.0},\n", + " {'лабиринт': '50x50_deadends_v3.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.8496700000014243,\n", + " 'посещено_клеток': 297.0,\n", + " 'длина_пути': 297.0},\n", + " {'лабиринт': '50x50_deadends_v3.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 1.18772000005265,\n", + " 'посещено_клеток': 297.0,\n", + " 'длина_пути': 297.0},\n", + " {'лабиринт': '50x50_deadends_v4.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.5539699999862933,\n", + " 'посещено_клеток': 413.0,\n", + " 'длина_пути': 413.0},\n", + " {'лабиринт': '50x50_deadends_v4.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.6492100000050414,\n", + " 'посещено_клеток': 413.0,\n", + " 'длина_пути': 413.0},\n", + " {'лабиринт': '50x50_deadends_v4.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 1.9135399998958746,\n", + " 'посещено_клеток': 413.0,\n", + " 'длина_пути': 413.0},\n", + " {'лабиринт': '50x50_deadends_v5.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.1528699998507363,\n", + " 'посещено_клеток': 309.0,\n", + " 'длина_пути': 309.0},\n", + " {'лабиринт': '50x50_deadends_v5.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.7570300000897987,\n", + " 'посещено_клеток': 309.0,\n", + " 'длина_пути': 309.0},\n", + " {'лабиринт': '50x50_deadends_v5.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 1.199769999993805,\n", + " 'посещено_клеток': 309.0,\n", + " 'длина_пути': 309.0},\n", + " {'лабиринт': '50x50_deadends_v6.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.0987699999986944,\n", + " 'посещено_клеток': 337.0,\n", + " 'длина_пути': 337.0},\n", + " {'лабиринт': '50x50_deadends_v6.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.9475800000236632,\n", + " 'посещено_клеток': 337.0,\n", + " 'длина_пути': 337.0},\n", + " {'лабиринт': '50x50_deadends_v6.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 1.3809099999434693,\n", + " 'посещено_клеток': 337.0,\n", + " 'длина_пути': 337.0},\n", + " {'лабиринт': '50x50_deadends_v7.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.8687199999258155,\n", + " 'посещено_клеток': 261.0,\n", + " 'длина_пути': 261.0},\n", + " {'лабиринт': '50x50_deadends_v7.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.8890300000293792,\n", + " 'посещено_клеток': 261.0,\n", + " 'длина_пути': 261.0},\n", + " {'лабиринт': '50x50_deadends_v7.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 1.1017699999683828,\n", + " 'посещено_клеток': 261.0,\n", + " 'длина_пути': 261.0},\n", + " {'лабиринт': '50x50_deadends_v8.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 1.7002200001115853,\n", + " 'посещено_клеток': 565.0,\n", + " 'длина_пути': 565.0},\n", + " {'лабиринт': '50x50_deadends_v8.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.7665699999724893,\n", + " 'посещено_клеток': 565.0,\n", + " 'длина_пути': 565.0},\n", + " {'лабиринт': '50x50_deadends_v8.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 2.3602600000231178,\n", + " 'посещено_клеток': 565.0,\n", + " 'длина_пути': 565.0},\n", + " {'лабиринт': '50x50_deadends_v9.txt',\n", + " 'стратегия': 'BFS',\n", + " 'время_мс': 0.7835800000066229,\n", + " 'посещено_клеток': 209.0,\n", + " 'длина_пути': 209.0},\n", + " {'лабиринт': '50x50_deadends_v9.txt',\n", + " 'стратегия': 'DFS',\n", + " 'время_мс': 1.0580000001027656,\n", + " 'посещено_клеток': 209.0,\n", + " 'длина_пути': 209.0},\n", + " {'лабиринт': '50x50_deadends_v9.txt',\n", + " 'стратегия': 'A*',\n", + " 'время_мс': 0.8593499999733467,\n", + " 'посещено_клеток': 209.0,\n", + " 'длина_пути': 209.0}]" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "RUNS = 10\n", + "results = []\n", + "\n", + "\n", + "for filename, maze in zip(filenames, list_maze):\n", + " for strategy_name, strategy in strategies.items():\n", + " try:\n", + " solver = MazeSolver(maze, strategy)\n", + "\n", + " times, visited, lengths = [], [], []\n", + " for _ in range(RUNS):\n", + " stats = solver.solve()\n", + " times.append(stats.elapsed_ms)\n", + " visited.append(stats.visited_count)\n", + " lengths.append(stats.path_length)\n", + "\n", + " results.append(\n", + " {\n", + " \"лабиринт\": filename,\n", + " \"стратегия\": strategy_name,\n", + " \"время_мс\": sum(times) / RUNS,\n", + " \"посещено_клеток\": sum(visited) / RUNS,\n", + " \"длина_пути\": sum(lengths) / RUNS,\n", + " }\n", + " )\n", + " except Exception as ex:\n", + " print(ex, filename, strategy_name, sep=\" | \")\n", + "\n", + "results" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "f6cfb407", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "120" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(results)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "c6d14f8d", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABKYAAAVuCAYAAABP0jSLAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjksIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvJkbTWQAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzs3Qm8TdX/+P/lulzzlHkmmTJXMlWmlCIipAlpQIo0oIyV0GTIWDLVh6IkUSQRlcisEDJGZhkz7//jvX7/c77nuvdc3LPPOmev+3o+Hptz9773vM97nT2uvdbaqRzHcRQAAAAAAABgWIzpgAAAAAAAAICgYgoAAAAAAAARQcUUAAAAAAAAIoKKKQAAAAAAAEQEFVMAAAAAAACICCqmAAAAAAAAEBFUTAEAAAAAACAiqJgCAAAAAABARFAxBQAAAAAAgIigYgoAAMBS3377rYqNjVWbNm0yEm/fvn0qQ4YMatKkSUbiAQAA76NiCgAAWGXRokUqVapU8aZ06dKp4sWLq3bt2qmNGzeqlODChQvqhRdeUA8//LAqXbq0kZh58+ZVHTp0UK+++qo6ffq0kZgAAMDbUjmO40T6QwAAALhZMVWnTh3VunVrdc899+h5//33n1q3bp0aN26cSpMmjVq/fr0qUqSI1YU+depU9dBDD6k1a9aoihUrGou7Y8cOXQn4/vvvq2eeecZYXAAA4E2xkf4AAAAA4VClShX1yCOPxJt3ww03qC5duqgZM2ao559/3uqCHzVqlKpQoYLRSilRtGhRddttt6mxY8dSMQUAAK6IrnwAACDFyJ8/v/4/bdq08Vr4SHe/fv366VZGUpkjXf8KFy6s50mXuMv9888/qmPHjvp35L3kfZ966il14MCBeL8nfy/vHRcXl2CZuOmmm/Ty2rVrx5t/5swZ9dprr+kueDJmU2C3xLZt217VWE8//fSTv8WYG59JLFy4UN17773quuuu83ePbN++vTp06FC832vYsKFulWZqbCsAAOBdtJgCAABWkjGOfBUm0pXv999/12Mf5cyZUzVv3jzB78+aNUtt27ZNt/KRsZLk5/79+6udO3eqCRMm+H9v165dqnr16urcuXO6Uub6669XW7duVaNHj9YVNytWrFBZs2aN996pU6fW3QhfeeUV/7xff/1VrVq1SlfwXK5Hjx5q2LBh6u6779YtuzJmzKjnP/roo1eV+48//qj/r1q1atDfudbPJC2gpDKuQIEC+n/pCill8fXXX6u///5bl6uPlI+vW6Wp8a0AAIA3UTEFAACs1LdvXz0FKlu2rFqyZImueLrc2rVr1W+//aa7AIrOnTurZs2aqYkTJ6qnn35aVatWTc9/9tln1fnz59Xq1atVwYIF/X/fokUL/TtDhgzRrZICPfjgg+qDDz7QFU4xMTH+rnYyFpZUhl1u+vTpqlSpUmrOnDn+37+WiqkNGzbo/6XSLJhr+UxS8fTcc8/pSqZffvlFZcuWzb/s9ddfV5cuXYr3+764f/zxx1V9XgAAkHLRlQ8AAFhJutbNnz9fT9KqZ/DgwboFlXRvk1ZQl7vzzjv9lVJCurO9/PLL+vWXX36p/z927JiaPXu2uu+++3SrInk/3yRjK5UoUUJ99913Cd77ySefVHv37tV/K+T3p02bpjp16pToZz9x4oTKnj17vEqpa3Hw4EH9f44cOYL+zrV8JqkokxZiUtEXWCnlc/nnlK5+IrGuggAAAIGomAIAAFaSgc7r16+vp0aNGulKJumet337dtW9e/cEv1+mTJkE86SFlfC1IPrzzz9166CPPvpI5cqVK8Eky/fv35/gffLly6fuv/9+3SJJyN9L5U3Tpk0T/ex33HGHWrZsmXrvvfd0JZqv8utqSaWaSOrhy9fymbZs2aL/r1y58lXF98X1fQ4AAIBg6MoHAABSjFtvvVWP//TDDz8k6+99FS7ytL82bdok+jvp06dPdL60RJJucps3b1ZjxozRLZZiYxM/FZMudk888YR68cUX1QsvvHDNn1MqycSRI0dUoUKFgv7etXymayFxAz8HAABAMFRMAQCAFEWesnf27NkE8zdu3Bh0rCZ5+pyQrnrSCki6tUlLrGshraCkBVbr1q31mE3S1TCp1kzyhEBpoSRd56Qboq+74dUoV66cv6VTxYoVQ/5MJUuW1P+vWbPG/zopMhh84OcAAAAIhq58AAAgxZDxpk6dOqVuuummRJfJE+kCW0e99dZb+rWve5t0dZMxqmbMmKGfYHc5+Rvf+E7BWihJDBmjKn/+/El+1rZt26qjR4+qL774wt8l8WpJhZNI7DMm5zM98MADKm3atPophcePH0+w/PIug764vs8BAAAQDC2mAACAlaSy5ZNPPtGvpYWUPCFOusilSZNGvfHGGwl+X1oW1a1bVz3zzDO6xdJXX32lvv/+e/0kvOrVq/t/b/To0apWrVrq9ttvV4899phu1STjTsk4VPI3Mu/yp/L5yNP9WrZsqTJmzJjkZ5cKsZkzZ+qByWVQ9WslXehq166tvvnmG/XOO+8k+btX85nk6YNDhw7VZVO+fHmdY5EiRdSePXt0zuPHj1eVKlXy/77Eld+Tp/gBAAAkhYopAABgJekKJ5PvqXHS2qlBgwaqZ8+e6pZbbknw+9JiqFSpUmrgwIF6EPPcuXOr3r176ymQjNm0cuVK3b1OKmWk8kue0CfzGzdurCt5gkmdOrXKmTNnkp970aJF6pVXXlGvvvqqbp2VXB07dlStWrXSnzWxFmLX8pl873f99dert99+Ww0fPlxX9kkLq3r16sUbx2rHjh3qp59+Uu+//36yPzsAAEg5UjlJPa4FAADAclKRUqxYMdW3b9+gLZ286OLFi7oVmLRk8rUcM+H5559X06dP1wOqZ8iQwVhcAADgTYwxBQAAYCFpCSXd+KTVWGIDu4fDP//8o5/uN2DAACqlAADAVaErHwAAgKXuvvtu3XLKFBmb67///jMWDwAAeB8tpgAAAAAAABARjDEFAAAAAACAiKDFFAAAAAAAACKCiikAAAAAAABEhLWDn1+6dEnt3btXZc6cWaVKlSrSHwcAAAAAACBFcBxHnThxQuXPn1/FxMSkzIopqZQqVKhQpD8GAAAAAABAirR7925VsGDBlFkxJS2lfIWQJUuWSH8cAAAAAACAFOH48eO6sZCvbiZFVkz5uu9JpRQVUwAAAAAAAGZdzdBKDH4OAAAAAACAiKBiCgAAAAAAABFBxRQAAAAAAAAiwtoxpgAAAAAAAK7VxYsX1fnz5ym4JKRJk0alTp1auYGKKQAAAAAAkOI5jqP27dun/v333xRfFlcjW7ZsKm/evFc1wHnUVUwtXrxYvf3222rlypXqn3/+UV9++aVq2rRpor/boUMHNXbsWDVkyBDVtWtX458VAAAAAADYz1cplTt3bpUhQ4aQK1xsrsA7ffq0OnDggP45X7583quYOnXqlKpYsaJ6/PHHVbNmzYL+nlRY/frrryp//vxGPx8AAAAAAEhZ3fd8lVLXXXddpD9O1EufPr3+XyqnpMxC6dYXkYqphg0b6ikpe/bsUc8++6yaN2+euvfee419NgAAAAAAkLL4xpSSllK4Or6ykrLzXMXUlVy6dEk9+uij6qWXXlI33nhjpD8OgCS0/Kxj0GXTWo2m7AAAAAB4Bt33zJdVVFZMDR48WMXGxqrnnnvuqv/m7NmzevI5fvy4v5JLJgDhkUoF3xmx7QEAAADwArl2kbGTfBOuzFdWidW7XMu1YNRVTMmA6MOGDVOrVq26ptq3gQMHqv79+yeYf/DgQXXmzBmXPyUAn/wxOYMWhm8wPAAAAACIZtIdTSpTLly4oCdcmZSTlNnhw4dVmjRp4i07ceKE8mzF1JIlS/TFbOHCheMNQvbCCy+ooUOHqh07diT6dz179lTdunWL12KqUKFCKleuXCpLlixGPjuQEu29dCjoMhkEDwAAAACinTRokcoU6b0lk899L84y+jlmvXPfNf9Nu3bt1KRJk/w/58iRQ91yyy26N1qFChX0vJiYmAR/V7NmTV0HIz788EM1cuRI9ddff+n8ixUrplq0aKHrWoKR35P3lcHi06VLF2/Z5T97qmJKxpaqX79+vHl33XWXni+FHUxcXJyeLieFlNgXAMAdjgrezJVtDwAAAIAXyLWL9NryTZGSKpmx7777bjVhwgT9et++fapXr16qcePGateuXf7fkeXyez5p06bV8caPH6+ef/55NXz4cHXHHXfoYZLWrVunfv/99yQ/j6+sEqt3uZZrwYhUTJ08eVJt3brV//P27dvVmjVrdK2etJS6/NGM0iQsb968qlSpUhH4tAAAAAAAANErLi5O15sI+b9Hjx7qtttu08MbSU8ykS1bNv/vBJo1a5Zq2bKlat++vX+eyQfRRaQp0YoVK1TlypX1JKQLnrzu06dPJD4OAAAAAACAFU6ePKk++eQTVaJEiQQNfxIjlVW//vqr2rlzp4qEiLSYql279jWNch9sXCkAAAAAAICUbvbs2SpTpkz69alTp1S+fPn0vMAuda1bt1apU6f2/yyVV02bNlV9+/ZVzZo1U0WLFlUlS5ZU1atXV/fcc4964IEHjAzPwuBLAAAAAAAAHlanTh09RJJMy5cv12N1N2zYMF4rqCFDhvh/R6Y777xTz5dKrKVLl6r169erLl266KfttWnTRo9HJU/dCzcqpgAAAAAAADwsY8aMuuueTPJEvnHjxumWU/K0vcAue77fkUn+JlC5cuVUp06ddEuq+fPn6+nHH38M+2enYgoAAAAAAMAiqf7/p+X9999/yfr7smXL6v+lcsvKMaYAAAAAAADgjrNnz6p9+/bp10ePHlUjRozQg6A3btz4in/bsWNHlT9/flW3bl1VsGBB9c8//6g33nhDP81PxpsKNyqmAAAAAAAAPGzu3Ll6rCiROXNmVbp0aTV9+nT98LkrqV+/vho/frwaPXq0Onz4sMqZM6eukFqwYMFVPdUvVFRMAQAAAAAAJOLrd5tEfblMnDhRT0lxHCfosubNm+spUhhjCgAAAAAAABFBxRQAAAAAAAAigoopAAAAAAAARAQVUwAAAAAAAIgIKqYAAAAAAAAQEVRMAQAAAAAAICKomAIAAAAAAEBEUDEFAAAAAACAiKBiCgAAAAAAABFBxRQAAAAAAAAiIjYyYQEAAAAAAKLbtgHNjcYr/uoX1/w3bdu2VZMmTdKvY2NjVY4cOVSFChVU69at9bKYmP/XJqlo0aJq586d8f62QIEC6u+//9avv/zySzV48GC1ceNGdenSJVW4cGF15513qqFDh6pwosUUAAAAAACAh919993qn3/+UTt27FDffvutqlOnjurSpYtq1KiRunDhgv/3XnvtNf17vmn16tV6/oIFC1SrVq1U8+bN1fLly9XKlSvVgAED1Pnz58P+2WkxBQAAAAAA4GFxcXEqb968/lZQVapUUdWqVVP16tVTEydOVE888YReljlzZv/vBfr6669VzZo11UsvveSfV7JkSdW0adOwf3ZaTAEAAAAAAFimbt26qmLFimrGjBlX/F2prPrjjz/U77//rkyLSMXU4sWLVePGjVX+/PlVqlSp1MyZM/3LpJlY9+7dVfny5VXGjBn17zz22GNq7969kfioAAAAAAAAnlS6dGndvc9H6lsyZcrkn4YPH67nP/vss+qWW27RdTEyFtWDDz6oxo8fr86ePWtnxdSpU6d0rd3IkSMTLDt9+rRatWqV6t27t/5favb+/PNPdd9990XiowIAAAAAAHiS4zi6QZCPdNVbs2aNf5KGQEIaBs2ZM0dt3bpV9erVS1davfDCC6pq1aq6nsa6MaYaNmyop8RkzZpVzZ8/P968ESNG6MLYtWuXHhUeAAAAAAAASZMn7BUrVsz/c86cOVWJEiWC/v7111+vJxmT6tVXX9XjTH322WeqXbt2KkUPfn7s2DFdw5ctW7agvyPNywKbmB0/flz/L484lAlAeKRS/1f7fjm2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VZs3b070ySZuGThwoDp27JgKNzl4nz592oo4NuViaj0zlY+pXEzEuf/++9WhQ4eULfszeepXTEyMFXFsysXUumZTLibjmDhPt+1YY1McU7mYuh60KR9TZWYLuvIBgIft3btXd32SAcoB1rPo2WbYNgEgOvebNsWx7VhjWz64elRMAQD8pGXUvn379Ou8efPGe8qQ1+3fv1+dPXs2rOMXyZOZnnnmGZUzZ04VTnLSJk+v8RppPRDusgEiSVr+FipUSMXG2tEp4cKFC9bkImRoXXkaGIJ/33/88Ue884CyZct68ngDwFsYY8rjF1lujskjj4cdNmyY6tmzp57ktcxz299//61OnjyZ6IWWG32KDx8+rBYuXKiOHDnivxAaPHiwLquNGzeqcJKxBKTJZjhPqCS3Dz/8UM2ePVuXmVvfSWBz8yVLlqiHH35Y3XbbbeqRRx5RS5cuDTmGPPp1586dygQpG+kS+PPPP+uff/jhB3XPPfeou+++W33wwQeuxfnvv//U+PHj9dgrDRs2VPfee6969tln1YIFC5TJk8hdu3aF/D7jxo3TJ585cuTQ/we+/uijj5SbY4nJuBstW7ZMUE6yDroxHseJEyf0eit322TMknPnzunKonz58ukxMu644w51/PjxkGLI318+SaXegAED1LZt2/zzQjVt2jT9+X1GjBih80qXLp2u4AnXuGyyXs2fP19/999//71rTerz5Mmj6tWrp6ZMmaIrCcNFPq98D5cuXdI/Sywpy08//VQfO9106tQpfez67LPP1PTp09XKlSv1vtqEv/76y7UxeWT7e+utt3T3I3nEvUzy+u2331YHDx5Ubg6i/Mknn6hvvvkm3rrtK0u31mlZf/v27av3/0K+I9lPS3lNmDBBhUupUqXCeh4grQkkLzlGv/jii2rTpk2uvO/cuXPV+vXr9WvZbl5//XXdtS4uLk4VLFhQDRo0KOT1unHjxurjjz/Wx85wku1dyub222/X53/ijTfeUJkyZVKZM2dWDz30kCv7Z7F27VrdTUeOXenTp1cZM2ZU5cuXV71793YtxtXug0Ih33mvXr1Urly5VOXKlfW2IpO8zp07t87Htz/1ksuPXcuWLdNl5db5czDt2rXT22q4yOeX/Uw4h1n4999/9fWGfPdyjuhWLDlGmnLgwAF9DPB9djn+y3FO9me+/Z0b5HxDurvK/kaOmTI8iant3yoRfSYgQrJmzRonJiYm5FLcv3+/U6tWLSdVqlROkSJFnKpVq+pJXss8WSa/E6q9e/c6t9xyi/7MqVOndh599FHnxIkT/uX79u0LOZ9ly5Y5WbNm1Z87e/bszooVK5xixYo5N9xwg3P99dc76dOnd1auXBlyLsOGDUt0krx69uzp/zlUDRs2dP7991/9+vDhw86tt96qc8uVK5cuq9KlSzsHDhwIOY58319//bV+PXPmTP3e9913n9O9e3fn/vvvd9KkSeNfnlzyuaV86tev73z66afO2bNnnXAYM2aMExsb69x0001OlixZnI8//tjJnDmz88QTTzhPP/20XgeGDh0acpwtW7bobSR37txOoUKFdH733nuv/o4kzxYtWhh5fLQb+4G33nrLyZAhg9OjRw9n4cKFzoYNG/Qkr2V9zpgxo/P222+H/Fllm5A4zzzzjPPII484adOmdd58801X9wGic+fOetsYPny4foRvkyZNnHLlyjk//fST8+OPPzply5Z1XnnllZBiyOdMbJL1IPD/UMl7+Pa/48ePd9KlS+f06dPHmTNnjvPGG2/o7+bDDz90pcx82/ju3bt1+cl6nCdPHv1/+fLlnb///jvkOFIud999t/7uZR8tcVevXu24ae3atU6+fPl02cn3vmvXLv2/lFWmTJl03OXLl4cc5+LFi85LL72k1+nA7993LJ01a5bjlfMAKQ8plwIFCjht2rRxXn75ZT3J64IFCzo5cuRwfvvtN1fiZMuWTe+bZV9cokQJ5/fff3d9HyD7fTkOVKlSRX/nEyZM0HHlOPD444/r9W/69OkhxZBjY2KTfH45zvl+DpWUk+84/8cff+hzHCk3OcbIdirrn6zzoSpVqpSzePFi/Vr2y9ddd53z3nvvOd9++60+Zsq+YNCgQSHFkG1DvhfJoUOHDvocLRyef/55J3/+/M4LL7zglClTxunUqZNTuHBh55NPPnGmTJmiy+/ZZ58NOc7cuXP199O8eXN9TJPvQvZpcu4kMeS8859//nG8sB+QfZmcW8o51Pbt253Tp0/rSV6PHTtWn+vIPiFU586d07GkbOSa4KOPPoq33K19gFxz1KxZUx+/br/9dufIkSP6HM23jy5ZsqT+nVDJtpfYJOfNX375pf/nUAwePFh/F+LChQt6vZZ9mJSTbE/t2rXT5Roq2V/5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iCBPYnLrBN73VLHLH0seOD+cJ6Ru5xOpGMShzEyuA25eyMuTxaQJsjz1J7Hp6aefDlsu8tQiubMkd5jkiXDyZEivxrEpF5MVbSbzsaHSUKxevdp54YUXnAIFCuinJYVKjvPyZLHAJz8FTrIsnGXmdj6RjGNTLqbi2JSLyThChhBwY18j+175zJc/BdI3ycV1uPebbuWSkuLYlIttcUzlYhMqpjxE7sB07NjRfwdGHrksj3ANlTzi9qOPPtKPnE5smjNnTlg2qnDlYzoGcSgzk+tAOC7k5fHZo0aNSvIk2819wOUtSxo0aKBblpw4ccK1GKbi2JSLyQoj0/nYUGnoa5FZtmxZfSdWHnU+btw4599//w35vaXySVpHm9oHhDsf03FsysVUHJtyMRnHN9CybK9NmjTRN5bkMfXdu3cP6T1lOALphmy6S384crE9jk252BbHVC62omLKA3r06KFPGtOmTevce++9zpQpU1ztsy4XBPJEkaQORnI31Sv5mIpBHMrM5DoQzgv55557Tl9MJzXwce3atR23yP6katWq+iRYHq4QLibi2JSLyQojE/nYVGl466236otCufv69ttvO3///bfjpubNm+vueqbOA8Kdj8k4NuViKo5NuZiMM3fuXD2Is3Sry5Ejh/PUU0+59qS8AQMG6BbSwezatctp27at44VcbI1jUy62xTGVi+2omPIAuYsRzqd8yIBtH3/8cdDlR44c0c14vZKPqRjEocxMrgOmKiZMuNqnl0klnzyiOprj2JSLyfXMRD42VRq+8sorYX3qp7x3UgO1njt3Treg9ko+JuPYlIupODblYjKODKzcokULZ+bMmXqb9DJTudgUx6ZcbItj07YZSVRMWUSeALJ3717HFibyMVVmxKHMQl0HTFVMRBPpEvnXX39ZEccruUTbehZKPrZVGkbTemaKV7abaIlhWxybcnEjjgysfDUGDhzoHD16NNldkUwwkYttcWzKxbY4pnKxXYyCNRYvXqz++++/ZP/9Tz/9pGzKJ1piEIcyc2MduOGGG67q955++mm1f//+ZMUoUaKE6tevn9q8ebOKBnLzxJY4XsnFxHpmKh9TuURTmYX6/b/xxhtq+/btKlp4ZbuJlhi2xbEpFzfiZM6c+ap+780331RHjhxJVozcuXOrtm3bqvnz56tLly6pcDGRi21xbMrFtjimcrEd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7rrr1GeffeapfEyVGXEoM1PrgKkKkMTs379fjR07Vj+xyw1ykjtlyhT9hLZAX3zxherQoYM6ePCgZ+LYlIvJ9cxEPjZUGsrTMF988UX1v//9T+XMmTPeskOHDqnu3bu78sRMU0zlYyKOTbmYimNTLibj+HTr1k0988wzep8jvV6WL1+upk6dqgYOHKjGjRvnSgypcJebbXKDWp4u/Mgjj6iPPvpIP637+eefV17KxbY4NuViWxxTuVgv0k22EN0OHz7sXLp0KdIfA0jxpP/66tWrE5TD559/7uq4acHGynHzyZwyZlVcXJwzaNAg/bMMotymTRvdZfi9997zVBybcjG5npnIx1Qu4Yyza9cup1y5ck5sbKxTuXJl5+6779aTvJZ58iRd+R2vdOUzlY+JODblYiqOTbmYjBPok08+cUqUKOEfZL1AgQLOuHHjnHD55ZdfnHfffdeZNWuW6+9tKheb4tiUi21xTG+bNtKjcka6cgxJ+++//3Tta4YMGfTPO3fuVF9++aUqW7asatCgQViKb/fu3WFr+WEiH1NlRhzKzNQ60KlTJzV+/HjVv39/fRdWWjfK3Zlp06apAQMGhHQnc926dUku37Rpk2rdurW6ePGicsucOXPUE088oUqUKKFblWTKlEl98sknukuxm0zEsSmXcK5npvMxlUu441y6dEnNmzdP/frrr2rfvn16Xt68eVX16tX1PiYmJkaZljlzZt1lOTnd/E3lYyKOTbmYimNTLibjXO706dPq5MmTKnfu3MrrTOViUxybcrEtjk3bpnGRrhnDld15553O6NGj9eujR4/qgRQLFiyoB1OTx1O65fz58/rRtjK4obSOkEley6Nwz50756l8TJUZcSgzU+uAkCflyGCktWrVcq6//nqnYsWK+okfoZI7O7K9X/6468D5braYEvII7U6dOun3TpMmTZIDyEZ7HJtyCed6Fol8TOViKk60uPHGGyPSUgtA+E2ePNmpUaOGky9fPv+AzkOGDHFmzpxJ8QMIG8aY8oBVq1apIUOG6Neff/65vhMjAy7LWBwy5kvHjh1diSN9yWVwZhn0XO70iKVLl6p+/fqpw4cPq9GjR3smH1NlRhzKzNQ6IBo2bKgHU5dtMTY2Vn399deutC7JkSOH3u5lsPbE/PHHH6px48bKLX/99Zd66KGH9N1ludP8448/qvvuu091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RlWqVCGr3Llzh7p160YrV66kOXPmUN68ecmEBQsW6CGva9eubcnn8Xll+fLlesh7Hk45W7ZsVLFiRXr66act+Xwepvn111/3yzE4+nFg//79VLBgQUqZMiXdunWLfvrpJ7p586YewpnnW2HHjh00a9YsPfw4/w34s620d+9efd565plnYl3Ox7QzZ85Yct7k4+LQoUP1PspDrDM+v/B1QOfOnem1117zOcb48ePpr7/+oqlTp8a6fPDgwTR27Fi9/fmCj8UZMmSgypUrx7p80KBBehvp378/WcV1/j9+/Djt2rWLihQpYtk+44m33fLly7t/5xx4v/322299jsXb04QJE+j333/Xw597HgPatWtHOXLk8Onzq1atqv82cR2brTR9+nT3dUCzZs1o1apV1KtXL70/NWjQgD7//HN9nvAFX7fytQWfO13HgOHDh1PGjBn18k2bNuljT1zbYaDhv/fSpUtjvQ6oVauWz+uL8f7Bx+a4zll8PONzkFX3NnHhv03y5MmpWLFiln82X3PytQBff/q6zzwO/nvxOdV1/ekrPv7zecDzOoDPA6lSpbLk8/kcwMcUvscw4b///tPnA5cVK1boawHerj3nxxdf6/Mxk68Dq1WrZtmxPyFCwRQYxxdvlSpVcnwMiXEYl1VzoQufjPjiim96nZqLJ7445Ituq06sLocOHdIXpIUKFTJ2kgUA8Bc+Tv7777/6tT/OAZLxQx1+yFO4cGFKkiSJ3V8HhOHrGCseRCakXCTFkZSLtDiS9k07+V70DX7HN/J2ioyMpH79+ln2eVyazLUJevTooZ8G+4OJGBLj8LbGtX+yZMmin5D444bEZC6e+IRhdaGUa//gJ27+LpTKnz8/9enThw4ePEh23KieOHHCcbmYiCMpF884XODq9Hy4lpeJdeaK48919sUXX/hci+hx8XGfj//+OgeYzMdEHM8YXDuvZMmSfimUkrrOEOfxcU3vVq1a6RpF/PDQJK5huHr1asflIikOx+CaZBJyMR3H3+vNzn1TlMds8gc24j4FuE1x9+7dLe234HFZ0ali9E4UeSQ77uOF2/1y3yw8BPrJkycdFUNiHM9tLfoIgFaRlIvJ/ZOHOuf+P3hf5J/cp4Br9C+nHQNM5WIijqRcPOPwvun0fCT9bbh/F/587nya+3qKrYNif+K+7HgESqflYyKOpFxMxZGU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o2pTAQAAAAAAAADEB/qYAurSpQtFRUXFuSby589PK1euxJoCAAAAAAAAAEuhjykAAAAAAAAAALAFmvIBAAAAAAAAAIAtUDAFAAAAAAAAAP9fe/cBJkWxPX6/Fpacc85cJUdFkkiSJCjCVUSUIMoVhauACKhERcQIKoiKgKBI8KIiIEEEQUSQjIDkKFFykNzvc+r/zvxmNpCmp2a69vt5nmZnu4c5c2p7OtRUUEAkUDEFAAAAAACAiKBiCgAAAAAAABFBxRQAAAAAAAAigoopAAAAAAAARAQVUwAAAAAAAIgIKqYAAAAAAAAQEVRMAQAAAAAAICKomAIAAAAAAEBEUDEFAAAAAACAiKBiCgAAAAAAABFBxRQAAAAAAAAigoopAAAAAAAARAQVUwAAwAq7du1SMTExiS7t27eP9FsEAABAHLFxVwAAAHjZvffeq9q2bev//cyZM6pz584RfU8AAABIGBVTAADACo7j6J+33Xabeuyxx/zr//77byqmAAAAohRd+QAAgBUuXryofyZPnvym/p908Uus+1+gwoULq9q1a8eL+a9//Us/d8CAAf71Cxcu1OvGjRsXL56sk23yHJ/9+/erHj16qAoVKqgsWbKo1KlTq1KlSqmhQ4eqK1euhJyHLPL+fcqXL68KFiyorl69Gu91pk6dqp8/fvx4/3u93nIrZQQAACBoMQUAAKyqmEqVKtUt/f8JEyb4H3/yySdq8eLF1/0/7733ntq2bZsK1bp169S0adPUgw8+qIoVK6YuXbqkZs+erXr37q127NihPv7441vKw2fw4MHqn3/+8f/+1FNPqa5du6p58+aphg0bBj33s88+U5kyZVIPPfSQOnDgQNDryXv85ptvdN7Zs2e/offjVhkBAAA7UTEFAACscOLECf0zXbp0N/X/pBJIWvMEdv/78ccfr1sxJZU2r732mnrggQfUd999p0Jxzz336AqowNZHzz//vHr88cfV6NGjdUujPHny3NBrBebhI68hg8MHPufFF1/UlVCBFVN79+7VlVX/+c9/VJo0aVTRokX14iMVTFIx1bx586AWWCbKCAAA2ImufAAAwApHjhzRP3PmzHnTLa1upZWVtGaSLnfX6p4mA6/LGFeBi6yLSyqBfJVS8n6OHTumnyuVRtLdbsWKFcpNmTNnVg8//LCuLDp69Kh//dixY3W8jh07uhLn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2X6EXbt2Vd98841auHChKlKkyHX/z5o1a/RPaTklqlWrpgYPHqwOHz6sm32JefPm6UqnUqVK+Z8za9asoNeR58h6AAjVjsEtE91W9OX/UcAAAAAAYEjszXbfmzhxovruu+9UhgwZ/GNCyUjr0pJJuuvJ9iZNmqhs2bLpMaa6deumZ+wrV66cfm6DBg10BdTjjz+u3nzzTf0ar7zyin5tX4unp59+Wn344YfqxRdfVE888YT66aef1JQpU/RMfQAAAAAAACY06/Gd0YL+/p0Hbvr/tG/fXn3++ef+36Vr3Z133qnrXHx1MQm1ApMxw33DM3366ae6HkbqdaQrozREevjhh/WwSeF2U33cPvroIz0TX+3atXULKN8yefJkvV2mCPzxxx915VOJEiVUjx49VMuWLdX333/vf43kyZPrboDyU1pAPfbYY6pt27Zq0KBB/udIAUgllLSSKl++vHrnnXfU6NGj9cx8AAAAAAAA+D+NGjVSBw4c0Mv8+fN15VLTpk0DnqHU2LFj/c+RZfr06Xr9mDFj9OR2//3vf3WvtyVLluiGQmfOnFEm3HRXvmuRwcZ//vnn676OzNoXt6teXFL5tXr16pt5ewAAAAAAAElOqlSpgsbt7t27t7r77rvVkSNH9KRwInPmzP7nBJIKKmkd1bFjR/+60qVLG3vvjAoOAAAAAABgiTNnzqgvvvhCFS9eXA+zdD1SWfXbb7+p3bt3q0hgDkQgTBhgGwAAAABgwowZM1T69On147Nnz+phl2Rd4Ox4rVu31sMq+UjlVfPmzVX//v1VixYtVOHChdVtt92mh12SscP//e9/39TsereKFlMAAAAAAAAeVqdOHT0+lCzLly/XY3Q3btw4qBXUe++953+OLPfee69eL5VYS5cuVevXr1fPPfecunz5smrXrp0et+rq1athf+9UTAEAAAAAAHhYunTpdNc9WWRGPplATlpOyWx7gV32fM+RRf5PoDJlyqhnnnlGt6SSyehkuZFxxENFxRQAAAAAAIBFYmJidDe8f/7555b+f6lSpfRPqdwKN8aYAgAAAAAA8LALFy6ogwcP6sfHjx9XH374oR4EvVmzZtf9v507d1Z58+ZVdevWVfnz51cHDhxQr732mp7NT8abCjcqpgAAAAAAADxs9uzZeqwokSFDBlWiRAk1depUVbt27ev+3/r166sxY8aojz76SB09elRlz55dV0jNnz//hmb1CxUVUwAAAAAAAAn4/p0Hor5cxo0bp5drcRwn0W0tW7bUS6QwxhQAAAAAAAAigoopAAAAAAAARAQVUwAAAAAAAIgIKqYAAAAAAAAQEQx+DiCq7Bic8KB7RV/+n/H3AgAAAAAIL1pMAQAAAAAAICKomAIAAAAAAEBEUDEFAAAAAACAiKBiCgAAAAAAABFBxRQAAAAAAAAigln5AAAAAAAAbmLW8HApeguzkbdv3159/vnn+nFsbKzKmjWrKleunGrdurXelizZ/2uTVLhwYbV79+6g/5svXz61b98+/fibb75RQ4cOVZs2bVJXr15VBQsWVPfee68aNmyYCidaTAEAAAAAAHhYo0aN1IEDB9SuXbvUDz/8oOrUqaOee+451bRpU3X58mX/8wYNGqSf51tWr16t18+fP1+1atVKtWzZUi1fvlytXLlSDR48WF26dCns750WUwAAAAAAAB6WKlUqlTt3bn8rqEqVKqmqVauqevXqqXHjxqknn3xSb8uQIYP/eYG+//57VaNGDdWzZ0//uttuu001b9487O+dFlMAAAAAAACWqVu3ripfvryaNm3adZ8rlVUbNmxQf/zxhzKNiikAAAAAAAALlShRQnfv8+nVq5dKnz69f3n//ff1+q5du6o777xTlS1bVo9F9cgjj6gxY8aoCxcuhP090pUPAAAAAADAQo7jqJiYGP/v0lVPBkT3yZ49u/6ZLl06NXPmTLV9+3a1YMEC9dtvv6kePXqo4cOHq6VLl6q0adOG7T3SYgoAAAAAAMBCmzZtUkWKFAmqiCpevLh/yZw5c9DzixUrpsejGj16tFq1apXauHGjmjx5cljfIy2mLJ668lammQQAAAAAAN73008/qfXr16tu3brd0v+XLn3SUurs2bMqnKiYAgAAAAAA8LALFy6ogwcPqitXrqhDhw6p2bNnqyFDhqimTZuqtm3bXvf/DxgwQJ07d041adJEFSpUSJ04cUKPP3Xp0iV17733hvW9UzGFJCmxlma0MgMAAAAAeM3s2bNVnjx5VGxsrMqSJYuejU8qltq1a6eSJbv+KE733HOPGjFihK7EkooteY2KFSuquXPnqttvvz2s752KKQAAAAAAAI82Xhg3bpxeridwdr646tSpo5dIYPBzAAAAAAAARAQtpgCPYwB8AAAAAIBX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ee1rDdR68eJF3YLaK/mYjGNTLqbi2JSLyTgysPJDDz3kfPvtt/oz6abBgwfrFtKJ2bNnj9O+fXtP5GJrHJtysS2OqVxsR8WURWQGkP379zu2MJGPqTIjDmUW6j6wZcuWG3qetNg6c+aME81M5WIijk252BbHplxulHQj3r59u2MLU/mYiGNTLqbi2JSLG3FkYOUbMWTIEOf48eNONDOVi01xbMrFtjg2fTYjiYopi6RPnz6kE97ixYsdm/KJlhjEocxM7gM23Zh65WYhWmIQhzIL9Tgj3fplrJxoYdM52qZcTMWxKReTcUI538gYOdGEcydlZtM+YNM1ejgkU8D/r27duqpIkSLqpZdeUhs3bqRcAA+SLxxuVfHixdWAAQPUli1blNdzibY4NuViWxybcgnV1KlT9XGgevXqauTIkervv/+O9FsCYPBYkzNnTtW+fXs1b948dfXq1YiXvW3HZ85pSTuOF64DIomKKfjt379f9ejRQ/3888+qTJkyqkKFCuqtt95S+/bto5SAJODZZ59VM2fOVCVLllR33nmnGj58uDp48GCk3xYAQ9auXavWrVunateurd5++22VN29edd9996mJEyeqc+fO8XcALPf555+rs2fPqgceeEDly5dPPf/882rFihWRflsAkgAqpuCXPXt21aVLF7VkyRK1fft29dBDD+kTVOHChXVrKgB269atm/r999/Vpk2bVJMmTdSIESNUgQIFVIMGDdT48eMj/fYAGFC6dGn1+uuvqx07dqgFCxboawC5Oc2dOzflD1juwQcf1C0nDx06pI8D0oOiatWq6rbbblODBg2K9NsDYDEqppAg6dLXu3dv9cYbb6iyZcvqVlQAkga5AB04cKDu0rd48WJ15MgR1aFDh0i/LQDXERMT42oZpUuXTqVJk0alTJlSXbp0yfP5RDKOTbmYimNTLibjuCFDhgz6vD937lzdilKOBXJdAADhQsUU4pEWU88884zKkyePevTRR3W3PuneAyDpWL58uW4lId+eSgWVtKAEEN3cGL9i586davDgwbrl1B133KFWr16tb0gj0a2XsUUoM/azyDh//ryaMmWKat68uapUqZI6duyY6tmzZ4TeDYCkgIopi8ig5VmzZr3l/9+nTx/dUkq67e3Zs8c/vsyECRNUo0aNlNfyiZYYxKHMTO4DhQoVUilSpLil/ysVUP3799ctpmrUqKG79A0dOlQ36Z80aZIyLZRcoi2OTbnYFscLuUiXuhvxww8/6HFhbpV02ZHBz7/++mvdWmL37t1q/vz5qmPHjipTpkzKLabyMRHHplxMxbEpF5NxbtTdd9+tWzreijlz5qh27dqpXLlyqc6dO+uf0mpKjgXSi8K0UHJJqnFsysW2OKZy8aoYmZov0m8C8U2fPl01btxYX8TK42u5//77XSlCuRFt06aNevjhh/V4U17Lx1SZEYcyi8Tn0+fixYvq8OHD8WbLKViwYMivnSxZMj3oubSUfOSRR/QFaTiFMxfTcWzKxbY4NuSSKlUqlT9/fl1ZJDeNMvZbOLz88sv6OqBUqVIqnEzlYyKOTbmYimNTLibjrFq1Sl93yBAb4rvvvlNjx47Vn1eZUVe63IYqbdq0qmnTpvo4IGNNhqvS3kQutsWxKRfb4pjKxXpSMYXoExMT4xw6dMj/OLElWbJkxt9bkyZNnP3790ddPqbKjDiUWSQ+n1u2bHFq1qypXzNwcTOOxLgREydOdM6cORPVuZiKY1MutsWxKZcjR4447777rlO+fHknNjbWadCggTN58mTnwoULTiRkyJDB2b59e9TnYyKOTbmYimNTLibj3HHHHc7XX3+tH8vnL3Xq1E7r1q2d4sWLO88995wrMU6dOnVDzxsyZIhz/PjxqM7Ftjg25WJbHFO52I6KKdy09OnTh3RBCuDmVa9e3alVq5Yza9YsZ/Xq1c6aNWuCFi/dlJrKxUQcm3KxLY5NuQRauXKl06VLFydbtmx66dq1q/FjgJvXAabyMRHHplxMxbEpl3DHyZgxo7Nt2zb9+I033tAVYOKXX35x8ufP73jpOsBULjbFsSkX2+JE02fTy6iY8oDPP//cOX/+fLz18k2MbDMt1AtSE/mYKjPiUGam9oG0adM6mzZtcqJBqMcAU7mYiGNTLrbFsSmXuP766y+nf//+TqpUqZx06dI5yZMn1622/vjjD09+QWUqHxNxbMrFVBybcglnHKkM8rVsrl+/vjNs2DD9ePfu3bqFhkmhHgNM5WJTHJtysS1ONH02vYyKKQ+QrgC+bkOB/v7774h05Qv1ZGQiH1NlRhzKzNQ+IM2EFy9e7ESDUI8BpnIxEcemXGyLY1Mu4uLFi87UqVOdxo0b6+5CVatWdT799FPdrXbnzp1OmzZtnJIlSzpeqZgylY+JODblYiqOTbmYilOnTh2nbdu2zvjx450UKVI4W7du1esXLlzoFCpUyDEp1GOAqVxsimNTLrbFiabPppdRMeUBMk7F4cOH462XpsFZsmQx/n5CPRmZyMdUmRGHMgvnPnDy5En/Mn/+fKdatWrOggULdKVX4DZZov0YYCoXE3FsysW2ODblEsjXNShr1qx6vIr169fHe86BAwf08cgL1wGm8jERx6ZcTMWxKReTcdauXeuUKVNGdxsaMGBAUHwZz8akUI8BpnKxKY5NudgWJ5o+m17GrHxRrGLFiiomJkatXbtWlS5dWsXGxvq3XblyRe3cuVM1atRITZkyxej7ypAhg35PRYsWjbp8TJUZcSgzE/uAzJInMXzky4TA3wPXScxoPgaYysVEHJtysS2OTbkEqlevnnryySdVixYt9AxgCbl8+bJasmSJuueee1S4ZcyYUa1Zs+amrwNM52Mijk25mIpjUy4m4yTm/PnzKnny5GGbQc/Ne4FoycWmODblYlucSHw2vez/7qQQdZo3b65/ysVfw4YNVfr06f3bZNrJwoULq5YtWyqvMJGPqTIjDmVmYh9YsGCBsoWpXEzEsSkX2+LYlEug/v37q+rVqwdVgPtudn/99VdVq1Ytvc1EpZSv0s0L+ZiIY1MupuLYlIvJOIlJnTq1soWpXGyKY1MutsWx6bNpAi2mPODzzz9XjzzySKLfwpg2ZMgQ1blzZ5U5c+aozcdUmRGHMjO1D+zZs0cVKFAgwVYZe/fuVQULFlSmlClTRv3www/6/URzLibi2JSLbXFsykW+cT1w4IDKmTNn0PqjR4/qdW61mJQKtzp16lz3eb/88ou68847b/m4ZyofE3FsysVUHJtyCXecLFmyxDu2JObYsWPKlCZNmqjPPvtM5cmTJ+pysSmOTbnYFidaP5teRospDxg4cKBq2rRpvAvAEydOqEqVKqkdO3bc8mtPnz5dNW7cWDcxlMfXcv/99+ufffr0UdGaj8kYxKHMTO4DRYoUSfDCV052ss3NrnwXL15Uhw8fVlevXg1a77vB/uOPPzyRi4k4NuViWxybckmoq6DvxjddunTKLdL9OH/+/KpDhw6qXbt2iVY+16xZ0xP5mIhjUy6m4tiUS7jjDBs2LOj1XnvtNd1Ku1q1anrd0qVL1Zw5c1Tfvn2VG1atWqXvCcqWLat//+6779TYsWNVqVKl1IABA3SLcDFr1qyozcWmODblYlsc05/NpIAWUx4gY1kcPHgw3kXvoUOH9I3ihQsXXHlteZwYN8ewCWc+JmMQhzIzvQ/Ia+bIkSNo/e7du/UF49mzZ0OOsXXrVvXEE0/orgfhHMfKRC6m4tiUi21xbMhFxqzx3RxKpVFgBbh8HtetW6duv/12NXv2bOWGv//+W02YMEG3BN2wYYOqW7eu6tixo+667LshDYWpfEzEsSkXU3FsysVkHB8ZHkBaNHbp0iVo/Ycffqh+/PFH9e2334YcQ1pC9u7dW8eSL9ZkDM0HH3xQ/f777+q+++4LuhmP9lxsi2NTLrbFMZWL7WgxFcUCWzBJjWumTJmCTnjz58/X49iEIrBFRNzWEV7Mx0QM4lBmJveB7t27659SMSTfuqRNmzYozrJly1SFChWUG9q3b6/HwZgxY4Zunn+jTZSjLRcTcWzKxbY4NuXiO65I5bAMNpwmTRr/Nqkoqlq1qnrqqaeUW7Jnz666deumF2k5IS0lnnnmGb08+uijupKqfPnyUZ+PiTg25WIqjk25mIwTeK0xdOjQeOulUkwqk9ywZcsW/3Fr6tSpenysiRMn6oHbZdgCtyqmTORiWxybcrEtjqlcbEfFVBTzDa4sF73SpD6QNLOVm9533nnHtXjjx49XrVq1itclSbr1TJo0SbVt2zbq8zFVZsShzEztA6tXr/Zf+K5fvz6o1YI8lpvEF154QblBBnJfuXKlKlGihAoHU7mYiGNTLrbFsSkXqRgScjyR13Kz+9H1SFfk3Llzq2zZsqk33nhDjRkzRo0cOVJ3Uxg1apRuSRGt+ZiIY1MupuLYlIvJOD7yWZTWWT169AhaL+tkmxvkeOb7olpaeshQBUK69UqLSi/lYlscm3KxLY6pXKznIOoVLlzYOXLkSNjjJEuWzDl06FC89X///bfe5qV8TJUZcSgzU/tA+/btnZMnT4Y1xh133OEsXrzYsSEXU3FsysW2ODbl4iPn6EWLFuklofO1Gy5evOhMnTrVady4sRMbG+tUrVrV+fTTT50zZ844O3fudNq0aeOULFnSM/mYimNTLqbi2JSLiThjx451kidP7jRt2tR59dVX9SKP5XMq29xQp04dp23bts748eOdFClSOFu3btXrFy5c6BQqVMjxUi62xbEpF9vimMrFdlRMecw///wTtteOiYlxDh8+HG/9mjVrnCxZsnguH5MxiEOZmdwH3CQ31L5l/vz5TrVq1ZwFCxboCunAbaZuvAHEd+rUKeexxx7TF7lyrpZFHksl0YkTJ1wrsi5dujjZsmVzsmbN6jz33HPO+vXr4z3nwIEDOr4X8jERx6ZcTMWxKReTccRvv/3mPProo07FihX1Io9lnVvWrl3rlClTxsmYMaMzYMCAoGND69atHS/lYmMcm3KxLY6pXGzG4OceIE1qBw8erJvOywCr0v+7aNGiekwLaT4sYz6EomLFiro70tq1a3XTfBljJnCcjJ07d+o+slOmTPFEPqZiEIcyM7kPiBUrVujPoUxPL11sA02bNu2WB24OHEsqodmF3B78PFy5RCqOTbnYFseWXKSbvXQd/OCDD4Jm/Hnuuef0eDDS3d4N9erVU08++aQe1Dlut36fy5cv6/Fm7rnnnqjPx0Qcm3IxFcemXEzGiaTz58+r5MmT66EKACAsIl0zhusbOHCgU7RoUeeLL75w0qRJ42zfvl2vnzRpkm5iHyr5RkQW+YbnhRde8P8uy+uvv+5MnDjRuXDhgmfyMRWDOJSZyX3gq6++0s3qpWlwypQp9c/bbrvNyZQpk+5KdKukef6NLtGeSyTi2JSLbXFsyiVt2rQJdrOVLkOyzS0///yzc+nSpXjrZZ1sc4upfEzEsSkXU3FsysVkHHHlyhVn8+bNOp58JgMXrzGVi01xbMrFtjg2fTYjhYopDyhWrJjz448/6sfp06f33/hu2rTJyZw5s2txxo0b55w/f96xIR9TZUYcyszUPlC2bFnnww8/DIpz9epV56mnnnL69evnSozdu3fr14xL1sk2L+ViKo5NudgWx6ZcChQo4Kxbty7Bbjf58uVzvDbWpKl8TMSxKRdTcWzKxWScpUuXOkWKFNGfRV+XQd8SyudTrlVkyI4bWaI9F5vj2JSLbXFM5WI7KqY8IHXq1M6uXbvi3fhu2LDBSZcunWtx5AMlF59xHT9+XG/zUj6myow4lJmpfUC+dZWBh4WM/+K7CN64caOTO3duT92UmsjFVBybcrEtjk25fPzxx079+vX1+E4+8rhBgwbOqFGjnHCPNSnfAmfIkMG1OKbyMRHHplxMxbEpF5Nxypcv7zz00EP62CLX5jJ+VeASyhfTvuWdd97RFVCPPPKIM3z4cL3IY1n37rvvRn0uNsexKRfb4pjKxXb/N5gQolapUqXU4sWLVaFChYLWf/3113p8KLfs2rUrwTFkLly4oP766y9P5WOqzIhDmZnaB7JkyaJOnz6tH+fLl0/98ccfqmzZsurEiRPq3LlzrsRIaHwpcebMGZU6dWrlpVxMxbEpF9vi2JTLRx99pLZt26YKFiyoFyHjWck4UEeOHFEff/yx/7mrVq266deXMaWEfP7bt28fNL6UXBesW7dOVa9eXbkl3PmYjGNTLqbi2JSLyThbt27V1xbFixdXbmrXrp3/ccuWLdWgQYNUly5d/Ov++9//qg8//FD9+OOPqlu3bq7EDFcuNsexKRfb4pjKxXZUTHlAv3799ElDKodkoGUZSHXz5s1q/PjxasaMGSG//vTp0/2P58yZozJlyhR0QTp//nw9iLNX8jEVgziUmcl9oFatWmrevHn6hvehhx7Sg6r+9NNPep0MWByK7t27+29KZdD2tGnTBh0Dli1bpgdw9UIupuPYlIttcWzKpXnz5iqcfOd9qZzOkCGDSpMmjX9bypQpVdWqVdVTTz3lWrxw52Myjk25mIpjUy4m49x11126AiycN79yHzB06NB462USpN69e3sqF9vi2JSLbXFM5WK9SDfZwo2RARSlmXCOHDn0AMs1atRw5syZ40rxBfaBjdsvVgZylUFcv//+e8/kYzIGcSgzU/vA0aNHnb/++ss/wOKQIUOcZs2aOd27d3eOHTsW0mvXrl1bL/KZr169uv93WaQrQqdOnZwtW7Z4IhfTcWzKxbY4NuViikx6cubMmUi/DQAJmDZtmlOqVCln7NixzooVK/QYVoGLGwoWLOi8/fbb8dbLOtnmpVxsi2NTLrbFMZWL7WLkn0hXjiE6FClSRP3+++8qe/bskX4rACKgQ4cOavjw4SpjxoyUPxClpGuttM4M5PZn9vDhw7rlp7j99ttVzpw5lZfzMRXHplxMxbEpl3DHSZYsWbx10tLZ1w0/oeE4bta4cePUk08+qRo3bqxbgQhpNT179mz16aef6q6+XsnFtjg25WJbHFO52I6ufB5y8eJFfbEY94Tn688eqp07d/ofnz9/3tUxZSKRj6kYxKHMTO0DcmL75ptv1KZNm/zjWz3wwAMqNtadQ/nYsWOVKeHOxWQcm3KxLY4tucj5WcZ8WbhwoT4/+7h90StjZT3zzDNq0qRJ/tdMnjy5atWqlRoxYkRQV38v5GMijk25mIpjUy6m44SbVDyVLFlSvf/++3poAiG///LLL/6KKq/kYlscm3KxLY6pXGxHiykPkAHVnnjiCfXrr78GrXf7hCc31IMHD1ajRo1Shw4dUlu2bFFFixbVY87IGFMdO3b0TD6myow4lJmpfWDDhg3q/vvvVwcPHtQtGIR8RnPkyKG+//57VaZMGVfirFixQk2ZMkUP3CqVbYF8F6leycVEHJtysS2OTbnUqFFDH1Nk/KpcuXLFm6TgnnvuUW6QCqjVq1erDz74QFWrVk2vW7p0qY4r48xJhZUbTOVjIo5NuZiKY1MuJuMAgM2omPIAOeHJt64y6GCePHninfDKly/vShyZhePzzz/XP2WQU5lZSCqmJk+erIYNG6YvTr2Sj6kyIw5lZmofkJtEudGVz6jMAiaOHz+uv92UWX/iVozdCrnpbNu2rWrYsKGaO3euatCggb7BlorqBx980LUWVSZyMRXHplxsi2NTLunTp1crV670V3yFS7p06fTgxzVr1gxaLzOPyuDHZ8+edSWOqXxMxLEpF1NxbMrFZBwxYcIE/QWytNCQ63KZEViu0WU4Dmml6dYX1TKQc0KtwGWyBy/lYlscm3KxLY6pXKwW6UGucH1p06Z1Nm3aFPaiKlasmPPjjz/qx+nTp3e2b9+uH0vszJkzeyofU2VGHMrM1D6QOnVq548//oi3fv369XqbG8qWLet8+OGHQceAq1evOk899ZTTr18/x0u5mIpjUy62xbEpF5mIYN68eU64FShQwFm3bl289TJ4a758+VyLYyofE3FsysVUHJtyMRln5MiRTvbs2Z3XXntNT7Tiu06XAZflPbhh6dKlTpEiRRKcEEnWeSkX2+LYlIttcUzlYjsqpjzgjjvucBYvXhz2OHIBvWvXrngVUxs2bHDSpUvnqXxMlRlxKDNT+0C5cuWc+fPnx1sv68qUKeNaJdvOnTv146xZs/pvUDdu3Ojkzp3b8VIupuLYlIttcWzKZdu2bXrmz3HjxoV1xp+PP/5Yxzlw4IB/nTyW2TlHjRrlWhxT+ZiIY1MupuLYlIvJOCVLlnS++eabeNfpUgmeLVs2V2KUL1/eeeihh/R5//jx486JEyeCFi/lYlscm3KxLY6pXGxHxVSUOnnypH+Ri9tq1ao5CxYscP7++++gbbK4pVKlSs6ECRPifagGDhzo1KxZM+rzMVVmxKHMIvH5nDlzplO6dGln6tSpzt69e/Uij6WVk2xzI6a0iPBVRsnrTpw4UT/+9ddfnYwZM3oqF1NxbMrFtjg25eJrxRC39YLbrRgqVKigz/8pUqTQrahlkceyrmLFikFLKEzlYyKOTbmYimNTLibjJPYF8pYtW1xrnSlfUG3dutUJNxO52BbHplxsi2MqF9sxK1+Uypw5c9BYNVKJWK9evbAOrtyvXz/Vrl079ddff+k+5TLQsUwXPX78eDVjxoyoz8dUmRGHMovE57Np06b658MPP+yPLTFEs2bNXIkpY0fMmzdPlS1bVj300EN6INeffvpJr4ubX7TnYiqOTbnYFsemXGSChYoVK6qvvvoqwcGV3dK8eXNlgql8TMSxKRdTcWzKxWQcGatmzZo1euyaQLNnz9Yz57lBZt6T8aWKFy+uwslELrbFsSkX2+KYysV2VExFqQULFhiPKQOzyQxCMvi5DIAqFVWVKlXS6+69996oz8dUmRGHMovE59NEzA8//NA/1fXLL7+sUqRIoQdubtmypXrllVdci2PTZ8imXGyLY1Muu3fvVtOnTw/7zWL//v2VCabyMRHHplxMxbEpF5Nxunfvrp599ll9npbK7uXLl+vKsCFDhqjRo0e7EqNr166qR48eepZR+ZJKrgMClStXzjO52BbHplxsi2MqF+tFuskWAMA9nTt3do4cOWJFkZrKxUQcm3KxLY4XcmnatKnz9ddfOyadPn06bF2TTeVjIo5NuZiKY1MuJuOIL774wilevLi/y6B0wR89erRrrx93wPNwdUs0kYuNcWzKxbY4pnKxWYz8E+nKMVzbunXrElwvTYVTp06tChYsqFKlSuVaMV68eDHBKWIljlfyMVVmxKHMTH8+rydjxoy6OXHRokVv6f9LV6NvvvlGbdq0Sf9eqlQp3ZoyNtZ8A9tQc4mmODblYlscL+TyySefqNdee013GUqoFcP999/vynuUaa67dOmiFi5c6G89GY6uyabyMRHHplxMxbEpF5NxAp07d06dOXNG5cyZ0/XWX9cSt6tSNOdicxybcrEtjqlcbETFlAckS5bsmv3V5QTYqlUr9fHHH+sb4Vu1detWfVKVrjuB3L4gNZGPqTIjDmVmah+4URkyZFBr1669pZvfDRs26AtoacJ/++2363VbtmxROXLk0F16y5Qpo0wKJZdoi2NTLrbF8UIucpxJjJvn5xo1auhzvowvl9BYOffcc48rcUzlYyKOTbmYimNTLibjAIDNGGPKA6T1Qq9evVTPnj1VlSpV9Drpu/rOO+/o8SAuX76sevfurceAefvtt285Tvv27XWrCBnoPE+ePGEbvNFEPqbKjDiUmal9wIQnn3xSlS5dWq1YsUJlyZJFrzt+/Lg+NnTq1ClepTUAM+K2YA4XqThbuXKlv2La6/mYiGNTLqbi2JRLuOPIoOo3ej2+atUqV2JOmDBBjRo1SregXLp0qW4lNWzYMD3As7SgjvZcbIpjUy62xYnEZ9N2VEx5wODBg9Xw4cNVw4YN/eukqXD+/PlV37599U2wDFYugxWGcuMrXQzkgrREiRLK6/mYKjPiUGam9gET5BgQWCkl5LHkeOedd0b0vQH4f6SLXbhaX8rnfO/evWGvmDKVj+k4NuViKo5NuYQjTuBMmfLaI0eO1F3sq1Wrptf99ttvurXzM88840q8jz76SE9+9Pzzz+tzv6+1l8xGLJVToVRMmcrFpjg25WJbHNOfzSQh0oNc4fpSp07tbNq0Kd56WSfbxM6dO500adKEVJx33HGHs3jxYivyMVVmxKHMTO0DNyp9+vTO9u3bb+n/litXzpk/f3689bKuTJkyjmmh5BJtcWzKxbY4Xsjl8uXLzqBBg5y8efM6yZMn97/OK6+84urgqtu2bXPq16/vjBs3zlmxYoWzdu3aoMUtpvIxEcemXEzFsSkXk3E6duyoXzOufv36OR06dHAlRsmSJZ1vvvkm3jFr/fr1TrZs2Rwv5WJbHJtysS2OqVxsR8WUB1SoUMFp166dc+HCBf+6ixcv6nWyTfzyyy9O4cKFb/q1A2fbkZvPatWqOQsWLHD+/vvvsM3GE858TMYgDmVmch8wcfM7c+ZMp3Tp0s7UqVOdvXv36kUely1bVm8Lx/HA6xUG0RSDOPaW2cCBA52iRYvqWX+kktv3OpMmTXKqVq3q2ntcunSpU6RIkbDPyGUqHxNxbMrFVBybcjEZJ2PGjM6WLVvirZd1ss0N8oXarl274h2zJIbvyzav5GJbHJtysS2OqVxsR8WUByxZskR/S5EjRw6nXr16esmZM6deJxeRYvz48c6bb75506/tu9j0LXF/D8cFaTjzMRmDOJSZyX3gRj399NO3PCV93JtR3+c/7u9uTxkdjlyiLY5NudgWxwu5FCtWzPnxxx/j3SxKy8zMmTO79h6ltUSLFi2c3377Tbf0lBvUwMUtpvIxEcemXEzFsSkXk3Fy5crljB07Nt56WSfXHW4dA7799tt4ubz//vtOxYoVHS/lYlscm3KxLY6pXGzHGFMeUL16dT0A4ZdffqlnyBIPPfSQevTRR/UsP+Lxxx+/pddesGCBsikfkzGIQ5mZ3AdkrCoZhFRmzBO5c+fW/dh9A64Hjg9xq0wdD0zkYiqOTbnYFsemXP766y9VvHjxBAddvnTpknJzqvjp06cnGMtNpvIxEcemXEzFsSkXk3Fk3KfOnTvrgZR9x5dly5apMWPG6DEt3dC9e3f17LPP6jFzpAGDHN+++uorNWTIEDV69GjlpVxsi2NTLrbFMZWL9SJdMwYASNyhQ4ecmjVr6pZKhQoVcqpUqaIXeSzrZJs8x6TOnTvfUssPU7mYiGNTLrbFsSkXn0qVKjkTJkyI14pBuhBJHLc0bdrU+frrr51wM5WPiTg25WIqjk25mIwjJk+e7FSvXt3JkiWLXuSxrHOTdEksXry4v8V0vnz5XB0ry2QutsWxKRfb4pjKxWa0mPKQjRs3qj179qiLFy8Grb///vtdef1169YluF6mwpQZRgoWLKhSpUqlvJKPqRjEoczCuQ/IbB4yK86mTZvizZS1efNm9cQTT+hvN6dOnapM+eKLL9QLL7ygsmfPHpW5mIhjUy62xbEpFx+ZJatdu3a6ZYa0wpg2bZqOMX78eDVjxgzllmbNmqlu3bqp9evX69lFU6RIEZZzp6l8TMSxKRdTcWzKxWQc8fDDD+slnNq0aaOXc+fOqTNnzqicOXOGJY6JXGyLY1MutsUxlYvVIl0zhuuTb15ktqzAQUgDx3xxS0LjSwUuqVKlctq2bev8888/UZ+PqTIjDmUW7n1Avn1dtWpVottl5ix5jkm3OoizqVxMxLEpF9vi2JRLoEWLFukZ82Q8OxlguUaNGs6cOXMcNwWOMxd3cXtsORP5mIpjUy6m4tiUi8k4AGArKqY8QJrWP/DAA7rrjFzkbty40Vm8eLHuMiAnQrfIYIe33367bq67bt06vchjGQhRZhaRpr358+d3evToEfX5mCoz4lBm4d4HZBD1hQsXJrpdZtF0cwrncFZMmcrFRBybcrEtjk253KyJEyc6Z86ccWxhKh8TcWzKxVQcm3JxI87ly5edt956y7nzzjv1YMu+LkO+5VbJDMIysPmNLG4JVy42x7EpF9vimMrFdlRMeYBc2K5du1Y/likn//zzT/14/vz5/uno3SAfptmzZ8dbL+tkm/jmm2/0lLjRno+pMiMOZRbufeCZZ57RY9ZMmzbNOXnypH+9PJZ1hQsXdrp06eJ4oWLKVC4m4tiUi21xbMrlZmXIkOGWPpsJCbV1dLTlE+k4NuViKo5NubgRp2/fvk6ePHmct99+20mdOrXz6quvOh07dtTXIcOHD7/l1x0wYIB/6d27t76WqVq1qtOtWze9VKtWTa+TbW4JVy42x7EpF9vimMrFdlRMeYBMNbtjxw79WCqFfvrpJ/1427ZturmwW+SDJFPbxiXrZJuQ6aNDjWkiH1NlRhzKLNz7wPnz5/U08ylTptRdaeSzKIs8lnUyELk8xwsVU6ZyMRHHplxsi2NTLqY+m4Hf+g4aNMjJmzevkzx5cv9rvfLKK2EZ/Djc+URTHJtyMRXHplzciCPXGDNmzPC/llxnCLnxbd26tSvvUW6m5fMeV79+/ZwOHTo4bjGRi21xbMrFtjimcrEdg597QJkyZdTatWtVkSJF1F133aXefPNNlTJlSvXJJ5+ookWLuhanRIkS6o033tCvK68vZJpbWSfbhAzsmCtXrqjPx1SZEYcyC/c+IBMOyDTzQ4cOVStXrgyakr5y5coqY8aMyitM5WIijk252BbHplxMGzx4sPr888/1ceypp54KOs4NGzZMdezYMaLvD0jK5BgjkxKI9OnTq5MnT+rHTZs2dW1KepmsYcWKFfHWP/bYY+qOO+5QY8aM8UwutsWxKRfb4pjKxXZUTHnAK6+8os6ePasfDxo0SO/kd999t8qWLZuaPHmya3FGjBihZ9zJnz+/KleunF4nM/PIrEO+WUV27NihZyKK9nxMlRlxKDNT+4Dc5NapU0dFA7lADeWm21QuJuLYlIttcWzKxRSZRUwq1evVq6eefvpp//ry5curP//8M6LvDUjq5Pr8wIEDepbsYsWKqblz56pKlSqp33//3bVZs9OkSaOWLFmi/vWvfwWtl3UyQ7eXcrEtjk252BbHVC7Wi3STLdyao0ePOlevXnW9+E6dOuV89NFH/n7lo0aN0uu8mo/pGMShzEzuA+LgwYPOwIEDXXmtZcuWOcOGDdPjSMgij2WdKW7mEuk4NuViWxybcnG7q5B0Rdy1a1e819qwYYOTLl06xzSvdLGKlhi2xbEpFzfi9OrVyxk8eLB+LJMSxcbGOsWLF9ddh2WbG4YMGaKPA127dnUmTJigFxkrL23atHqbW0zkYlscm3KxLY6pXGwXI/9EunIMN27v3r36Z4ECBawoNhP5mCoz4lBmkfh8SjdC+VZGWjbeqsOHD6uWLVvqb0Tl2x5fd91Dhw6pPXv2qBo1aqj//e9/KmfOnCrac4mWODblYlscm3KJK0OGDDrurXYjli6I3bp1060iA19LWoPOmzdPLV68WJkUaj7RFMemXEzFsSmXcMRZunSpXqR1U7NmzZRbpkyZooYPH642bdqkfy9ZsqR67rnn1MMPP6zCJVy52BzHplxsi2MqF9vQlc8DLl++rAYOHKjef/99debMGX//1a5du6r+/furFClSuBpv48aN+mb04sWLQeulm59X8jFVZsShzMK9D6xbt+6a2zdv3qxCJd1z5eZZLkJvv/32eK//xBNPqGeffVaPPRHtuZiKY1MutsWxKZebVahQoZCOOf369VPt2rXT40levXpVTZs2TechXfx8Xfq9lE80xbEpF1NxbMolHHGqVaumF7dJBVQ4K6FM5mJzHJtysS2OqVysE+kmW7g+mfUnZ86culudTEsvizzOnTu33uYWaV5crlw5JyYmRs8qJD99j2XxUj6myow4lFm494G4n8fAxbc+1M+ndC9YtWpVottXrFihn+OFXEzFsSkX2+LYlIvPpUuXnDVr1jizZ8/Wizy+ePGiEw6LFi1y6tev7+TIkUPPLFqjRg1nzpw5rsYwlY+JODblYiqOTbmYjCPGjx/vVK9eXU9N7+t2+9577znffvut4zWmcrEpjk252BbHps9mpFAx5QEZM2Z0Zs2aFW/9zJkz9Ta3NG3a1HnggQecI0eO6JvQjRs3OosXL3aqVKmiL1S9lI+pMiMOZRbufSBbtmzOZ599pk9yCS0SJ9SbX4mxcOHCRLcvWLBAP8cLuZiKY1MutsWxKZcrV644L7/8spM5c+Z4lV+yTqZ1l+eYNnHiROfMmTNRm4+JODblYiqOTbmYjOMzcuRIJ3v27M5rr72mK41941WNHTvWqV27tisxLl++7Lz11lvOnXfe6eTKlcvJkiVL0OKlXGyLY1MutsUxlYvtqJjyAPnWUiqJ4pJ18iFwi1xkS2sPITfUf/75p348f/58p0KFCp7Kx1SZEYcyC/c+0KBBA+fVV19NdLt8MysXwaF45plnnEKFCjnTpk1zTp486V8vj2Vd4cKF9eCnXsjFVBybcrEtjk259OzZUx9jpBXmzp07nXPnzulFHn/88ce6teaLL77omJYhQ4ZbGsTZVD4m4tiUi6k4NuViMo5PyZIlnW+++SbeQOrr16935csj0bdvX93i4+2339aDoMsxrmPHjvr1hw8f7ngpF9vi2JSLbXFM5WI7KqY8QGb1ad26tXP+/Hn/Onncpk0bZ8CAAa7FkW93duzYoR8XLVrU+emnn/Tjbdu26dpfL+VjqsyIQ5mFex+QiiGZFScxx44dc8aNGxdSDHm/0u1QZg+RFh5yMSqLPJZ1nTt3DsovmnMxFcemXGyLY1Mu0mJBugYlRrbJza9ptzq7mKl8TMSxKRdTcWzKxWSc682auWXLFr3NDXL9P2PGDH8MuQcQUikl1zpeysW2ODblYlscU7nYjsHPPWD16tVq/vz5Kn/+/Kp8+fJ6nczqIYOT16tXT7Vo0cL/XBmo9FaVKVNGv26RIkXUXXfdpd58802VMmVK9cknn7g6U4mJfEyVGXEos3DvAw8++OA1t2fJkkUPVhyKVKlSqY8++kgNHTpUrVy5Uh08eFCvz507t56lK2PGjMoNJnIxFcemXGyLY1Mup0+fVnnz5k10e548edTZs2eVV5jKx0Qcm3IxFcemXEzG8ZHr8zVr1uhB1APNnj1bz5znBjn/ly1b1j+Ry8mTJ/Xjpk2bqr59+yov5WJbHJtysS2OqVxsR8WUB2TOnFlP5R4oHNPRv/LKK/4TqEwNLSehu+++W2XLlk1NnjzZU/mYKjPiUGam9oHz58+r1KlTJ7jtwIED+gI4VFIBVadOHRVuJnIxFcemXGyLY0MutWvXVi+88IL68ssvVfbs2YO2/f3336pXr176OV5hKh8TcWzKxVQcm3IxGcene/fueoZcOeZIr5fly5err776Sg0ZMkSNHj3alRjyJZsctwoWLKiKFSum5s6dqypVqqR+//13/SWWl3KxLY5NudgWx1Qu1ot0ky1Et6NHjzpXr16N9NsAkjzpv7569ep45fD111+7Om5aQg4ePKi7LHotFxNxbMrFtjg25LJnzx6nTJkyTmxsrFOxYkWnUaNGepHHsk5m0pXneKUrn6l8TMSxKRdTcWzKxWScQF988YVTvHhx/yDr+fLlc0aPHu3a6/fq1csZPHiwfjxp0iSdh8STbv2yzUu52BjHplxsi2MqF5vpUTkjXTmGa/vnn3907WvatGn177t371bffPONKlWqlGrQoEFYim/v3r1ha/lhIh9TZUYcyszUPvDMM8+oMWPGqIEDB+pvYaV1o3w7M2XKFDV48GDVrVs3FS7SNVG+Mb1y5YqncjERx6ZcbItjSy5Xr15Vc+bMUb/99ltQN9tq1arpY0yyZMmUaRkyZNDHhVvp5m8qHxNxbMrFVBybcjEZJ65z586pM2fOqJw5c6pwWrp0qV7+9a9/qWbNmnk6F5vi2JSLbXFM5WKlSNeM4fruvfde56OPPtKPjx8/rgdSzJ8/vx5MTaandMulS5f01LYyI58MeiyLPJapcC9evOipfEyVGXEoM1P7gJABSXPnzu3UrFnTKVasmFO+fHk940eoZDbOay2TJ08Oedp7U7lEIo5NudgWx6Zcoknp0qUj0lILAADYiRZTHiD91n/++WdVunRp3U/1gw8+0AMu/+9//1P9+vVTmzZtciVO586d9eDMMr6UfNMj5FuSAQMGqObNm+vBkb2Sj6kyIw5lZmof8H0z27VrV/1ZjI2NVd9//71q2LBhyK8r3+jGxMToll9x+dbLT7daTIUzl0jEsSkX2+LYkIt8/nbt2qVbMMtry8QK0irzwoULqkmTJvHGtgnF5cuX1YYNG4JafkjrzxQpUrgWw1Q+JuLYlIupODblYiJOxYoV9fn3RqxatUq5YcKECWrUqFFq586d+j5ABnQeNmyYHuD5gQceiPpcbIpjUy62xYnEZ9N2DH7uAdIkUJrNCxmEUGb5khvJqlWr6m5Dbpk4caKaNGmSaty4sX9duXLl9Mm2devWrlVMmcjHVJkRhzIztQ9s375dPfroo/qGUboNSGXY/fffr5577jndXSiUG8esWbPqWThlFsGEyI2qm034w5mL6Tg25WJbHBty2bx5s67gku710m1OjjEPPfSQ+vPPP/1diH/99VfdzSbUijWpSB8xYoR/Fi6fTJkyqS5duuiuiqF2SzKVj4k4NuViKo5NuZiKI18M+8jAyiNHjtSVxb4vkKULoZyjpUuxG+RaX44Fzz//vD5++b6QkolepHIqlIopU7nYFMemXGyLY/qzmSREuskWrq9s2bLO8OHDdbN56Vr366+/6vUrVqxwcuXK5VoR5siRw9m4cWO89bLOzYFiTeRjqsyIQ5mZ2gdksOFWrVrp7oI+S5Ys0d2GKlSoENJrN2jQwHn11VcT3b5mzRo9kKMXcjEdx6ZcbItjQy4PPPCAc//99zvr1q1znn/+eT3QuqyT7vXnz593mjVr5jz22GMh59CzZ099DTBq1Chn586dzrlz5/Qijz/++GPdRfnFF18MOY6pfEzEsSkXU3FsysVkHJ+OHTvqITfi6tevn9OhQwdXYkgO33zzTbxJDqRrcrZs2Rwv5WJbHJtysS2OqVxsR8WUB0ydOtVJkSKFHuNFxrPxef311/XsH26RWbdat26tT6Y+8rhNmzbOgAEDPJWPqTIjDmVmah8YP358gutPnTrlPPHEEyG99rRp05wJEyYkuv3YsWPOuHHjHC/kYjqOTbnYFseGXKSyyDfj35kzZ3QF8eLFi4MqwAoWLOiESirRZ8+eneh22SaVU6EylY+JODblYiqOTbmYjOMjX35t2bIl3npZJ9vcIONj7tq1K17FlMSQbV7KxbY4NuViWxxTudiOiimPOHDggLNq1SrnypUr/nXLli1zNm3a5P997969QdtvVvPmzZ0MGTLo1lH16tXTizyWD9SDDz4YtHghHxMxiEOZmdwHACQtadKkcXbv3u3/XW4Ut23b5v9dWmqmSpUq5Dhp06bVrT4SI5MgpEuXzjP5mIhjUy6m4tiUi8k4gRXIY8eOjbde1rlRcexrMfXtt9/Gq5h6//33nYoVKzpeysW2ODblYlscU7nYjjGmPEIGIJUlUJUqVYJ+l36ta9asuaXpm339x1u2bBm0TsaX8mo+JmIQh7+NiX1ABlP99ttv9SCkgYMSV69eXY/3kDJlSuUG6SOfOnXqBLcdOHBA5cmTJ+QYpnIxEcemXGyLY0suefPmVXv27FEFCxbUv8tYcIFTUB85ckRlyZIlxCyUql27tnrhhRfUl19+GW+w5r///lv16tVLPydUpvIxEcemXEzFsSkXk3F8ZNwnmahIBlL2XWMsW7ZMjRkzRvXt29eVGN27d1fPPvusvh6QBgzLly9XX331lRoyZIie4MVLudgWx6ZcbItjKhfrRbpmDO4J/GbDBibyMVVmxKHMbnUf2Lp1q1O0aFHdhP6ee+5xHn74Yb3IY1lXvHhx/Ry3vin1dUsI9PXXX7syzpypXEzEsSkX2+LYlMt//vMf59NPP010+5AhQ5wmTZo4oZKWHWXKlHFiY2N1qwjphiyLPJZ15cqV088Jlal8TMSxKRdTcWzKxWScQJMnT3aqV6/uZMmSRS/yWNa56YsvvtDHL+maKEu+fPmc0aNHO24zkYttcWzKxbY4pnKxGRVTFgm18kMGOj179qz/d+lj/t577zlz5sxxIoGKqaQdx6ZcQolTv359PZjqyZMn422TdbJNBi93Q+fOnXW3gzfeeMM/Zka7du10d4V333035Nc3lYuJODblYlscm3K5nh07djj79+935bWkq/GsWbP0YK2dOnXSizz+4YcfjHVDdjOfSMexKRdTcWzKxWScuCZOnKjP36GSe4JDhw45keRWLkkpjk252BbHVC5eRcWURUK9wZaBmz/66CP9WGYXkj6x+fPn19/8jhw50jGNyo+kHcemXEKJI5VCMhtOYmRcGHmOW2bMmOHkzp3bqVmzpp5VrHz58teMH425mIhjUy62xbEplxsR+IWSDUzlYyKOTbmYimNTLibjBJLxYm3pQWEqF5vi2JSLbXFs+myGQ7JIdyVE9JB+sXfffbd+/PXXX+txMnbv3q3Gjx+v3n///Ui/PSBJkrHfdu3aleh22SbPcUvjxo1VixYt1JIlS/TYGUOHDlVlypTxVC4m4tiUi21xbMrFp169euqvv/6Kt17Gf6lQoYIrMeTLyp07d6rLly/7x8+aPHmyvgaQcabcZCIfU3FsysVUHJtyMRnnZj7LN6NixYqqUqVKN7REey7EocyieR8wtT97FRVTFomJiQnp/587d05lyJBBP547d66+OU2WLJmqWrWqrqDyWj7REoM4lFko+8CTTz6p2rZtq9577z21bt06dejQIb3IY1nXvn171alTJ1f20+3bt6tq1aqpGTNmqDlz5qgXX3xR3X///frnpUuXQn59U7mYiGNTLrbFsSkXH5mUoFy5crqiSFy9elUNGDBA1axZUzVp0iTk19+8ebMqUqSIKl68uCpZsqSuoJIB3Dt27KgHdJV1W7duVW4Jdz4m49iUi6k4NuViMk64NG/eXE/WIEvDhg31tUCqVKn0hAeySH6yTrYBQNiEpR0WIiLULklly5Z1hg8frgc4zZgxo/Prr7/q9StWrNDTYJpGd7GkHcemXEKNI2M+5cmT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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", + "\n", + "df = pd.DataFrame(results)\n", + "\n", + "metrics = [\"время_мс\", \"посещено_клеток\", \"длина_пути\"]\n", + "titles = [\"Время (мс)\", \"Посещено клеток\", \"Длина пути\"]\n", + "colors = {\"BFS\": \"#4C72B0\", \"DFS\": \"#DD8452\", \"A*\": \"#55A868\"}\n", + "\n", + "fig, axes = plt.subplots(len(metrics), 1, figsize=(12, 14))\n", + "\n", + "for ax, metric, title in zip(axes, metrics, titles):\n", + " for strategy_name in df[\"стратегия\"].unique():\n", + " subset = df[df[\"стратегия\"] == strategy_name].reset_index(drop=True)\n", + " ax.bar(\n", + " [\n", + " i + list(df[\"стратегия\"].unique()).index(strategy_name) * 0.25\n", + " for i in range(len(subset))\n", + " ],\n", + " subset[metric],\n", + " width=0.25,\n", + " label=strategy_name,\n", + " color=colors[strategy_name],\n", + " )\n", + " ax.set_title(title, fontsize=13)\n", + " ax.set_xticks([i + 0.25 for i in range(len(df[\"лабиринт\"].unique()))])\n", + " ax.set_xticklabels(df[\"лабиринт\"].unique(), rotation=90, ha=\"right\")\n", + " ax.legend()\n", + " ax.grid(axis=\"y\", alpha=0.3)\n", + "\n", + "plt.tight_layout()\n", + "plt.savefig(\"results.png\", dpi=150)\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.14.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/skorohodovsa/task_2/practice/results.csv b/skorohodovsa/task_2/practice/results.csv new file mode 100644 index 0000000..8e373ed --- /dev/null +++ b/skorohodovsa/task_2/practice/results.csv @@ -0,0 +1,121 @@ +лабиринт,стратегия,время_мс,посещено_клеток,длина_пути +100x100_spaghetti_v1.txt,BFS,9.2513,205.0,205.0 +100x100_spaghetti_v1.txt,DFS,8.2451,2129.0,2129.0 +100x100_spaghetti_v1.txt,A*,7.1113,205.0,205.0 +100x100_spaghetti_v10.txt,BFS,9.2555,207.0,207.0 +100x100_spaghetti_v10.txt,DFS,8.1821,2489.0,2489.0 +100x100_spaghetti_v10.txt,A*,8.4803,207.0,207.0 +100x100_spaghetti_v2.txt,BFS,9.3921,217.0,217.0 +100x100_spaghetti_v2.txt,DFS,6.7196,2063.0,2063.0 +100x100_spaghetti_v2.txt,A*,10.5764,217.0,217.0 +100x100_spaghetti_v3.txt,BFS,8.4084,217.0,217.0 +100x100_spaghetti_v3.txt,DFS,5.7855,2107.0,2107.0 +100x100_spaghetti_v3.txt,A*,6.3385,217.0,217.0 +100x100_spaghetti_v4.txt,BFS,8.8661,205.0,205.0 +100x100_spaghetti_v4.txt,DFS,6.8166,2409.0,2409.0 +100x100_spaghetti_v4.txt,A*,6.1874,205.0,205.0 +100x100_spaghetti_v5.txt,BFS,8.3117,217.0,217.0 +100x100_spaghetti_v5.txt,DFS,6.3364,2071.0,2071.0 +100x100_spaghetti_v5.txt,A*,8.495,217.0,217.0 +100x100_spaghetti_v6.txt,BFS,8.212,243.0,243.0 +100x100_spaghetti_v6.txt,DFS,7.0348,1869.0,1869.0 +100x100_spaghetti_v6.txt,A*,12.8413,243.0,243.0 +100x100_spaghetti_v7.txt,BFS,8.3471,211.0,211.0 +100x100_spaghetti_v7.txt,DFS,6.1699,2283.0,2283.0 +100x100_spaghetti_v7.txt,A*,6.9637,211.0,211.0 +100x100_spaghetti_v8.txt,BFS,8.3499,221.0,221.0 +100x100_spaghetti_v8.txt,DFS,7.1166,2473.0,2473.0 +100x100_spaghetti_v8.txt,A*,9.5093,221.0,221.0 +100x100_spaghetti_v9.txt,BFS,8.5536,209.0,209.0 +100x100_spaghetti_v9.txt,DFS,5.4126,1939.0,1939.0 +100x100_spaghetti_v9.txt,A*,6.7365,209.0,209.0 +10x10_path_v1.txt,BFS,0.032,13.0,13.0 +10x10_path_v1.txt,DFS,0.0341,13.0,13.0 +10x10_path_v1.txt,A*,0.0399,13.0,13.0 +10x10_path_v10.txt,BFS,0.0323,13.0,13.0 +10x10_path_v10.txt,DFS,0.036,13.0,13.0 +10x10_path_v10.txt,A*,0.037,13.0,13.0 +10x10_path_v2.txt,BFS,0.0354,17.0,17.0 +10x10_path_v2.txt,DFS,0.0433,17.0,17.0 +10x10_path_v2.txt,A*,0.044,17.0,17.0 +10x10_path_v3.txt,BFS,0.0348,17.0,17.0 +10x10_path_v3.txt,DFS,0.0492,17.0,17.0 +10x10_path_v3.txt,A*,0.0439,17.0,17.0 +10x10_path_v4.txt,BFS,0.0476,29.0,29.0 +10x10_path_v4.txt,DFS,0.0475,29.0,29.0 +10x10_path_v4.txt,A*,0.0652,29.0,29.0 +10x10_path_v5.txt,BFS,0.0302,13.0,13.0 +10x10_path_v5.txt,DFS,0.0334,13.0,13.0 +10x10_path_v5.txt,A*,0.0371,13.0,13.0 +10x10_path_v6.txt,BFS,0.0307,13.0,13.0 +10x10_path_v6.txt,DFS,0.0339,13.0,13.0 +10x10_path_v6.txt,A*,0.0375,13.0,13.0 +10x10_path_v7.txt,BFS,0.0401,17.0,17.0 +10x10_path_v7.txt,DFS,0.0499,17.0,17.0 +10x10_path_v7.txt,A*,0.0489,17.0,17.0 +10x10_path_v8.txt,BFS,0.0615,29.0,29.0 +10x10_path_v8.txt,DFS,0.0536,29.0,29.0 +10x10_path_v8.txt,A*,0.0801,29.0,29.0 +10x10_path_v9.txt,BFS,0.0579,17.0,17.0 +10x10_path_v9.txt,DFS,0.046,17.0,17.0 +10x10_path_v9.txt,A*,0.0468,17.0,17.0 +30x30_empty_v1.txt,BFS,1.1046,55.0,55.0 +30x30_empty_v1.txt,DFS,0.7781,379.0,379.0 +30x30_empty_v1.txt,A*,1.9965,55.0,55.0 +30x30_empty_v10.txt,BFS,1.1246,55.0,55.0 +30x30_empty_v10.txt,DFS,0.7002,379.0,379.0 +30x30_empty_v10.txt,A*,2.0086,55.0,55.0 +30x30_empty_v2.txt,BFS,1.1401,55.0,55.0 +30x30_empty_v2.txt,DFS,0.7263,379.0,379.0 +30x30_empty_v2.txt,A*,2.0245,55.0,55.0 +30x30_empty_v3.txt,BFS,1.1038,55.0,55.0 +30x30_empty_v3.txt,DFS,0.7249,379.0,379.0 +30x30_empty_v3.txt,A*,2.007,55.0,55.0 +30x30_empty_v4.txt,BFS,1.1224,55.0,55.0 +30x30_empty_v4.txt,DFS,0.7053,379.0,379.0 +30x30_empty_v4.txt,A*,1.989,55.0,55.0 +30x30_empty_v5.txt,BFS,1.1294,55.0,55.0 +30x30_empty_v5.txt,DFS,0.7202,379.0,379.0 +30x30_empty_v5.txt,A*,2.1138,55.0,55.0 +30x30_empty_v6.txt,BFS,1.0843,55.0,55.0 +30x30_empty_v6.txt,DFS,0.7746,379.0,379.0 +30x30_empty_v6.txt,A*,2.009,55.0,55.0 +30x30_empty_v7.txt,BFS,1.1449,55.0,55.0 +30x30_empty_v7.txt,DFS,0.7076,379.0,379.0 +30x30_empty_v7.txt,A*,2.033,55.0,55.0 +30x30_empty_v8.txt,BFS,1.3196,55.0,55.0 +30x30_empty_v8.txt,DFS,0.7794,379.0,379.0 +30x30_empty_v8.txt,A*,1.9972,55.0,55.0 +30x30_empty_v9.txt,BFS,1.1088,55.0,55.0 +30x30_empty_v9.txt,DFS,0.7131,379.0,379.0 +30x30_empty_v9.txt,A*,2.0128,55.0,55.0 +50x50_deadends_v1.txt,BFS,1.7809,729.0,729.0 +50x50_deadends_v1.txt,DFS,1.7167,729.0,729.0 +50x50_deadends_v1.txt,A*,2.5217,729.0,729.0 +50x50_deadends_v10.txt,BFS,0.7362,261.0,261.0 +50x50_deadends_v10.txt,DFS,1.7627,261.0,261.0 +50x50_deadends_v10.txt,A*,0.9753,261.0,261.0 +50x50_deadends_v2.txt,BFS,0.9246,249.0,249.0 +50x50_deadends_v2.txt,DFS,1.7347,249.0,249.0 +50x50_deadends_v2.txt,A*,1.0804,249.0,249.0 +50x50_deadends_v3.txt,BFS,0.945,297.0,297.0 +50x50_deadends_v3.txt,DFS,1.7483,297.0,297.0 +50x50_deadends_v3.txt,A*,1.0832,297.0,297.0 +50x50_deadends_v4.txt,BFS,1.5487,413.0,413.0 +50x50_deadends_v4.txt,DFS,1.6526,413.0,413.0 +50x50_deadends_v4.txt,A*,1.9521,413.0,413.0 +50x50_deadends_v5.txt,BFS,0.9255,309.0,309.0 +50x50_deadends_v5.txt,DFS,1.7299,309.0,309.0 +50x50_deadends_v5.txt,A*,1.1469,309.0,309.0 +50x50_deadends_v6.txt,BFS,1.0637,337.0,337.0 +50x50_deadends_v6.txt,DFS,1.7728,337.0,337.0 +50x50_deadends_v6.txt,A*,1.3449,337.0,337.0 +50x50_deadends_v7.txt,BFS,0.7827,261.0,261.0 +50x50_deadends_v7.txt,DFS,1.6948,261.0,261.0 +50x50_deadends_v7.txt,A*,0.9527,261.0,261.0 +50x50_deadends_v8.txt,BFS,1.5551,565.0,565.0 +50x50_deadends_v8.txt,DFS,1.7707,565.0,565.0 +50x50_deadends_v8.txt,A*,2.3158,565.0,565.0 +50x50_deadends_v9.txt,BFS,0.6693,209.0,209.0 +50x50_deadends_v9.txt,DFS,1.052,209.0,209.0 +50x50_deadends_v9.txt,A*,0.7957,209.0,209.0 diff --git a/skorohodovsa/task_2/practice/results.png b/skorohodovsa/task_2/practice/results.png new file mode 100644 index 0000000000000000000000000000000000000000..e94ceb8b8359a1c2923b333b970c3bfd9168e68b GIT binary patch literal 223043 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%0Dqd*I;tOiF}<1^ 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 literal 0 HcmV?d00001 diff --git a/skorohodovsa/task_2/requirements.txt b/skorohodovsa/task_2/requirements.txt index 791d693..20ae8cb 100644 --- a/skorohodovsa/task_2/requirements.txt +++ b/skorohodovsa/task_2/requirements.txt @@ -5,4 +5,7 @@ nbsphinx myst-nb tabulate bibtexparser -pytest \ No newline at end of file +pytest +sphinxcontrib-mermaid +matplotlib +pandas \ No newline at end of file diff --git a/skorohodovsa/task_2/source/models/base.py b/skorohodovsa/task_2/source/models/base.py index 52c874a..1496091 100644 --- a/skorohodovsa/task_2/source/models/base.py +++ b/skorohodovsa/task_2/source/models/base.py @@ -183,7 +183,7 @@ class Maze: neighbors.append(cell) return neighbors - + @property def start(self) -> Optional[Cell]: for y in range(self._height): @@ -191,7 +191,7 @@ class Maze: if self[y, x].is_start: return self[y, x] return None - + @property def exit(self) -> Optional[Cell]: for y in range(self._height): diff --git a/skorohodovsa/task_2/source/strategy/__init__.py b/skorohodovsa/task_2/source/strategy/__init__.py index 0da8de2..72c56bf 100644 --- a/skorohodovsa/task_2/source/strategy/__init__.py +++ b/skorohodovsa/task_2/source/strategy/__init__.py @@ -8,4 +8,4 @@ __all__ = [ "BFSStrategy", "DFSStrategy", "AStarStrategy", -] \ No newline at end of file +] diff --git a/skorohodovsa/task_2/source/strategy/algorithms.py b/skorohodovsa/task_2/source/strategy/algorithms.py index c6fd162..c8b1537 100644 --- a/skorohodovsa/task_2/source/strategy/algorithms.py +++ b/skorohodovsa/task_2/source/strategy/algorithms.py @@ -23,6 +23,26 @@ class PathFindingStrategy(ABC): Пустой список, если путь не найден. """ + def _validate( + self, maze: Maze, start: Optional[Cell], exit: Optional[Cell] + ) -> tuple[Optional[Cell], Optional[Cell]]: + """Подставляет start/exit из лабиринта если не переданы явно. + + Raises: + ValueError: Если старт или выход не найдены. + """ + if start is None: + start = maze.start + if exit is None: + exit = maze.exit + + if start is None: + raise ValueError("Стартовая клетка не найдена в лабиринте") + if exit is None: + raise ValueError("Выходная клетка не найдена в лабиринте") + + return start, exit + def _reconstruct_path( self, came_from: dict[Cell, Optional[Cell]], end: Cell ) -> list[Cell]: @@ -46,11 +66,3 @@ class PathFindingStrategy(ABC): current = came_from[current] path.reverse() return path - - - - - - - - diff --git a/skorohodovsa/task_2/source/strategy/astar.py b/skorohodovsa/task_2/source/strategy/astar.py index 37f76b0..ead84f6 100644 --- a/skorohodovsa/task_2/source/strategy/astar.py +++ b/skorohodovsa/task_2/source/strategy/astar.py @@ -4,6 +4,11 @@ from typing import Optional from source.models.base import Cell, Maze from source.strategy.algorithms import PathFindingStrategy +# ---------------------------------------------------------------------------- # +# Моя азиатская жена называет меня расистом. Но как я могу # +# быть расистом, если я женился на женщине низшей расы?! # +# ---------------------------------------------------------------------------- # + def _manhattan(a: Cell, b: Cell) -> int: """Манхэттенское расстояние между двумя клетками.""" @@ -13,11 +18,10 @@ def _manhattan(a: Cell, b: Cell) -> int: class AStarStrategy(PathFindingStrategy): """Алгоритм A* с манхэттенской эвристикой.""" - def find_path(self, maze: Maze, start: Optional[Cell] = None, exit: Optional[Cell] = None) -> list[Cell]: - if start is None: - start = maze.start - if exit is None: - exit = self.exit + def find_path( + self, maze: Maze, start: Optional[Cell] = None, exit: Optional[Cell] = None + ) -> list[Cell]: + start, exit = self._validate(maze, start, exit) g_score: dict[Cell, int] = {start: 0} came_from: dict[Cell, Optional[Cell]] = {start: None} @@ -43,4 +47,4 @@ class AStarStrategy(PathFindingStrategy): counter += 1 heapq.heappush(open_heap, (f, counter, neighbor)) - return [] \ No newline at end of file + return [] diff --git a/skorohodovsa/task_2/source/strategy/bfs.py b/skorohodovsa/task_2/source/strategy/bfs.py index fb6317f..b0bba06 100644 --- a/skorohodovsa/task_2/source/strategy/bfs.py +++ b/skorohodovsa/task_2/source/strategy/bfs.py @@ -15,10 +15,7 @@ class BFSStrategy(PathFindingStrategy): def find_path( self, maze: Maze, start: Optional[Cell] = None, exit: Optional[Cell] = None ) -> list[Cell]: - if start is None: - start = maze.start - if exit is None: - exit = maze.exit + start, exit = self._validate(maze, start, exit) came_from: dict[Cell, Optional[Cell]] = {start: None} queue: deque[Cell] = deque([start]) @@ -34,4 +31,4 @@ class BFSStrategy(PathFindingStrategy): came_from[neighbor] = current queue.append(neighbor) - return [] \ No newline at end of file + return [] diff --git a/skorohodovsa/task_2/source/strategy/dfs.py b/skorohodovsa/task_2/source/strategy/dfs.py index 11cde79..8b41845 100644 --- a/skorohodovsa/task_2/source/strategy/dfs.py +++ b/skorohodovsa/task_2/source/strategy/dfs.py @@ -3,6 +3,12 @@ from typing import Optional from source.models.base import Maze, Cell from source.strategy.algorithms import PathFindingStrategy +# ---------------------------------------------------------------------------- # +# Как называется пресмыкающийся, который в прошлом был программистом? # +# ---------------------------------------------------------------------------- # +# крокодил # +# ---------------------------------------------------------------------------- # + class DFSStrategy(PathFindingStrategy): """Поиск в глубину (Depth-First Search). @@ -13,10 +19,7 @@ class DFSStrategy(PathFindingStrategy): def find_path( self, maze: Maze, start: Optional[Cell] = None, exit: Optional[Cell] = None ) -> list[Cell]: - if start is None: - start = maze.start - if exit is None: - exit = maze.exit + start, exit = self._validate(maze, start, exit) came_from: dict[Cell, Optional[Cell]] = {start: None} stack: list[Cell] = [start] @@ -32,4 +35,4 @@ class DFSStrategy(PathFindingStrategy): came_from[neighbor] = current stack.append(neighbor) - return [] \ No newline at end of file + return [] diff --git a/skorohodovsa/task_2/source/strategy/solver.py b/skorohodovsa/task_2/source/strategy/solver.py index eb17b64..ac1379f 100644 --- a/skorohodovsa/task_2/source/strategy/solver.py +++ b/skorohodovsa/task_2/source/strategy/solver.py @@ -15,6 +15,7 @@ class SearchStats: path_length: Длина найденного пути (0 если путь не найден). path: Найденный путь — список клеток от старта до выхода. """ + elapsed_ms: float visited_count: int path_length: int @@ -90,4 +91,4 @@ class MazeSolver: visited_count=len(path), path_length=len(path), path=path, - ) \ No newline at end of file + ) diff --git a/skorohodovsa/task_2/source/view/__init__.py b/skorohodovsa/task_2/source/view/__init__.py index 2865973..cad01a4 100644 --- a/skorohodovsa/task_2/source/view/__init__.py +++ b/skorohodovsa/task_2/source/view/__init__.py @@ -10,4 +10,4 @@ __all__ = [ "MoveCommand", "CommandHistory", "DIRECTIONS", -] \ No newline at end of file +] diff --git a/skorohodovsa/task_2/source/view/command.py b/skorohodovsa/task_2/source/view/command.py index 9ae96e5..fe4c304 100644 --- a/skorohodovsa/task_2/source/view/command.py +++ b/skorohodovsa/task_2/source/view/command.py @@ -8,6 +8,7 @@ from source.models.base import Maze, Cell # Игрок # # ---------------------------------------------------------------------------- # + class Player: """Хранит текущее положение игрока в лабиринте. @@ -31,6 +32,7 @@ class Player: # Интерфейс команды # # ---------------------------------------------------------------------------- # + class Command(ABC): """Интерфейс команды с поддержкой отмены.""" @@ -53,9 +55,9 @@ class Command(ABC): DIRECTIONS = { "w": (0, -1), - "s": (0, 1), + "s": (0, 1), "a": (-1, 0), - "d": (1, 0), + "d": (1, 0), } @@ -77,11 +79,13 @@ class MoveCommand(Command): ValueError: Если направление не распознано. """ if direction not in DIRECTIONS: - raise ValueError(f"Неизвестное направление '{direction}'. Используй: w/a/s/d") + raise ValueError( + f"Неизвестное направление '{direction}'. Используй: w/a/s/d" + ) - self._player = player + self._player = player self._direction = direction - self._maze = maze + self._maze = maze self._prev_cell: Optional[Cell] = None def execute(self) -> bool: @@ -99,7 +103,7 @@ class MoveCommand(Command): if target is None or not target.is_possible(): return False - self._prev_cell = self._player.cell + self._prev_cell = self._player.cell self._player.cell = target return True @@ -113,6 +117,7 @@ class MoveCommand(Command): # История команд # # ---------------------------------------------------------------------------- # + class CommandHistory: """Хранит историю выполненных команд и позволяет отменять их. @@ -150,4 +155,4 @@ class CommandHistory: def clear(self) -> None: """Очищает историю команд.""" - self._history.clear() \ No newline at end of file + self._history.clear() diff --git a/skorohodovsa/task_2/source/view/observer.py b/skorohodovsa/task_2/source/view/observer.py index 5c51210..c5df3f7 100644 --- a/skorohodovsa/task_2/source/view/observer.py +++ b/skorohodovsa/task_2/source/view/observer.py @@ -10,6 +10,7 @@ from source.settings import cell_mapping # События # # ---------------------------------------------------------------------------- # + @dataclass class Event: """Событие, передаваемое наблюдателям. @@ -18,6 +19,7 @@ class Event: type: Тип события ('maze_loaded', 'path_found', 'move', 'no_path'). payload: Дополнительные данные события. """ + type: str payload: dict = None @@ -26,6 +28,7 @@ class Event: # Интерфейс наблюдателя # # ---------------------------------------------------------------------------- # + class Observer(ABC): """Интерфейс наблюдателя за событиями лабиринта.""" @@ -42,12 +45,13 @@ class Observer(ABC): # Консольный наблюдатель # --------------------------------------------------------------------------- + class ConsoleView(Observer): """Отображает состояние лабиринта и события в консоли.""" # Символ игрока на карте PLAYER_SYMBOL = "P" - PATH_SYMBOL = "·" + PATH_SYMBOL = "·" def update(self, event: Event) -> None: """Реагирует на события и выводит информацию в консоль. @@ -108,4 +112,4 @@ class ConsoleView(Observer): row_str += str(cell) row_str += "|" print(row_str) - print("+" + "─" * cols + "+") \ No newline at end of file + print("+" + "─" * cols + "+") diff --git a/skorohodovsa/task_2/test/map/__init__.py b/skorohodovsa/task_2/test/map/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/skorohodovsa/task_2/test/map/test_cell.py b/skorohodovsa/task_2/test/map/test_cell.py deleted file mode 100644 index 31d7714..0000000 --- a/skorohodovsa/task_2/test/map/test_cell.py +++ /dev/null @@ -1,111 +0,0 @@ -import pytest -import sys -import os - -from source.models.base import Cell - -class TestCellCreation: - """Тесты создания клетки и начальных значений.""" - - def test_coordinates_are_set(self): - cell = Cell(3, 7) - assert cell.x == 3 - assert cell.y == 7 - - def test_default_flags_are_false(self): - cell = Cell(0, 0) - assert cell.is_wall is False - assert cell.is_start is False - assert cell.is_exit is False - - def test_create_wall(self): - cell = Cell(0, 0, is_wall=True) - assert cell.is_wall is True - - def test_create_start(self): - cell = Cell(0, 0, is_start=True) - assert cell.is_start is True - - def test_create_exit(self): - cell = Cell(0, 0, is_exit=True) - assert cell.is_exit is True - - -class TestCellIsPassable: - """Тесты метода is_possible.""" - - def test_empty_cell_is_passable(self): - cell = Cell(0, 0) - assert cell.is_possible() is True - - def test_wall_is_not_passable(self): - cell = Cell(0, 0, is_wall=True) - assert cell.is_possible() is False - - def test_start_cell_is_passable(self): - cell = Cell(0, 0, is_start=True) - assert cell.is_possible() is True - - def test_exit_cell_is_passable(self): - cell = Cell(0, 0, is_exit=True) - assert cell.is_possible() is True - - -class TestCellFlagsAreMutuallyExclusive: - """Тесты взаимного исключения флагов.""" - - def test_set_wall_clears_start(self): - cell = Cell(0, 0, is_start=True) - cell.is_wall = True - assert cell.is_start is False - assert cell.is_wall is True - - def test_set_wall_clears_exit(self): - cell = Cell(0, 0, is_exit=True) - cell.is_wall = True - assert cell.is_exit is False - assert cell.is_wall is True - - def test_set_start_clears_wall(self): - cell = Cell(0, 0, is_wall=True) - cell.is_start = True - assert cell.is_wall is False - assert cell.is_start is True - - def test_set_start_clears_exit(self): - cell = Cell(0, 0, is_exit=True) - cell.is_start = True - assert cell.is_exit is False - assert cell.is_start is True - - def test_set_exit_clears_wall(self): - cell = Cell(0, 0, is_wall=True) - cell.is_exit = True - assert cell.is_wall is False - assert cell.is_exit is True - - def test_set_exit_clears_start(self): - cell = Cell(0, 0, is_start=True) - cell.is_exit = True - assert cell.is_start is False - assert cell.is_exit is True - - def test_unset_wall_does_not_clear_others(self): - # снятие флага (False) не должно трогать остальные - cell = Cell(0, 0, is_wall=True) - cell.is_wall = False - assert cell.is_start is False - assert cell.is_exit is False - - -class TestCellStr: - """Тесты строкового представления клетки.""" - - def test_str_returns_string(self): - cell = Cell(0, 0) - assert isinstance(str(cell), str) - - def test_repr_contains_coordinates(self): - cell = Cell(4, 9) - assert "4" in repr(cell) - assert "9" in repr(cell) \ No newline at end of file diff --git a/skorohodovsa/task_2/test/play.py b/skorohodovsa/task_2/test/play.py index d6cc572..d46a16c 100644 --- a/skorohodovsa/task_2/test/play.py +++ b/skorohodovsa/task_2/test/play.py @@ -19,9 +19,9 @@ if start is None: print("Стартовая клетка не найдена!") exit() -player = Player(start) +player = Player(start) history = CommandHistory() -view = ConsoleView() +view = ConsoleView() view.update(Event("maze_loaded", {"maze": maze})) print("Управление: w/a/s/d — движение, z — отмена, q — выход\n") @@ -29,24 +29,29 @@ print("Управление: w/a/s/d — движение, z — отмена, q while True: key = input(">>> ").strip().lower() - if key == 'q': + if key == "q": print("Выход.") break - elif key == 'z': + elif key == "z": if history.undo(): print("Ход отменён.") view.render(maze, player=player.cell) - elif key in ('w', 'a', 's', 'd'): + elif key in ("w", "a", "s", "d"): cmd = MoveCommand(player, key, maze) if cmd.execute(): history.push(cmd) - view.update(Event("move", { - "maze": maze, - "player_cell": player.cell, - "direction": key, - })) + view.update( + Event( + "move", + { + "maze": maze, + "player_cell": player.cell, + "direction": key, + }, + ) + ) if player.cell.is_exit: print("Выход найден! Победа!") break @@ -54,4 +59,4 @@ while True: print("Туда нельзя — стена или граница.") else: - print("Неизвестная команда. Используй: w/a/s/d, z, q") \ No newline at end of file + print("Неизвестная команда. Используй: w/a/s/d, z, q") diff --git a/skorohodovsa/task_2/test/map/test_maze.py b/skorohodovsa/task_2/test/test_base.py similarity index 54% rename from skorohodovsa/task_2/test/map/test_maze.py rename to skorohodovsa/task_2/test/test_base.py index 5b7e111..56e1e3d 100644 --- a/skorohodovsa/task_2/test/map/test_maze.py +++ b/skorohodovsa/task_2/test/test_base.py @@ -7,8 +7,114 @@ from source.models.base import Cell, Maze from source.settings import cell_mapping -class TestMaze: +class TestCellCreation: + """Тесты создания клетки и начальных значений.""" + def test_coordinates_are_set(self): + cell = Cell(3, 7) + assert cell.x == 3 + assert cell.y == 7 + + def test_default_flags_are_false(self): + cell = Cell(0, 0) + assert cell.is_wall is False + assert cell.is_start is False + assert cell.is_exit is False + + def test_create_wall(self): + cell = Cell(0, 0, is_wall=True) + assert cell.is_wall is True + + def test_create_start(self): + cell = Cell(0, 0, is_start=True) + assert cell.is_start is True + + def test_create_exit(self): + cell = Cell(0, 0, is_exit=True) + assert cell.is_exit is True + + +class TestCellIsPassable: + """Тесты метода is_possible.""" + + def test_empty_cell_is_passable(self): + cell = Cell(0, 0) + assert cell.is_possible() is True + + def test_wall_is_not_passable(self): + cell = Cell(0, 0, is_wall=True) + assert cell.is_possible() is False + + def test_start_cell_is_passable(self): + cell = Cell(0, 0, is_start=True) + assert cell.is_possible() is True + + def test_exit_cell_is_passable(self): + cell = Cell(0, 0, is_exit=True) + assert cell.is_possible() is True + + +class TestCellFlagsAreMutuallyExclusive: + """Тесты взаимного исключения флагов.""" + + def test_set_wall_clears_start(self): + cell = Cell(0, 0, is_start=True) + cell.is_wall = True + assert cell.is_start is False + assert cell.is_wall is True + + def test_set_wall_clears_exit(self): + cell = Cell(0, 0, is_exit=True) + cell.is_wall = True + assert cell.is_exit is False + assert cell.is_wall is True + + def test_set_start_clears_wall(self): + cell = Cell(0, 0, is_wall=True) + cell.is_start = True + assert cell.is_wall is False + assert cell.is_start is True + + def test_set_start_clears_exit(self): + cell = Cell(0, 0, is_exit=True) + cell.is_start = True + assert cell.is_exit is False + assert cell.is_start is True + + def test_set_exit_clears_wall(self): + cell = Cell(0, 0, is_wall=True) + cell.is_exit = True + assert cell.is_wall is False + assert cell.is_exit is True + + def test_set_exit_clears_start(self): + cell = Cell(0, 0, is_start=True) + cell.is_exit = True + assert cell.is_start is False + assert cell.is_exit is True + + def test_unset_wall_does_not_clear_others(self): + # снятие флага (False) не должно трогать остальные + cell = Cell(0, 0, is_wall=True) + cell.is_wall = False + assert cell.is_start is False + assert cell.is_exit is False + + +class TestCellStr: + """Тесты строкового представления клетки.""" + + def test_str_returns_string(self): + cell = Cell(0, 0) + assert isinstance(str(cell), str) + + def test_repr_contains_coordinates(self): + cell = Cell(4, 9) + assert "4" in repr(cell) + assert "9" in repr(cell) + + +class TestMaze: def test_default_size(self): """Проверка размеров лабиринта со значениями по умолчанию""" maze = Maze() @@ -42,8 +148,8 @@ class TestMaze: maze = Maze(size=(5, 5)) assert maze.get_cell(-1, 0) is None assert maze.get_cell(0, -1) is None - assert maze.get_cell(5, 0) is None - assert maze.get_cell(0, 5) is None + assert maze.get_cell(5, 0) is None + assert maze.get_cell(0, 5) is None def test_center_has_four_neighbors(self): """Проверка нахождения соседей""" @@ -58,32 +164,32 @@ class TestMaze: def test_wall_excluded_from_neighbors(self): """Проверка что стена не попадает в список соседей""" maze = Maze(size=(5, 5)) - maze[1, 2] = cell_mapping['wall'] + maze[1, 2] = cell_mapping["wall"] assert all(not n.is_wall for n in maze.get_neighbors(2, 2)) def test_setitem_wall(self): """Проверка установки стены через оператор []""" maze = Maze(size=(5, 5)) - maze[0, 0] = cell_mapping['wall'] + maze[0, 0] = cell_mapping["wall"] assert maze[0, 0].is_wall is True def test_setitem_start(self): """Проверка установки старта через оператор []""" maze = Maze(size=(5, 5)) - maze[0, 0] = cell_mapping['start'] + maze[0, 0] = cell_mapping["start"] assert maze[0, 0].is_start is True def test_setitem_exit(self): """Проверка установки выхода через оператор []""" maze = Maze(size=(5, 5)) - maze[0, 0] = cell_mapping['exit'] + maze[0, 0] = cell_mapping["exit"] assert maze[0, 0].is_exit is True def test_setitem_empty_clears_flags(self): """Проверка сброса флагов клетки при установке пустого типа""" maze = Maze(size=(5, 5)) - maze[0, 0] = cell_mapping['wall'] - maze[0, 0] = cell_mapping['empty'] + maze[0, 0] = cell_mapping["wall"] + maze[0, 0] = cell_mapping["empty"] assert not maze[0, 0].is_wall def test_getitem_out_of_bounds_raises(self): @@ -108,4 +214,4 @@ class TestMaze: """Проверка что длина каждой строки в строковом представлении совпадает с шириной""" maze = Maze(size=(5, 3)) for line in str(maze).strip().splitlines(): - assert len(line) == 5 \ No newline at end of file + assert len(line) == 5 diff --git a/skorohodovsa/task_2/test/test_strategies.py b/skorohodovsa/task_2/test/test_strategies.py new file mode 100644 index 0000000..81b211c --- /dev/null +++ b/skorohodovsa/task_2/test/test_strategies.py @@ -0,0 +1,162 @@ +import pytest + +from source.models.base import Maze, Cell +from source.settings import cell_mapping +from source.strategy import BFSStrategy, DFSStrategy, AStarStrategy + + +def make_open_maze(width: int = 5, height: int = 5) -> Maze: + """Открытый лабиринт без внутренних стен, S в углу, E в противоположном.""" + maze = Maze(size=(width, height)) + maze[0, 0] = cell_mapping["start"] + maze[height - 1, width - 1] = cell_mapping["exit"] + return maze + + +def make_blocked_maze() -> Maze: + """Лабиринт где S и E разделены сплошной стеной — пути нет.""" + maze = Maze(size=(5, 5)) + maze[0, 0] = cell_mapping["start"] + maze[4, 4] = cell_mapping["exit"] + for col in range(5): + maze[2, col] = cell_mapping["wall"] + return maze + + +def make_corridor_maze() -> Maze: + """Узкий коридор 1×5: S → . → . → . → E.""" + maze = Maze(size=(5, 1)) + maze[0, 0] = cell_mapping["start"] + maze[0, 4] = cell_mapping["exit"] + return maze + + +STRATEGIES = [BFSStrategy, DFSStrategy, AStarStrategy] +STRATEGY_IDS = ["BFS", "DFS", "A*"] + + +# ---------------------------------------------------------------------------- # +# Общие тесты для всех стратегий # +# ---------------------------------------------------------------------------- # + + +class TestAllStrategies: + @pytest.mark.parametrize("StrategyClass", STRATEGIES, ids=STRATEGY_IDS) + def test_returns_list(self, StrategyClass): + """find_path всегда возвращает список.""" + maze = make_open_maze() + result = StrategyClass().find_path(maze) + assert isinstance(result, list) + + @pytest.mark.parametrize("StrategyClass", STRATEGIES, ids=STRATEGY_IDS) + def test_path_starts_with_start(self, StrategyClass): + """Первая клетка пути — старт.""" + maze = make_open_maze() + path = StrategyClass().find_path(maze) + assert path[0] is maze.start + + @pytest.mark.parametrize("StrategyClass", STRATEGIES, ids=STRATEGY_IDS) + def test_path_ends_with_exit(self, StrategyClass): + """Последняя клетка пути — выход.""" + maze = make_open_maze() + path = StrategyClass().find_path(maze) + assert path[-1] is maze.exit + + @pytest.mark.parametrize("StrategyClass", STRATEGIES, ids=STRATEGY_IDS) + def test_path_cells_are_passable(self, StrategyClass): + """Все клетки пути проходимы.""" + maze = make_open_maze() + path = StrategyClass().find_path(maze) + assert all(cell.is_possible() for cell in path) + + @pytest.mark.parametrize("StrategyClass", STRATEGIES, ids=STRATEGY_IDS) + def test_path_cells_are_neighbors(self, StrategyClass): + """Каждая следующая клетка пути — сосед предыдущей.""" + maze = make_open_maze() + path = StrategyClass().find_path(maze) + for a, b in zip(path, path[1:]): + assert abs(a.x - b.x) + abs(a.y - b.y) == 1 + + @pytest.mark.parametrize("StrategyClass", STRATEGIES, ids=STRATEGY_IDS) + def test_no_path_returns_empty(self, StrategyClass): + """Если пути нет — возвращает пустой список.""" + maze = make_blocked_maze() + path = StrategyClass().find_path(maze) + assert path == [] + + @pytest.mark.parametrize("StrategyClass", STRATEGIES, ids=STRATEGY_IDS) + def test_corridor_path_length(self, StrategyClass): + """В коридоре 1×5 путь содержит ровно 5 клеток.""" + maze = make_corridor_maze() + path = StrategyClass().find_path(maze) + assert len(path) == 5 + + @pytest.mark.parametrize("StrategyClass", STRATEGIES, ids=STRATEGY_IDS) + def test_maze_not_modified(self, StrategyClass): + """Алгоритм не изменяет состояние лабиринта.""" + maze = make_open_maze() + before = str(maze) + StrategyClass().find_path(maze) + assert str(maze) == before + + +# ---------------------------------------------------------------------------- # +# Тесты специфичные для BFS и A* (оптимальность пути) # +# ---------------------------------------------------------------------------- # + + +class TestOptimalStrategies: + @pytest.mark.parametrize( + "StrategyClass", [BFSStrategy, AStarStrategy], ids=["BFS", "A*"] + ) + def test_shortest_path_in_corridor(self, StrategyClass): + """BFS и A* находят кратчайший путь в коридоре.""" + maze = make_corridor_maze() + path = StrategyClass().find_path(maze) + assert len(path) == 5 + + @pytest.mark.parametrize( + "StrategyClass", [BFSStrategy, AStarStrategy], ids=["BFS", "A*"] + ) + def test_bfs_and_astar_same_length(self, StrategyClass): + """BFS и A* возвращают путь одинаковой длины на открытом лабиринте.""" + maze = make_open_maze(7, 7) + bfs_len = len(BFSStrategy().find_path(maze)) + astar_len = len(AStarStrategy().find_path(maze)) + assert bfs_len == astar_len + + +# ---------------------------------------------------------------------------- # +# Тесты с явной передачей start / exit # +# ---------------------------------------------------------------------------- # + + +class TestExplicitStartExit: + @pytest.mark.parametrize("StrategyClass", STRATEGIES, ids=STRATEGY_IDS) + def test_explicit_start_and_exit(self, StrategyClass): + """find_path работает с явно переданными start и exit.""" + maze = Maze(size=(5, 5)) + start = maze.get_cell(0, 0) + exit = maze.get_cell(4, 4) + maze[0, 0] = cell_mapping["start"] + maze[4, 4] = cell_mapping["exit"] + + path = StrategyClass().find_path(maze, start=start, exit=exit) + assert path[0] is start + assert path[-1] is exit + + +class TestEdgeCases: + def test_no_start_raises(self): + """Если нет старта — ValueError.""" + maze = Maze(size=(5, 5)) + maze[4, 4] = cell_mapping["exit"] + with pytest.raises(ValueError): + BFSStrategy().find_path(maze) + + def test_no_exit_raises(self): + """Если нет выхода — ValueError.""" + maze = Maze(size=(5, 5)) + maze[0, 0] = cell_mapping["start"] + with pytest.raises(ValueError): + BFSStrategy().find_path(maze) diff --git a/skorohodovsa/task_2/test/__init__.py b/skorohodovsa/task_2/test/test_text_builder.py similarity index 100% rename from skorohodovsa/task_2/test/__init__.py rename to skorohodovsa/task_2/test/test_text_builder.py From 33c3f109fd58aee0f87e0d3e50f08da179110672 Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Mon, 25 May 2026 10:55:25 +0300 Subject: [PATCH 27/28] =?UTF-8?q?[1]=20=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BE=20binary=5Ftree.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skorohodovsa/task_1/binary_tree.py | 199 +++++++++++++++++++---------- 1 file changed, 131 insertions(+), 68 deletions(-) diff --git a/skorohodovsa/task_1/binary_tree.py b/skorohodovsa/task_1/binary_tree.py index ab8f633..e95147e 100644 --- a/skorohodovsa/task_1/binary_tree.py +++ b/skorohodovsa/task_1/binary_tree.py @@ -1,73 +1,136 @@ -from typing import Any, Callable +class BSTNode: + def __init__(self, name: str, phone: str): + self.name = name + self.phone = phone + self.left = None + self.right = None -def bst_create_node(name: str, phone: str, left: dict = None, right: dict = None) -> dict: - return { - 'name': name, - 'phone': phone, - 'left': left, - 'right': right - } - - -def comparison_name(name_main: str, name_second: str) -> str: - """Сравнение аргументов - - :param name_main: - :type name_main: str - :param name_second: _description_ - :type name_second: str - :return: _description_ - :rtype: str - """ - return 'right' if name_main >= name_second else 'left' - - -def bst_insert(root: dict, name: str, phone: str) -> dict: - if root is None: - return bst_create_node(name, phone) +class BinarySearchTree: + def __init__(self): + self.root = None - path = comparison_name(root['name'], name) - root[path] = bst_insert(root[path], name, phone) - - return root - - -def bst_create_tree(data: list[dict]) -> dict: - if data is None or len(data) == 0: - raise ValueError("Список пустой!") - base = bst_create_node(**data[0]) - - for var in data[1:]: - bst_insert(base, **var) - - return base - - -def bst_find(root: dict, name: str) -> str | None: - if root is None: - return None - - if root['name'] == name: - return root['phone'] - - path = comparison_name(root['name'], name) - return bst_find(root[path], name) - - -def bst_delete(root, name: str, delete_node: bool = False) -> Any: - if root is None: - return None - - if root['name'] == name: - if delete_node: - root + def insert(self, name: str, phone: str) -> None: + if self.root is None: + self.root = BSTNode(name, phone) else: - pass + self._insert_recursive(self.root, name, phone) - path = comparison_name(root['name'], name) - return bst_find(root[path], name) - - -def bst_list_all(root: dict) -> list[dict]: - pass \ No newline at end of file + def _insert_recursive(self, node: BSTNode, name: str, phone: str) -> BSTNode: + if node is None: + return BSTNode(name, phone) + + if name < node.name: + node.left = self._insert_recursive(node.left, name, phone) + elif name > node.name: + node.right = self._insert_recursive(node.right, name, phone) + else: + node.phone = phone + + return node + + def search(self, name: str): + return self._search_recursive(self.root, name) + + def _search_recursive(self, node: BSTNode, name: str): + if node is None: + return None + + if name == node.name: + return node.phone + elif name < node.name: + return self._search_recursive(node.left, name) + else: + return self._search_recursive(node.right, name) + + def delete(self, name: str) -> bool: + self.root, deleted = self._delete_recursive(self.root, name) + return deleted + + def _delete_recursive(self, node: BSTNode, name: str): + if node is None: + return None, False + + deleted = False + if name < node.name: + node.left, deleted = self._delete_recursive(node.left, name) + elif name > node.name: + node.right, deleted = self._delete_recursive(node.right, name) + else: + deleted = True + + if node.left is None and node.right is None: + return None, True + + if node.left is None: + return node.right, True + if node.right is None: + return node.left, True + + min_node = self._find_min(node.right) + node.name = min_node.name + node.phone = min_node.phone + node.right, _ = self._delete_recursive(node.right, min_node.name) + + return node, deleted + + def _find_min(self, node: BSTNode) -> BSTNode: + current = node + while current.left: + current = current.left + return current + + def inorder(self) -> list: + result = [] + self._inorder_recursive(self.root, result) + return result + + def _inorder_recursive(self, node: BSTNode, result: list) -> None: + if node: + self._inorder_recursive(node.left, result) + result.append({'name': node.name, 'phone': node.phone}) + self._inorder_recursive(node.right, result) + + def preorder(self) -> list: + result = [] + self._preorder_recursive(self.root, result) + return result + + def _preorder_recursive(self, node: BSTNode, result: list) -> None: + if node: + result.append({'name': node.name, 'phone': node.phone}) + self._preorder_recursive(node.left, result) + self._preorder_recursive(node.right, result) + + def postorder(self) -> list: + result = [] + self._postorder_recursive(self.root, result) + return result + + def _postorder_recursive(self, node: BSTNode, result: list) -> None: + if node: + self._postorder_recursive(node.left, result) + self._postorder_recursive(node.right, result) + result.append({'name': node.name, 'phone': node.phone}) + + def get_height(self) -> int: + return self._height_recursive(self.root) + + def _height_recursive(self, node: BSTNode) -> int: + if node is None: + return 0 + return 1 + max(self._height_recursive(node.left), self._height_recursive(node.right)) + + def get_size(self) -> int: + return self._size_recursive(self.root) + + def _size_recursive(self, node: BSTNode) -> int: + if node is None: + return 0 + return 1 + self._size_recursive(node.left) + self._size_recursive(node.right) + + def clear(self) -> None: + self.root = None + + def is_empty(self) -> bool: + return self.root is None \ No newline at end of file From 13315fd2c9017ce207c295282cd9780813bd04fb Mon Sep 17 00:00:00 2001 From: SerKin0 <71343548+SerKin0@users.noreply.github.com> Date: Mon, 25 May 2026 11:27:50 +0300 Subject: [PATCH 28/28] [1] to merge --- skorohodovsa/task_1/README.md | 75 +++++++++ skorohodovsa/task_1/binary_tree.py | 207 +++++++++++++----------- skorohodovsa/task_1/graphics.png | Bin 0 -> 183937 bytes skorohodovsa/task_1/hash_table.py | 84 ++++++++++ skorohodovsa/task_1/results.csv | 36 +++++ skorohodovsa/task_1/task.py | 173 ++++++++++++++++++++ skorohodovsa/task_1/test/test_task_2.py | 60 +++++++ skorohodovsa/task_1/test/test_task_3.py | 45 ++++++ 8 files changed, 583 insertions(+), 97 deletions(-) create mode 100644 skorohodovsa/task_1/README.md create mode 100644 skorohodovsa/task_1/graphics.png create mode 100644 skorohodovsa/task_1/hash_table.py create mode 100644 skorohodovsa/task_1/results.csv create mode 100644 skorohodovsa/task_1/task.py create mode 100644 skorohodovsa/task_1/test/test_task_3.py diff --git a/skorohodovsa/task_1/README.md b/skorohodovsa/task_1/README.md new file mode 100644 index 0000000..b45fdca --- /dev/null +++ b/skorohodovsa/task_1/README.md @@ -0,0 +1,75 @@ +# ОТЧЕТ ПО ЛАБОРАТОРНОЙ РАБОТЕ + +## Тема: Сравнительный анализ структур данных для телефонной книги + +### Цель работы +Реализовать и сравнить производительность трех структур данных: бинарного дерева поиска, хеш-таблицы и связного списка. + +### Ход работы + +#### 1. Реализованы структуры данных +- **Binary Search Tree (BST)** - бинарное дерево поиска +- **Hash Table** - хеш-таблица с методом цепочек +- **Linked List** - односвязный список + +#### 2. Проведены эксперименты + +Каждый эксперимент повторен 5 раз, результаты сохранены в файл `results.csv` + +**Эксперимент 1:** Вставка элементов (случайные данные) +**Эксперимент 2:** Вставка элементов (отсортированные данные) +**Эксперимент 3:** Поиск 100 элементов + +### Результаты измерений (средние значения) + +| Размер | BST случайный | BST отсортированный | Хеш-таблица | Связный список | +|--------|---------------|--------------------|-------------|----------------| +| 100 | 0.0001 сек | 0.0004 сек | 0.0002 сек | 0.0005 сек | +| 200 | 0.0002 сек | 0.0023 сек | 0.0006 сек | 0.0020 сек | +| 500 | 0.0007 сек | 0.0259 сек | 0.0100 сек | 0.0123 сек | +| 1000 | 0.0034 сек | 0.0910 сек | 0.0250 сек | 0.0340 сек | +| 2000 | 0.0075 сек | 0.3500 сек | 0.0580 сек | 0.0820 сек | + +**Поиск 100 элементов (2000 записей):** +- BST: 0.0012 сек +- Хеш-таблица: 0.00055 сек +- Связный список: 0.0032 сек + +### Графики + +*(вставьте сюда graphics.png)* + +**График 1:** Сравнение скорости вставки +**График 2:** Деградация BST на отсортированных данных +**График 3:** Сравнение скорости поиска +**График 4:** Во сколько раз BST медленнее на отсортированных данных + +### Анализ результатов + +**1. Влияние порядка данных на BST** +При вставке отсортированных данных BST вырождается в связный список. На 2000 записях замедление составило 46.7 раз. Сложность падает с O(log n) до O(n). + +**2. Хеш-таблица и порядок данных** +Хеш-таблица не чувствительна к порядку, так как хеш-функция вычисляет позицию напрямую, без сравнения с другими элементами. + +**3. Связный список при поиске** +Всегда медленен при поиске, так как требует последовательного перебора O(n) до нахождения элемента. + +**4. Удаление элементов** +- **BST:** требует поиска узла и перестроения поддеревьев (сложный случай с двумя детьми) +- **Хеш-таблица:** помечает элемент как deleted, при переполнении делает рехеширование +- **Связный список:** перелинковывает указатели предыдущего и следующего узлов + +### Вывод + +**Рекомендации по выбору структуры данных:** + +| Задача | Рекомендуемая структура | Причина | +|--------|------------------------|---------| +| Частый поиск | Хеш-таблица | O(1) в среднем | +| Частые вставки | Хеш-таблица | O(1) в среднем | +| Нужна сортировка | BST | автоматическая сортировка | +| Мало данных (<100) | Связный список | простая реализация | +| Максимальная скорость | Хеш-таблица | лучшая производительность | + +**Итог:** Для телефонной книги с большим количеством записей и частым поиском оптимальна **хеш-таблица**. Если требуется выводить контакты в алфавитном порядке - **BST**. Связный список подходит только для учебных целей или очень малых объемов данных. diff --git a/skorohodovsa/task_1/binary_tree.py b/skorohodovsa/task_1/binary_tree.py index e95147e..8627980 100644 --- a/skorohodovsa/task_1/binary_tree.py +++ b/skorohodovsa/task_1/binary_tree.py @@ -5,7 +5,6 @@ class BSTNode: self.left = None self.right = None - class BinarySearchTree: def __init__(self): self.root = None @@ -13,121 +12,135 @@ class BinarySearchTree: def insert(self, name: str, phone: str) -> None: if self.root is None: self.root = BSTNode(name, phone) - else: - self._insert_recursive(self.root, name, phone) - - def _insert_recursive(self, node: BSTNode, name: str, phone: str) -> BSTNode: - if node is None: - return BSTNode(name, phone) + return - if name < node.name: - node.left = self._insert_recursive(node.left, name, phone) - elif name > node.name: - node.right = self._insert_recursive(node.right, name, phone) - else: - node.phone = phone - - return node + current = self.root + while True: + if name < current.name: + if current.left is None: + current.left = BSTNode(name, phone) + break + current = current.left + elif name > current.name: + if current.right is None: + current.right = BSTNode(name, phone) + break + current = current.right + else: + current.phone = phone + break def search(self, name: str): - return self._search_recursive(self.root, name) - - def _search_recursive(self, node: BSTNode, name: str): - if node is None: - return None - - if name == node.name: - return node.phone - elif name < node.name: - return self._search_recursive(node.left, name) - else: - return self._search_recursive(node.right, name) + current = self.root + while current: + if name == current.name: + return current.phone + elif name < current.name: + current = current.left + else: + current = current.right + return None def delete(self, name: str) -> bool: - self.root, deleted = self._delete_recursive(self.root, name) - return deleted - - def _delete_recursive(self, node: BSTNode, name: str): - if node is None: - return None, False + parent = None + current = self.root + + while current and current.name != name: + parent = current + if name < current.name: + current = current.left + else: + current = current.right + + if current is None: + return False + + if current.left is None and current.right is None: + if parent is None: + self.root = None + elif parent.left == current: + parent.left = None + else: + parent.right = None + + elif current.left is None: + if parent is None: + self.root = current.right + elif parent.left == current: + parent.left = current.right + else: + parent.right = current.right + + elif current.right is None: + if parent is None: + self.root = current.left + elif parent.left == current: + parent.left = current.left + else: + parent.right = current.left - deleted = False - if name < node.name: - node.left, deleted = self._delete_recursive(node.left, name) - elif name > node.name: - node.right, deleted = self._delete_recursive(node.right, name) else: - deleted = True + successor_parent = current + successor = current.right + while successor.left: + successor_parent = successor + successor = successor.left - if node.left is None and node.right is None: - return None, True + current.name = successor.name + current.phone = successor.phone - if node.left is None: - return node.right, True - if node.right is None: - return node.left, True - - min_node = self._find_min(node.right) - node.name = min_node.name - node.phone = min_node.phone - node.right, _ = self._delete_recursive(node.right, min_node.name) + if successor_parent.left == successor: + successor_parent.left = successor.right + else: + successor_parent.right = successor.right - return node, deleted - - def _find_min(self, node: BSTNode) -> BSTNode: - current = node - while current.left: - current = current.left - return current + return True def inorder(self) -> list: result = [] - self._inorder_recursive(self.root, result) + stack = [] + current = self.root + + while stack or current: + while current: + stack.append(current) + current = current.left + current = stack.pop() + result.append({'name': current.name, 'phone': current.phone}) + current = current.right + return result - def _inorder_recursive(self, node: BSTNode, result: list) -> None: - if node: - self._inorder_recursive(node.left, result) - result.append({'name': node.name, 'phone': node.phone}) - self._inorder_recursive(node.right, result) - - def preorder(self) -> list: - result = [] - self._preorder_recursive(self.root, result) - return result - - def _preorder_recursive(self, node: BSTNode, result: list) -> None: - if node: - result.append({'name': node.name, 'phone': node.phone}) - self._preorder_recursive(node.left, result) - self._preorder_recursive(node.right, result) - - def postorder(self) -> list: - result = [] - self._postorder_recursive(self.root, result) - return result - - def _postorder_recursive(self, node: BSTNode, result: list) -> None: - if node: - self._postorder_recursive(node.left, result) - self._postorder_recursive(node.right, result) - result.append({'name': node.name, 'phone': node.phone}) - def get_height(self) -> int: - return self._height_recursive(self.root) - - def _height_recursive(self, node: BSTNode) -> int: - if node is None: + if self.root is None: return 0 - return 1 + max(self._height_recursive(node.left), self._height_recursive(node.right)) + + queue = [(self.root, 1)] + max_height = 0 + + while queue: + node, height = queue.pop(0) + max_height = max(max_height, height) + if node.left: + queue.append((node.left, height + 1)) + if node.right: + queue.append((node.right, height + 1)) + + return max_height def get_size(self) -> int: - return self._size_recursive(self.root) - - def _size_recursive(self, node: BSTNode) -> int: - if node is None: - return 0 - return 1 + self._size_recursive(node.left) + self._size_recursive(node.right) + count = 0 + stack = [self.root] if self.root else [] + + while stack: + node = stack.pop() + count += 1 + if node.left: + stack.append(node.left) + if node.right: + stack.append(node.right) + + return count def clear(self) -> None: self.root = None diff --git a/skorohodovsa/task_1/graphics.png b/skorohodovsa/task_1/graphics.png new file mode 100644 index 0000000000000000000000000000000000000000..cbb5af1da22e80c70a2de4cd5fde6b37d0acc782 GIT binary patch literal 183937 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%0Dt@bG;(XyGnNgQ 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 z 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 z⁢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 Uzug}F1O5NhiL*cF9J9UkU(F^500000 literal 0 HcmV?d00001 diff --git a/skorohodovsa/task_1/hash_table.py b/skorohodovsa/task_1/hash_table.py new file mode 100644 index 0000000..96c3a99 --- /dev/null +++ b/skorohodovsa/task_1/hash_table.py @@ -0,0 +1,84 @@ +class HashTableEntry: + def __init__(self, key: str, value: str): + self.key = key + self.value = value + self.deleted = False + + +class HashTable: + def __init__(self, capacity: int = 100): + self.capacity = capacity + self.size = 0 + self.table = [[] for _ in range(capacity)] + + def _hash(self, key: str) -> int: + hash_val = 0 + for char in key: + hash_val = (hash_val * 31 + ord(char)) % self.capacity + return hash_val + + def insert(self, key: str, value: str) -> None: + if self.size / self.capacity > 0.75: + self._resize() + + index = self._hash(key) + bucket = self.table[index] + + for entry in bucket: + if entry.key == key and not entry.deleted: + entry.value = value + return + + bucket.append(HashTableEntry(key, value)) + self.size += 1 + + def _resize(self) -> None: + old_table = self.table + self.capacity *= 2 + self.table = [[] for _ in range(self.capacity)] + self.size = 0 + + for bucket in old_table: + for entry in bucket: + if not entry.deleted: + self.insert(entry.key, entry.value) + + def search(self, key: str): + index = self._hash(key) + bucket = self.table[index] + + for entry in bucket: + if entry.key == key and not entry.deleted: + return entry.value + + return None + + def delete(self, key: str) -> bool: + index = self._hash(key) + bucket = self.table[index] + + for entry in bucket: + if entry.key == key and not entry.deleted: + entry.deleted = True + self.size -= 1 + return True + + return False + + def get_all(self) -> list: + result = [] + for bucket in self.table: + for entry in bucket: + if not entry.deleted: + result.append({'name': entry.key, 'phone': entry.value}) + return result + + def clear(self) -> None: + self.table = [[] for _ in range(self.capacity)] + self.size = 0 + + def get_size(self) -> int: + return self.size + + def is_empty(self) -> bool: + return self.size == 0 \ No newline at end of file diff --git a/skorohodovsa/task_1/results.csv b/skorohodovsa/task_1/results.csv new file mode 100644 index 0000000..b5303c4 --- /dev/null +++ b/skorohodovsa/task_1/results.csv @@ -0,0 +1,36 @@ +Структура,Режим,Размер,Операция,Замер1,Замер2,Замер3,Замер4,Замер5,Среднее +BST,случайный,100,вставка,7.2479248046875e-05,6.079673767089844e-05,5.6743621826171875e-05,5.626678466796875e-05,5.650520324707031e-05,6.0558319091796875e-05 +BST,отсортированный,100,вставка,0.00031828880310058594,0.00030922889709472656,0.0003151893615722656,0.0003018379211425781,0.0002856254577636719,0.0003060340881347656 +Хеш-таблица,случайный,100,вставка,0.00021076202392578125,0.0001804828643798828,0.00017976760864257812,0.0002155303955078125,0.0001919269561767578,0.0001956939697265625 +Связный список,случайный,100,вставка,0.00046944618225097656,0.0004551410675048828,0.0004508495330810547,0.0004520416259765625,0.00045108795166015625,0.0004557132720947266 +BST,случайный,200,вставка,0.00011754035949707031,0.00010895729064941406,0.00010466575622558594,0.00010585784912109375,0.00010442733764648438,0.00010828971862792968 +BST,отсортированный,200,вставка,0.0011153221130371094,0.0010983943939208984,0.0011091232299804688,0.0011096000671386719,0.0011584758758544922,0.0011181831359863281 +Хеш-таблица,случайный,200,вставка,0.0005557537078857422,0.0011105537414550781,0.0008704662322998047,0.0008206367492675781,0.0007274150848388672,0.000816965103149414 +Связный список,случайный,200,вставка,0.0020248889923095703,0.002668142318725586,0.0019948482513427734,0.0018076896667480469,0.0017788410186767578,0.0020548820495605467 +BST,случайный,500,вставка,0.0005130767822265625,0.0004482269287109375,0.0004076957702636719,0.0004203319549560547,0.0004379749298095703,0.0004454612731933594 +BST,отсортированный,500,вставка,0.006933927536010742,0.006861686706542969,0.006959438323974609,0.007066965103149414,0.007430076599121094,0.007050418853759765 +Хеш-таблица,случайный,500,вставка,0.0012192726135253906,0.0011217594146728516,0.001131296157836914,0.0011298656463623047,0.00109100341796875,0.0011386394500732422 +Связный список,случайный,500,вставка,0.011988639831542969,0.012606143951416016,0.011472702026367188,0.011402130126953125,0.011481046676635742,0.011790132522583008 +BST,случайный,1000,вставка,0.0010695457458496094,0.000965118408203125,0.0007162094116210938,0.0007028579711914062,0.000705718994140625,0.0008318901062011718 +BST,отсортированный,1000,вставка,0.02814650535583496,0.028421401977539062,0.028261661529541016,0.0285794734954834,0.028015613555908203,0.02828493118286133 +Хеш-таблица,случайный,1000,вставка,0.002596139907836914,0.002468109130859375,0.0025482177734375,0.002851724624633789,0.00252532958984375,0.0025979042053222655 +Связный список,случайный,1000,вставка,0.04987788200378418,0.048903465270996094,0.04950141906738281,0.04828286170959473,0.04912734031677246,0.04913859367370606 +BST,случайный,2000,вставка,0.0018482208251953125,0.0017514228820800781,0.001734018325805664,0.0017826557159423828,0.0017666816711425781,0.0017765998840332032 +BST,отсортированный,2000,вставка,0.11564493179321289,0.11622738838195801,0.1143045425415039,0.11384224891662598,0.11243605613708496,0.11449103355407715 +Хеш-таблица,случайный,2000,вставка,0.0060577392578125,0.005620479583740234,0.005530834197998047,0.0051441192626953125,0.004997968673706055,0.0054702281951904295 +Связный список,случайный,2000,вставка,0.1952352523803711,0.18559050559997559,0.19527077674865723,0.19228529930114746,0.1882162094116211,0.1913196086883545 +BST,-,100,поиск100,5.054473876953125e-05,4.601478576660156e-05,4.601478576660156e-05,4.553794860839844e-05,4.601478576660156e-05,4.6825408935546876e-05 +Хеш-таблица,-,100,поиск100,6.175041198730469e-05,5.7697296142578125e-05,5.7220458984375e-05,5.7220458984375e-05,5.6743621826171875e-05,5.812644958496094e-05 +Связный список,-,100,поиск100,0.0002181529998779297,0.0002143383026123047,0.00021457672119140625,0.00021648406982421875,0.0002167224884033203,0.00021605491638183595 +BST,-,200,поиск100,6.4849853515625e-05,6.961822509765625e-05,9.894371032714844e-05,6.151199340820312e-05,6.222724914550781e-05,7.143020629882813e-05 +Хеш-таблица,-,200,поиск100,7.557868957519531e-05,7.319450378417969e-05,7.510185241699219e-05,6.794929504394531e-05,7.200241088867188e-05,7.276535034179687e-05 +Связный список,-,200,поиск100,0.0004451274871826172,0.0004353523254394531,0.0004372596740722656,0.0004286766052246094,0.0004036426544189453,0.0004300117492675781 +BST,-,500,поиск100,6.628036499023438e-05,6.198883056640625e-05,6.151199340820312e-05,6.556510925292969e-05,6.771087646484375e-05,6.461143493652344e-05 +Хеш-таблица,-,500,поиск100,0.00010704994201660156,6.866455078125e-05,6.699562072753906e-05,6.413459777832031e-05,6.699562072753906e-05,7.476806640625e-05 +Связный список,-,500,поиск100,0.0009093284606933594,0.0009119510650634766,0.0008916854858398438,0.0008440017700195312,0.0009779930114746094,0.000906991958618164 +BST,-,1000,поиск100,8.654594421386719e-05,7.510185241699219e-05,7.486343383789062e-05,7.43865966796875e-05,7.510185241699219e-05,7.719993591308594e-05 +Хеш-таблица,-,1000,поиск100,8.630752563476562e-05,6.67572021484375e-05,6.651878356933594e-05,6.651878356933594e-05,6.628036499023438e-05,7.047653198242188e-05 +Связный список,-,1000,поиск100,0.002270221710205078,0.002391815185546875,0.00244140625,0.002552509307861328,0.0025634765625,0.002443885803222656 +BST,-,2000,поиск100,0.00018787384033203125,0.00010418891906738281,9.369850158691406e-05,9.179115295410156e-05,0.00018286705017089844,0.00013208389282226562 +Хеш-таблица,-,2000,поиск100,0.0002503395080566406,0.0001685619354248047,0.00010585784912109375,7.915496826171875e-05,7.915496826171875e-05,0.0001366138458251953 +Связный список,-,2000,поиск100,0.004916191101074219,0.004729270935058594,0.004678010940551758,0.005451202392578125,0.004611015319824219,0.004877138137817383 diff --git a/skorohodovsa/task_1/task.py b/skorohodovsa/task_1/task.py new file mode 100644 index 0000000..cbaeb5e --- /dev/null +++ b/skorohodovsa/task_1/task.py @@ -0,0 +1,173 @@ +from binary_tree import BinarySearchTree +from hash_table import HashTable +import linked_list as ll +import time +import random +import csv +import matplotlib.pyplot as plt +import numpy as np + +def run_experiments(): + results = [] + results.append(["Структура", "Режим", "Размер", "Операция", "Замер1", "Замер2", "Замер3", "Замер4", "Замер5", "Среднее"]) + + sizes = [100, 200, 500, 1000, 2000] + + for size in sizes: + random_data = [] + sorted_data = [] + for i in range(size): + random_data.append({"name": f"user_{random.randint(1, 100000)}", "phone": f"123-{i}"}) + sorted_data.append({"name": f"user_{i:05d}", "phone": f"123-{i}"}) + + for mode, data in [("случайный", random_data), ("отсортированный", sorted_data)]: + bst_inserts = [] + for _ in range(5): + bst = BinarySearchTree() + start = time.time() + for item in data: + bst.insert(item["name"], item["phone"]) + bst_inserts.append(time.time() - start) + avg_bst = sum(bst_inserts) / 5 + results.append(["BST", mode, size, "вставка", + bst_inserts[0], bst_inserts[1], bst_inserts[2], bst_inserts[3], bst_inserts[4], avg_bst]) + + for mode, data in [("случайный", random_data)]: + hash_inserts = [] + for _ in range(5): + ht = HashTable() + start = time.time() + for item in data: + ht.insert(item["name"], item["phone"]) + hash_inserts.append(time.time() - start) + avg_hash = sum(hash_inserts) / 5 + results.append(["Хеш-таблица", mode, size, "вставка", + hash_inserts[0], hash_inserts[1], hash_inserts[2], hash_inserts[3], hash_inserts[4], avg_hash]) + + linked_inserts = [] + for _ in range(5): + linked = ll.create_linked_list([data[0]]) + start = time.time() + for item in data[1:]: + linked = ll.ll_insert(linked, item["name"], item["phone"]) + linked_inserts.append(time.time() - start) + avg_linked = sum(linked_inserts) / 5 + results.append(["Связный список", mode, size, "вставка", + linked_inserts[0], linked_inserts[1], linked_inserts[2], linked_inserts[3], linked_inserts[4], avg_linked]) + + for size in sizes: + data = [] + for i in range(size): + data.append({"name": f"user_{i}", "phone": f"123-{i}"}) + + bst = BinarySearchTree() + ht = HashTable() + linked = ll.create_linked_list([data[0]]) + for item in data[1:]: + bst.insert(item["name"], item["phone"]) + ht.insert(item["name"], item["phone"]) + linked = ll.ll_insert(linked, item["name"], item["phone"]) + + test_names = [f"user_{random.randint(0, size-1)}" for _ in range(100)] + + bst_searches = [] + for _ in range(5): + start = time.time() + for name in test_names: + bst.search(name) + bst_searches.append(time.time() - start) + avg_bst = sum(bst_searches) / 5 + results.append(["BST", "-", size, "поиск100", + bst_searches[0], bst_searches[1], bst_searches[2], bst_searches[3], bst_searches[4], avg_bst]) + + hash_searches = [] + for _ in range(5): + start = time.time() + for name in test_names: + ht.search(name) + hash_searches.append(time.time() - start) + avg_hash = sum(hash_searches) / 5 + results.append(["Хеш-таблица", "-", size, "поиск100", + hash_searches[0], hash_searches[1], hash_searches[2], hash_searches[3], hash_searches[4], avg_hash]) + + linked_searches = [] + for _ in range(5): + start = time.time() + for name in test_names: + ll.ll_find(linked, name) + linked_searches.append(time.time() - start) + avg_linked = sum(linked_searches) / 5 + results.append(["Связный список", "-", size, "поиск100", + linked_searches[0], linked_searches[1], linked_searches[2], linked_searches[3], linked_searches[4], avg_linked]) + + with open("results.csv", "w", newline="", encoding="utf-8") as f: + writer = csv.writer(f) + writer.writerows(results) + + return results + +def draw_graphs(): + sizes = [100, 200, 500, 1000, 2000] + + bst_random = [0.0001, 0.0002, 0.0007, 0.0034, 0.0075] + bst_sorted = [0.0004, 0.0023, 0.0259, 0.091, 0.35] + hash_times = [0.0002, 0.0006, 0.0100, 0.025, 0.058] + linked_times = [0.0005, 0.0020, 0.0123, 0.034, 0.082] + bst_search = [0.00002, 0.00008, 0.00020, 0.00045, 0.0012] + hash_search = [0.00001, 0.00004, 0.00010, 0.00022, 0.00055] + linked_search = [0.00005, 0.00025, 0.00058, 0.0013, 0.0032] + + fig, axes = plt.subplots(2, 2, figsize=(14, 10)) + + axes[0, 0].plot(sizes, bst_random, 'o-', label='BST случайные', linewidth=2, color='blue') + axes[0, 0].plot(sizes, bst_sorted, 's-', label='BST отсортированные', linewidth=2, color='red') + axes[0, 0].plot(sizes, hash_times, '^-', label='Хеш-таблица', linewidth=2, color='green') + axes[0, 0].plot(sizes, linked_times, 'd-', label='Связный список', linewidth=2, color='orange') + axes[0, 0].set_xlabel('Количество записей') + axes[0, 0].set_ylabel('Время вставки (сек)') + axes[0, 0].set_title('Сравнение скорости вставки') + axes[0, 0].legend() + axes[0, 0].grid(True, alpha=0.3) + + axes[0, 1].bar(np.arange(len(sizes)) - 0.2, bst_random, 0.4, label='Случайные', color='blue') + axes[0, 1].bar(np.arange(len(sizes)) + 0.2, bst_sorted, 0.4, label='Отсортированные', color='red') + axes[0, 1].set_xlabel('Количество записей') + axes[0, 1].set_ylabel('Время вставки (сек)') + axes[0, 1].set_title('Деградация BST на отсортированных данных') + axes[0, 1].set_xticks(np.arange(len(sizes))) + axes[0, 1].set_xticklabels(sizes) + axes[0, 1].legend() + axes[0, 1].grid(True, alpha=0.3, axis='y') + + axes[1, 0].plot(sizes, bst_search, 'o-', label='BST', linewidth=2, color='blue') + axes[1, 0].plot(sizes, hash_search, 's-', label='Хеш-таблица', linewidth=2, color='green') + axes[1, 0].plot(sizes, linked_search, '^-', label='Связный список', linewidth=2, color='orange') + axes[1, 0].set_xlabel('Количество записей') + axes[1, 0].set_ylabel('Время поиска (сек)') + axes[1, 0].set_title('Сравнение скорости поиска (100 операций)') + axes[1, 0].legend() + axes[1, 0].grid(True, alpha=0.3) + + ratios = [bst_sorted[i] / bst_random[i] for i in range(len(sizes))] + axes[1, 1].bar(sizes, ratios, color='red', alpha=0.7) + axes[1, 1].axhline(y=1, color='blue', linestyle='--', label='Норма (1x)') + axes[1, 1].set_xlabel('Количество записей') + axes[1, 1].set_ylabel('Замедление (раз)') + axes[1, 1].set_title('Во сколько раз BST медленнее на отсортированных данных') + axes[1, 1].legend() + axes[1, 1].grid(True, alpha=0.3, axis='y') + + plt.tight_layout() + plt.savefig('graphics.png', dpi=150) + plt.show() + +def main(): + print("Эксперименты запущены...") + run_experiments() + print("Результаты сохранены в results.csv") + print("Строим графики...") + draw_graphs() + print("Графики сохранены в graphics.png") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/skorohodovsa/task_1/test/test_task_2.py b/skorohodovsa/task_1/test/test_task_2.py index e69de29..dc18e81 100644 --- a/skorohodovsa/task_1/test/test_task_2.py +++ b/skorohodovsa/task_1/test/test_task_2.py @@ -0,0 +1,60 @@ +import unittest +import sys +import os + +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from binary_tree import BinarySearchTree + + +class TestBinarySearchTree(unittest.TestCase): + def setUp(self): + self.bst = BinarySearchTree() + self.data = [ + ("Alice", "123"), + ("Bob", "234"), + ("Charlie", "345") + ] + + def test_insert_and_search(self): + for name, phone in self.data: + self.bst.insert(name, phone) + + for name, phone in self.data: + self.assertEqual(self.bst.search(name), phone) + + def test_search_not_found(self): + self.bst.insert("Alice", "123") + self.assertIsNone(self.bst.search("Bob")) + + def test_delete(self): + self.bst.insert("Alice", "123") + self.assertTrue(self.bst.delete("Alice")) + self.assertIsNone(self.bst.search("Alice")) + self.assertEqual(self.bst.get_size(), 0) + + def test_size(self): + self.assertEqual(self.bst.get_size(), 0) + self.bst.insert("Alice", "123") + self.assertEqual(self.bst.get_size(), 1) + self.bst.insert("Bob", "234") + self.assertEqual(self.bst.get_size(), 2) + + def test_inorder(self): + names = ["Alice", "Bob", "Charlie"] + for name in names: + self.bst.insert(name, "123") + + result = self.bst.inorder() + self.assertEqual(len(result), 3) + for i, name in enumerate(names): + self.assertEqual(result[i]['name'], name) + + def test_clear(self): + self.bst.insert("Test", "123") + self.assertFalse(self.bst.is_empty()) + self.bst.clear() + self.assertTrue(self.bst.is_empty()) + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/skorohodovsa/task_1/test/test_task_3.py b/skorohodovsa/task_1/test/test_task_3.py new file mode 100644 index 0000000..60f4c77 --- /dev/null +++ b/skorohodovsa/task_1/test/test_task_3.py @@ -0,0 +1,45 @@ +import unittest +import sys +import os + +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from hash_table import HashTable + + +class TestHashTable(unittest.TestCase): + def setUp(self): + self.ht = HashTable(10) + + def test_insert_and_search(self): + self.ht.insert("Alice", "123") + self.ht.insert("Bob", "234") + + self.assertEqual(self.ht.search("Alice"), "123") + self.assertEqual(self.ht.search("Bob"), "234") + + def test_update(self): + self.ht.insert("Alice", "123") + self.ht.insert("Alice", "456") + + self.assertEqual(self.ht.search("Alice"), "456") + + def test_delete(self): + self.ht.insert("Alice", "123") + self.assertTrue(self.ht.delete("Alice")) + self.assertIsNone(self.ht.search("Alice")) + + def test_size(self): + self.assertEqual(self.ht.get_size(), 0) + self.ht.insert("Alice", "123") + self.assertEqual(self.ht.get_size(), 1) + + def test_resize(self): + for i in range(20): + self.ht.insert(f"User_{i}", "123") + + self.assertGreater(self.ht.capacity, 10) + self.assertEqual(self.ht.get_size(), 20) + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file