mirror of
https://github.com/TheAlgorithms/Python.git
synced 2025-01-18 16:27:02 +00:00
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 <cclauss@me.com> * 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 <cclauss@me.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
This commit is contained in:
parent
ae4d7d4d04
commit
c6dd975389
|
@ -206,6 +206,7 @@
|
||||||
* [Heaps Algorithm](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/heaps_algorithm.py)
|
* [Heaps Algorithm](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/heaps_algorithm.py)
|
||||||
* [Heaps Algorithm Iterative](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/heaps_algorithm_iterative.py)
|
* [Heaps Algorithm Iterative](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/heaps_algorithm_iterative.py)
|
||||||
* [Inversions](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/inversions.py)
|
* [Inversions](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/inversions.py)
|
||||||
|
* [Kth Order Statistic](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/kth_order_statistic.py)
|
||||||
* [Max Subarray Sum](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/max_subarray_sum.py)
|
* [Max Subarray Sum](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/max_subarray_sum.py)
|
||||||
* [Mergesort](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/mergesort.py)
|
* [Mergesort](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/mergesort.py)
|
||||||
* [Power](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/power.py)
|
* [Power](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/power.py)
|
||||||
|
@ -390,6 +391,7 @@
|
||||||
* [Chudnovsky Algorithm](https://github.com/TheAlgorithms/Python/blob/master/maths/chudnovsky_algorithm.py)
|
* [Chudnovsky Algorithm](https://github.com/TheAlgorithms/Python/blob/master/maths/chudnovsky_algorithm.py)
|
||||||
* [Collatz Sequence](https://github.com/TheAlgorithms/Python/blob/master/maths/collatz_sequence.py)
|
* [Collatz Sequence](https://github.com/TheAlgorithms/Python/blob/master/maths/collatz_sequence.py)
|
||||||
* [Combinations](https://github.com/TheAlgorithms/Python/blob/master/maths/combinations.py)
|
* [Combinations](https://github.com/TheAlgorithms/Python/blob/master/maths/combinations.py)
|
||||||
|
* [Decimal Isolate](https://github.com/TheAlgorithms/Python/blob/master/maths/decimal_isolate.py)
|
||||||
* [Entropy](https://github.com/TheAlgorithms/Python/blob/master/maths/entropy.py)
|
* [Entropy](https://github.com/TheAlgorithms/Python/blob/master/maths/entropy.py)
|
||||||
* [Eulers Totient](https://github.com/TheAlgorithms/Python/blob/master/maths/eulers_totient.py)
|
* [Eulers Totient](https://github.com/TheAlgorithms/Python/blob/master/maths/eulers_totient.py)
|
||||||
* [Explicit Euler](https://github.com/TheAlgorithms/Python/blob/master/maths/explicit_euler.py)
|
* [Explicit Euler](https://github.com/TheAlgorithms/Python/blob/master/maths/explicit_euler.py)
|
||||||
|
@ -681,6 +683,8 @@
|
||||||
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_062/sol1.py)
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_062/sol1.py)
|
||||||
* Problem 063
|
* Problem 063
|
||||||
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_063/sol1.py)
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_063/sol1.py)
|
||||||
|
* Problem 064
|
||||||
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_064/sol1.py)
|
||||||
* Problem 065
|
* Problem 065
|
||||||
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_065/sol1.py)
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_065/sol1.py)
|
||||||
* Problem 067
|
* Problem 067
|
||||||
|
@ -694,6 +698,7 @@
|
||||||
* [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_072/sol2.py)
|
* [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_072/sol2.py)
|
||||||
* Problem 074
|
* Problem 074
|
||||||
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_074/sol1.py)
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_074/sol1.py)
|
||||||
|
* [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_074/sol2.py)
|
||||||
* Problem 075
|
* Problem 075
|
||||||
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_075/sol1.py)
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_075/sol1.py)
|
||||||
* Problem 076
|
* Problem 076
|
||||||
|
@ -726,12 +731,16 @@
|
||||||
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_174/sol1.py)
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_174/sol1.py)
|
||||||
* Problem 191
|
* Problem 191
|
||||||
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_191/sol1.py)
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_191/sol1.py)
|
||||||
|
* Problem 203
|
||||||
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_203/sol1.py)
|
||||||
* Problem 206
|
* Problem 206
|
||||||
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_206/sol1.py)
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_206/sol1.py)
|
||||||
* Problem 207
|
* Problem 207
|
||||||
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_207/sol1.py)
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_207/sol1.py)
|
||||||
* Problem 234
|
* Problem 234
|
||||||
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_234/sol1.py)
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_234/sol1.py)
|
||||||
|
* Problem 301
|
||||||
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_301/sol1.py)
|
||||||
* Problem 551
|
* Problem 551
|
||||||
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_551/sol1.py)
|
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_551/sol1.py)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ This is a type of divide and conquer algorithm which divides the search space in
|
||||||
Time Complexity : O(log3 N)
|
Time Complexity : O(log3 N)
|
||||||
Space Complexity : O(1)
|
Space Complexity : O(1)
|
||||||
"""
|
"""
|
||||||
import sys
|
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
# This is the precision for this function which can be altered.
|
# This is the precision for this function which can be altered.
|
||||||
|
@ -15,90 +14,156 @@ precision = 10
|
||||||
|
|
||||||
|
|
||||||
# This is the linear search that will occur after the search space has become smaller.
|
# This is the linear search that will occur after the search space has become smaller.
|
||||||
def lin_search(left: int, right: int, A: List[int], target: int):
|
|
||||||
for i in range(left, right + 1):
|
|
||||||
if A[i] == target:
|
def lin_search(left: int, right: int, array: List[int], target: int) -> int:
|
||||||
|
"""Perform linear search in list. Returns -1 if element is not found.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
left : int
|
||||||
|
left index bound.
|
||||||
|
right : int
|
||||||
|
right index bound.
|
||||||
|
array : List[int]
|
||||||
|
List of elements to be searched on
|
||||||
|
target : int
|
||||||
|
Element that is searched
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
int
|
||||||
|
index of element that is looked for.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
>>> lin_search(0, 4, [4, 5, 6, 7], 7)
|
||||||
|
3
|
||||||
|
>>> lin_search(0, 3, [4, 5, 6, 7], 7)
|
||||||
|
-1
|
||||||
|
>>> lin_search(0, 2, [-18, 2], -18)
|
||||||
|
0
|
||||||
|
>>> lin_search(0, 1, [5], 5)
|
||||||
|
0
|
||||||
|
>>> lin_search(0, 3, ['a', 'c', 'd'], 'c')
|
||||||
|
1
|
||||||
|
>>> lin_search(0, 3, [.1, .4 , -.1], .1)
|
||||||
|
0
|
||||||
|
>>> lin_search(0, 3, [.1, .4 , -.1], -.1)
|
||||||
|
2
|
||||||
|
"""
|
||||||
|
for i in range(left, right):
|
||||||
|
if array[i] == target:
|
||||||
return i
|
return i
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
||||||
# This is the iterative method of the ternary search algorithm.
|
def ite_ternary_search(array: List[int], target: int) -> int:
|
||||||
def ite_ternary_search(A: List[int], target: int):
|
"""Iterative method of the ternary search algorithm.
|
||||||
|
>>> test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42]
|
||||||
|
>>> ite_ternary_search(test_list, 3)
|
||||||
|
-1
|
||||||
|
>>> ite_ternary_search(test_list, 13)
|
||||||
|
4
|
||||||
|
>>> ite_ternary_search([4, 5, 6, 7], 4)
|
||||||
|
0
|
||||||
|
>>> ite_ternary_search([4, 5, 6, 7], -10)
|
||||||
|
-1
|
||||||
|
>>> ite_ternary_search([-18, 2], -18)
|
||||||
|
0
|
||||||
|
>>> ite_ternary_search([5], 5)
|
||||||
|
0
|
||||||
|
>>> ite_ternary_search(['a', 'c', 'd'], 'c')
|
||||||
|
1
|
||||||
|
>>> ite_ternary_search(['a', 'c', 'd'], 'f')
|
||||||
|
-1
|
||||||
|
>>> ite_ternary_search([], 1)
|
||||||
|
-1
|
||||||
|
>>> ite_ternary_search([.1, .4 , -.1], .1)
|
||||||
|
0
|
||||||
|
"""
|
||||||
|
|
||||||
left = 0
|
left = 0
|
||||||
right = len(A) - 1
|
right = len(array)
|
||||||
while True:
|
while left <= right:
|
||||||
if left < right:
|
|
||||||
|
|
||||||
if right - left < precision:
|
|
||||||
return lin_search(left, right, A, target)
|
|
||||||
|
|
||||||
oneThird = (left + right) / 3 + 1
|
|
||||||
twoThird = 2 * (left + right) / 3 + 1
|
|
||||||
|
|
||||||
if A[oneThird] == target:
|
|
||||||
return oneThird
|
|
||||||
elif A[twoThird] == target:
|
|
||||||
return twoThird
|
|
||||||
|
|
||||||
elif target < A[oneThird]:
|
|
||||||
right = oneThird - 1
|
|
||||||
elif A[twoThird] < target:
|
|
||||||
left = twoThird + 1
|
|
||||||
|
|
||||||
else:
|
|
||||||
left = oneThird + 1
|
|
||||||
right = twoThird - 1
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
# This is the recursive method of the ternary search algorithm.
|
|
||||||
def rec_ternary_search(left: int, right: int, A: List[int], target: int):
|
|
||||||
if left < right:
|
|
||||||
|
|
||||||
if right - left < precision:
|
if right - left < precision:
|
||||||
return lin_search(left, right, A, target)
|
return lin_search(left, right, array, target)
|
||||||
|
|
||||||
oneThird = (left + right) / 3 + 1
|
one_third = (left + right) / 3 + 1
|
||||||
twoThird = 2 * (left + right) / 3 + 1
|
two_third = 2 * (left + right) / 3 + 1
|
||||||
|
|
||||||
if A[oneThird] == target:
|
if array[one_third] == target:
|
||||||
return oneThird
|
return one_third
|
||||||
elif A[twoThird] == target:
|
elif array[two_third] == target:
|
||||||
return twoThird
|
return two_third
|
||||||
|
|
||||||
elif target < A[oneThird]:
|
elif target < array[one_third]:
|
||||||
return rec_ternary_search(left, oneThird - 1, A, target)
|
right = one_third - 1
|
||||||
elif A[twoThird] < target:
|
elif array[two_third] < target:
|
||||||
return rec_ternary_search(twoThird + 1, right, A, target)
|
left = two_third + 1
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return rec_ternary_search(oneThird + 1, twoThird - 1, A, target)
|
|
||||||
|
left = one_third + 1
|
||||||
|
right = two_third - 1
|
||||||
else:
|
else:
|
||||||
return None
|
return -1
|
||||||
|
|
||||||
|
|
||||||
# This function is to check if the array is sorted.
|
def rec_ternary_search(left: int, right: int, array: List[int], target: int) -> int:
|
||||||
def __assert_sorted(collection: List[int]) -> bool:
|
"""Recursive method of the ternary search algorithm.
|
||||||
if collection != sorted(collection):
|
|
||||||
raise ValueError("Collection must be sorted")
|
>>> test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42]
|
||||||
return True
|
>>> rec_ternary_search(0, len(test_list), test_list, 3)
|
||||||
|
-1
|
||||||
|
>>> rec_ternary_search(4, len(test_list), test_list, 42)
|
||||||
|
8
|
||||||
|
>>> rec_ternary_search(0, 2, [4, 5, 6, 7], 4)
|
||||||
|
0
|
||||||
|
>>> rec_ternary_search(0, 3, [4, 5, 6, 7], -10)
|
||||||
|
-1
|
||||||
|
>>> rec_ternary_search(0, 1, [-18, 2], -18)
|
||||||
|
0
|
||||||
|
>>> rec_ternary_search(0, 1, [5], 5)
|
||||||
|
0
|
||||||
|
>>> rec_ternary_search(0, 2, ['a', 'c', 'd'], 'c')
|
||||||
|
1
|
||||||
|
>>> rec_ternary_search(0, 2, ['a', 'c', 'd'], 'f')
|
||||||
|
-1
|
||||||
|
>>> rec_ternary_search(0, 0, [], 1)
|
||||||
|
-1
|
||||||
|
>>> rec_ternary_search(0, 3, [.1, .4 , -.1], .1)
|
||||||
|
0
|
||||||
|
"""
|
||||||
|
if left < right:
|
||||||
|
if right - left < precision:
|
||||||
|
return lin_search(left, right, array, target)
|
||||||
|
one_third = (left + right) / 3 + 1
|
||||||
|
two_third = 2 * (left + right) / 3 + 1
|
||||||
|
|
||||||
|
if array[one_third] == target:
|
||||||
|
return one_third
|
||||||
|
elif array[two_third] == target:
|
||||||
|
return two_third
|
||||||
|
|
||||||
|
elif target < array[one_third]:
|
||||||
|
return rec_ternary_search(left, one_third - 1, array, target)
|
||||||
|
elif array[two_third] < target:
|
||||||
|
return rec_ternary_search(two_third + 1, right, array, target)
|
||||||
|
else:
|
||||||
|
return rec_ternary_search(one_third + 1, two_third - 1, array, target)
|
||||||
|
else:
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
user_input = input("Enter numbers separated by coma:\n").strip()
|
user_input = input("Enter numbers separated by comma:\n").strip()
|
||||||
collection = [int(item) for item in user_input.split(",")]
|
collection = [int(item.strip()) for item in user_input.split(",")]
|
||||||
|
assert collection == sorted(collection), f"List must be ordered.\n{collection}."
|
||||||
try:
|
target = int(input("Enter the number to be found in the list:\n").strip())
|
||||||
__assert_sorted(collection)
|
|
||||||
except ValueError:
|
|
||||||
sys.exit("Sequence must be sorted to apply the ternary search")
|
|
||||||
|
|
||||||
target_input = input("Enter a single number to be found in the list:\n")
|
|
||||||
target = int(target_input)
|
|
||||||
result1 = ite_ternary_search(collection, target)
|
result1 = ite_ternary_search(collection, target)
|
||||||
result2 = rec_ternary_search(0, len(collection) - 1, collection, target)
|
result2 = rec_ternary_search(0, len(collection) - 1, collection, target)
|
||||||
|
if result2 != -1:
|
||||||
if result2 is not None:
|
|
||||||
print(f"Iterative search: {target} found at positions: {result1}")
|
print(f"Iterative search: {target} found at positions: {result1}")
|
||||||
print(f"Recursive search: {target} found at positions: {result2}")
|
print(f"Recursive search: {target} found at positions: {result2}")
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user