@@ -66,6 +66,10 @@ def bisect_right(
6666 5
6767 >>> bisect_right([0, 5, 7, 10, 15], 6)
6868 2
69+ >>> bisect_right([0, 5, 7, 10, 15], 15, 1, 3)
70+ 3
71+ >>> bisect_right([0, 5, 7, 10, 15], 6, 2)
72+ 2
6973 """
7074 if hi < 0 :
7175 hi = len (sorted_collection )
@@ -91,6 +95,14 @@ def insort_left(
9195 >>> insort_left(sorted_collection, 6)
9296 >>> sorted_collection
9397 [0, 5, 6, 7, 10, 15]
98+ >>> sorted_collection = [0, 5, 7, 10, 15]
99+ >>> insort_left(sorted_collection, 20)
100+ >>> sorted_collection
101+ [0, 5, 7, 10, 15, 20]
102+ >>> sorted_collection = [0, 5, 7, 10, 15]
103+ >>> insort_left(sorted_collection, 15, 1, 3)
104+ >>> sorted_collection
105+ [0, 5, 7, 15, 10, 15]
94106 """
95107 sorted_collection .insert (bisect_left (sorted_collection , item , lo , hi ), item )
96108
@@ -106,24 +118,27 @@ def insort_right(
106118 >>> insort_right(sorted_collection, 6)
107119 >>> sorted_collection
108120 [0, 5, 6, 7, 10, 15]
121+ >>> sorted_collection = [0, 5, 7, 10, 15]
122+ >>> insort_right(sorted_collection, 20)
123+ >>> sorted_collection
124+ [0, 5, 7, 10, 15, 20]
125+ >>> sorted_collection = [0, 5, 7, 10, 15]
126+ >>> insort_right(sorted_collection, 15, 1, 3)
127+ >>> sorted_collection
128+ [0, 5, 7, 15, 10, 15]
109129 """
110130 sorted_collection .insert (bisect_right (sorted_collection , item , lo , hi ), item )
111131
112132
113133def binary_search (sorted_collection : list [int ], item : int ) -> int :
114134 """Pure implementation of a binary search algorithm in Python.
115- Updated to find the first occurrence of the item.
116-
117- :param sorted_collection: some ascending sorted collection with comparable items
118- :param item: item value to search
119- :return: index of the found item or -1 if the item is not found
120135
121136 Examples:
122137 >>> binary_search([0, 5, 7, 10, 15], 0)
123138 0
124139 >>> binary_search([0, 5, 7, 10, 15], 15)
125140 4
126- >>> binary_search([1, 2, 2, 2, 3 ], 2 )
141+ >>> binary_search([0, 5, 7, 10, 15 ], 5 )
127142 1
128143 >>> binary_search([0, 5, 7, 10, 15], 6)
129144 -1
@@ -139,7 +154,7 @@ def binary_search(sorted_collection: list[int], item: int) -> int:
139154 midpoint = left + (right - left ) // 2
140155 if sorted_collection [midpoint ] == item :
141156 result = midpoint
142- right = midpoint - 1 # Continue searching left
157+ right = midpoint - 1 # Logic for first occurrence
143158 elif item < sorted_collection [midpoint ]:
144159 right = midpoint - 1
145160 else :
@@ -148,13 +163,16 @@ def binary_search(sorted_collection: list[int], item: int) -> int:
148163
149164
150165def binary_search_std_lib (sorted_collection : list [int ], item : int ) -> int :
151- """Binary search algorithm in Python using stdlib.
152- Finds the first occurrence.
166+ """Binary search using stdlib.
153167
154168 >>> binary_search_std_lib([0, 5, 7, 10, 15], 0)
155169 0
156- >>> binary_search_std_lib([1, 2, 2, 2, 3], 2)
170+ >>> binary_search_std_lib([0, 5, 7, 10, 15], 15)
171+ 4
172+ >>> binary_search_std_lib([0, 5, 7, 10, 15], 5)
157173 1
174+ >>> binary_search_std_lib([0, 5, 7, 10, 15], 6)
175+ -1
158176 """
159177 index = bisect .bisect_left (sorted_collection , item )
160178 if index != len (sorted_collection ) and sorted_collection [index ] == item :
@@ -166,6 +184,10 @@ def binary_search_with_duplicates(sorted_collection: list[int], item: int) -> li
166184 """Returns a list of all indexes where the target occurs.
167185
168186 Examples:
187+ >>> binary_search_with_duplicates([0, 5, 7, 10, 15], 0)
188+ [0]
189+ >>> binary_search_with_duplicates([0, 5, 7, 10, 15], 15)
190+ [4]
169191 >>> binary_search_with_duplicates([1, 2, 2, 2, 3], 2)
170192 [1, 2, 3]
171193 >>> binary_search_with_duplicates([1, 2, 2, 2, 3], 4)
@@ -182,42 +204,49 @@ def binary_search_with_duplicates(sorted_collection: list[int], item: int) -> li
182204def binary_search_by_recursion (
183205 sorted_collection : list [int ], item : int , left : int = 0 , right : int = - 1
184206) -> int :
185- """
186- Recursive binary search finding the first occurrence.
207+ """Recursive binary search.
208+
209+ Examples:
210+ >>> binary_search_by_recursion([0, 5, 7, 10, 15], 0, 0, 4)
211+ 0
212+ >>> binary_search_by_recursion([0, 5, 7, 10, 15], 15, 0, 4)
213+ 4
214+ >>> binary_search_by_recursion([0, 5, 7, 10, 15], 5, 0, 4)
215+ 1
216+ >>> binary_search_by_recursion([0, 5, 7, 10, 15], 6, 0, 4)
217+ -1
187218 """
188219 if right < 0 :
189220 right = len (sorted_collection ) - 1
190221
191- # Base case: range is empty
192222 if right < left :
193223 return - 1
194224
195225 midpoint = left + (right - left ) // 2
196226
197227 if sorted_collection [midpoint ] == item :
198- # We found a match! Now see if there's an earlier one to the left.
199- # CRITICAL: Only recurse if there is actually space to the left
200228 if midpoint > left :
201- res = binary_search_by_recursion (
202- sorted_collection , item , left , midpoint - 1
203- )
229+ res = binary_search_by_recursion (sorted_collection , item , left , midpoint - 1 )
204230 return res if res != - 1 else midpoint
205231 return midpoint
206-
207232 elif sorted_collection [midpoint ] > item :
208233 return binary_search_by_recursion (sorted_collection , item , left , midpoint - 1 )
209234 else :
210235 return binary_search_by_recursion (sorted_collection , item , midpoint + 1 , right )
211236
212237
213238def exponential_search (sorted_collection : list [int ], item : int ) -> int :
214- """Implementation of an exponential search algorithm finding the first occurrence .
239+ """Exponential search algorithm.
215240
216241 Examples:
217242 >>> exponential_search([0, 5, 7, 10, 15], 0)
218243 0
219- >>> exponential_search([1, 2, 2, 2, 3], 2)
244+ >>> exponential_search([0, 5, 7, 10, 15], 15)
245+ 4
246+ >>> exponential_search([0, 5, 7, 10, 15], 5)
220247 1
248+ >>> exponential_search([0, 5, 7, 10, 15], 6)
249+ -1
221250 """
222251 if not sorted_collection :
223252 return - 1
@@ -239,23 +268,4 @@ def exponential_search(sorted_collection: list[int], item: int) -> int:
239268
240269if __name__ == "__main__" :
241270 import doctest
242- import timeit
243-
244- doctest .testmod ()
245- for search in searches :
246- name = f"{ search .__name__ :>26} "
247- print (f"{ name } : { search ([0 , 5 , 7 , 10 , 15 ], 10 ) = } " )
248-
249- print ("\n Benchmarks..." )
250- setup = "collection = range(1000)"
251- for search in searches :
252- name = search .__name__
253- print (
254- f"{ name :>26} :" ,
255- timeit .timeit (
256- f"{ name } (list(collection), 500)" ,
257- setup = setup ,
258- number = 5_000 ,
259- globals = globals (),
260- ),
261- )
271+ doctest .testmod ()
0 commit comments