Skip to content

Commit c6dd975

Browse files
polosocclaussgithub-actions
authored
Add type hints and tests. (#2461)
* Add type hints, documentation and tests. * Update searches/ternary_search.py Sort collection and remove the assertion logic. Co-authored-by: Christian Clauss <[email protected]> * Remove assert sorted logic. * Add assertion list is ordered. * updating DIRECTORY.md * updating DIRECTORY.md * Format with black. * Change names of variables to descriptive names * Remove print in doctests * Fix variables to snake_case notation. Co-authored-by: Christian Clauss <[email protected]> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
1 parent ae4d7d4 commit c6dd975

File tree

2 files changed

+141
-67
lines changed

2 files changed

+141
-67
lines changed

Diff for: DIRECTORY.md

+9
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@
206206
* [Heaps Algorithm](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/heaps_algorithm.py)
207207
* [Heaps Algorithm Iterative](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/heaps_algorithm_iterative.py)
208208
* [Inversions](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/inversions.py)
209+
* [Kth Order Statistic](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/kth_order_statistic.py)
209210
* [Max Subarray Sum](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/max_subarray_sum.py)
210211
* [Mergesort](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/mergesort.py)
211212
* [Power](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/power.py)
@@ -390,6 +391,7 @@
390391
* [Chudnovsky Algorithm](https://github.com/TheAlgorithms/Python/blob/master/maths/chudnovsky_algorithm.py)
391392
* [Collatz Sequence](https://github.com/TheAlgorithms/Python/blob/master/maths/collatz_sequence.py)
392393
* [Combinations](https://github.com/TheAlgorithms/Python/blob/master/maths/combinations.py)
394+
* [Decimal Isolate](https://github.com/TheAlgorithms/Python/blob/master/maths/decimal_isolate.py)
393395
* [Entropy](https://github.com/TheAlgorithms/Python/blob/master/maths/entropy.py)
394396
* [Eulers Totient](https://github.com/TheAlgorithms/Python/blob/master/maths/eulers_totient.py)
395397
* [Explicit Euler](https://github.com/TheAlgorithms/Python/blob/master/maths/explicit_euler.py)
@@ -681,6 +683,8 @@
681683
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_062/sol1.py)
682684
* Problem 063
683685
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_063/sol1.py)
686+
* Problem 064
687+
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_064/sol1.py)
684688
* Problem 065
685689
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_065/sol1.py)
686690
* Problem 067
@@ -694,6 +698,7 @@
694698
* [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_072/sol2.py)
695699
* Problem 074
696700
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_074/sol1.py)
701+
* [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_074/sol2.py)
697702
* Problem 075
698703
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_075/sol1.py)
699704
* Problem 076
@@ -726,12 +731,16 @@
726731
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_174/sol1.py)
727732
* Problem 191
728733
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_191/sol1.py)
734+
* Problem 203
735+
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_203/sol1.py)
729736
* Problem 206
730737
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_206/sol1.py)
731738
* Problem 207
732739
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_207/sol1.py)
733740
* Problem 234
734741
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_234/sol1.py)
742+
* Problem 301
743+
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_301/sol1.py)
735744
* Problem 551
736745
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_551/sol1.py)
737746

Diff for: searches/ternary_search.py

