Skip to content

Commit 7ea868a

Browse files
authored
Merge branch 'TheAlgorithms:master' into mypy-fix-trie
2 parents 1c6d7e5 + 1b0ac73 commit 7ea868a

File tree

42 files changed

+381
-151
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+381
-151
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Algorithms in this repo should not be how-to examples for existing Python packag
5353
Use [pre-commit](https://pre-commit.com/#installation) to automatically format your code to match our coding style:
5454

5555
```bash
56-
python3 -m pip install pre-commit # required only once
56+
python3 -m pip install pre-commit # only required the first time
5757
pre-commit install
5858
```
5959
That's it! The plugin will run every time you commit any changes. If there are any errors found during the run, fix them and commit those changes. You can even run the plugin manually on all files:

DIRECTORY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,7 @@
514514
* [Sum Of Arithmetic Series](https://github.com/TheAlgorithms/Python/blob/master/maths/sum_of_arithmetic_series.py)
515515
* [Sum Of Digits](https://github.com/TheAlgorithms/Python/blob/master/maths/sum_of_digits.py)
516516
* [Sum Of Geometric Progression](https://github.com/TheAlgorithms/Python/blob/master/maths/sum_of_geometric_progression.py)
517+
* [Sylvester Sequence](https://github.com/TheAlgorithms/Python/blob/master/maths/sylvester_sequence.py)
517518
* [Test Prime Check](https://github.com/TheAlgorithms/Python/blob/master/maths/test_prime_check.py)
518519
* [Trapezoidal Rule](https://github.com/TheAlgorithms/Python/blob/master/maths/trapezoidal_rule.py)
519520
* [Triplet Sum](https://github.com/TheAlgorithms/Python/blob/master/maths/triplet_sum.py)
@@ -931,7 +932,6 @@
931932
* [Reverse Letters](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_letters.py)
932933
* [Reverse Words](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_words.py)
933934
* [Split](https://github.com/TheAlgorithms/Python/blob/master/strings/split.py)
934-
* [Swap Case](https://github.com/TheAlgorithms/Python/blob/master/strings/swap_case.py)
935935
* [Upper](https://github.com/TheAlgorithms/Python/blob/master/strings/upper.py)
936936
* [Word Occurrence](https://github.com/TheAlgorithms/Python/blob/master/strings/word_occurrence.py)
937937
* [Word Patterns](https://github.com/TheAlgorithms/Python/blob/master/strings/word_patterns.py)

data_structures/disjoint_set/disjoint_set.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
11
"""
2-
disjoint set
2+
Disjoint set.
33
Reference: https://en.wikipedia.org/wiki/Disjoint-set_data_structure
44
"""
55

66

77
class Node:
8-
def __init__(self, data):
8+
def __init__(self, data: int) -> None:
99
self.data = data
10+
self.rank: int
11+
self.parent: Node
1012

1113

12-
def make_set(x):
14+
def make_set(x: Node) -> None:
1315
"""
14-
make x as a set.
16+
Make x as a set.
1517
"""
1618
# rank is the distance from x to its' parent
1719
# root's rank is 0
1820
x.rank = 0
1921
x.parent = x
2022

2123

22-
def union_set(x, y):
24+
def union_set(x: Node, y: Node) -> None:
2325
"""
24-
union two sets.
26+
Union of two sets.
2527
set with bigger rank should be parent, so that the
2628
disjoint set tree will be more flat.
2729
"""
@@ -37,9 +39,9 @@ def union_set(x, y):
3739
y.rank += 1
3840

3941

40-
def find_set(x):
42+
def find_set(x: Node) -> Node:
4143
"""
42-
return the parent of x
44+
Return the parent of x
4345
"""
4446
if x != x.parent:
4547
x.parent = find_set(x.parent)
@@ -57,7 +59,7 @@ def find_python_set(node: Node) -> set:
5759
raise ValueError(f"{node.data} is not in {sets}")
5860

5961

60-
def test_disjoint_set():
62+
def test_disjoint_set() -> None:
6163
"""
6264
>>> test_disjoint_set()
6365
"""

data_structures/linked_list/__init__.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
- Last node: points to null
77
"""
88

9-
from typing import Any
9+
from typing import Any, Optional
1010

1111

1212
class Node:
@@ -17,15 +17,18 @@ def __init__(self, item: Any, next: Any) -> None:
1717

1818
class LinkedList:
1919
def __init__(self) -> None:
20-
self.head = None
20+
self.head: Optional[Node] = None
2121
self.size = 0
2222

2323
def add(self, item: Any) -> None:
2424
self.head = Node(item, self.head)
2525
self.size += 1
2626

2727
def remove(self) -> Any:
28-
if self.is_empty():
28+
# Switched 'self.is_empty()' to 'self.head is None'
29+
# because mypy was considering the possibility that 'self.head'
30+
# can be None in below else part and giving error
31+
if self.head is None:
2932
return None
3033
else:
3134
item = self.head.item
@@ -50,7 +53,7 @@ def __str__(self) -> str:
5053
else:
5154
iterate = self.head
5255
item_str = ""
53-
item_list = []
56+
item_list: list[str] = []
5457
while iterate:
5558
item_list.append(str(iterate.item))
5659
iterate = iterate.next

data_structures/linked_list/circular_linked_list.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
from typing import Any
1+
from typing import Any, Iterator, Optional
22

33

44
class Node:
55
def __init__(self, data: Any):
6-
self.data = data
7-
self.next = None
6+
self.data: Any = data
7+
self.next: Optional[Node] = None
88

99

1010
class CircularLinkedList:
1111
def __init__(self):
1212
self.head = None
1313
self.tail = None
1414

15-
def __iter__(self):
15+
def __iter__(self) -> Iterator[Any]:
1616
node = self.head
1717
while self.head:
1818
yield node.data
@@ -54,10 +54,10 @@ def insert_nth(self, index: int, data: Any) -> None:
5454
def delete_front(self):
5555
return self.delete_nth(0)
5656

57-
def delete_tail(self) -> None:
57+
def delete_tail(self) -> Any:
5858
return self.delete_nth(len(self) - 1)
5959

60-
def delete_nth(self, index: int = 0):
60+
def delete_nth(self, index: int = 0) -> Any:
6161
if not 0 <= index < len(self):
6262
raise IndexError("list index out of range.")
6363
delete_node = self.head
@@ -76,7 +76,7 @@ def delete_nth(self, index: int = 0):
7676
self.tail = temp
7777
return delete_node.data
7878

79-
def is_empty(self):
79+
def is_empty(self) -> bool:
8080
return len(self) == 0
8181

8282

data_structures/linked_list/has_loop.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any
1+
from typing import Any, Optional
22

33

44
class ContainsLoopError(Exception):
@@ -7,8 +7,8 @@ class ContainsLoopError(Exception):
77

88
class Node:
99
def __init__(self, data: Any) -> None:
10-
self.data = data
11-
self.next_node = None
10+
self.data: Any = data
11+
self.next_node: Optional[Node] = None
1212

1313
def __iter__(self):
1414
node = self

data_structures/linked_list/middle_element_of_linked_list.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
from typing import Optional
2+
3+
14
class Node:
2-
def __init__(self, data: int) -> int:
5+
def __init__(self, data: int) -> None:
36
self.data = data
47
self.next = None
58

@@ -14,7 +17,7 @@ def push(self, new_data: int) -> int:
1417
self.head = new_node
1518
return self.head.data
1619

17-
def middle_element(self) -> int:
20+
def middle_element(self) -> Optional[int]:
1821
"""
1922
>>> link = LinkedList()
2023
>>> link.middle_element()
@@ -54,6 +57,7 @@ def middle_element(self) -> int:
5457
return slow_pointer.data
5558
else:
5659
print("No element found.")
60+
return None
5761

5862

5963
if __name__ == "__main__":

data_structures/linked_list/skip_list.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
from __future__ import annotations
66

77
from random import random
8-
from typing import Generic, TypeVar
8+
from typing import Generic, Optional, TypeVar, Union
99

1010
KT = TypeVar("KT")
1111
VT = TypeVar("VT")
1212

1313

1414
class Node(Generic[KT, VT]):
15-
def __init__(self, key: KT, value: VT):
15+
def __init__(self, key: Union[KT, str] = "root", value: Optional[VT] = None):
1616
self.key = key
1717
self.value = value
1818
self.forward: list[Node[KT, VT]] = []
@@ -49,7 +49,7 @@ def level(self) -> int:
4949

5050
class SkipList(Generic[KT, VT]):
5151
def __init__(self, p: float = 0.5, max_level: int = 16):
52-
self.head = Node("root", None)
52+
self.head: Node[KT, VT] = Node[KT, VT]()
5353
self.level = 0
5454
self.p = p
5555
self.max_level = max_level

divide_and_conquer/inversions.py

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,25 @@
22
Given an array-like data structure A[1..n], how many pairs
33
(i, j) for all 1 <= i < j <= n such that A[i] > A[j]? These pairs are
44
called inversions. Counting the number of such inversions in an array-like
5-
object is the important. Among other things, counting inversions can help
6-
us determine how close a given array is to being sorted
7-
5+
object is the important. Among other things, counting inversions can help
6+
us determine how close a given array is to being sorted.
87
In this implementation, I provide two algorithms, a divide-and-conquer
98
algorithm which runs in nlogn and the brute-force n^2 algorithm.
10-
119
"""
1210

1311

1412
def count_inversions_bf(arr):
1513
"""
1614
Counts the number of inversions using a a naive brute-force algorithm
17-
1815
Parameters
1916
----------
2017
arr: arr: array-like, the list containing the items for which the number
2118
of inversions is desired. The elements of `arr` must be comparable.
22-
2319
Returns
2420
-------
2521
num_inversions: The total number of inversions in `arr`
26-
2722
Examples
2823
---------
29-
3024
>>> count_inversions_bf([1, 4, 2, 4, 1])
3125
4
3226
>>> count_inversions_bf([1, 1, 2, 4, 4])
@@ -49,20 +43,16 @@ def count_inversions_bf(arr):
4943
def count_inversions_recursive(arr):
5044
"""
5145
Counts the number of inversions using a divide-and-conquer algorithm
52-
5346
Parameters
5447
-----------
5548
arr: array-like, the list containing the items for which the number
5649
of inversions is desired. The elements of `arr` must be comparable.
57-
5850
Returns
5951
-------
6052
C: a sorted copy of `arr`.
6153
num_inversions: int, the total number of inversions in 'arr'
62-
6354
Examples
6455
--------
65-
6656
>>> count_inversions_recursive([1, 4, 2, 4, 1])
6757
([1, 1, 2, 4, 4], 4)
6858
>>> count_inversions_recursive([1, 1, 2, 4, 4])
@@ -72,40 +62,34 @@ def count_inversions_recursive(arr):
7262
"""
7363
if len(arr) <= 1:
7464
return arr, 0
75-
else:
76-
mid = len(arr) // 2
77-
P = arr[0:mid]
78-
Q = arr[mid:]
65+
mid = len(arr) // 2
66+
P = arr[0:mid]
67+
Q = arr[mid:]
7968

80-
A, inversion_p = count_inversions_recursive(P)
81-
B, inversions_q = count_inversions_recursive(Q)
82-
C, cross_inversions = _count_cross_inversions(A, B)
69+
A, inversion_p = count_inversions_recursive(P)
70+
B, inversions_q = count_inversions_recursive(Q)
71+
C, cross_inversions = _count_cross_inversions(A, B)
8372

84-
num_inversions = inversion_p + inversions_q + cross_inversions
85-
return C, num_inversions
73+
num_inversions = inversion_p + inversions_q + cross_inversions
74+
return C, num_inversions
8675

8776

8877
def _count_cross_inversions(P, Q):
8978
"""
9079
Counts the inversions across two sorted arrays.
9180
And combine the two arrays into one sorted array
92-
9381
For all 1<= i<=len(P) and for all 1 <= j <= len(Q),
9482
if P[i] > Q[j], then (i, j) is a cross inversion
95-
9683
Parameters
9784
----------
9885
P: array-like, sorted in non-decreasing order
9986
Q: array-like, sorted in non-decreasing order
100-
10187
Returns
10288
------
10389
R: array-like, a sorted array of the elements of `P` and `Q`
10490
num_inversion: int, the number of inversions across `P` and `Q`
105-
10691
Examples
10792
--------
108-
10993
>>> _count_cross_inversions([1, 2, 3], [0, 2, 5])
11094
([0, 1, 2, 2, 3, 5], 4)
11195
>>> _count_cross_inversions([1, 2, 3], [3, 4, 5])

0 commit comments

Comments
 (0)