diff --git a/DIRECTORY.md b/DIRECTORY.md index fb8312c635f8..2b4e1728266b 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -86,6 +86,7 @@ * [Decimal To Hexadecimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_hexadecimal.py) * [Decimal To Octal](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_octal.py) * [Roman To Integer](https://github.com/TheAlgorithms/Python/blob/master/conversions/roman_to_integer.py) + * [Temperature Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/temperature_conversions.py) ## Data Structures * Binary Tree @@ -266,6 +267,7 @@ * [Kahns Algorithm Topo](https://github.com/TheAlgorithms/Python/blob/master/graphs/kahns_algorithm_topo.py) * [Minimum Spanning Tree Boruvka](https://github.com/TheAlgorithms/Python/blob/master/graphs/minimum_spanning_tree_boruvka.py) * [Minimum Spanning Tree Kruskal](https://github.com/TheAlgorithms/Python/blob/master/graphs/minimum_spanning_tree_kruskal.py) + * [Minimum Spanning Tree Kruskal2](https://github.com/TheAlgorithms/Python/blob/master/graphs/minimum_spanning_tree_kruskal2.py) * [Minimum Spanning Tree Prims](https://github.com/TheAlgorithms/Python/blob/master/graphs/minimum_spanning_tree_prims.py) * [Multi Heuristic Astar](https://github.com/TheAlgorithms/Python/blob/master/graphs/multi_heuristic_astar.py) * [Page Rank](https://github.com/TheAlgorithms/Python/blob/master/graphs/page_rank.py) @@ -337,6 +339,7 @@ * [Binary Exp Mod](https://github.com/TheAlgorithms/Python/blob/master/maths/binary_exp_mod.py) * [Binary Exponentiation](https://github.com/TheAlgorithms/Python/blob/master/maths/binary_exponentiation.py) * [Binomial Coefficient](https://github.com/TheAlgorithms/Python/blob/master/maths/binomial_coefficient.py) + * [Binomial Distribution](https://github.com/TheAlgorithms/Python/blob/master/maths/binomial_distribution.py) * [Bisection](https://github.com/TheAlgorithms/Python/blob/master/maths/bisection.py) * [Ceil](https://github.com/TheAlgorithms/Python/blob/master/maths/ceil.py) * [Chudnovsky Algorithm](https://github.com/TheAlgorithms/Python/blob/master/maths/chudnovsky_algorithm.py) @@ -633,6 +636,7 @@ * [I Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/i_sort.py) * [Insertion Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/insertion_sort.py) * [Iterative Merge Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/iterative_merge_sort.py) + * [Merge Insertion Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/merge_insertion_sort.py) * [Merge Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/merge_sort.py) * [Odd Even Transposition Parallel](https://github.com/TheAlgorithms/Python/blob/master/sorts/odd_even_transposition_parallel.py) * [Odd Even Transposition Single Threaded](https://github.com/TheAlgorithms/Python/blob/master/sorts/odd_even_transposition_single_threaded.py) diff --git a/conversions/temperature_conversions.py b/conversions/temperature_conversions.py index 6b99d7688e44..591322badc96 100644 --- a/conversions/temperature_conversions.py +++ b/conversions/temperature_conversions.py @@ -85,4 +85,5 @@ def kelvin_to_celsius(kelvin: float) -> float: if __name__ == "__main__": import doctest + doctest.testmod() diff --git a/graphs/minimum_spanning_tree_kruskal2.py b/graphs/minimum_spanning_tree_kruskal2.py new file mode 100644 index 000000000000..dfb87efeb89a --- /dev/null +++ b/graphs/minimum_spanning_tree_kruskal2.py @@ -0,0 +1,109 @@ +from __future__ import annotations + + +class DisjointSetTreeNode: + # Disjoint Set Node to store the parent and rank + def __init__(self, key: int) -> None: + self.key = key + self.parent = self + self.rank = 0 + + +class DisjointSetTree: + # Disjoint Set DataStructure + def __init__(self): + # map from node name to the node object + self.map = {} + + def make_set(self, x: int) -> None: + # create a new set with x as its member + self.map[x] = DisjointSetTreeNode(x) + + def find_set(self, x: int) -> DisjointSetTreeNode: + # find the set x belongs to (with path-compression) + elem_ref = self.map[x] + if elem_ref != elem_ref.parent: + elem_ref.parent = self.find_set(elem_ref.parent.key) + return elem_ref.parent + + def link(self, x: int, y: int) -> None: + # helper function for union operation + if x.rank > y.rank: + y.parent = x + else: + x.parent = y + if x.rank == y.rank: + y.rank += 1 + + def union(self, x: int, y: int) -> None: + # merge 2 disjoint sets + self.link(self.find_set(x), self.find_set(y)) + + +class GraphUndirectedWeighted: + def __init__(self): + # connections: map from the node to the neighbouring nodes (with weights) + self.connections = {} + + def add_node(self, node: int) -> None: + # add a node ONLY if its not present in the graph + if node not in self.connections: + self.connections[node] = {} + + def add_edge(self, node1: int, node2: int, weight: int) -> None: + # add an edge with the given weight + self.add_node(node1) + self.add_node(node2) + self.connections[node1][node2] = weight + self.connections[node2][node1] = weight + + def kruskal(self) -> GraphUndirectedWeighted: + # Kruskal's Algorithm to generate a Minimum Spanning Tree (MST) of a graph + """ + Details: https://en.wikipedia.org/wiki/Kruskal%27s_algorithm + + Example: + + >>> graph = GraphUndirectedWeighted() + >>> graph.add_edge(1, 2, 1) + >>> graph.add_edge(2, 3, 2) + >>> graph.add_edge(3, 4, 1) + >>> graph.add_edge(3, 5, 100) # Removed in MST + >>> graph.add_edge(4, 5, 5) + >>> assert 5 in graph.connections[3] + >>> mst = graph.kruskal() + >>> assert 5 not in mst.connections[3] + """ + + # getting the edges in ascending order of weights + edges = [] + seen = set() + for start in self.connections: + for end in self.connections[start]: + if (start, end) not in seen: + seen.add((end, start)) + edges.append((start, end, self.connections[start][end])) + edges.sort(key=lambda x: x[2]) + # creating the disjoint set + disjoint_set = DisjointSetTree() + [disjoint_set.make_set(node) for node in self.connections] + # MST generation + num_edges = 0 + index = 0 + graph = GraphUndirectedWeighted() + while num_edges < len(self.connections) - 1: + u, v, w = edges[index] + index += 1 + parentu = disjoint_set.find_set(u) + parentv = disjoint_set.find_set(v) + if parentu != parentv: + num_edges += 1 + graph.add_edge(u, v, w) + disjoint_set.union(u, v) + return graph + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/linear_algebra/src/test_linear_algebra.py b/linear_algebra/src/test_linear_algebra.py index be6245747f87..8db480ceb29d 100644 --- a/linear_algebra/src/test_linear_algebra.py +++ b/linear_algebra/src/test_linear_algebra.py @@ -8,14 +8,7 @@ """ import unittest -from lib import ( - Matrix, - Vector, - axpy, - squareZeroMatrix, - unitBasisVector, - zeroVector, -) +from lib import Matrix, Vector, axpy, squareZeroMatrix, unitBasisVector, zeroVector class Test(unittest.TestCase): diff --git a/web_programming/daily_horoscope.py b/web_programming/daily_horoscope.py index ecb37ce106f4..b0dd1cd65924 100644 --- a/web_programming/daily_horoscope.py +++ b/web_programming/daily_horoscope.py @@ -1,5 +1,5 @@ -from bs4 import BeautifulSoup import requests +from bs4 import BeautifulSoup def horoscope(zodiac_sign: int, day: str) -> str: