From d3cf0d1841d196f34d305badfa287519be53d916 Mon Sep 17 00:00:00 2001 From: Umair Kamran Date: Sat, 3 Oct 2020 13:01:41 +0500 Subject: [PATCH 1/5] Chore: Added type hints to searches/binary_search.py --- searches/binary_search.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/searches/binary_search.py b/searches/binary_search.py index d0f6296168fa..231d1b9f4f64 100644 --- a/searches/binary_search.py +++ b/searches/binary_search.py @@ -10,9 +10,12 @@ python binary_search.py """ import bisect +from typing import List, Optional -def bisect_left(sorted_collection, item, lo=0, hi=None): +def bisect_left( + sorted_collection: List[int], item: int, lo: int = 0, hi: Optional[int] = None +) -> int: """ Locates the first element in a sorted array that is larger or equal to a given value. @@ -56,7 +59,9 @@ def bisect_left(sorted_collection, item, lo=0, hi=None): return lo -def bisect_right(sorted_collection, item, lo=0, hi=None): +def bisect_right( + sorted_collection: List[int], item: int, lo: int = 0, hi: Optional[int] = None +) -> int: """ Locates the first element in a sorted array that is larger than a given value. @@ -99,7 +104,9 @@ def bisect_right(sorted_collection, item, lo=0, hi=None): return lo -def insort_left(sorted_collection, item, lo=0, hi=None): +def insort_left( + sorted_collection: List[int], item: int, lo: int = 0, hi: Optional[int] = None +) -> None: """ Inserts a given value into a sorted array before other values with the same value. @@ -140,7 +147,9 @@ def insort_left(sorted_collection, item, lo=0, hi=None): sorted_collection.insert(bisect_left(sorted_collection, item, lo, hi), item) -def insort_right(sorted_collection, item, lo=0, hi=None): +def insort_right( + sorted_collection: List[int], item: int, lo: int = 0, hi: Optional[int] = None +) -> None: """ Inserts a given value into a sorted array after other values with the same value. @@ -181,7 +190,7 @@ def insort_right(sorted_collection, item, lo=0, hi=None): sorted_collection.insert(bisect_right(sorted_collection, item, lo, hi), item) -def binary_search(sorted_collection, item): +def binary_search(sorted_collection: List[int], item: int) -> Optional[int]: """Pure implementation of binary search algorithm in Python Be careful collection must be ascending sorted, otherwise result will be @@ -219,7 +228,7 @@ def binary_search(sorted_collection, item): return None -def binary_search_std_lib(sorted_collection, item): +def binary_search_std_lib(sorted_collection, item) -> Optional[int]: """Pure implementation of binary search algorithm in Python using stdlib Be careful collection must be ascending sorted, otherwise result will be @@ -248,7 +257,9 @@ def binary_search_std_lib(sorted_collection, item): return None -def binary_search_by_recursion(sorted_collection, item, left, right): +def binary_search_by_recursion( + sorted_collection: List[int], item: int, left: int, right: int +) -> Optional[int]: """Pure implementation of binary search algorithm in Python by recursion @@ -286,7 +297,7 @@ def binary_search_by_recursion(sorted_collection, item, left, right): return binary_search_by_recursion(sorted_collection, item, midpoint + 1, right) -def __assert_sorted(collection): +def __assert_sorted(collection: List[int]) -> bool: """Check if collection is ascending sorted, if not - raises :py:class:`ValueError` :param collection: collection From 40b52c40940a8b7c7e5d6e1e7ed631b7e4a6973e Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 9 Dec 2020 14:09:42 +0100 Subject: [PATCH 2/5] Use -1 as the sentinal value --- searches/binary_search.py | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/searches/binary_search.py b/searches/binary_search.py index 231d1b9f4f64..d070df134af5 100644 --- a/searches/binary_search.py +++ b/searches/binary_search.py @@ -1,21 +1,19 @@ +#!/usr/bin/env python3 + """ This is pure Python implementation of binary search algorithms For doctests run following command: -python -m doctest -v binary_search.py -or python3 -m doctest -v binary_search.py For manual testing run: -python binary_search.py +python3 binary_search.py """ import bisect from typing import List, Optional -def bisect_left( - sorted_collection: List[int], item: int, lo: int = 0, hi: Optional[int] = None -) -> int: +def bisect_left(sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1) -> int: """ Locates the first element in a sorted array that is larger or equal to a given value. @@ -46,7 +44,7 @@ def bisect_left( >>> bisect_left([0, 5, 7, 10, 15], 6, 2) 2 """ - if hi is None: + if hi < 0: hi = len(sorted_collection) while lo < hi: @@ -59,9 +57,7 @@ def bisect_left( return lo -def bisect_right( - sorted_collection: List[int], item: int, lo: int = 0, hi: Optional[int] = None -) -> int: +def bisect_right(sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1) -> int: """ Locates the first element in a sorted array that is larger than a given value. @@ -91,7 +87,7 @@ def bisect_right( >>> bisect_right([0, 5, 7, 10, 15], 6, 2) 2 """ - if hi is None: + if hi < 0: hi = len(sorted_collection) while lo < hi: @@ -104,9 +100,7 @@ def bisect_right( return lo -def insort_left( - sorted_collection: List[int], item: int, lo: int = 0, hi: Optional[int] = None -) -> None: +def insort_left(sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1) -> None: """ Inserts a given value into a sorted array before other values with the same value. @@ -147,9 +141,7 @@ def insort_left( sorted_collection.insert(bisect_left(sorted_collection, item, lo, hi), item) -def insort_right( - sorted_collection: List[int], item: int, lo: int = 0, hi: Optional[int] = None -) -> None: +def insort_right(sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1) -> None: """ Inserts a given value into a sorted array after other values with the same value. @@ -311,10 +303,10 @@ def __assert_sorted(collection: List[int]) -> bool: >>> __assert_sorted([10, -1, 5]) Traceback (most recent call last): ... - ValueError: Collection must be ascending sorted + ValueError: Collection must be sorted in ascending order """ if collection != sorted(collection): - raise ValueError("Collection must be ascending sorted") + raise ValueError("Collection must be sorted in ascending order") return True @@ -323,15 +315,11 @@ def __assert_sorted(collection: List[int]) -> bool: user_input = input("Enter numbers separated by comma:\n").strip() collection = [int(item) for item in user_input.split(",")] - try: - __assert_sorted(collection) - except ValueError: - sys.exit("Sequence must be ascending sorted to apply binary search") - + __assert_sorted(collection) target_input = input("Enter a single number to be found in the list:\n") target = int(target_input) result = binary_search(collection, target) if result is not None: - print(f"{target} found at positions: {result}") + print(f"{target} was found at position: {result}") else: print("Not found") From 1081c577ecd2af601c45a0370e147d8945cc9a6e Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 9 Dec 2020 14:13:48 +0100 Subject: [PATCH 3/5] Wrap long lines --- searches/binary_search.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/searches/binary_search.py b/searches/binary_search.py index d070df134af5..6f17e2585614 100644 --- a/searches/binary_search.py +++ b/searches/binary_search.py @@ -13,7 +13,9 @@ from typing import List, Optional -def bisect_left(sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1) -> int: +def bisect_left( + sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1 +) -> int: """ Locates the first element in a sorted array that is larger or equal to a given value. @@ -57,7 +59,9 @@ def bisect_left(sorted_collection: List[int], item: int, lo: int = 0, hi: int = return lo -def bisect_right(sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1) -> int: +def bisect_right( + sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1 +) -> int: """ Locates the first element in a sorted array that is larger than a given value. @@ -100,7 +104,9 @@ def bisect_right(sorted_collection: List[int], item: int, lo: int = 0, hi: int = return lo -def insort_left(sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1) -> None: +def insort_left( + sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1 +) -> None: """ Inserts a given value into a sorted array before other values with the same value. @@ -141,7 +147,9 @@ def insort_left(sorted_collection: List[int], item: int, lo: int = 0, hi: int = sorted_collection.insert(bisect_left(sorted_collection, item, lo, hi), item) -def insort_right(sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1) -> None: +def insort_right( + sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1 +) -> None: """ Inserts a given value into a sorted array after other values with the same value. From 251bb1ed5962d23f3a0df00d10cc6b8dee5a996e Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 9 Dec 2020 14:20:36 +0100 Subject: [PATCH 4/5] Update binary_search.py --- searches/binary_search.py | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/searches/binary_search.py b/searches/binary_search.py index 6f17e2585614..7368d617df8f 100644 --- a/searches/binary_search.py +++ b/searches/binary_search.py @@ -297,37 +297,12 @@ def binary_search_by_recursion( return binary_search_by_recursion(sorted_collection, item, midpoint + 1, right) -def __assert_sorted(collection: List[int]) -> bool: - """Check if collection is ascending sorted, if not - raises :py:class:`ValueError` - - :param collection: collection - :return: True if collection is ascending sorted - :raise: :py:class:`ValueError` if collection is not ascending sorted - - Examples: - >>> __assert_sorted([0, 1, 2, 4]) - True - - >>> __assert_sorted([10, -1, 5]) - Traceback (most recent call last): - ... - ValueError: Collection must be sorted in ascending order - """ - if collection != sorted(collection): - raise ValueError("Collection must be sorted in ascending order") - return True - - if __name__ == "__main__": - import sys - user_input = input("Enter numbers separated by comma:\n").strip() - collection = [int(item) for item in user_input.split(",")] - __assert_sorted(collection) - target_input = input("Enter a single number to be found in the list:\n") - target = int(target_input) + collection = sorted(int(item) for item in user_input.split(",")) + target = int(input("Enter a single number to be found in the list:\n")) result = binary_search(collection, target) - if result is not None: - print(f"{target} was found at position: {result}") + if result is None: + print(f"{target} was not found in {collection}.") else: - print("Not found") + print(f"{target} was found at position {result} in {collection}.") From 05f5221dc0f86d67ab2c5fe5b4035bdd590e19b3 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 9 Dec 2020 14:28:30 +0100 Subject: [PATCH 5/5] Update binary_search.py --- searches/binary_search.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/searches/binary_search.py b/searches/binary_search.py index 7368d617df8f..35e0dd0596d2 100644 --- a/searches/binary_search.py +++ b/searches/binary_search.py @@ -228,7 +228,7 @@ def binary_search(sorted_collection: List[int], item: int) -> Optional[int]: return None -def binary_search_std_lib(sorted_collection, item) -> Optional[int]: +def binary_search_std_lib(sorted_collection: List[int], item: int) -> Optional[int]: """Pure implementation of binary search algorithm in Python using stdlib Be careful collection must be ascending sorted, otherwise result will be