From d5237d10942efa7524ba99785279ac84fcc72f2a Mon Sep 17 00:00:00 2001 From: yeldmitrenko Date: Tue, 28 Sep 2021 11:02:06 +0300 Subject: [PATCH 01/12] added files to different folders --- heap_sort.py => lab1/heap_sort.py | 0 test.py => lab1/test.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename heap_sort.py => lab1/heap_sort.py (100%) rename test.py => lab1/test.py (100%) diff --git a/heap_sort.py b/lab1/heap_sort.py similarity index 100% rename from heap_sort.py rename to lab1/heap_sort.py diff --git a/test.py b/lab1/test.py similarity index 100% rename from test.py rename to lab1/test.py From 2a756053efeb5a9d25aec5b5e22e414db3225ea2 Mon Sep 17 00:00:00 2001 From: yeldmitrenko Date: Tue, 28 Sep 2021 12:52:19 +0300 Subject: [PATCH 02/12] added implementation of hashtable --- hash_main.py | 14 +++++++++++ hash_table.py | 55 ++++++++++++++++++++++++++++++++++++++++ hash_test.py | 19 ++++++++++++++ lab1/heap_sort.py | 64 ----------------------------------------------- lab1/test.py | 28 --------------------- 5 files changed, 88 insertions(+), 92 deletions(-) create mode 100644 hash_main.py create mode 100644 hash_table.py create mode 100644 hash_test.py delete mode 100644 lab1/heap_sort.py delete mode 100644 lab1/test.py diff --git a/hash_main.py b/hash_main.py new file mode 100644 index 0000000..7b4448e --- /dev/null +++ b/hash_main.py @@ -0,0 +1,14 @@ +from hash_table import HashTable + +if __name__ == "__main__": + table = HashTable() + + table.insert(0, "value1") + table.insert(1, "value2") + table.insert(2, "value3") + print(table.get_hashmap()) + + print(table.get(0)) + print(table.delete(2)) + + print(table.get_hashmap()) diff --git a/hash_table.py b/hash_table.py new file mode 100644 index 0000000..d65fe59 --- /dev/null +++ b/hash_table.py @@ -0,0 +1,55 @@ +class HashTable: + def __init__(self): + self.size = 8 + self.hashmap = [[] for _ in range(self.size)] + + def hashing_func(self, key): + hashed_key = hash(key) % self.size + return hashed_key + + def insert(self, key, value): + global i + hash_key = self.hashing_func(key) + key_exist = False + bucket = self.hashmap[hash_key] + for i, kv in enumerate(bucket): + k, v = kv + if key == k: + key_exist = True + break + if key_exist: + bucket[i] = (key, value) + return bucket + else: + bucket.append((key, value)) + return bucket + + def get(self, key): + hash_key = self.hashing_func(key) + bucket = self.hashmap[hash_key] + if bucket: + for kv in bucket: + k, v = kv + if key == k: + return bucket + elif not bucket: + raise KeyError("does not exist") + + def delete(self, key): + global i + hash_key = self.hashing_func(key) + key_exist = False + bucket = self.hashmap[hash_key] + for i, kv in enumerate(bucket): + k, v = kv + if key == k: + key_exist = True + break + if key_exist: + del bucket[i] + return key + else: + raise KeyError("does not exist") + + def get_hashmap(self): + return self.hashmap diff --git a/hash_test.py b/hash_test.py new file mode 100644 index 0000000..8795b6b --- /dev/null +++ b/hash_test.py @@ -0,0 +1,19 @@ +import unittest +from hash_table import HashTable + + +class TestHashTable(unittest.TestCase): + + def setUp(self) -> None: + self.table = HashTable() + + def test_insert(self): + self.assertEqual(self.table.insert("key1", "value1"), [("key1", "value1")]) + + def test_get(self): + self.table.insert("key1", "value1") + self.assertEqual(self.table.get("key1"), [("key1", "value1")]) + + def test_delete(self): + self.table.insert("key1", "value1") + self.assertEqual(self.table.delete("key1"), "key1") diff --git a/lab1/heap_sort.py b/lab1/heap_sort.py deleted file mode 100644 index 5826411..0000000 --- a/lab1/heap_sort.py +++ /dev/null @@ -1,64 +0,0 @@ -import time - -compare_count = 0 -swap_count = 0 - - -def heapify(array, current_index, heap_size, sort_order): - global compare_count - global swap_count - - largest_element = current_index - left_child = 2 * current_index + 1 - right_child = 2 * current_index + 2 - - def compare(a, b): - if a >= b: - return 1 - else: - return -1 - - if left_child < heap_size and compare(array[left_child], array[largest_element]) != compare(sort_order, "desc"): - largest_element = left_child - compare_count += 4 - - if right_child < heap_size and compare(array[right_child], array[largest_element]) != compare(sort_order, "desc"): - largest_element = right_child - compare_count += 4 - - if largest_element != current_index: - array[current_index], array[largest_element] = array[largest_element], array[current_index] - compare_count += 1 - swap_count += 1 - heapify(array, largest_element, heap_size, sort_order) - - -def heap_sort(array, sort_order): - global swap_count - - array_length = len(array) - for i in range(array_length // 2, -1, -1): - heapify(array, i, array_length, sort_order) - - for i in range(array_length - 1, 0, -1): - array[i], array[0] = array[0], array[i] - heapify(array, 0, i, sort_order) - swap_count += 1 - - return array - - -if __name__ == "__main__": - sort_order = str(input("Enter sort order (asc or desc): ")) - array = [int(item) for item in input("Enter initial array: ").split(",")] - - start_time = time.perf_counter() - heap_sort(array, sort_order) - end_time = time.perf_counter() - execution_time = (end_time - start_time) * 1000 - print(f"Execution time: {execution_time} ms") - - print(f"Comparisons: {compare_count}") - print(f"Swaps: {swap_count}") - - print("Heap sort:", heap_sort(array, sort_order)) diff --git a/lab1/test.py b/lab1/test.py deleted file mode 100644 index cbeda88..0000000 --- a/lab1/test.py +++ /dev/null @@ -1,28 +0,0 @@ -import unittest -from heap_sort import heap_sort -from copy import deepcopy - - -class TestHeapSort(unittest.TestCase): - def setUp(self) -> None: - self.array_example = [1, 2, 56, 45, -9, 78, 11] - self.array_sorted_asc = [-9, 1, 2, 11, 45, 56, 78] - self.array_sorted_desc = [78, 56, 45, 11, 2, 1, -9] - - def test_sort_asc(self): - self.assertListEqual(heap_sort(deepcopy(self.array_example), "asc"), self.array_sorted_asc) - - def test_sort_desc(self): - self.assertListEqual(heap_sort(deepcopy(self.array_example), "desc"), self.array_sorted_desc) - - def test_sort_asc_in_asc(self): - self.assertListEqual(heap_sort(deepcopy(self.array_sorted_asc), "asc"), self.array_sorted_asc) - - def test_sort_asc_in_desc(self): - self.assertListEqual(heap_sort(deepcopy(self.array_sorted_asc), "desc"), self.array_sorted_desc) - - def test_sort_desc_in_asc(self): - self.assertListEqual(heap_sort(deepcopy(self.array_sorted_desc), "asc"), self.array_sorted_asc) - - def test_sort_desc_in_desc(self): - self.assertListEqual(heap_sort(deepcopy(self.array_sorted_desc), "desc"), self.array_sorted_desc) From 332092dc6548561673c7fa7217bf930377532f2e Mon Sep 17 00:00:00 2001 From: yeldmitrenko Date: Sun, 17 Oct 2021 16:53:50 +0300 Subject: [PATCH 03/12] added implementation of calendar --- calendar.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 calendar.py diff --git a/calendar.py b/calendar.py new file mode 100644 index 0000000..5fb39bd --- /dev/null +++ b/calendar.py @@ -0,0 +1,48 @@ +def sort_ranges(array): + if len(array) <= 1: + return array + + current_position = 0 + + for i in range(1, len(array)): + if sum(array[0]) >= sum(array[i]): + current_position += 1 + array[i], array[current_position] = array[current_position], array[i] + array[0], array[current_position] = array[current_position], array[0] + + return [*sort_ranges(array[:current_position]), + array[current_position], + *sort_ranges(array[current_position + 1:])] + + +def merge_ranges(meetings): + sorted_meetings = sort_ranges(meetings) + merged_meetings = [] + previous_meeting_start, previous_meeting_end = sorted_meetings[0] + + for current_meeting_start, current_meeting_end in sorted_meetings[1:]: + if current_meeting_start <= previous_meeting_end: + previous_meeting_end = max(current_meeting_end, previous_meeting_end) + else: + merged_meetings.append((previous_meeting_start, previous_meeting_end)) + previous_meeting_start, previous_meeting_end = current_meeting_start, current_meeting_end + merged_meetings.append((previous_meeting_start, previous_meeting_end)) + + return merged_meetings + + +def normalize_output(array): + array = merge_ranges(array) + time_block = 30 + time_start = 540 + text = "Team's work time: \n" + for time in array: + start = time_start + time[0] * time_block + end = time_start + time[1] * time_block + text += f"\t{start // 60:02d}:{start % 60:02d} - {end // 60:02d}:{end % 60:02d}\n" + print(text) + + +if __name__ == '__main__': + input_array = [(0, 1), (3, 5), (4, 8), (10, 12), (9, 10)] + normalize_output(input_array) From 6571d8f98f54aa9159d74006f232d9a9469cee36 Mon Sep 17 00:00:00 2001 From: yeldmitrenko Date: Wed, 10 Nov 2021 13:07:22 +0200 Subject: [PATCH 04/12] added implementation of dijkstra algorithm --- calendar.py | 48 -------------------------------------------- dijkstra.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ hash_main.py | 14 ------------- hash_table.py | 55 --------------------------------------------------- hash_test.py | 19 ------------------ 5 files changed, 53 insertions(+), 136 deletions(-) delete mode 100644 calendar.py create mode 100644 dijkstra.py delete mode 100644 hash_main.py delete mode 100644 hash_table.py delete mode 100644 hash_test.py diff --git a/calendar.py b/calendar.py deleted file mode 100644 index 5fb39bd..0000000 --- a/calendar.py +++ /dev/null @@ -1,48 +0,0 @@ -def sort_ranges(array): - if len(array) <= 1: - return array - - current_position = 0 - - for i in range(1, len(array)): - if sum(array[0]) >= sum(array[i]): - current_position += 1 - array[i], array[current_position] = array[current_position], array[i] - array[0], array[current_position] = array[current_position], array[0] - - return [*sort_ranges(array[:current_position]), - array[current_position], - *sort_ranges(array[current_position + 1:])] - - -def merge_ranges(meetings): - sorted_meetings = sort_ranges(meetings) - merged_meetings = [] - previous_meeting_start, previous_meeting_end = sorted_meetings[0] - - for current_meeting_start, current_meeting_end in sorted_meetings[1:]: - if current_meeting_start <= previous_meeting_end: - previous_meeting_end = max(current_meeting_end, previous_meeting_end) - else: - merged_meetings.append((previous_meeting_start, previous_meeting_end)) - previous_meeting_start, previous_meeting_end = current_meeting_start, current_meeting_end - merged_meetings.append((previous_meeting_start, previous_meeting_end)) - - return merged_meetings - - -def normalize_output(array): - array = merge_ranges(array) - time_block = 30 - time_start = 540 - text = "Team's work time: \n" - for time in array: - start = time_start + time[0] * time_block - end = time_start + time[1] * time_block - text += f"\t{start // 60:02d}:{start % 60:02d} - {end // 60:02d}:{end % 60:02d}\n" - print(text) - - -if __name__ == '__main__': - input_array = [(0, 1), (3, 5), (4, 8), (10, 12), (9, 10)] - normalize_output(input_array) diff --git a/dijkstra.py b/dijkstra.py new file mode 100644 index 0000000..5f94f54 --- /dev/null +++ b/dijkstra.py @@ -0,0 +1,53 @@ +from queue import PriorityQueue + +INFINITE = float('inf') + + +class Graph: + def __init__(self, vertices_number): + self.vertices = vertices_number + self.edges = [[-1 for row in range(vertices_number)] + for column in range(vertices_number)] + self.visited = [] + + def add_edge(self, from_node_to_u, from_node_to_v, weight): + self.edges[from_node_to_u][from_node_to_v] = weight + self.edges[from_node_to_v][from_node_to_u] = weight + + def dijkstra(self, start_vertex): + graph = {vertex: INFINITE for vertex in range(self.vertices)} + graph[start_vertex] = 0 + + queue = PriorityQueue() + queue.put((0, start_vertex)) + + while not queue.empty(): + (distance, current_vertex) = queue.get() + self.visited.append(current_vertex) + for neighbor in range(self.vertices): + if self.edges[current_vertex][neighbor] != -1: + distance = self.edges[current_vertex][neighbor] + if neighbor not in self.visited: + old_cost = graph[neighbor] + new_cost = graph[current_vertex] + distance + if new_cost < old_cost: + queue.put((new_cost, neighbor)) + graph[neighbor] = new_cost + return graph + + +if __name__ == '__main__': + graph = Graph(8) + graph.add_edge(0, 3, 8) + graph.add_edge(1, 4, 9) + graph.add_edge(4, 2, 4) + graph.add_edge(5, 0, 9) + graph.add_edge(5, 4, 6) + graph.add_edge(5, 1, 7) + graph.add_edge(1, 2, 1) + graph.add_edge(3, 1, 0) + + D = graph.dijkstra(1) + + for vertex in range(len(D)): + print("Distance from 1 to vertex", vertex, "is", D[vertex]) diff --git a/hash_main.py b/hash_main.py deleted file mode 100644 index 7b4448e..0000000 --- a/hash_main.py +++ /dev/null @@ -1,14 +0,0 @@ -from hash_table import HashTable - -if __name__ == "__main__": - table = HashTable() - - table.insert(0, "value1") - table.insert(1, "value2") - table.insert(2, "value3") - print(table.get_hashmap()) - - print(table.get(0)) - print(table.delete(2)) - - print(table.get_hashmap()) diff --git a/hash_table.py b/hash_table.py deleted file mode 100644 index d65fe59..0000000 --- a/hash_table.py +++ /dev/null @@ -1,55 +0,0 @@ -class HashTable: - def __init__(self): - self.size = 8 - self.hashmap = [[] for _ in range(self.size)] - - def hashing_func(self, key): - hashed_key = hash(key) % self.size - return hashed_key - - def insert(self, key, value): - global i - hash_key = self.hashing_func(key) - key_exist = False - bucket = self.hashmap[hash_key] - for i, kv in enumerate(bucket): - k, v = kv - if key == k: - key_exist = True - break - if key_exist: - bucket[i] = (key, value) - return bucket - else: - bucket.append((key, value)) - return bucket - - def get(self, key): - hash_key = self.hashing_func(key) - bucket = self.hashmap[hash_key] - if bucket: - for kv in bucket: - k, v = kv - if key == k: - return bucket - elif not bucket: - raise KeyError("does not exist") - - def delete(self, key): - global i - hash_key = self.hashing_func(key) - key_exist = False - bucket = self.hashmap[hash_key] - for i, kv in enumerate(bucket): - k, v = kv - if key == k: - key_exist = True - break - if key_exist: - del bucket[i] - return key - else: - raise KeyError("does not exist") - - def get_hashmap(self): - return self.hashmap diff --git a/hash_test.py b/hash_test.py deleted file mode 100644 index 8795b6b..0000000 --- a/hash_test.py +++ /dev/null @@ -1,19 +0,0 @@ -import unittest -from hash_table import HashTable - - -class TestHashTable(unittest.TestCase): - - def setUp(self) -> None: - self.table = HashTable() - - def test_insert(self): - self.assertEqual(self.table.insert("key1", "value1"), [("key1", "value1")]) - - def test_get(self): - self.table.insert("key1", "value1") - self.assertEqual(self.table.get("key1"), [("key1", "value1")]) - - def test_delete(self): - self.table.insert("key1", "value1") - self.assertEqual(self.table.delete("key1"), "key1") From 3e6907f92f1e3398cdad273f4ccb2f02c69f8f81 Mon Sep 17 00:00:00 2001 From: yeldmitrenko Date: Wed, 10 Nov 2021 13:27:52 +0200 Subject: [PATCH 05/12] modified readme file --- README.md | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/README.md b/README.md index 89f4e1e..e69de29 100644 --- a/README.md +++ b/README.md @@ -1,24 +0,0 @@ -# Lab-1 - -## Task -Implement a sorting algorithm - HeapSort(ascending/descending) - -## Result output -- Algorithm's name -- Execution time -- Counters: swaps, comparisons -- Sorting result - -## Code must be covered with tests -- sort the input array -- sort in ascending order of sorted array in ascending order -- sort in descending order of sorted array in ascending order -- sort in ascending order of sorted array in descending order -- sort in descending order of sorted array in descending order - -## How to run -- 'cd' into folder where you want to store this repository -- Clone this repository with command 'git clone https://github.com/yeldmitrenko/Algorithms_Labs.git' -- Choose branch lab_1 with command 'git checkout lab_1' -- Go into folder with files with command 'cd Algorithms_Labs' -- run command 'python main.py' \ No newline at end of file From 6c8343547e83194df3b746eac8b6401fb24fa4da Mon Sep 17 00:00:00 2001 From: yeldmitrenko Date: Wed, 10 Nov 2021 13:31:08 +0200 Subject: [PATCH 06/12] added readme file --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index e69de29..4c09a76 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,5 @@ +# Lab 4 + +## Implementation of Dijkstra's algorithm for finding shortest path distances in a connected graph. + +### Results in time complexity of this algorithm being O(|E|+|V|log|V|). Where |V| - the number of vertices and |E| - the number of edges \ No newline at end of file From ad722d489ea1c84b5e263cb5791a9b97a6f672f4 Mon Sep 17 00:00:00 2001 From: yeldmitrenko Date: Tue, 16 Nov 2021 11:06:46 +0200 Subject: [PATCH 07/12] added implementation of kruskal's algorithm' --- README.md | 6 +--- dijkstra.py | 53 --------------------------------- kruskal's.py | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 58 deletions(-) delete mode 100644 dijkstra.py create mode 100644 kruskal's.py diff --git a/README.md b/README.md index 4c09a76..83c1396 100644 --- a/README.md +++ b/README.md @@ -1,5 +1 @@ -# Lab 4 - -## Implementation of Dijkstra's algorithm for finding shortest path distances in a connected graph. - -### Results in time complexity of this algorithm being O(|E|+|V|log|V|). Where |V| - the number of vertices and |E| - the number of edges \ No newline at end of file +# Lab 5 \ No newline at end of file diff --git a/dijkstra.py b/dijkstra.py deleted file mode 100644 index 5f94f54..0000000 --- a/dijkstra.py +++ /dev/null @@ -1,53 +0,0 @@ -from queue import PriorityQueue - -INFINITE = float('inf') - - -class Graph: - def __init__(self, vertices_number): - self.vertices = vertices_number - self.edges = [[-1 for row in range(vertices_number)] - for column in range(vertices_number)] - self.visited = [] - - def add_edge(self, from_node_to_u, from_node_to_v, weight): - self.edges[from_node_to_u][from_node_to_v] = weight - self.edges[from_node_to_v][from_node_to_u] = weight - - def dijkstra(self, start_vertex): - graph = {vertex: INFINITE for vertex in range(self.vertices)} - graph[start_vertex] = 0 - - queue = PriorityQueue() - queue.put((0, start_vertex)) - - while not queue.empty(): - (distance, current_vertex) = queue.get() - self.visited.append(current_vertex) - for neighbor in range(self.vertices): - if self.edges[current_vertex][neighbor] != -1: - distance = self.edges[current_vertex][neighbor] - if neighbor not in self.visited: - old_cost = graph[neighbor] - new_cost = graph[current_vertex] + distance - if new_cost < old_cost: - queue.put((new_cost, neighbor)) - graph[neighbor] = new_cost - return graph - - -if __name__ == '__main__': - graph = Graph(8) - graph.add_edge(0, 3, 8) - graph.add_edge(1, 4, 9) - graph.add_edge(4, 2, 4) - graph.add_edge(5, 0, 9) - graph.add_edge(5, 4, 6) - graph.add_edge(5, 1, 7) - graph.add_edge(1, 2, 1) - graph.add_edge(3, 1, 0) - - D = graph.dijkstra(1) - - for vertex in range(len(D)): - print("Distance from 1 to vertex", vertex, "is", D[vertex]) diff --git a/kruskal's.py b/kruskal's.py new file mode 100644 index 0000000..5db9112 --- /dev/null +++ b/kruskal's.py @@ -0,0 +1,83 @@ +from typing import List + + +class Edge: + def __init__(self, start_vertex, end_vertex, weight): + self.start_vertex = start_vertex + self.end_vertex = end_vertex + self.weight = weight + + +class Graph: + def __init__(self, nodes_number, edge_list : List[Edge]): + self.nodes_number = nodes_number + self.edge_list = edge_list + self.parent = [] + self.rank = [] + self.mst = [] + + def find_parent(self, node): + if node == self.parent[node]: + return node + return self.find_parent(self.parent[node]) + + def kruskal_mst(self): + self.edge_list.sort(key=lambda Edge : Edge.weight) + self.parent = [None] * self.nodes_number + self.rank = [None] * self.nodes_number + + for node in range(self.nodes_number): + self.parent[node] = node + self.rank[node] = 0 + + for edge in self.edge_list: + root1 = self.find_parent(edge.start_vertex) + root2 = self.find_parent(edge.end_vertex) + if root1 != root2: + self.mst.append(edge) + if self.rank[root1] < self.rank[root2]: + self.parent[root1] = root2 + self.rank[root2] += 1 + else: + self.parent[root2] = root1 + self.rank[root1] += 1 + print("\nEdges of minimum spanning tree in graph :", end=' ') + cost = 0 + for edge in self.mst: + print("[" + str(edge.start_vertex) + "-" + str(edge.end_vertex) + "](" + str(edge.weight) + ")", end=' ') + cost += edge.weight + print("\nCost of minimum spanning tree : " + str(cost)) + + +if __name__ == '__main__': + nodes_number = 6 + e1 = Edge(0, 1, 4) + e2 = Edge(0, 2, 1) + e3 = Edge(0, 3, 5) + e4 = Edge(1, 3, 2) + e5 = Edge(1, 4, 3) + e6 = Edge(1, 5, 3) + e7 = Edge(2, 3, 2) + e8 = Edge(2, 4, 8) + e9 = Edge(3, 4, 1) + e10 = Edge(4, 5, 3) + + graph1 = Graph(nodes_number, [e1, e2, e3, e4, e5, e6, e7, e8, e9, e10]) + graph1.kruskal_mst() + + num_nodes = 7 + a = Edge(0, 1, 1) + b = Edge(0, 2, 2) + c = Edge(0, 3, 1) + d = Edge(0, 4, 1) + e = Edge(0, 5, 2) + f = Edge(0, 6, 1) + g = Edge(1, 2, 2) + h = Edge(1, 6, 2) + i = Edge(2, 3, 1) + j = Edge(3, 4, 2) + k = Edge(4, 5, 2) + l = Edge(5, 6, 1) + + graph2 = Graph(num_nodes, [a, b, c, d, e, f, g, h, i, j, k, l]) + graph2.kruskal_mst() From 42815b3e629c4056a59b8ddc3f4dfe991892b100 Mon Sep 17 00:00:00 2001 From: yeldmitrenko Date: Mon, 29 Nov 2021 22:45:48 +0200 Subject: [PATCH 08/12] added lab 6 --- ijones.in | 4 +++ ijones.out | 1 + ijones.py | 45 ++++++++++++++++++++++++++++ kruskal's.py | 83 ---------------------------------------------------- test.py | 34 +++++++++++++++++++++ 5 files changed, 84 insertions(+), 83 deletions(-) create mode 100644 ijones.in create mode 100644 ijones.out create mode 100644 ijones.py delete mode 100644 kruskal's.py create mode 100644 test.py diff --git a/ijones.in b/ijones.in new file mode 100644 index 0000000..f170e15 --- /dev/null +++ b/ijones.in @@ -0,0 +1,4 @@ +3 3 +aaa +cab +def \ No newline at end of file diff --git a/ijones.out b/ijones.out new file mode 100644 index 0000000..7813681 --- /dev/null +++ b/ijones.out @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/ijones.py b/ijones.py new file mode 100644 index 0000000..e7fc566 --- /dev/null +++ b/ijones.py @@ -0,0 +1,45 @@ +from collections import defaultdict +from typing import List + + +def find_ways_count(corridor: List, columns: int, rows: int): + memorized_path = defaultdict(int) + plates = [[1] for elem in range(rows)] + + for row in range(rows): + memorized_path[corridor[row][0]] += 1 + + for column in range(1, columns): + all_ways = {} + + for row in range(rows): + plate = corridor[row][column] + + if plate is not corridor[row][column - 1]: + cur_way = plates[row][column - 1] + memorized_path[plate] + else: + cur_way = memorized_path[plate] + + plates[row].append(cur_way) + all_ways[plate] = cur_way + all_ways.get(plate, 0) + + if column < columns: + for plate in all_ways: + memorized_path[plate] += all_ways[plate] + + if columns == 1: + return plates[0][columns - 1] + + return plates[0][columns - 1] + plates[rows - 1][columns - 1] + + +if __name__ == '__main__': + input_file = open("ijones.in", "r") + row, column = map(int, input_file.readline().split()) + corridor = [[] for _ in range(row)] + for plate in range(column): + corridor[plate] = input_file.readline() + input_file.close() + + output_file = open("ijones.out", "w") + output_file.write(str(find_ways_count(corridor, row, column))) diff --git a/kruskal's.py b/kruskal's.py deleted file mode 100644 index 5db9112..0000000 --- a/kruskal's.py +++ /dev/null @@ -1,83 +0,0 @@ -from typing import List - - -class Edge: - def __init__(self, start_vertex, end_vertex, weight): - self.start_vertex = start_vertex - self.end_vertex = end_vertex - self.weight = weight - - -class Graph: - def __init__(self, nodes_number, edge_list : List[Edge]): - self.nodes_number = nodes_number - self.edge_list = edge_list - self.parent = [] - self.rank = [] - self.mst = [] - - def find_parent(self, node): - if node == self.parent[node]: - return node - return self.find_parent(self.parent[node]) - - def kruskal_mst(self): - self.edge_list.sort(key=lambda Edge : Edge.weight) - self.parent = [None] * self.nodes_number - self.rank = [None] * self.nodes_number - - for node in range(self.nodes_number): - self.parent[node] = node - self.rank[node] = 0 - - for edge in self.edge_list: - root1 = self.find_parent(edge.start_vertex) - root2 = self.find_parent(edge.end_vertex) - if root1 != root2: - self.mst.append(edge) - if self.rank[root1] < self.rank[root2]: - self.parent[root1] = root2 - self.rank[root2] += 1 - else: - self.parent[root2] = root1 - self.rank[root1] += 1 - print("\nEdges of minimum spanning tree in graph :", end=' ') - cost = 0 - for edge in self.mst: - print("[" + str(edge.start_vertex) + "-" + str(edge.end_vertex) + "](" + str(edge.weight) + ")", end=' ') - cost += edge.weight - print("\nCost of minimum spanning tree : " + str(cost)) - - -if __name__ == '__main__': - nodes_number = 6 - e1 = Edge(0, 1, 4) - e2 = Edge(0, 2, 1) - e3 = Edge(0, 3, 5) - e4 = Edge(1, 3, 2) - e5 = Edge(1, 4, 3) - e6 = Edge(1, 5, 3) - e7 = Edge(2, 3, 2) - e8 = Edge(2, 4, 8) - e9 = Edge(3, 4, 1) - e10 = Edge(4, 5, 3) - - graph1 = Graph(nodes_number, [e1, e2, e3, e4, e5, e6, e7, e8, e9, e10]) - graph1.kruskal_mst() - - num_nodes = 7 - a = Edge(0, 1, 1) - b = Edge(0, 2, 2) - c = Edge(0, 3, 1) - d = Edge(0, 4, 1) - e = Edge(0, 5, 2) - f = Edge(0, 6, 1) - g = Edge(1, 2, 2) - h = Edge(1, 6, 2) - i = Edge(2, 3, 1) - j = Edge(3, 4, 2) - k = Edge(4, 5, 2) - l = Edge(5, 6, 1) - - graph2 = Graph(num_nodes, [a, b, c, d, e, f, g, h, i, j, k, l]) - graph2.kruskal_mst() diff --git a/test.py b/test.py new file mode 100644 index 0000000..7372895 --- /dev/null +++ b/test.py @@ -0,0 +1,34 @@ +import unittest + +from lab6.ijones import find_ways_count + + +class FindWaysCountTest(unittest.TestCase): + def setUp(self) -> None: + self.matrix1 = [ + ["a", "a", "a"], + ["c", "a", "b"], + ["d", "e", "f"] + ] + self.matrix2 = [['a', 'b', 'c', 'd', 'e', 'f', 'a', 'g', 'h', 'i']] + self.matrix3 = [ + ["a", "a", "a", "a", "a", "a", "a"], + ["a", "a", "a", "a", "a", "a", "a"], + ["a", "a", "a", "a", "a", "a", "a"], + ["a", "a", "a", "a", "a", "a", "a"], + ["a", "a", "a", "a", "a", "a", "a"], + ["a", "a", "a", "a", "a", "a", "a"] + ] + + def test_first_case(self): + self.assertEqual(find_ways_count(self.matrix1, 3, 3), 5) + + def test_second_case(self): + self.assertEqual(find_ways_count(self.matrix2, 10, 1), 4) + + def test_third_case(self): + self.assertEqual(find_ways_count(self.matrix3, 7, 6), 201684) + + +if __name__ == '__main__': + unittest.main() From bcba79e799ca5460e442d8465fd771d254812c24 Mon Sep 17 00:00:00 2001 From: yeldmitrenko Date: Sun, 5 Dec 2021 20:15:40 +0200 Subject: [PATCH 09/12] added lab 7 --- ijones.in | 4 ---- ijones.out | 1 - ijones.py | 45 --------------------------------------------- rabin_karp.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ test.py | 42 +++++++++++++++++------------------------- 5 files changed, 63 insertions(+), 75 deletions(-) delete mode 100644 ijones.in delete mode 100644 ijones.out delete mode 100644 ijones.py create mode 100644 rabin_karp.py diff --git a/ijones.in b/ijones.in deleted file mode 100644 index f170e15..0000000 --- a/ijones.in +++ /dev/null @@ -1,4 +0,0 @@ -3 3 -aaa -cab -def \ No newline at end of file diff --git a/ijones.out b/ijones.out deleted file mode 100644 index 7813681..0000000 --- a/ijones.out +++ /dev/null @@ -1 +0,0 @@ -5 \ No newline at end of file diff --git a/ijones.py b/ijones.py deleted file mode 100644 index e7fc566..0000000 --- a/ijones.py +++ /dev/null @@ -1,45 +0,0 @@ -from collections import defaultdict -from typing import List - - -def find_ways_count(corridor: List, columns: int, rows: int): - memorized_path = defaultdict(int) - plates = [[1] for elem in range(rows)] - - for row in range(rows): - memorized_path[corridor[row][0]] += 1 - - for column in range(1, columns): - all_ways = {} - - for row in range(rows): - plate = corridor[row][column] - - if plate is not corridor[row][column - 1]: - cur_way = plates[row][column - 1] + memorized_path[plate] - else: - cur_way = memorized_path[plate] - - plates[row].append(cur_way) - all_ways[plate] = cur_way + all_ways.get(plate, 0) - - if column < columns: - for plate in all_ways: - memorized_path[plate] += all_ways[plate] - - if columns == 1: - return plates[0][columns - 1] - - return plates[0][columns - 1] + plates[rows - 1][columns - 1] - - -if __name__ == '__main__': - input_file = open("ijones.in", "r") - row, column = map(int, input_file.readline().split()) - corridor = [[] for _ in range(row)] - for plate in range(column): - corridor[plate] = input_file.readline() - input_file.close() - - output_file = open("ijones.out", "w") - output_file.write(str(find_ways_count(corridor, row, column))) diff --git a/rabin_karp.py b/rabin_karp.py new file mode 100644 index 0000000..7cb8c4c --- /dev/null +++ b/rabin_karp.py @@ -0,0 +1,46 @@ +alphabet_size = 256 + + +def calculate_hash(pattern, primary_number): + reducing_hash_number = 1 + + for i in range(len(pattern) - 1): + reducing_hash_number = (reducing_hash_number * alphabet_size) % primary_number + + return reducing_hash_number + + +def rabin_karp_search(text, pattern, primary_number=101): + positions_array = [] + text_hash_value = 0 + pattern_hash_value = 0 + + reducing_hash_number = calculate_hash(pattern, primary_number) + + for i in range(len(pattern)): + text_hash_value = (alphabet_size * text_hash_value + ord(text[i])) % primary_number + pattern_hash_value = (alphabet_size * pattern_hash_value + ord(pattern[i])) % primary_number + + for i in range(len(text) - len(pattern) + 1): + if pattern_hash_value == text_hash_value: + matches_number = 0 + for j in range(len(pattern)): + if pattern[j] == text[j + i]: + matches_number += 1 + else: + break + if matches_number == len(pattern): + positions_array.append(i) + + if i < len(text) - len(pattern): + text_hash_value = (alphabet_size * (text_hash_value - ord(text[i]) * reducing_hash_number) + ord( + text[i + len(pattern)])) % primary_number + text_hash_value = text_hash_value + primary_number if text_hash_value < 0 else text_hash_value + return positions_array + + +if __name__ == '__main__': + text = "BBCLLNMNLLN" + pattern = "LLN" + + print(rabin_karp_search(text, pattern)) diff --git a/test.py b/test.py index 7372895..bd9f4c3 100644 --- a/test.py +++ b/test.py @@ -1,33 +1,25 @@ import unittest -from lab6.ijones import find_ways_count +from lab7.rabin_karp import rabin_karp_search -class FindWaysCountTest(unittest.TestCase): +class RabinKarpTest(unittest.TestCase): def setUp(self) -> None: - self.matrix1 = [ - ["a", "a", "a"], - ["c", "a", "b"], - ["d", "e", "f"] - ] - self.matrix2 = [['a', 'b', 'c', 'd', 'e', 'f', 'a', 'g', 'h', 'i']] - self.matrix3 = [ - ["a", "a", "a", "a", "a", "a", "a"], - ["a", "a", "a", "a", "a", "a", "a"], - ["a", "a", "a", "a", "a", "a", "a"], - ["a", "a", "a", "a", "a", "a", "a"], - ["a", "a", "a", "a", "a", "a", "a"], - ["a", "a", "a", "a", "a", "a", "a"] - ] - - def test_first_case(self): - self.assertEqual(find_ways_count(self.matrix1, 3, 3), 5) - - def test_second_case(self): - self.assertEqual(find_ways_count(self.matrix2, 10, 1), 4) - - def test_third_case(self): - self.assertEqual(find_ways_count(self.matrix3, 7, 6), 201684) + self.test_text1 = "AAA NN MM LL K AA" + self.test_pattern1 = "AA" + self.benchmark_positions_array1 = [0, 1, 15] + + self.test_pattern2 = "LLN" + self.test_text2 = "BBCLLNMNLLN" + self.benchmark_positions_array2 = [3, 8] + + def test_rabin_karp_search_1(self): + pattern_positions = rabin_karp_search(self.test_text1, self.test_pattern1) + self.assertEqual(pattern_positions, self.benchmark_positions_array1) + + def test_rabin_karp_search_2(self): + pattern_positions = rabin_karp_search(self.test_text2, self.test_pattern2) + self.assertEqual(pattern_positions, self.benchmark_positions_array2) if __name__ == '__main__': From 503920fa7abbe249bfa5256be52386fed6a6c95b Mon Sep 17 00:00:00 2001 From: yeldmitrenko Date: Sun, 5 Dec 2021 20:49:55 +0200 Subject: [PATCH 10/12] added readme file --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 83c1396..a7c8691 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ -# Lab 5 \ No newline at end of file +Rabin Karp String Matching Algorithm + From ef9d6d7cfdd2ff57a9dfb6f9342661207829146f Mon Sep 17 00:00:00 2001 From: Yelizaveta Dmitrenko <74879089+yeldmitrenko@users.noreply.github.com> Date: Sun, 5 Dec 2021 21:50:30 +0300 Subject: [PATCH 11/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a7c8691..b9a13c7 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -Rabin Karp String Matching Algorithm +# Rabin Karp String Matching Algorithm From 6857982df2ebb44ed101a23d2b4e3a39ee4255ee Mon Sep 17 00:00:00 2001 From: Yelizaveta Dmitrenko <74879089+yeldmitrenko@users.noreply.github.com> Date: Thu, 20 Oct 2022 00:03:24 +0300 Subject: [PATCH 12/12] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b9a13c7..48bda65 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ -# Rabin Karp String Matching Algorithm +# Lab 7 - Dynamic Programming + +### Rabin Karp String Matching Algorithm