Fix: Multiple errors in fibonacci search. (#2659)

* Fix: Multiple errors in fibonacci search.

- Test lists were not ordered, this is required for Fibonacci search
- Place documentation of function inside function
- Create multiple different tests including, float, char and negatives
- Add type hints in line with #2128

* Fix: sort of modules and delete typehint.

* Apply suggestions from code review

Co-authored-by: Dhruv <dhruvmanila@gmail.com>

* Correct invocation of lru_cache.

* Add check for input in fibonacci and doctest.

* Correct typehints to comply to numpy style.

* Correct ValueError to TypeError.

Co-authored-by: Dhruv <dhruvmanila@gmail.com>

* Correct doctest for TypeError.

* Rename  single letter names as mentioned in CONTRIBUTING.md.

* Fix: Bug in big lists.

* Remove print(.) in doctests.

* Refactor iterator to while loop.

* Update searches/fibonacci_search.py

Co-authored-by: Dhruv <dhruvmanila@gmail.com>
This commit is contained in:
poloso 2020-10-07 22:36:19 -05:00 committed by GitHub
parent ef53bbdf5a
commit 21581eae3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,51 +1,129 @@
# run using python fibonacci_search.py -v
""" """
@params This is pure Python implementation of fibonacci search.
arr: input array
val: the value to be searched Resources used:
output: the index of element in the array or -1 if not found https://en.wikipedia.org/wiki/Fibonacci_search_technique
return 0 if input array is empty
For doctests run following command:
python3 -m doctest -v fibonacci_search.py
For manual testing run:
python3 fibonacci_search.py
""" """
from functools import lru_cache
def fibonacci_search(arr, val): @lru_cache()
def fibonacci(k: int) -> int:
"""Finds fibonacci number in index k.
""" Parameters
>>> fibonacci_search([1,6,7,0,0,0], 6) ----------
1 k :
>>> fibonacci_search([1,-1, 5, 2, 9], 10) Index of fibonacci.
-1
>>> fibonacci_search([], 9) Returns
-------
int
Fibonacci number in position k.
>>> fibonacci(0)
0 0
>>> fibonacci(2)
1
>>> fibonacci(5)
5
>>> fibonacci(15)
610
>>> fibonacci('a')
Traceback (most recent call last):
TypeError: k must be an integer.
>>> fibonacci(-5)
Traceback (most recent call last):
ValueError: k integer must be greater or equal to zero.
""" """
fib_N_2 = 0 if not isinstance(k, int):
fib_N_1 = 1 raise TypeError("k must be an integer.")
fibNext = fib_N_1 + fib_N_2 if k < 0:
length = len(arr) raise ValueError("k integer must be greater or equal to zero.")
if length == 0: if k == 0:
return 0 return 0
while fibNext < len(arr): elif k == 1:
fib_N_2 = fib_N_1 return 1
fib_N_1 = fibNext else:
fibNext = fib_N_1 + fib_N_2 return fibonacci(k - 1) + fibonacci(k - 2)
index = -1
while fibNext > 1:
i = min(index + fib_N_2, (length - 1)) def fibonacci_search(arr: list, val: int) -> int:
if arr[i] < val: """A pure Python implementation of a fibonacci search algorithm.
fibNext = fib_N_1
fib_N_1 = fib_N_2 Parameters
fib_N_2 = fibNext - fib_N_1 ----------
index = i arr
elif arr[i] > val: List of sorted elements.
fibNext = fib_N_2 val
fib_N_1 = fib_N_1 - fib_N_2 Element to search in list.
fib_N_2 = fibNext - fib_N_1
else: Returns
return i -------
if (fib_N_1 and index < length - 1) and (arr[index + 1] == val): int
return index + 1 The index of the element in the array.
return -1 -1 if the element is not found.
>>> fibonacci_search([4, 5, 6, 7], 4)
0
>>> fibonacci_search([4, 5, 6, 7], -10)
-1
>>> fibonacci_search([-18, 2], -18)
0
>>> fibonacci_search([5], 5)
0
>>> fibonacci_search(['a', 'c', 'd'], 'c')
1
>>> fibonacci_search(['a', 'c', 'd'], 'f')
-1
>>> fibonacci_search([], 1)
-1
>>> fibonacci_search([.1, .4 , 7], .4)
1
>>> fibonacci_search([], 9)
-1
>>> fibonacci_search(list(range(100)), 63)
63
>>> fibonacci_search(list(range(100)), 99)
99
>>> fibonacci_search(list(range(-100, 100, 3)), -97)
1
>>> fibonacci_search(list(range(-100, 100, 3)), 0)
-1
>>> fibonacci_search(list(range(-100, 100, 5)), 0)
20
>>> fibonacci_search(list(range(-100, 100, 5)), 95)
39
"""
len_list = len(arr)
# Find m such that F_m >= n where F_i is the i_th fibonacci number.
i = 0
while True:
if fibonacci(i) >= len_list:
fibb_k = i
break
i += 1
offset = 0
while fibb_k > 0:
index_k = min(
offset + fibonacci(fibb_k - 1), len_list - 1
) # Prevent out of range
item_k_1 = arr[index_k]
if item_k_1 == val:
return index_k
elif val < item_k_1:
fibb_k -= 1
elif val > item_k_1:
offset += fibonacci(fibb_k - 1)
fibb_k -= 2
else:
return -1
if __name__ == "__main__": if __name__ == "__main__":