+132-67
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
Time Complexity : O(log3 N)
77
Space Complexity : O(1)
88
"""
9-
import sys
109
from typing import List
1110

1211
# This is the precision for this function which can be altered.
@@ -15,90 +14,156 @@
1514

1615

1716
# This is the linear search that will occur after the search space has become smaller.
18-
def lin_search(left: int, right: int, A: List[int], target: int):
19-
for i in range(left, right + 1):
20-
if A[i] == target:
21-
return i
2217

2318

24-
# This is the iterative method of the ternary search algorithm.
25-
def ite_ternary_search(A: List[int], target: int):
26-
left = 0
27-
right = len(A) - 1
28-
while True:
29-
if left < right:
19+
def lin_search(left: int, right: int, array: List[int], target: int) -> int:
20+
"""Perform linear search in list. Returns -1 if element is not found.
21+
22+
Parameters
23+
----------
24+
left : int
25+
left index bound.
26+
right : int
27+
right index bound.
28+
array : List[int]
29+
List of elements to be searched on
30+
target : int
31+
Element that is searched
32+
33+
Returns
34+
-------
35+
int
36+
index of element that is looked for.
37+
38+
Examples
39+
--------
40+
>>> lin_search(0, 4, [4, 5, 6, 7], 7)
41+
3
42+
>>> lin_search(0, 3, [4, 5, 6, 7], 7)
43+
-1
44+
>>> lin_search(0, 2, [-18, 2], -18)
45+
0
46+
>>> lin_search(0, 1, [5], 5)
47+
0
48+
>>> lin_search(0, 3, ['a', 'c', 'd'], 'c')
49+
1
50+
>>> lin_search(0, 3, [.1, .4 , -.1], .1)
51+
0
52+
>>> lin_search(0, 3, [.1, .4 , -.1], -.1)
53+
2
54+
"""
55+
for i in range(left, right):
56+
if array[i] == target:
57+
return i
58+
return -1
59+
60+
61+
def ite_ternary_search(array: List[int], target: int) -> int:
62+
"""Iterative method of the ternary search algorithm.
63+
>>> test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42]
64+
>>> ite_ternary_search(test_list, 3)
65+
-1
66+
>>> ite_ternary_search(test_list, 13)
67+
4
68+
>>> ite_ternary_search([4, 5, 6, 7], 4)
69+
0
70+
>>> ite_ternary_search([4, 5, 6, 7], -10)
71+
-1
72+
>>> ite_ternary_search([-18, 2], -18)
73+
0
74+
>>> ite_ternary_search([5], 5)
75+
0
76+
>>> ite_ternary_search(['a', 'c', 'd'], 'c')
77+
1
78+
>>> ite_ternary_search(['a', 'c', 'd'], 'f')
79+
-1
80+
>>> ite_ternary_search([], 1)
81+
-1
82+
>>> ite_ternary_search([.1, .4 , -.1], .1)
83+
0
84+
"""
3085

31-
if right - left < precision:
32-
return lin_search(left, right, A, target)
86+
left = 0
87+
right = len(array)
88+
while left <= right:
89+
if right - left < precision:
90+
return lin_search(left, right, array, target)
3391

34-
oneThird = (left + right) / 3 + 1
35-
twoThird = 2 * (left + right) / 3 + 1
92+
one_third = (left + right) / 3 + 1
93+
two_third = 2 * (left + right) / 3 + 1
3694

37-
if A[oneThird] == target:
38-
return oneThird
39-
elif A[twoThird] == target:
40-
return twoThird
95+
if array[one_third] == target:
96+
return one_third
97+
elif array[two_third] == target:
98+
return two_third
4199

42-
elif target < A[oneThird]:
43-
right = oneThird - 1
44-
elif A[twoThird] < target:
45-
left = twoThird + 1
100+
elif target < array[one_third]:
101+
right = one_third - 1
102+
elif array[two_third] < target:
103+
left = two_third + 1
46104

47-
else:
48-
left = oneThird + 1
49-
right = twoThird - 1
50105
else:
51-
return None
52106

53-
54-
# This is the recursive method of the ternary search algorithm.
55-
def rec_ternary_search(left: int, right: int, A: List[int], target: int):
107+
left = one_third + 1
108+
right = two_third - 1
109+
else:
110+
return -1
111+
112+
113+
def rec_ternary_search(left: int, right: int, array: List[int], target: int) -> int:
114+
"""Recursive method of the ternary search algorithm.
115+
116+
>>> test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42]
117+
>>> rec_ternary_search(0, len(test_list), test_list, 3)
118+
-1
119+
>>> rec_ternary_search(4, len(test_list), test_list, 42)
120+
8
121+
>>> rec_ternary_search(0, 2, [4, 5, 6, 7], 4)
122+
0
123+
>>> rec_ternary_search(0, 3, [4, 5, 6, 7], -10)
124+
-1
125+
>>> rec_ternary_search(0, 1, [-18, 2], -18)
126+
0
127+
>>> rec_ternary_search(0, 1, [5], 5)
128+
0
129+
>>> rec_ternary_search(0, 2, ['a', 'c', 'd'], 'c')
130+
1
131+
>>> rec_ternary_search(0, 2, ['a', 'c', 'd'], 'f')
132+
-1
133+
>>> rec_ternary_search(0, 0, [], 1)
134+
-1
135+
>>> rec_ternary_search(0, 3, [.1, .4 , -.1], .1)
136+
0
137+
"""
56138
if left < right:
57-
58139
if right - left < precision:
59-
return lin_search(left, right, A, target)
60-
61-
oneThird = (left + right) / 3 + 1
62-
twoThird = 2 * (left + right) / 3 + 1
63-
64-
if A[oneThird] == target:
65-
return oneThird
66-
elif A[twoThird] == target:
67-
return twoThird
68-
69-
elif target < A[oneThird]:
70-
return rec_ternary_search(left, oneThird - 1, A, target)
71-
elif A[twoThird] < target:
72-
return rec_ternary_search(twoThird + 1, right, A, target)
73-
140+
return lin_search(left, right, array, target)
141+
one_third = (left + right) / 3 + 1
142+
two_third = 2 * (left + right) / 3 + 1
143+
144+
if array[one_third] == target:
145+
return one_third
146+
elif array[two_third] == target:
147+
return two_third
148+
149+
elif target < array[one_third]:
150+
return rec_ternary_search(left, one_third - 1, array, target)
151+
elif array[two_third] < target:
152+
return rec_ternary_search(two_third + 1, right, array, target)
74153
else:
75-
return rec_ternary_search(oneThird + 1, twoThird - 1, A, target)
154+
return rec_ternary_search(one_third + 1, two_third - 1, array, target)
76155
else:
77-
return None
78-
79-
80-
# This function is to check if the array is sorted.
81-
def __assert_sorted(collection: List[int]) -> bool:
82-
if collection != sorted(collection):
83-
raise ValueError("Collection must be sorted")
84-
return True
156+
return -1
85157

86158

87159
if __name__ == "__main__":
88-
user_input = input("Enter numbers separated by coma:\n").strip()
89-
collection = [int(item) for item in user_input.split(",")]
90-
91-
try:
92-
__assert_sorted(collection)
93-
except ValueError:
94-
sys.exit("Sequence must be sorted to apply the ternary search")
95-
96-
target_input = input("Enter a single number to be found in the list:\n")
97-
target = int(target_input)
160+
user_input = input("Enter numbers separated by comma:\n").strip()
161+
collection = [int(item.strip()) for item in user_input.split(",")]
162+
assert collection == sorted(collection), f"List must be ordered.\n{collection}."
163+
target = int(input("Enter the number to be found in the list:\n").strip())
98164
result1 = ite_ternary_search(collection, target)
99165
result2 = rec_ternary_search(0, len(collection) - 1, collection, target)
100-
101-
if result2 is not None:
166+
if result2 != -1:
102167
print(f"Iterative search: {target} found at positions: {result1}")
103168
print(f"Recursive search: {target} found at positions: {result2}")
104169
else:

0 commit comments

Comments
 (0)