From 4808d620850e5b4fd87b4f4ec7312cb5b7354360 Mon Sep 17 00:00:00 2001 From: Vineet Kumar <108144301+whyvineet@users.noreply.github.com> Date: Wed, 2 Oct 2024 12:26:29 +0530 Subject: [PATCH 1/6] Implemented Exponential Search with binary search for improved performance on large sorted arrays. --- searches/Exponential_Search.py | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 searches/Exponential_Search.py diff --git a/searches/Exponential_Search.py b/searches/Exponential_Search.py new file mode 100644 index 000000000000..3df0e9dcb413 --- /dev/null +++ b/searches/Exponential_Search.py @@ -0,0 +1,42 @@ +# Python program to perform Exponential Search +from bisect import bisect_left + +# Binary search function +def binary_search(arr, left, right, target): + while left <= right: + mid = left + (right - left) // 2 + if arr[mid] == target: + return mid + elif arr[mid] < target: + left = mid + 1 + else: + right = mid - 1 + return -1 + +# Exponential search function +def exponential_search(arr, target): + n = len(arr) + + # If the target is at the first position + if arr[0] == target: + return 0 + + # Find the range for binary search by repeatedly doubling the index + i = 1 + while i < n and arr[i] <= target: + i *= 2 + + # Perform binary search within the found range + return binary_search(arr, i // 2, min(i, n - 1), target) + +# Example usage +if __name__ == "__main__": + arr = [2, 3, 4, 10, 40, 50, 60, 70, 80, 90, 100] + target = 10 + + result = exponential_search(arr, target) + + if result != -1: + print(f"Element found at index {result}") + else: + print("Element not found in the array") From ec85644e6e8446c4060e7cf554928c616af1e419 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2024 06:58:57 +0000 Subject: [PATCH 2/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- searches/Exponential_Search.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/searches/Exponential_Search.py b/searches/Exponential_Search.py index 3df0e9dcb413..30bfb3985cd4 100644 --- a/searches/Exponential_Search.py +++ b/searches/Exponential_Search.py @@ -1,6 +1,7 @@ # Python program to perform Exponential Search from bisect import bisect_left + # Binary search function def binary_search(arr, left, right, target): while left <= right: @@ -13,6 +14,7 @@ def binary_search(arr, left, right, target): right = mid - 1 return -1 + # Exponential search function def exponential_search(arr, target): n = len(arr) @@ -29,6 +31,7 @@ def exponential_search(arr, target): # Perform binary search within the found range return binary_search(arr, i // 2, min(i, n - 1), target) + # Example usage if __name__ == "__main__": arr = [2, 3, 4, 10, 40, 50, 60, 70, 80, 90, 100] From e3d13d3938228ad55b2a89f41245fdbdcec61824 Mon Sep 17 00:00:00 2001 From: Vineet Kumar <108144301+whyvineet@users.noreply.github.com> Date: Wed, 2 Oct 2024 12:33:14 +0530 Subject: [PATCH 3/6] Added type hints and doctests for binary_search and exponential_search functions. Improved code documentation and ensured testability. --- searches/Exponential_Search.py | 50 +++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/searches/Exponential_Search.py b/searches/Exponential_Search.py index 30bfb3985cd4..dd7e07b135af 100644 --- a/searches/Exponential_Search.py +++ b/searches/Exponential_Search.py @@ -1,9 +1,24 @@ -# Python program to perform Exponential Search -from bisect import bisect_left +from typing import List +def binary_search(arr: List[int], left: int, right: int, target: int) -> int: + """ + Perform binary search on a sorted array. -# Binary search function -def binary_search(arr, left, right, target): + Parameters: + arr (List[int]): The sorted list in which to search. + left (int): The starting index for the search range. + right (int): The ending index for the search range. + target (int): The value to search for. + + Returns: + int: The index of the target if found, otherwise -1. + + Doctest: + >>> binary_search([2, 3, 4, 10, 40], 0, 4, 10) + 3 + >>> binary_search([2, 3, 4, 10, 40], 0, 4, 5) + -1 + """ while left <= right: mid = left + (right - left) // 2 if arr[mid] == target: @@ -15,8 +30,27 @@ def binary_search(arr, left, right, target): return -1 -# Exponential search function -def exponential_search(arr, target): +def exponential_search(arr: List[int], target: int) -> int: + """ + Perform exponential search on a sorted array. + + Exponential search first finds a range where the target may reside + by repeatedly doubling the index. It then performs binary search + within that range. + + Parameters: + arr (List[int]): The sorted list in which to search. + target (int): The value to search for. + + Returns: + int: The index of the target if found, otherwise -1. + + Doctest: + >>> exponential_search([2, 3, 4, 10, 40, 50, 60, 70, 80, 90, 100], 10) + 3 + >>> exponential_search([2, 3, 4, 10, 40, 50, 60, 70, 80, 90, 100], 5) + -1 + """ n = len(arr) # If the target is at the first position @@ -32,8 +66,10 @@ def exponential_search(arr, target): return binary_search(arr, i // 2, min(i, n - 1), target) -# Example usage if __name__ == "__main__": + """ + Example to demonstrate the usage of exponential_search function. + """ arr = [2, 3, 4, 10, 40, 50, 60, 70, 80, 90, 100] target = 10 From e38e6264918cbff7e3d186cde522ce26de2e859f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2024 07:03:51 +0000 Subject: [PATCH 4/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- searches/Exponential_Search.py | 1 + 1 file changed, 1 insertion(+) diff --git a/searches/Exponential_Search.py b/searches/Exponential_Search.py index dd7e07b135af..efbf8d468248 100644 --- a/searches/Exponential_Search.py +++ b/searches/Exponential_Search.py @@ -1,5 +1,6 @@ from typing import List + def binary_search(arr: List[int], left: int, right: int, target: int) -> int: """ Perform binary search on a sorted array. From aa1eee1b4051b4b8cb3c0ce679289bdb4303cad3 Mon Sep 17 00:00:00 2001 From: Vineet Kumar <108144301+whyvineet@users.noreply.github.com> Date: Wed, 2 Oct 2024 12:42:49 +0530 Subject: [PATCH 5/6] Update and rename Exponential_Search.py to exponential_search.py --- searches/Exponential_Search.py | 82 ------------------------ searches/exponential_search.py | 112 +++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 82 deletions(-) delete mode 100644 searches/Exponential_Search.py create mode 100644 searches/exponential_search.py diff --git a/searches/Exponential_Search.py b/searches/Exponential_Search.py deleted file mode 100644 index efbf8d468248..000000000000 --- a/searches/Exponential_Search.py +++ /dev/null @@ -1,82 +0,0 @@ -from typing import List - - -def binary_search(arr: List[int], left: int, right: int, target: int) -> int: - """ - Perform binary search on a sorted array. - - Parameters: - arr (List[int]): The sorted list in which to search. - left (int): The starting index for the search range. - right (int): The ending index for the search range. - target (int): The value to search for. - - Returns: - int: The index of the target if found, otherwise -1. - - Doctest: - >>> binary_search([2, 3, 4, 10, 40], 0, 4, 10) - 3 - >>> binary_search([2, 3, 4, 10, 40], 0, 4, 5) - -1 - """ - while left <= right: - mid = left + (right - left) // 2 - if arr[mid] == target: - return mid - elif arr[mid] < target: - left = mid + 1 - else: - right = mid - 1 - return -1 - - -def exponential_search(arr: List[int], target: int) -> int: - """ - Perform exponential search on a sorted array. - - Exponential search first finds a range where the target may reside - by repeatedly doubling the index. It then performs binary search - within that range. - - Parameters: - arr (List[int]): The sorted list in which to search. - target (int): The value to search for. - - Returns: - int: The index of the target if found, otherwise -1. - - Doctest: - >>> exponential_search([2, 3, 4, 10, 40, 50, 60, 70, 80, 90, 100], 10) - 3 - >>> exponential_search([2, 3, 4, 10, 40, 50, 60, 70, 80, 90, 100], 5) - -1 - """ - n = len(arr) - - # If the target is at the first position - if arr[0] == target: - return 0 - - # Find the range for binary search by repeatedly doubling the index - i = 1 - while i < n and arr[i] <= target: - i *= 2 - - # Perform binary search within the found range - return binary_search(arr, i // 2, min(i, n - 1), target) - - -if __name__ == "__main__": - """ - Example to demonstrate the usage of exponential_search function. - """ - arr = [2, 3, 4, 10, 40, 50, 60, 70, 80, 90, 100] - target = 10 - - result = exponential_search(arr, target) - - if result != -1: - print(f"Element found at index {result}") - else: - print("Element not found in the array") diff --git a/searches/exponential_search.py b/searches/exponential_search.py new file mode 100644 index 000000000000..10e4979a64c3 --- /dev/null +++ b/searches/exponential_search.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 + +""" +Pure Python implementation of exponential search algorithm + +For more information, see the Wikipedia page: +https://en.wikipedia.org/wiki/Exponential_search + +For doctests run the following command: +python3 -m doctest -v exponential_search.py + +For manual testing run: +python3 exponential_search.py +""" + +from __future__ import annotations + + +def binary_search_by_recursion( + sorted_collection: list[int], item: int, left: int = 0, right: int = -1 +) -> int: + """Pure implementation of binary search algorithm in Python using recursion + + Be careful: the collection must be ascending sorted otherwise, the result will be + unpredictable. + + :param sorted_collection: some ascending sorted collection with comparable items + :param item: item value to search + :param left: starting index for the search + :param right: ending index for the search + :return: index of the found item or -1 if the item is not found + + Examples: + >>> binary_search_by_recursion([0, 5, 7, 10, 15], 0, 0, 4) + 0 + >>> binary_search_by_recursion([0, 5, 7, 10, 15], 15, 0, 4) + 4 + >>> binary_search_by_recursion([0, 5, 7, 10, 15], 5, 0, 4) + 1 + >>> binary_search_by_recursion([0, 5, 7, 10, 15], 6, 0, 4) + -1 + """ + if right < 0: + right = len(sorted_collection) - 1 + if list(sorted_collection) != sorted(sorted_collection): + raise ValueError("sorted_collection must be sorted in ascending order") + if right < left: + return -1 + + midpoint = left + (right - left) // 2 + + if sorted_collection[midpoint] == item: + return midpoint + elif sorted_collection[midpoint] > item: + return binary_search_by_recursion(sorted_collection, item, left, midpoint - 1) + else: + return binary_search_by_recursion(sorted_collection, item, midpoint + 1, right) + + +def exponential_search(sorted_collection: list[int], item: int) -> int: + """ + Pure implementation of an exponential search algorithm in Python. + For more information, refer to: + https://en.wikipedia.org/wiki/Exponential_search + + Be careful: the collection must be ascending sorted, otherwise the result will be + unpredictable. + + :param sorted_collection: some ascending sorted collection with comparable items + :param item: item value to search + :return: index of the found item or -1 if the item is not found + + The time complexity of this algorithm is O(log i) where i is the index of the item. + + Examples: + >>> exponential_search([0, 5, 7, 10, 15], 0) + 0 + >>> exponential_search([0, 5, 7, 10, 15], 15) + 4 + >>> exponential_search([0, 5, 7, 10, 15], 5) + 1 + >>> exponential_search([0, 5, 7, 10, 15], 6) + -1 + """ + if list(sorted_collection) != sorted(sorted_collection): + raise ValueError("sorted_collection must be sorted in ascending order") + + if sorted_collection[0] == item: + return 0 + + bound = 1 + while bound < len(sorted_collection) and sorted_collection[bound] < item: + bound *= 2 + + left = bound // 2 + right = min(bound, len(sorted_collection) - 1) + return binary_search_by_recursion(sorted_collection, item, left, right) + + +if __name__ == "__main__": + import doctest + doctest.testmod() + + # Manual testing + user_input = input("Enter numbers separated by commas: ").strip() + collection = sorted(int(item) for item in user_input.split(",")) + target = int(input("Enter a number to search for: ")) + result = exponential_search(sorted_collection=collection, item=target) + if result == -1: + print(f"{target} was not found in {collection}.") + else: + print(f"{target} was found at index {result} in {collection}.") From afce723b83c4260ba873a09b885b042f64f9ab8b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2024 07:14:36 +0000 Subject: [PATCH 6/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- searches/exponential_search.py | 1 + 1 file changed, 1 insertion(+) diff --git a/searches/exponential_search.py b/searches/exponential_search.py index 10e4979a64c3..ed09b14e101c 100644 --- a/searches/exponential_search.py +++ b/searches/exponential_search.py @@ -99,6 +99,7 @@ def exponential_search(sorted_collection: list[int], item: int) -> int: if __name__ == "__main__": import doctest + doctest.testmod() # Manual testing