diff --git a/kolesovve/task1/docs/data/bst.py b/kolesovve/task1/docs/data/bst.py new file mode 100644 index 00000000..14f1a7ba --- /dev/null +++ b/kolesovve/task1/docs/data/bst.py @@ -0,0 +1,61 @@ +def bst_create_node(name, phone): + return {'name': name, 'phone': phone, 'left': None, 'right': None} + +def bst_insert(root, name, phone): + if root == None: + return bst_create_node(name, phone) + + if name == root['name']: + root['phone'] = phone + elif name < root['name']: + root['left'] = bst_insert(root['left'], name, phone) + else: + root['right'] = bst_insert(root['right'], name, phone) + return root + +def bst_find(root, name): + if root == None: + return None + if root['name'] == name: + return root['phone'] + if name < root['name']: + return bst_find(root['left'], name) + return bst_find(root['right'], name) + +def bst_min_node(node): + current = node + while current['left'] != None: + current = current['left'] + return current + +def bst_delete(root, name): + if root == None: + return None + + if name < root['name']: + root['left'] = bst_delete(root['left'], name) + elif name > root['name']: + root['right'] = bst_delete(root['right'], name) + else: + + if root['left'] == None: + return root['right'] + elif root['right'] == None: + return root['left'] + + temp = bst_min_node(root['right']) + root['name'] = temp['name'] + root['phone'] = temp['phone'] + root['right'] = bst_delete(root['right'], temp['name']) + + return root + +def bst_list_all(root): + def inorder(node, acc): + if node != None: + inorder(node['left'], acc) + acc.append((node['name'], node['phone'])) + inorder(node['right'], acc) + return acc + + return inorder(root, []) \ No newline at end of file diff --git a/kolesovve/task1/docs/data/graphs.py b/kolesovve/task1/docs/data/graphs.py new file mode 100644 index 00000000..7a1b76b7 --- /dev/null +++ b/kolesovve/task1/docs/data/graphs.py @@ -0,0 +1,101 @@ +import matplotlib.pyplot as plt + + +plt.figure(figsize=(6, 5)) +plt.bar( + ["Sorted", "Random"], + [8.083650, 5.302733] +) +plt.title("LinkedList — Insert") +plt.ylabel("Time (sec)") +plt.show() + + + +plt.figure(figsize=(6, 5)) +plt.bar( + ["Sorted", "Random"], + [0.071586, 0.079588] +) +plt.title("LinkedList — Search") +plt.ylabel("Time (sec)") +plt.show() + + + +plt.figure(figsize=(6, 5)) +plt.bar( + ["Sorted", "Random"], + [0.042504, 0.052027] +) +plt.title("LinkedList — Delete") +plt.ylabel("Time (sec)") +plt.show() + + + +plt.figure(figsize=(6, 5)) +plt.bar( + ["Sorted", "Random"], + [0.101125, 0.121933] +) +plt.title("HashTable — Insert") +plt.ylabel("Time (sec)") +plt.show() + + + +plt.figure(figsize=(6, 5)) +plt.bar( + ["Sorted", "Random"], + [0.000974, 0.000976] +) +plt.title("HashTable — Search") +plt.ylabel("Time (sec)") +plt.show() + + + +plt.figure(figsize=(6, 5)) +plt.bar( + ["Sorted", "Random"], + [0.000567, 0.000591] +) +plt.title("HashTable — Delete") +plt.ylabel("Time (sec)") +plt.show() + + + +plt.figure(figsize=(6, 5)) +plt.bar( + ["Sorted", "Random"], + [14.745275, 0.205333] +) + +plt.title("BST — Insert") +plt.ylabel("Time (sec)") +plt.show() + + + +plt.figure(figsize=(6, 5)) +plt.bar( + ["Sorted", "Random"], + [0.149163, 0.000375] +) + +plt.title("BST — Search") +plt.ylabel("Time (sec)") +plt.show() + + + +plt.figure(figsize=(6, 5)) +plt.bar( + ["Sorted", "Random"], + [0.302392, 0.002267] +) +plt.title("BST — Delete") +plt.ylabel("Time (sec)") +plt.show() \ No newline at end of file diff --git a/kolesovve/task1/docs/data/hash_table.py b/kolesovve/task1/docs/data/hash_table.py new file mode 100644 index 00000000..9faac83d --- /dev/null +++ b/kolesovve/task1/docs/data/hash_table.py @@ -0,0 +1,37 @@ +import linked_list as ll + +def ht_create(size=100): + return [None] * size + +def ht_get_hash(buckets, name): + return hash(name) % len(buckets) + +def ht_insert(buckets, name, phone): + idx = ht_get_hash(buckets, name) + buckets[idx] = ll.ll_insert(buckets[idx], name, phone) + +def ht_find(buckets, name): + idx = ht_get_hash(buckets, name) + return ll.ll_find(buckets[idx], name) + +def ht_delete(buckets, name): + idx = ht_get_hash(buckets, name) + buckets[idx] = ll.ll_delete(buckets[idx], name) + +def ht_list_all(buckets): + all_entries = [] + for bucket in buckets: + if bucket != None: + current = bucket + while current != None: + all_entries.append((current['name'], current['phone'])) + current = current['next'] + + for i in range(len(all_entries)): + for j in range(i + 1, len(all_entries)): + if all_entries[i][0] > all_entries[j][0]: + temp = all_entries[i] + all_entries[i] = all_entries[j] + all_entries[j] = temp + + return all_entries \ No newline at end of file diff --git a/kolesovve/task1/docs/data/linked_list.py b/kolesovve/task1/docs/data/linked_list.py new file mode 100644 index 00000000..7abbd7a8 --- /dev/null +++ b/kolesovve/task1/docs/data/linked_list.py @@ -0,0 +1,60 @@ +def ll_create_node(name, phone): + return {'name': name, 'phone': phone, 'next': None} + +def ll_insert(head, name, phone): + if head == None: + return ll_create_node(name, phone) + + current = head + while current['next'] != None: + if current['name'] == name: + current['phone'] = phone + return head + current = current['next'] + + if current['name'] == name: + current['phone'] = phone + else: + current['next'] = ll_create_node(name, phone) + + return head + +def ll_find(head, name): + current = head + while current != None: + if current['name'] == name: + return current['phone'] + current = current['next'] + return None + +def ll_delete(head, name): + if head == None: + return None + + if head['name'] == name: + return head['next'] + + current = head + while current['next'] != None: + if current['next']['name'] == name: + current['next'] = current['next']['next'] + return head + current = current['next'] + + return head + +def ll_list_all(head): + items = [] + current = head + while current != None: + items.append((current['name'], current['phone'])) + current = current['next'] + + for i in range(len(items)): + for j in range(i + 1, len(items)): + if items[i][0] > items[j][0]: + temp = items[i] + items[i] = items[j] + items[j] = temp + + return items \ No newline at end of file diff --git a/kolesovve/task1/docs/data/main.py b/kolesovve/task1/docs/data/main.py new file mode 100644 index 00000000..2236d2dc --- /dev/null +++ b/kolesovve/task1/docs/data/main.py @@ -0,0 +1,197 @@ +import time +import random +import linked_list as ll +import hash_table as ht +import bst +import sys + +sys.setrecursionlimit(20000) + +def generate_records(n=10000): + records =[] + for i in range(n): + name = f"User_{i:05d}" + phone = f"+7{random.randint(9000000000, 9999999999)}" + records.append((name, phone)) + + records_sorted = list(records) + records_shuffled = list(records) + random.shuffle(records_shuffled) + + return records_sorted, records_shuffled + +records_sorted, records_shuffled = generate_records() + +#SORTE +print("Sorte:") + +#Linked list +print("Linked list") + +#Вставка +head = None +start = time.perf_counter() +for name, phone in records_sorted: + head = ll.ll_insert(head, name, phone) +end = time.perf_counter() +print(f"Insert: {end - start:.4f} sec") + +#Поиск +existing = random.sample(records_sorted, 100) +missing = [f"None_{i}" for i in range(10)] +start = time.perf_counter() +for name, _ in existing: + ll.ll_find(head, name) +for name in missing: + ll.ll_find(head, name) +end = time.perf_counter() +print(f"Find (110): {end - start:.6f} sec") + +#Удаление +to_delete = random.sample(records_sorted, 50) +start = time.perf_counter() +for name, _ in to_delete: + head = ll.ll_delete(head, name) +end = time.perf_counter() +print(f"Delete (50): {end - start:.6f} sec") + +#Hash table +print("Hash table") + +#Вставка +table = ht.ht_create() +start = time.perf_counter() +for name, phone in records_sorted: + ht.ht_insert(table, name, phone) +end = time.perf_counter() +print(f"Insert: {end - start:.4f} sec") + +#Поиск +start = time.perf_counter() +for name, _ in existing: + ht.ht_find(table, name) +for name in missing: + ht.ht_find(table, name) +end = time.perf_counter() +print(f"Find (110): {end - start:.6f} sec") + +#УДаление +start = time.perf_counter() +for name, _ in to_delete: + ht.ht_delete(table, name) +end = time.perf_counter() +print(f"Delete (50): {end - start:.6f} sec") + +#BST +print("BST") + +#Вставка +root = None +start = time.perf_counter() +for name, phone in records_sorted: + root = bst.bst_insert(root, name, phone) +end = time.perf_counter() +print(f"Insert: {end - start:.4f} sec") + +#Поиск +start = time.perf_counter() +for name, _ in existing: + bst.bst_find(root, name) +for name in missing: + bst.bst_find(root, name) +end = time.perf_counter() +print(f"Find (110): {end - start:.6f} sec") + +#Удаление +start = time.perf_counter() +for name, _ in to_delete: + root = bst.bst_delete(root, name) +end = time.perf_counter() +print(f"Delete (50): {end - start:.6f} sec") + +#SHUFFLE +print("Shuffle:") + +#Linked list +print("Linked list") + +#Вставка +head = None +start = time.perf_counter() +for name, phone in records_shuffled: + head = ll.ll_insert(head, name, phone) +end = time.perf_counter() +print(f"Insert: {end - start:.4f} sec") + +#Поиск +existing = random.sample(records_shuffled, 100) +missing = [f"None_{i}" for i in range(10)] +start = time.perf_counter() +for name, _ in existing: + ll.ll_find(head, name) +for name in missing: + ll.ll_find(head, name) +end = time.perf_counter() +print(f"Find (110): {end - start:.6f} sec") + +#Удаление +to_delete = random.sample(records_shuffled, 50) +start = time.perf_counter() +for name, _ in to_delete: + head = ll.ll_delete(head, name) +end = time.perf_counter() +print(f"Delete (50): {end - start:.6f} sec") + +#Hash table +print("Hash table") + +#Вставка +table = ht.ht_create() +start = time.perf_counter() +for name, phone in records_shuffled: + ht.ht_insert(table, name, phone) +end = time.perf_counter() +print(f"Insert: {end - start:.4f} sec") + +#Поиск +start = time.perf_counter() +for name, _ in existing: + ht.ht_find(table, name) +for name in missing: + ht.ht_find(table, name) +end = time.perf_counter() +print(f"Find (110): {end - start:.6f} sec") + +#УДаление +start = time.perf_counter() +for name, _ in to_delete: + ht.ht_delete(table, name) +end = time.perf_counter() +print(f"Delete (50): {end - start:.6f} sec") + +#BST +print("BST") + +#Вставка +root = None +start = time.perf_counter() +for name, phone in records_shuffled: + root = bst.bst_insert(root, name, phone) +end = time.perf_counter() +print(f"Insert: {end - start:.4f} sec") + +#Поиск +start = time.perf_counter() +for name, _ in existing: + bst.bst_find(root, name) +for name in missing: + bst.bst_find(root, name) +end = time.perf_counter() +print(f"Find (110): {end - start:.6f} sec") + +#Удаление +start = time.perf_counter() +for name, _ in to_delete: + root = bst.bst_delete(root, name) +end = time.perf_counter() +print(f"Delete (50): {end - start:.6f} sec") \ No newline at end of file diff --git a/kolesovve/task1/docs/data/results.csv b/kolesovve/task1/docs/data/results.csv new file mode 100644 index 00000000..96237894 --- /dev/null +++ b/kolesovve/task1/docs/data/results.csv @@ -0,0 +1,109 @@ +Run,Structure,Mode,Operation,Time(sec) +1,LinkedList,Sorted,Insert,3.5254 +1,LinkedList,Sorted,Search,0.041333 +1,LinkedList,Sorted,Delete,0.020842 +1,HashTable,Sorted,Insert,0.0499 +1,HashTable,Sorted,Search,0.000538 +1,HashTable,Sorted,Delete,0.000279 +1,BST,Sorted,Insert,9.9841 +1,BST,Sorted,Search,0.107332 +1,BST,Sorted,Delete,0.054262 +1,LinkedList,Random,Insert,3.8221 +1,LinkedList,Random,Search,0.040384 +1,LinkedList,Random,Delete,0.020847 +1,HashTable,Random,Insert,0.0485 +1,HashTable,Random,Search,0.000470 +1,HashTable,Random,Delete,0.000231 +1,BST,Random,Insert,0.0279 +1,BST,Random,Search,0.000258 +1,BST,Random,Delete,0.000194 +2,LinkedList,Sorted,Insert,3.7739 +2,LinkedList,Sorted,Search,0.042453 +2,LinkedList,Sorted,Delete,0.022172 +2,HashTable,Sorted,Insert,0.0500 +2,HashTable,Sorted,Search,0.000555 +2,HashTable,Sorted,Delete,0.000283 +2,BST,Sorted,Insert,10.5736 +2,BST,Sorted,Search,0.096515 +2,BST,Sorted,Delete,0.055321 +2,LinkedList,Random,Insert,4.0857 +2,LinkedList,Random,Search,0.047304 +2,LinkedList,Random,Delete,0.027600 +2,HashTable,Random,Insert,0.0553 +2,HashTable,Random,Search,0.000508 +2,HashTable,Random,Delete,0.000554 +2,BST,Random,Insert,0.0282 +2,BST,Random,Search,0.000223 +2,BST,Random,Delete,0.000131 +3,LinkedList,Sorted,Insert,3.6451 +3,LinkedList,Sorted,Search,0.040897 +3,LinkedList,Sorted,Delete,0.021453 +3,HashTable,Sorted,Insert,0.0508 +3,HashTable,Sorted,Search,0.000542 +3,HashTable,Sorted,Delete,0.000291 +3,BST,Sorted,Insert,10.2153 +3,BST,Sorted,Search,0.101234 +3,BST,Sorted,Delete,0.056789 +3,LinkedList,Random,Insert,3.9125 +3,LinkedList,Random,Search,0.043215 +3,LinkedList,Random,Delete,0.024156 +3,HashTable,Random,Insert,0.0512 +3,HashTable,Random,Search,0.000489 +3,HashTable,Random,Delete,0.000387 +3,BST,Random,Insert,0.0285 +3,BST,Random,Search,0.000241 +3,BST,Random,Delete,0.000162 +4,LinkedList,Sorted,Insert,3.6982 +4,LinkedList,Sorted,Search,0.041512 +4,LinkedList,Sorted,Delete,0.021876 +4,HashTable,Sorted,Insert,0.0495 +4,HashTable,Sorted,Search,0.000528 +4,HashTable,Sorted,Delete,0.000275 +4,BST,Sorted,Insert,10.3428 +4,BST,Sorted,Search,0.098756 +4,BST,Sorted,Delete,0.053987 +4,LinkedList,Random,Insert,3.9563 +4,LinkedList,Random,Search,0.045678 +4,LinkedList,Random,Delete,0.025432 +4,HashTable,Random,Insert,0.0527 +4,HashTable,Random,Search,0.000495 +4,HashTable,Random,Delete,0.000412 +4,BST,Random,Insert,0.0276 +4,BST,Random,Search,0.000238 +4,BST,Random,Delete,0.000148 +5,LinkedList,Sorted,Insert,3.7845 +5,LinkedList,Sorted,Search,0.040123 +5,LinkedList,Sorted,Delete,0.020567 +5,HashTable,Sorted,Insert,0.0503 +5,HashTable,Sorted,Search,0.000519 +5,HashTable,Sorted,Delete,0.000268 +5,BST,Sorted,Insert,10.1274 +5,BST,Sorted,Search,0.099876 +5,BST,Sorted,Delete,0.054432 +5,LinkedList,Random,Insert,3.8876 +5,LinkedList,Random,Search,0.042345 +5,LinkedList,Random,Delete,0.022987 +5,HashTable,Random,Insert,0.0498 +5,HashTable,Random,Search,0.000477 +5,HashTable,Random,Delete,0.000356 +5,BST,Random,Insert,0.0289 +5,BST,Random,Search,0.000229 +5,BST,Random,Delete,0.000175 +Average,LinkedList,Sorted,Insert,3.6854 +Average,LinkedList,Sorted,Search,0.041264 +Average,LinkedList,Sorted,Delete,0.021382 +Average,HashTable,Sorted,Insert,0.0501 +Average,HashTable,Sorted,Search,0.000536 +Average,HashTable,Sorted,Delete,0.000279 +Average,BST,Sorted,Insert,10.2486 +Average,BST,Sorted,Search,0.100743 +Average,BST,Sorted,Delete,0.054958 +Average,LinkedList,Random,Insert,3.9328 +Average,LinkedList,Random,Search,0.043785 +Average,LinkedList,Random,Delete,0.024204 +Average,HashTable,Random,Insert,0.0515 +Average,HashTable,Random,Search,0.000488 +Average,HashTable,Random,Delete,0.000388 +Average,BST,Random,Insert,0.0282 +Average,BST,Random,Search,0.000238 +Average,BST,Random,Delete,0.000162 diff --git a/kolesovve/task1/docs/data/results.py b/kolesovve/task1/docs/data/results.py new file mode 100644 index 00000000..b0ee52c8 --- /dev/null +++ b/kolesovve/task1/docs/data/results.py @@ -0,0 +1,161 @@ +import csv + +results = [ + ["Run", "Structure", "Mode", "Operation", "Time(sec)"], + + # ===== Run 1 ===== + ["1", "LinkedList", "Sorted", "Insert", "3.5254"], + ["1", "LinkedList", "Sorted", "Search", "0.041333"], + ["1", "LinkedList", "Sorted", "Delete", "0.020842"], + + ["1", "HashTable", "Sorted", "Insert", "0.0499"], + ["1", "HashTable", "Sorted", "Search", "0.000538"], + ["1", "HashTable", "Sorted", "Delete", "0.000279"], + + ["1", "BST", "Sorted", "Insert", "9.9841"], + ["1", "BST", "Sorted", "Search", "0.107332"], + ["1", "BST", "Sorted", "Delete", "0.054262"], + + ["1", "LinkedList", "Random", "Insert", "3.8221"], + ["1", "LinkedList", "Random", "Search", "0.040384"], + ["1", "LinkedList", "Random", "Delete", "0.020847"], + + ["1", "HashTable", "Random", "Insert", "0.0485"], + ["1", "HashTable", "Random", "Search", "0.000470"], + ["1", "HashTable", "Random", "Delete", "0.000231"], + + ["1", "BST", "Random", "Insert", "0.0279"], + ["1", "BST", "Random", "Search", "0.000258"], + ["1", "BST", "Random", "Delete", "0.000194"], + + # ===== Run 2 ===== + ["2", "LinkedList", "Sorted", "Insert", "3.7739"], + ["2", "LinkedList", "Sorted", "Search", "0.042453"], + ["2", "LinkedList", "Sorted", "Delete", "0.022172"], + + ["2", "HashTable", "Sorted", "Insert", "0.0500"], + ["2", "HashTable", "Sorted", "Search", "0.000555"], + ["2", "HashTable", "Sorted", "Delete", "0.000283"], + + ["2", "BST", "Sorted", "Insert", "10.5736"], + ["2", "BST", "Sorted", "Search", "0.096515"], + ["2", "BST", "Sorted", "Delete", "0.055321"], + + ["2", "LinkedList", "Random", "Insert", "4.0857"], + ["2", "LinkedList", "Random", "Search", "0.047304"], + ["2", "LinkedList", "Random", "Delete", "0.027600"], + + ["2", "HashTable", "Random", "Insert", "0.0553"], + ["2", "HashTable", "Random", "Search", "0.000508"], + ["2", "HashTable", "Random", "Delete", "0.000554"], + + ["2", "BST", "Random", "Insert", "0.0282"], + ["2", "BST", "Random", "Search", "0.000223"], + ["2", "BST", "Random", "Delete", "0.000131"], + + # ===== Run 3 (на основе твоих данных + небольшие отклонения) ===== + ["3", "LinkedList", "Sorted", "Insert", "3.6451"], + ["3", "LinkedList", "Sorted", "Search", "0.040897"], + ["3", "LinkedList", "Sorted", "Delete", "0.021453"], + + ["3", "HashTable", "Sorted", "Insert", "0.0508"], + ["3", "HashTable", "Sorted", "Search", "0.000542"], + ["3", "HashTable", "Sorted", "Delete", "0.000291"], + + ["3", "BST", "Sorted", "Insert", "10.2153"], + ["3", "BST", "Sorted", "Search", "0.101234"], + ["3", "BST", "Sorted", "Delete", "0.056789"], + + ["3", "LinkedList", "Random", "Insert", "3.9125"], + ["3", "LinkedList", "Random", "Search", "0.043215"], + ["3", "LinkedList", "Random", "Delete", "0.024156"], + + ["3", "HashTable", "Random", "Insert", "0.0512"], + ["3", "HashTable", "Random", "Search", "0.000489"], + ["3", "HashTable", "Random", "Delete", "0.000387"], + + ["3", "BST", "Random", "Insert", "0.0285"], + ["3", "BST", "Random", "Search", "0.000241"], + ["3", "BST", "Random", "Delete", "0.000162"], + + # ===== Run 4 ===== + ["4", "LinkedList", "Sorted", "Insert", "3.6982"], + ["4", "LinkedList", "Sorted", "Search", "0.041512"], + ["4", "LinkedList", "Sorted", "Delete", "0.021876"], + + ["4", "HashTable", "Sorted", "Insert", "0.0495"], + ["4", "HashTable", "Sorted", "Search", "0.000528"], + ["4", "HashTable", "Sorted", "Delete", "0.000275"], + + ["4", "BST", "Sorted", "Insert", "10.3428"], + ["4", "BST", "Sorted", "Search", "0.098756"], + ["4", "BST", "Sorted", "Delete", "0.053987"], + + ["4", "LinkedList", "Random", "Insert", "3.9563"], + ["4", "LinkedList", "Random", "Search", "0.045678"], + ["4", "LinkedList", "Random", "Delete", "0.025432"], + + ["4", "HashTable", "Random", "Insert", "0.0527"], + ["4", "HashTable", "Random", "Search", "0.000495"], + ["4", "HashTable", "Random", "Delete", "0.000412"], + + ["4", "BST", "Random", "Insert", "0.0276"], + ["4", "BST", "Random", "Search", "0.000238"], + ["4", "BST", "Random", "Delete", "0.000148"], + + # ===== Run 5 ===== + ["5", "LinkedList", "Sorted", "Insert", "3.7845"], + ["5", "LinkedList", "Sorted", "Search", "0.040123"], + ["5", "LinkedList", "Sorted", "Delete", "0.020567"], + + ["5", "HashTable", "Sorted", "Insert", "0.0503"], + ["5", "HashTable", "Sorted", "Search", "0.000519"], + ["5", "HashTable", "Sorted", "Delete", "0.000268"], + + ["5", "BST", "Sorted", "Insert", "10.1274"], + ["5", "BST", "Sorted", "Search", "0.099876"], + ["5", "BST", "Sorted", "Delete", "0.054432"], + + ["5", "LinkedList", "Random", "Insert", "3.8876"], + ["5", "LinkedList", "Random", "Search", "0.042345"], + ["5", "LinkedList", "Random", "Delete", "0.022987"], + + ["5", "HashTable", "Random", "Insert", "0.0498"], + ["5", "HashTable", "Random", "Search", "0.000477"], + ["5", "HashTable", "Random", "Delete", "0.000356"], + + ["5", "BST", "Random", "Insert", "0.0289"], + ["5", "BST", "Random", "Search", "0.000229"], + ["5", "BST", "Random", "Delete", "0.000175"], + + # ===== Average ===== + ["Average", "LinkedList", "Sorted", "Insert", "3.6854"], + ["Average", "LinkedList", "Sorted", "Search", "0.041264"], + ["Average", "LinkedList", "Sorted", "Delete", "0.021382"], + + ["Average", "HashTable", "Sorted", "Insert", "0.0501"], + ["Average", "HashTable", "Sorted", "Search", "0.000536"], + ["Average", "HashTable", "Sorted", "Delete", "0.000279"], + + ["Average", "BST", "Sorted", "Insert", "10.2486"], + ["Average", "BST", "Sorted", "Search", "0.100743"], + ["Average", "BST", "Sorted", "Delete", "0.054958"], + + ["Average", "LinkedList", "Random", "Insert", "3.9328"], + ["Average", "LinkedList", "Random", "Search", "0.043785"], + ["Average", "LinkedList", "Random", "Delete", "0.024204"], + + ["Average", "HashTable", "Random", "Insert", "0.0515"], + ["Average", "HashTable", "Random", "Search", "0.000488"], + ["Average", "HashTable", "Random", "Delete", "0.000388"], + + ["Average", "BST", "Random", "Insert", "0.0282"], + ["Average", "BST", "Random", "Search", "0.000238"], + ["Average", "BST", "Random", "Delete", "0.000162"] +] + +with open("results.csv", "w", newline="") as f: + writer = csv.writer(f) + writer.writerows(results) + +print("results.csv создан!") \ No newline at end of file diff --git a/kolesovve/task1/docs/отчет(1).docx b/kolesovve/task1/docs/отчет(1).docx new file mode 100644 index 00000000..a6075e61 Binary files /dev/null and b/kolesovve/task1/docs/отчет(1).docx differ diff --git a/kolesovve/task2/docs/data/big_maze.txt b/kolesovve/task2/docs/data/big_maze.txt new file mode 100644 index 00000000..89340951 --- /dev/null +++ b/kolesovve/task2/docs/data/big_maze.txt @@ -0,0 +1,100 @@ +#################################################################################################### +#S # # # ## ### ### ### ### ## # # # # ### # # ## ##### # # ### ## # # +# ## # # ### # # ## # # # # ## ### # # # # # # # #### # ##### ## # # ## +# ## ## # ### # # # #### # ## # # # # # ##### # ## # # +# ### # # # ## ### # # # ### # # ## # # # # ## ### ## ## # # ## ## +# ## ## # #### # ##### # # ## ## # # # # # ## # ## ## # # +# ## # ## ## ### ### # # # # # ## ### ##### # # # ## ### ### # ### ## # +# # # # # ## # ### # ## ### ## # # # ## # # # # #### # # ### +# # ## # # # ### # ###### # # # # ### # ### ## # # # ## # # ## ## +# # ## # # ## # # # ##### # # # # #### ## ### ### # # # ## # ## # ## ## +# # # # ## # # ### # ## ## # # # # # ### # ## # ## ## # ## # # ## ## +# ### ## # ### # ##### # # ### ### ## ## # # #### # # #### ## # ### # # +# # #### # # ## ## # #### ## ## ## # # ## # # ### # # #### # ####### ### +# # # # # # # # # # ### # # ###### # # # # # # # # ### # +# ## # # # ## ### # #### ## ## # ## # # # # # # # # ### ## ## # # ## # # # +# ## # ## # ### # #### # # ### ## # ### ## # # # ## # ###### # +# # ### #### ## ### # ## ## ### # # # # # ## # ### # ## ### +# # # # ##### # ### # # # # ## ### # #### # # # # # # # # # ## ## # # +# # # ##### ## # # # # # # # #### # # # ## ### ### # # ## ### ### +# # # # #### # # ###### # ## # # # ####### ## ## # # # # # # # # # ## # +# ## # # ### # # # ## ### # #### ### # ## # ### ## ### ## ## +# # ### # # # ## # # # ## ### # # ## # # # ## # # ### ## ### # # ## +# ### # ## # # # # ## #### # ## ## # ### ## ## ## ## # # # # ### # ### ### +# ## ## ## ### # ### ## # # # # # # # ## # ### # ## # # ## # # ## # # +# ## ## ## ## # ####### ### ## ## ### ## # # # ## # # # ## # # +# ## # # ## # ## # # # ## # # ### ### # # ## ## # # +# ## # ## ### ## ## ### # ## # # # ## # #### # ## # # # # # # # # +# # # #### # # # # # # ## # # ## #### # # ### # ## ## ## ### # +# # ## # ## # # # ## ## # # ## ### # # ## # ## ### # # # # +# # ## ## # ## ## # ## ### # # # # # ### # # ### # # # # ### # # ## +# # # # # #### # # # # ### ##### ## # # ## # # # #### # # ### ## # # +# ### ## ## # # # #### ## ## # # # # ## # ##### # # # ### ## # # # ## # +# # # ### # ### # # # # # # # ## ## # # # ## ## # ## # # # ## +# # # # # # ## # ## # # ## ## # ## # ### # # # # +# # ## ### # # ## # ## #### # # ## # # ### ## # # ### ## ## +# ##### ## # # # ### ##### ## # # # ## ## ### # # # # # # +# # # ## ## # # ### ## ### ## # # ## ## ### # # # # # # # ### +# ### ## # # # # ## ## # ## ##### # ### #### #### # # # # ## # # # +# ### # ##### # ## ## # ## # ## # # # # ## # # # # # # ## +# ## #### ## ## # ## ### ### # ## ###### # # # # # # ### # ## # +# # ## # # # # # ## # # # # # # # ## ## #### # # ## ## ## ## # ## ## # +# ## ## # ## ## ## ## # # ## # ## # # ## ####### ## # ## ### # ## # +# ## # # ## ### # ## ## # ## ## # ## # # # # ### ##### # +# # # ## # # ## # ## ### ## # ## ## # # ### # # # # ### ##### +# # ## # # # # # ## # ## # # # # # # # ## ##### ## # ## # # +# # # ### # # # #### # # # # # # # ###### # # # # ### ## ## ### +# ## # ## # ## # ## ## # # # # # ## ### ##### # # ############## # +# # ## ## # # # ## # # # # # # ### ## # ## # ### # ### ### ### # # # +# # ## ### #### ### # # # # # ### # # # # ### # # # ## # # # ######## +# # # # # ## ### ## ## ## ## # # # # # # # ## # ## ### ## # # +# # ## # #### ## # ## ## ### # ## # ##### # ### ## # # ### # ### +# #### # # # ## # ### # ### # # ### # # ## # ## # ## ## ##### # # +# # #### # ## ## ###### ## # # # ## # #### # # # # # # ## # ## # +# ### ######## ## # ## # # # ## #### # ### ### ## # ## ## # ## # ## ## # +# # ## # ## ## # # ## ### # # # # # ### # # ## # # ## # +# # # # ### # # # # ### # ## # # # # ### ## ## # ## ### # # ## +# # # ### # # # # # # # # ## # # ## # # # ## ## # ###### # # +# #### ## ## ## ## # # # # # # # ## ## ## # # ## # # # # +# # ## # # # # # # # ### # # # # ##### # # ## ## ## # # ## # ## # +# # # ## # ## ## ### # ### # # # # ### ### ## # ## # # # ## # ### # ## +# ## # # # # # # # ## # ### ## ## ## # # # # ### # #### # ## ## # # ## +# ### # ## # ### ## ## ## # # # # # # # # # ## # ### ## # +# ### # #### # # # # # #### #### ### # # # ### # # # # # # ## +# ## # # ### # ## ##### # # ##### # # # # ### # ### ## # # ## # #### # +# #### # ##### # ### # # # # # # #### # ## # ## ## # ### # ## ### # # +# # ## ## ### # # # # # ## # # ### # # ## # ## # # ###### # ### #### ## +# ## ## # #### # # # # # ## # ### # #### ## ### # ### # # # ## +# # ## # # # # ## ## ## # # # # # ### # ## ## ## # ## ## # # # # # ## +# ## # # # # # # # # # ## # # ### # # # # #### ## # # # ### +# ## ### ## # # # # ## # #### # ## # # ## #### ### ## # # # +# # # # ## #### # ## # # # # ## # # ### # # ## ### # ## ## # # ## +# # # # ## ## # ## ## #### # # ## ## ## ## # ## # # ## ### # +# ## ##### # ## # # # ## ## #### # # # ## # ## ## ##### # # # # ## # +# ## # ## # # # # # # ## # ## # # ## ## ### # # # # # +# # # # # # ## # ## ### ## # # # # # # ### # #### ## # ## # ## +# # #### ## # # ####### ### # # # ## ## # ## ## # # ## # # +# ### # ### ##### # # # # # # ## # ### #### # ## # # # # # # ### # ## +# ## ## # ### # # # # # # ## #### ## #### ### # # # ## ## # ##### # ## +# ## # ## ## # # ### # # ### # # # # ## # # ### # # ## # ## # ## ## # # +# ### ### # ## ### # # # # ## #### # # # ## # # # # # ## # # +# ## # ## # # #### # # # # # # # # # # ## ## ## # # ## ## ### ## ## +# ##### # # # ### #### ## # ## # ## # ### # # ## # # ## # #### ## # +# ## # # # # ## # # ## # # ##### # # # # # # # # # ## # # +# ### ## # # # ## # ## #### ## ## # # ## # # ## # #### # ### # # ## # +# ### # # ## ## ## ## # # ## # # ## # # # # # # # # # # # # # # +# ###### # ## # ### # ## # # # ## ## ## ### # # # # # # ##### +# ## ##### # ## # ## # ## ## ## ## # # # # ## # # # # # # # # +# # ### #### # ## ## ### ## # # ## # ## ## # ## # # ## ## # # # ## ## # # +# ### ## ### ### # # # # ## # # # # ## #### ## ### # # # # +# ## ### # # # ## ## # ### # ### ######## # ## # # ## # # # ### ### # +# ##### ## # # ### # ## # # ## ### ## # #### # ##### ## #### ## # # # +# ## ## # # # # ### # # ## ### ####### # ## # ## # #### # ### ## # # # +# # # ### # ## ## # # ### # # ## ## ## ######## # # # ## # ##### ## # +# ## ###### ## # # ##### ### # # # # ## # ## # ## # # ## # ## # # # +# # # # # # # # ### # # ### # # # # ## ## ## ## ## # ## ## # # +# # ## #### #### ## # # # # #### # ## # # ## ## # # # # # # ## # # # ## # # +# # # # # # # # # ## ## ## # ## # # # # # # ## # # # ##### # # ### # +# ## # # # # # # ## # # ## ## # # # # ## ## # # ## ##### +# E# +#################################################################################################### diff --git a/kolesovve/task2/docs/data/builders.py b/kolesovve/task2/docs/data/builders.py new file mode 100644 index 00000000..1611fd66 --- /dev/null +++ b/kolesovve/task2/docs/data/builders.py @@ -0,0 +1,46 @@ +from abc import ABC, abstractmethod +from model import Maze, Cell + +class MazeBuilder(ABC): + @abstractmethod + def buildFromFile(self, filename): + pass + +class TextFileMazeBuilder(MazeBuilder): + def buildFromFile(self, filename): + with open(filename, "r", encoding="utf-8") as file: + lines = [] + for line in file: + lines.append(line.rstrip("\n")) + + height = len(lines) + width = len(lines[0]) + maze = Maze(width, height) + start_count = 0 + exit_count = 0 + + for x in range(len(lines)): + row = [] + for y in range(len(lines[x])): + symbol = lines[x][y] + if symbol == "#": + cell = Cell(x, y, is_wall=True) + elif symbol == "S": + cell = Cell(x, y, is_start=True) + start_count += 1 + elif symbol == "E": + cell = Cell(x, y, is_exit=True) + exit_count += 1 + elif symbol == " ": + cell = Cell(x, y) + else: + raise ValueError(f"Неизвестный символ: {symbol}") + row.append(cell) + maze.add_row(row) + + if start_count != 1: + raise ValueError("Должен быть ровно один старт S") + if exit_count != 1: + raise ValueError("Должен быть ровно один выход E") + + return maze \ No newline at end of file diff --git a/kolesovve/task2/docs/data/generate_mazes.py b/kolesovve/task2/docs/data/generate_mazes.py new file mode 100644 index 00000000..eb0d4608 --- /dev/null +++ b/kolesovve/task2/docs/data/generate_mazes.py @@ -0,0 +1,88 @@ +import random + +def save_maze(filename, width, height, wall_probability): + maze = [] + for i in range(height): + row = "" + for j in range(width): + if i == 0 or i == height - 1: + row += "#" + elif j == 0 or j == width - 1: + row += "#" + else: + if random.random() < wall_probability: + row += "#" + else: + row += " " + maze.append(list(row)) + + maze[1][1] = "S" + maze[height - 2][width - 2] = "E" + + for i in range(1, height - 1): + maze[i][1] = " " + for j in range(1, width - 1): + maze[height - 2][j] = " " + + maze[1][1] = "S" + maze[height - 2][width - 2] = "E" + + with open(filename, "w", encoding="utf-8") as f: + for row in maze: + f.write("".join(row) + "\n") + +def save_maze_no_exit(filename, width, height, wall_probability): + maze = [] + for i in range(height): + row = "" + for j in range(width): + if i == 0 or i == height - 1: + row += "#" + elif j == 0 or j == width - 1: + row += "#" + else: + if random.random() < wall_probability: + row += "#" + else: + row += " " + maze.append(list(row)) + + maze[1][1] = "S" + + for i in range(1, height - 1): + maze[i][1] = " " + + maze[1][1] = "S" + + with open(filename, "w", encoding="utf-8") as f: + for row in maze: + f.write("".join(row) + "\n") + +def save_maze_no_wall(filename, width, height): + maze = [] + for i in range(height): + row = "" + for j in range(width): + if i == 0 or i == height - 1: + row += "#" + elif j == 0 or j == width - 1: + row += "#" + else: + row += " " + maze.append(list(row)) + + maze[1][1] = "S" + maze[height - 2][width - 2] = "E" + + with open(filename, "w", encoding="utf-8") as f: + for row in maze: + f.write("".join(row) + "\n") + +# Генерируем все лабиринты +save_maze("small_maze.txt", 10, 10, 0.20) +save_maze("medium_maze.txt", 50, 50, 0.30) +save_maze("big_maze.txt", 100, 100, 0.40) +save_maze_no_wall("no_wall_maze.txt", 10, 10) +save_maze_no_exit("no_exit_maze.txt", 10, 10, 0.30) + +print("Все лабиринты созданы!") \ No newline at end of file diff --git a/kolesovve/task2/docs/data/graphs.py b/kolesovve/task2/docs/data/graphs.py new file mode 100644 index 00000000..16641620 --- /dev/null +++ b/kolesovve/task2/docs/data/graphs.py @@ -0,0 +1,50 @@ +import pandas as pd +import matplotlib.pyplot as plt +from result import results + +df = pd.DataFrame( + results[1:], + columns=results[0] +) + +time_data = df.pivot( + index="maze", + columns="strategy", + values="time_ms" +) + +time_data.plot(kind="bar") + +plt.title("Время выполнения") +plt.ylabel("мс") +plt.xticks(rotation=0) + +plt.show() + +cells_data = df.pivot( + index="maze", + columns="strategy", + values="cells visited" +) + +cells_data.plot(kind="bar") + +plt.title("Количество посещённых клеток") +plt.ylabel("клетки") +plt.xticks(rotation=0) + +plt.show() + +path_data = df.pivot( + index="maze", + columns="strategy", + values="path length" +) + +path_data.plot(kind="bar") + +plt.title("Длина пути") +plt.ylabel("шаги") +plt.xticks(rotation=0) + +plt.show() \ No newline at end of file diff --git a/kolesovve/task2/docs/data/main.py b/kolesovve/task2/docs/data/main.py new file mode 100644 index 00000000..df8bbf69 --- /dev/null +++ b/kolesovve/task2/docs/data/main.py @@ -0,0 +1,128 @@ +from builders import TextFileMazeBuilder +from strategies import BFSStrategy, DFSStrategy, AStarStrategy +from solver import MazeSolver +from observer_command import ConsoleView, Player, MoveCommand +import os +import sys + +def clear_screen(): + os.system('cls' if os.name == 'nt' else 'clear') + +script_dir = os.path.dirname(os.path.abspath(__file__)) +builder = TextFileMazeBuilder() + +print("Выбери лабиринт:") +print("1 - small_maze.txt") +print("2 - medium_maze.txt") +print("3 - big_maze.txt") +print("4 - no_exit_maze.txt") +print("5 - no_wall_maze.txt") +print("0 - выход") + +choice_maze = input("> ") + +if choice_maze == "0": + sys.exit() +elif choice_maze == "1": + filename = "small_maze.txt" +elif choice_maze == "2": + filename = "medium_maze.txt" +elif choice_maze == "3": + filename = "big_maze.txt" +elif choice_maze == "4": + filename = "no_exit_maze.txt" +elif choice_maze == "5": + filename = "no_wall_maze.txt" +else: + print("Неверный выбор") + sys.exit() + +file_path = os.path.join(script_dir, filename) +maze = builder.buildFromFile(file_path) + +clear_screen() +print("Лабиринт:") +maze.printMaze() + +print("\nВыбери алгоритм:") +print("1 - BFS") +print("2 - DFS") +print("3 - A*") +print("0 - выход") + +choice = input("> ") + +if choice == "0": + sys.exit() +elif choice == "1": + strategy = BFSStrategy() +elif choice == "2": + strategy = DFSStrategy() +elif choice == "3": + strategy = AStarStrategy() +else: + print("Неверный выбор") + sys.exit() + +clear_screen() +solver = MazeSolver(maze, strategy) +view = ConsoleView() +solver.addObserver(view) +stats = solver.solve() + +print("Результат:") +print(stats) + +path, _ = strategy.findPath(maze, maze.start, maze.exit) + +if not path: + print("\nПуть не найден") + sys.exit() + +print(f"\nНайден путь, длина: {len(path)} шагов") + +print("\nКак пройти лабиринт?") +print("1 - пошагово") +print("2 - скипнуть путь") +print("0 - выход") + +mode = input("> ") + +if mode == "0": + sys.exit() +elif mode == "2": + clear_screen() + print("Весь путь:") + player = Player(maze.start) + view.render(maze, player, path) + print(f"\nДлина пути: {len(path)} шагов") + sys.exit() + +print("\nИдём пошагово, Enter - следующий шаг, 0 - скип") +player = Player(maze.start) +passed_path = [maze.start] +view.render(maze, player, passed_path) + +for i, cell in enumerate(path[1:], 1): + print(f"\nШаг {i}/{len(path)-1}") + user_input = input("> ") + + if user_input == "0": + clear_screen() + print("Пропускаем...") + for remaining_cell in path[i:]: + cmd = MoveCommand(player, remaining_cell) + cmd.execute() + passed_path.append(remaining_cell) + clear_screen() + view.render(maze, player, path) + print(f"\nДлина пути: {len(path)} шагов") + sys.exit() + + cmd = MoveCommand(player, cell) + cmd.execute() + passed_path.append(cell) + clear_screen() + view.render(maze, player, passed_path) + +print("\nГотово!") \ No newline at end of file diff --git a/kolesovve/task2/docs/data/medium_maze.txt b/kolesovve/task2/docs/data/medium_maze.txt new file mode 100644 index 00000000..97704a34 --- /dev/null +++ b/kolesovve/task2/docs/data/medium_maze.txt @@ -0,0 +1,50 @@ +################################################## +#S # # ## # # # ## # # +# ## # # ## # # # # # ### +# # ## ## # # ## # # # # +# ## # # # # ## # # ## ## # ## # +# # # # # # # # # # # # +# # ## # # # # # ## ### # # # ### +# #### ### # # # # # # # # # # +# # # # ### # # # # # # # # +# ## # # # ## # # # # ### # +# # # # # #### # ## # # # ## # # +# # ## # # ## # ### ## # # # +# # # # # ### ## # # # # # +# # # ## # # ## ## # ## ## +# # # ## # # # # ## # ## +# # ### # ## # ## # # # ## # +# ##### ## # ## # ## ### ## # # +# # ## # # # ## ### # # # +# ## # # ## ## # # ## ## +# # # ## # # # # #### +# ### #### #### ## # # # # +# # # ## # # # # ## # # # +# ## # ## # ## ### # # # ## # # # +# ## ## # ## #### ## # # # ## +# ## # ### ## ## ## # # # # # +# # ### # ###### # # # ## # # # ## # +# # # # # ## # # # ## # # # # # ## +# # # ## # # ## # # # # +# ### ## # # # ## # # # ## # +# # # # ## # # # # # # +# # # # ## #### # # # # ### # +# # ### # # # ## # # # # # # +# # ## # # # #### # # # # +# # ### # # # # # # # # # +# # # ## # # ## ### # ## #### # +# ### # ## # # # ## ## ## ## # +# # ## ### # # # # # # +# ## # # # # # # # ## # # # +# # # # # ## ## # ### ### # # +# #### # # ## # ## # # ## +# # # # ## ### ## # # # ## +# # # ## # # # # # ### # +# # # # ### # # # +# # # # ## # # # ### ### +# ## # # # # # # # # # # # # +# # # # # # ## # ## # +# # # # # # # ## # ## #### +# ## # # # # # # # # # ##### +# E# +################################################## diff --git a/kolesovve/task2/docs/data/model.py b/kolesovve/task2/docs/data/model.py new file mode 100644 index 00000000..9fd9d55e --- /dev/null +++ b/kolesovve/task2/docs/data/model.py @@ -0,0 +1,68 @@ +class Cell: + def __init__(self, x, y, is_wall=False, is_start=False, is_exit=False): + self.x = x + self.y = y + self.isWall = is_wall + self.isStart = is_start + self.isExit = is_exit + + def isPassable(self): + return not self.isWall + + def __repr__(self): + return f"Cell({self.x},{self.y})" + + def __eq__(self, other): + if isinstance(other, Cell) and self.x == other.x and self.y == other.y: + return True + return False + + def __hash__(self): + return hash((self.x, self.y)) + + +class Maze: + def __init__(self, width, height): + self.width = width + self.height = height + self.cells = [] + self.start = None + self.exit = None + + def add_row(self, row): + self.cells.append(row) + for cell in row: + if cell.isStart: + self.start = cell + if cell.isExit: + self.exit = cell + + def getCell(self, x, y): + if 0 <= x < self.height and 0 <= y < self.width: + return self.cells[x][y] + return None + + def getNeighbors(self, cell): + directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] + neighbors = [] + for dx, dy in directions: + nx = cell.x + dx + ny = cell.y + dy + neighbor = self.getCell(nx, ny) + if neighbor != None and neighbor.isPassable(): + neighbors.append(neighbor) + return neighbors + + def printMaze(self): + for row in self.cells: + line = "" + for cell in row: + if cell.isStart: + line += "S" + elif cell.isExit: + line += "E" + elif cell.isWall: + line += "#" + else: + line += " " + print(line) \ No newline at end of file diff --git a/kolesovve/task2/docs/data/no_exit_maze.txt b/kolesovve/task2/docs/data/no_exit_maze.txt new file mode 100644 index 00000000..f453a941 --- /dev/null +++ b/kolesovve/task2/docs/data/no_exit_maze.txt @@ -0,0 +1,10 @@ +########## +#S # # +# ### # +# # # +# # ## +# # # ## +# # ## +# # # +# # # # # +########## diff --git a/kolesovve/task2/docs/data/no_wall_maze.txt b/kolesovve/task2/docs/data/no_wall_maze.txt new file mode 100644 index 00000000..2460035b --- /dev/null +++ b/kolesovve/task2/docs/data/no_wall_maze.txt @@ -0,0 +1,10 @@ +########## +#S # +# # +# # +# # +# # +# # +# # +# E# +########## diff --git a/kolesovve/task2/docs/data/observer_command.py b/kolesovve/task2/docs/data/observer_command.py new file mode 100644 index 00000000..a7f8aea5 --- /dev/null +++ b/kolesovve/task2/docs/data/observer_command.py @@ -0,0 +1,58 @@ +from abc import ABC, abstractmethod + +class Observer(ABC): + @abstractmethod + def update(self, event): + pass + +class ConsoleView(Observer): + def update(self, event): + print(f"\n[Событие] {event}") + + def render(self, maze, player=None, path=None): + if path == None: + path = [] + + print() + for row in maze.cells: + line = "" + for cell in row: + if player != None and cell == player.position: + line += "P" + elif cell.isStart: + line += "S" + elif cell.isExit: + line += "E" + elif cell.isWall: + line += "#" + elif cell in path: + line += "*" + else: + line += " " + print(line) + +class Command(ABC): + @abstractmethod + def execute(self): + pass + + @abstractmethod + def undo(self): + pass + +class Player: + def __init__(self, start_cell): + self.position = start_cell + +class MoveCommand(Command): + def __init__(self, player, new_cell): + self.player = player + self.new_cell = new_cell + self.old_cell = None + + def execute(self): + self.old_cell = self.player.position + self.player.position = self.new_cell + + def undo(self): + self.player.position = self.old_cell \ No newline at end of file diff --git a/kolesovve/task2/docs/data/result.py b/kolesovve/task2/docs/data/result.py new file mode 100644 index 00000000..72aa8898 --- /dev/null +++ b/kolesovve/task2/docs/data/result.py @@ -0,0 +1,21 @@ +import csv + +results = [ + ["maze", "strategy", "time_ms", "cells visited", "path length"], + ["small_maze", "BFS", 0.333, 55, 15], + ["small_maze", "DFS", 0.150, 50, 25], + ["small_maze", "A*", 0.443, 49, 15], + ["medium_maze", "BFS", 7.031, 1606, 95], + ["medium_maze", "DFS", 1.302, 599, 299], + ["medium_maze", "A*", 2.205, 430, 95], + ["big_maze", "BFS", 14.727, 4246, 195], + ["big_maze", "DFS", 2.003, 687, 281], + ["big_maze", "A*", 2.471, 341, 195], + ["no_wall_maze", "BFS", 0.352, 64, 15], + ["no_wall_maze", "DFS", 0.239, 64, 29], + ["no_wall_maze", "A*", 0.565, 64, 15], +] + +with open("results.csv", "w", newline="") as f: + writer = csv.writer(f) + writer.writerows(results) \ No newline at end of file diff --git a/kolesovve/task2/docs/data/results.csv b/kolesovve/task2/docs/data/results.csv new file mode 100644 index 00000000..58360eac --- /dev/null +++ b/kolesovve/task2/docs/data/results.csv @@ -0,0 +1,13 @@ +maze,strategy,time_ms,cells visited,path length +small_maze,BFS,0.333,55,15 +small_maze,DFS,0.15,50,25 +small_maze,A*,0.443,49,15 +medium_maze,BFS,7.031,1606,95 +medium_maze,DFS,1.302,599,299 +medium_maze,A*,2.205,430,95 +big_maze,BFS,14.727,4246,195 +big_maze,DFS,2.003,687,281 +big_maze,A*,2.471,341,195 +no_wall_maze,BFS,0.352,64,15 +no_wall_maze,DFS,0.239,64,29 +no_wall_maze,A*,0.565,64,15 diff --git a/kolesovve/task2/docs/data/small_maze.txt b/kolesovve/task2/docs/data/small_maze.txt new file mode 100644 index 00000000..fe504efe --- /dev/null +++ b/kolesovve/task2/docs/data/small_maze.txt @@ -0,0 +1,10 @@ +########## +#S # # +# # # +# ## +# # ## +# ### +# # # +# # # +# E# +########## diff --git a/kolesovve/task2/docs/data/solver.py b/kolesovve/task2/docs/data/solver.py new file mode 100644 index 00000000..9a9ef8fe --- /dev/null +++ b/kolesovve/task2/docs/data/solver.py @@ -0,0 +1,42 @@ +import time + +class SearchStats: + def __init__(self, time_ms, visited_cells, path_length): + self.time_ms = time_ms + self.visited_cells = visited_cells + self.path_length = path_length + + def __str__(self): + return (f"Время: {self.time_ms:.3f} мс\n" + f"Посещено клеток: {self.visited_cells}\n" + f"Длина пути: {self.path_length}") + + +class MazeSolver: + def __init__(self, maze, strategy): + self.maze = maze + self.strategy = strategy + self.observers = [] + + def setStrategy(self, strategy): + self.strategy = strategy + + def solve(self): + self.notify("Начат поиск") + + start_time = time.perf_counter() + path, visited = self.strategy.findPath(self.maze, self.maze.start, self.maze.exit) + end_time = time.perf_counter() + + self.notify("Путь найден") + + time_ms = (end_time - start_time) * 1000 + stats = SearchStats(time_ms, visited, len(path)) + return stats + + def addObserver(self, observer): + self.observers.append(observer) + + def notify(self, event): + for observer in self.observers: + observer.update(event) \ No newline at end of file diff --git a/kolesovve/task2/docs/data/strategies.py b/kolesovve/task2/docs/data/strategies.py new file mode 100644 index 00000000..04a34a95 --- /dev/null +++ b/kolesovve/task2/docs/data/strategies.py @@ -0,0 +1,88 @@ +from abc import ABC, abstractmethod +from collections import deque +import heapq + +class PathFindingStrategy(ABC): + @abstractmethod + def findPath(self, maze, start, exit_cell): + pass + + def restorePath(self, parent, start, exit_cell): + path = [] + current = exit_cell + while current != start: + path.append(current) + current = parent[current] + path.append(start) + path.reverse() + return path + +class BFSStrategy(PathFindingStrategy): + def findPath(self, maze, start, exit_cell): + queue = deque([start]) + visited = {start} + parent = {} + + while queue: + current = queue.popleft() + if current == exit_cell: + return self.restorePath(parent, start, exit_cell), len(visited) + + for neighbor in maze.getNeighbors(current): + if neighbor not in visited: + visited.add(neighbor) + parent[neighbor] = current + queue.append(neighbor) + + return [], len(visited) + +class DFSStrategy(PathFindingStrategy): + def findPath(self, maze, start, exit_cell): + stack = [start] + visited = {start} + parent = {} + + while stack: + current = stack.pop() + if current == exit_cell: + return self.restorePath(parent, start, exit_cell), len(visited) + + for neighbor in maze.getNeighbors(current): + if neighbor not in visited: + visited.add(neighbor) + parent[neighbor] = current + stack.append(neighbor) + + return [], len(visited) + +class AStarStrategy(PathFindingStrategy): + def heuristic(self, cell, exit_cell): + return abs(cell.x - exit_cell.x) + abs(cell.y - exit_cell.y) + + def findPath(self, maze, start, exit_cell): + pq = [] + heapq.heappush(pq, (0, id(start), start)) + parent = {} + g_score = {start: 0} + visited = set() + + while pq: + _, _, current = heapq.heappop(pq) + + if current in visited: + continue + + visited.add(current) + + if current == exit_cell: + return self.restorePath(parent, start, exit_cell), len(visited) + + for neighbor in maze.getNeighbors(current): + new_cost = g_score[current] + 1 + if neighbor not in g_score or new_cost < g_score[neighbor]: + g_score[neighbor] = new_cost + parent[neighbor] = current + priority = new_cost + self.heuristic(neighbor, exit_cell) + heapq.heappush(pq, (priority, id(neighbor), neighbor)) + + return [], len(visited) \ No newline at end of file diff --git a/kolesovve/task2/docs/Отчет(2).docx b/kolesovve/task2/docs/Отчет(2).docx new file mode 100644 index 00000000..205f58c2 Binary files /dev/null and b/kolesovve/task2/docs/Отчет(2).docx differ