diff --git a/src/binary_search.py b/src/binary_search.py new file mode 100644 index 00000000..8fd7a98f --- /dev/null +++ b/src/binary_search.py @@ -0,0 +1,46 @@ +def binary_search(arr, target): + """ + Perform binary search on a sorted array to find the index of the target element. + + Args: + arr (list): A sorted list of comparable elements + target: The element to search for + + Returns: + int: Index of the target element if found, otherwise -1 + + Raises: + TypeError: If input is not a list + ValueError: If the input list is not sorted + """ + # Check if input is a list + if not isinstance(arr, list): + raise TypeError("Input must be a list") + + # Check if list is sorted + if any(arr[i] > arr[i+1] for i in range(len(arr)-1)): + raise ValueError("Input list must be sorted in ascending order") + + # Handle empty list + if not arr: + return -1 + + # Perform binary search + left, right = 0, len(arr) - 1 + + while left <= right: + # Calculate mid point to avoid potential integer overflow + mid = left + (right - left) // 2 + + # Check if target is found + if arr[mid] == target: + return mid + + # Decide which half to search + if arr[mid] < target: + left = mid + 1 + else: + right = mid - 1 + + # Target not found + return -1 \ No newline at end of file diff --git a/tests/test_binary_search.py b/tests/test_binary_search.py new file mode 100644 index 00000000..8f4c634d --- /dev/null +++ b/tests/test_binary_search.py @@ -0,0 +1,42 @@ +import pytest +from src.binary_search import binary_search + +def test_binary_search_found(): + """Test finding an existing element in the list""" + arr = [1, 3, 5, 7, 9, 11, 13] + assert binary_search(arr, 7) == 3 + assert binary_search(arr, 1) == 0 + assert binary_search(arr, 13) == 6 + +def test_binary_search_not_found(): + """Test searching for elements not in the list""" + arr = [1, 3, 5, 7, 9, 11, 13] + assert binary_search(arr, 0) == -1 + assert binary_search(arr, 14) == -1 + assert binary_search(arr, 6) == -1 + +def test_binary_search_empty_list(): + """Test searching in an empty list""" + assert binary_search([], 5) == -1 + +def test_binary_search_single_element(): + """Test searching in a list with a single element""" + assert binary_search([5], 5) == 0 + assert binary_search([5], 6) == -1 + +def test_binary_search_invalid_input(): + """Test error handling for invalid inputs""" + # Test non-list input + with pytest.raises(TypeError, match="Input must be a list"): + binary_search("not a list", 5) + + # Test unsorted list + with pytest.raises(ValueError, match="Input list must be sorted in ascending order"): + binary_search([5, 3, 1], 3) + +def test_binary_search_duplicates(): + """Test behavior with lists containing duplicates""" + arr = [1, 2, 2, 3, 3, 3, 4, 4, 5] + # Note: with multiple matches, it returns the first (lowest) index + assert binary_search(arr, 3) in [3, 4, 5] + assert binary_search(arr, 4) in [6, 7] \ No newline at end of file