Repository: TheAlgorithms/Python

Issue:
Dev sprint ideas: More tests, type hints and less complexity
currently, some of the programs use static type checking like this [program](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/fast_fibonacci.py) but some of the programs did not use static typing.

it's a good practice to use static typing as it makes code more clear and readable, should we make it a standard for this repository.we can use [mypy](http://mypy-lang.org/) for testing code 

[more on static typing](https://medium.com/@ageitgey/learn-how-to-use-static-type-checking-in-python-3-6-in-10-minutes-12c86d72677b)
 
thank you

### Dev sprint ideas:
* [ ] [Add tests to Python files with <10% test coverage.](https://github.com/TheAlgorithms/Python/issues/2128#issuecomment-645231020)
* [ ] [Add static typing to functions and methods.](https://github.com/TheAlgorithms/Python/issues/2128)
* [ ] [Set `flake8 --max-complexity=15`](https://github.com/TheAlgorithms/Python/issues/2128#issuecomment-645190839) (Ensure files have strong tests ___before___ refactoring).  Test results from #2139...
    * [ ] ./boolean_algebra/quine_mc_cluskey.py:82:1: C901 'selection' is too complex (17)
    * [ ] ./digital_image_processing/edge_detection/canny.py:20:1: C901 'canny' is too complex (17) @lighttxu
    * [ ] ./graphs/minimum_spanning_tree_prims.py:5:1: C901 'PrimsAlgorithm' is too complex (21)
        * [ ] Add doctests aligned with https://en.wikipedia.org/wiki/Prim%27s_algorithm
        * [ ] In a ___separate___ PR reduce the McCabe complexity
    * [ ] ./linear_algebra/src/polynom-for-points.py:1:1: C901 'points_to_polynomial' is too complex (23) @nic-dern
    * [ ] ./machine_learning/linear_discriminant_analysis.py:251:1: C901 'main' is too complex (25)
    * [x] ./hashes/hamming_code.py:71:1: C901 'emitterConverter' is too complex (16) #2140
    * [x] ./hashes/hamming_code.py:153:1: C901 'receptorConverter' is too complex (20) #2140
    * [x] ./project_euler/problem_551/sol1.py:20:1: C901 'next_term' is too complex (16) #2141


Discussion:
We push all new contributions to use type hints as discussed in CONTRIBUTING.md.
All efforts to add type hints to existing algorithms would be warmly received.

> We can use mypy for testing code

We do this already https://github.com/TheAlgorithms/Python/blob/master/.travis.yml#L17
@cclauss How about a _dev sprint_ **kind** of thing where we go about adding all such improvements?
Cool idea!  Another thing (a sprint topic?) that is bugging me is [code complexity](https://flake8.pycqa.org/en/latest/user/options.html#cmdoption-flake8-max-complexity) which [we currently set to 25](https://github.com/TheAlgorithms/Python/blob/master/.travis.yml#L13) but I would be much happier to see it at 15.  We would need to ensure that the files have strong type hints and tests _before_ modifying them to [reduce their cyclomatic complexity](https://en.wikipedia.org/wiki/Cyclomatic_complexity).

Resolving patch:
diff --git a/graphs/minimum_spanning_tree_kruskal.py b/graphs/minimum_spanning_tree_kruskal.py
--- a/graphs/minimum_spanning_tree_kruskal.py
+++ b/graphs/minimum_spanning_tree_kruskal.py
@@ -1,13 +1,5 @@
-if __name__ == "__main__":
-    num_nodes, num_edges = list(map(int, input().strip().split()))
-
-    edges = []
-
-    for i in range(num_edges):
-        node1, node2, cost = list(map(int, input().strip().split()))
-        edges.append((i, node1, node2, cost))
-
-    edges = sorted(edges, key=lambda edge: edge[3])
+def kruskal(num_nodes, num_edges, edges):
+    edges = sorted(edges, key=lambda edge: edge[2])
 
     parent = list(range(num_nodes))
 
@@ -20,13 +12,22 @@ def find_parent(i):
     minimum_spanning_tree = []
 
     for edge in edges:
-        parent_a = find_parent(edge[1])
-        parent_b = find_parent(edge[2])
+        parent_a = find_parent(edge[0])
+        parent_b = find_parent(edge[1])
         if parent_a != parent_b:
-            minimum_spanning_tree_cost += edge[3]
+            minimum_spanning_tree_cost += edge[2]
             minimum_spanning_tree.append(edge)
             parent[parent_a] = parent_b
 
-    print(minimum_spanning_tree_cost)
-    for edge in minimum_spanning_tree:
-        print(edge)
+    return minimum_spanning_tree
+
+
+if __name__ == "__main__":  # pragma: no cover
+    num_nodes, num_edges = list(map(int, input().strip().split()))
+    edges = []
+
+    for _ in range(num_edges):
+        node1, node2, cost = [int(x) for x in input().strip().split()]
+        edges.append((node1, node2, cost))
+
+    kruskal(num_nodes, num_edges, edges)
diff --git a/searches/simple_binary_search.py b/searches/simple_binary_search.py
--- a/searches/simple_binary_search.py
+++ b/searches/simple_binary_search.py
@@ -42,7 +42,7 @@ def binary_search(a_list: List[int], item: int) -> bool:
     if item < a_list[midpoint]:
         return binary_search(a_list[:midpoint], item)
     else:
-        return binary_search(a_list[midpoint + 1:], item)
+        return binary_search(a_list[midpoint + 1 :], item)
 
 
 if __name__ == "__main__":


Test patch:
diff --git a/graphs/tests/test_min_spanning_tree_kruskal.py b/graphs/tests/test_min_spanning_tree_kruskal.py
new file mode 100644
--- /dev/null
+++ b/graphs/tests/test_min_spanning_tree_kruskal.py
@@ -0,0 +1,36 @@
+from graphs.minimum_spanning_tree_kruskal import kruskal
+
+
+def test_kruskal_successful_result():
+    num_nodes, num_edges = 9, 14
+    edges = [
+        [0, 1, 4],
+        [0, 7, 8],
+        [1, 2, 8],
+        [7, 8, 7],
+        [7, 6, 1],
+        [2, 8, 2],
+        [8, 6, 6],
+        [2, 3, 7],
+        [2, 5, 4],
+        [6, 5, 2],
+        [3, 5, 14],
+        [3, 4, 9],
+        [5, 4, 10],
+        [1, 7, 11],
+    ]
+
+    result = kruskal(num_nodes, num_edges, edges)
+
+    expected = [
+        [7, 6, 1],
+        [2, 8, 2],
+        [6, 5, 2],
+        [0, 1, 4],
+        [2, 5, 4],
+        [2, 3, 7],
+        [0, 7, 8],
+        [3, 4, 9],
+    ]
+
+    assert sorted(expected) == sorted(result)