@@ -126,14 +126,6 @@ def insort_left(
126126 True
127127 >>> item is sorted_collection[2]
128128 False
129- >>> sorted_collection = [0, 5, 7, 10, 15]
130- >>> insort_left(sorted_collection, 20)
131- >>> sorted_collection
132- [0, 5, 7, 10, 15, 20]
133- >>> sorted_collection = [0, 5, 7, 10, 15]
134- >>> insort_left(sorted_collection, 15, 1, 3)
135- >>> sorted_collection
136- [0, 5, 7, 15, 10, 15]
137129 """
138130 sorted_collection .insert (bisect_left (sorted_collection , item , lo , hi ), item )
139131
@@ -157,23 +149,6 @@ def insort_right(
157149 >>> insort_right(sorted_collection, 6)
158150 >>> sorted_collection
159151 [0, 5, 6, 7, 10, 15]
160- >>> sorted_collection = [(0, 0), (5, 5), (7, 7), (10, 10), (15, 15)]
161- >>> item = (5, 5)
162- >>> insort_right(sorted_collection, item)
163- >>> sorted_collection
164- [(0, 0), (5, 5), (5, 5), (7, 7), (10, 10), (15, 15)]
165- >>> item is sorted_collection[1]
166- False
167- >>> item is sorted_collection[2]
168- True
169- >>> sorted_collection = [0, 5, 7, 10, 15]
170- >>> insort_right(sorted_collection, 20)
171- >>> sorted_collection
172- [0, 5, 7, 10, 15, 20]
173- >>> sorted_collection = [0, 5, 7, 10, 15]
174- >>> insort_right(sorted_collection, 15, 1, 3)
175- >>> sorted_collection
176- [0, 5, 7, 15, 10, 15]
177152 """
178153 sorted_collection .insert (bisect_right (sorted_collection , item , lo , hi ), item )
179154
@@ -182,9 +157,6 @@ def binary_search(sorted_collection: list[int], item: int) -> int:
182157 """Pure implementation of a binary search algorithm in Python.
183158 Finds the first occurrence of the item.
184159
185- Be careful collection must be ascending sorted otherwise, the result will be
186- unpredictable
187-
188160 :param sorted_collection: some ascending sorted collection with comparable items
189161 :param item: item value to search
190162 :return: index of the first found item or -1 if the item is not found
@@ -194,10 +166,6 @@ def binary_search(sorted_collection: list[int], item: int) -> int:
194166 0
195167 >>> binary_search([0, 5, 7, 10, 15], 15)
196168 4
197- >>> binary_search([0, 5, 7, 10, 15], 5)
198- 1
199- >>> binary_search([0, 5, 7, 10, 15], 6)
200- -1
201169 >>> binary_search([1, 2, 2, 2, 3], 2)
202170 1
203171 """
@@ -212,7 +180,7 @@ def binary_search(sorted_collection: list[int], item: int) -> int:
212180 current_item = sorted_collection [midpoint ]
213181 if current_item == item :
214182 result = midpoint
215- right = midpoint - 1 # Search left for first occurrence
183+ right = midpoint - 1
216184 elif item < current_item :
217185 right = midpoint - 1
218186 else :
@@ -221,25 +189,7 @@ def binary_search(sorted_collection: list[int], item: int) -> int:
221189
222190
223191def binary_search_std_lib (sorted_collection : list [int ], item : int ) -> int :
224- """Pure implementation of a binary search algorithm in Python using stdlib
225-
226- Be careful collection must be ascending sorted otherwise, the result will be
227- unpredictable
228-
229- :param sorted_collection: some ascending sorted collection with comparable items
230- :param item: item value to search
231- :return: index of the found item or -1 if the item is not found
232-
233- Examples:
234- >>> binary_search_std_lib([0, 5, 7, 10, 15], 0)
235- 0
236- >>> binary_search_std_lib([0, 5, 7, 10, 15], 15)
237- 4
238- >>> binary_search_std_lib([0, 5, 7, 10, 15], 5)
239- 1
240- >>> binary_search_std_lib([0, 5, 7, 10, 15], 6)
241- -1
242- """
192+ """Pure implementation using stdlib"""
243193 if list (sorted_collection ) != sorted (sorted_collection ):
244194 raise ValueError ("sorted_collection must be sorted in ascending order" )
245195 index = bisect .bisect_left (sorted_collection , item )
@@ -249,54 +199,28 @@ def binary_search_std_lib(sorted_collection: list[int], item: int) -> int:
249199
250200
251201def binary_search_with_duplicates (sorted_collection : list [int ], item : int ) -> list [int ]:
252- """Pure implementation of a binary search algorithm in Python that supports
253- duplicates.
254-
255- Resources used:
256- https://stackoverflow.com/questions/13197552/using-binary-search-with-sorted-array-with-duplicates
257-
258- The collection must be sorted in ascending order; otherwise the result will be
259- unpredictable. If the target appears multiple times, this function returns a
260- list of all indexes where the target occurs. If the target is not found,
261- this function returns an empty list.
262-
263- :param sorted_collection: some ascending sorted collection with comparable items
264- :param item: item value to search for
265- :return: a list of indexes where the item is found (empty list if not found)
266-
267- Examples:
268- >>> binary_search_with_duplicates([0, 5, 7, 10, 15], 0)
269- [0]
270- >>> binary_search_with_duplicates([0, 5, 7, 10, 15], 15)
271- [4]
272- >>> binary_search_with_duplicates([1, 2, 2, 2, 3], 2)
273- [1, 2, 3]
274- >>> binary_search_with_duplicates([1, 2, 2, 2, 3], 4)
275- []
276- """
202+ """Returns a list of all indexes where the item is found."""
277203 if list (sorted_collection ) != sorted (sorted_collection ):
278204 raise ValueError ("sorted_collection must be sorted in ascending order" )
279205
280206 def lower_bound (sorted_collection : list [int ], item : int ) -> int :
281- left = 0
282- right = len (sorted_collection )
207+ left , right = 0 , len (sorted_collection )
283208 while left < right :
284- midpoint = left + (right - left ) // 2
285- if sorted_collection [midpoint ] < item :
286- left = midpoint + 1
209+ mid = left + (right - left ) // 2
210+ if sorted_collection [mid ] < item :
211+ left = mid + 1
287212 else :
288- right = midpoint
213+ right = mid
289214 return left
290215
291216 def upper_bound (sorted_collection : list [int ], item : int ) -> int :
292- left = 0
293- right = len (sorted_collection )
217+ left , right = 0 , len (sorted_collection )
294218 while left < right :
295- midpoint = left + (right - left ) // 2
296- if sorted_collection [midpoint ] <= item :
297- left = midpoint + 1
219+ mid = left + (right - left ) // 2
220+ if sorted_collection [mid ] <= item :
221+ left = mid + 1
298222 else :
299- right = midpoint
223+ right = mid
300224 return left
301225
302226 left = lower_bound (sorted_collection , item )
@@ -310,29 +234,7 @@ def upper_bound(sorted_collection: list[int], item: int) -> int:
310234def binary_search_by_recursion (
311235 sorted_collection : list [int ], item : int , left : int = 0 , right : int = - 1
312236) -> int :
313- """Pure implementation of a binary search algorithm in Python by recursion.
314- Finds the first occurrence of the item.
315-
316- Be careful collection must be ascending sorted otherwise, the result will be
317- unpredictable
318- First recursion should be started with left=0 and right=(len(sorted_collection)-1)
319-
320- :param sorted_collection: some ascending sorted collection with comparable items
321- :param item: item value to search
322- :return: index of the first found item or -1 if the item is not found
323-
324- Examples:
325- >>> binary_search_by_recursion([0, 5, 7, 10, 15], 0, 0, 4)
326- 0
327- >>> binary_search_by_recursion([0, 5, 7, 10, 15], 15, 0, 4)
328- 4
329- >>> binary_search_by_recursion([0, 5, 7, 10, 15], 5, 0, 4)
330- 1
331- >>> binary_search_by_recursion([0, 5, 7, 10, 15], 6, 0, 4)
332- -1
333- >>> binary_search_by_recursion([1, 2, 2, 2, 3], 2, 0, 4)
334- 1
335- """
237+ """Recursive implementation finding the first occurrence."""
336238 if right < 0 :
337239 right = len (sorted_collection ) - 1
338240 if list (sorted_collection ) != sorted (sorted_collection ):
@@ -343,7 +245,6 @@ def binary_search_by_recursion(
343245 midpoint = left + (right - left ) // 2
344246
345247 if sorted_collection [midpoint ] == item :
346- # Check if there's an earlier occurrence to the left
347248 res = binary_search_by_recursion (sorted_collection , item , left , midpoint - 1 )
348249 return res if res != - 1 else midpoint
349250 elif sorted_collection [midpoint ] > item :
@@ -353,45 +254,20 @@ def binary_search_by_recursion(
353254
354255
355256def exponential_search (sorted_collection : list [int ], item : int ) -> int :
356- """Pure implementation of an exponential search algorithm in Python
357- Resources used:
358- https://en.wikipedia.org/wiki/Exponential_search
359-
360- Be careful collection must be ascending sorted otherwise, result will be
361- unpredictable
362-
363- :param sorted_collection: some ascending sorted collection with comparable items
364- :param item: item value to search
365- :return: index of the found item or -1 if the item is not found
366-
367- the order of this algorithm is O(lg I) where I is index position of item if exist
368-
369- Examples:
370- >>> exponential_search([0, 5, 7, 10, 15], 0)
371- 0
372- >>> exponential_search([0, 5, 7, 10, 15], 15)
373- 4
374- >>> exponential_search([0, 5, 7, 10, 15], 5)
375- 1
376- >>> exponential_search([0, 5, 7, 10, 15], 6)
377- -1
378- """
379- if list (sorted_collection ) != sorted (sorted_collection ):
380- raise ValueError ("sorted_collection must be sorted in ascending order" )
257+ """Exponential search implementation."""
258+ if not sorted_collection :
259+ return - 1
260+ if sorted_collection [0 ] == item :
261+ return 0
381262 bound = 1
382263 while bound < len (sorted_collection ) and sorted_collection [bound ] < item :
383264 bound *= 2
384265 left = bound // 2
385266 right = min (bound , len (sorted_collection ) - 1 )
386- last_result = binary_search_by_recursion (
387- sorted_collection = sorted_collection , item = item , left = left , right = right
388- )
389- if last_result is None :
390- return - 1
391- return last_result
267+ return binary_search_by_recursion (sorted_collection , item , left , right )
392268
393269
394- searches = ( # Fastest to slowest...
270+ searches = (
395271 binary_search_std_lib ,
396272 binary_search ,
397273 exponential_search ,
@@ -406,7 +282,7 @@ def exponential_search(sorted_collection: list[int], item: int) -> int:
406282 doctest .testmod ()
407283 for search in searches :
408284 name = f"{ search .__name__ :>26} "
409- print (f"{ name } : { search ([0 , 5 , 7 , 10 , 15 ], 10 ) = } " ) # type: ignore[operator]
285+ print (f"{ name } : { search ([0 , 5 , 7 , 10 , 15 ], 10 ) = } " )
410286
411287 print ("\n Benchmarks..." )
412288 setup = "collection = range(1000)"
@@ -417,13 +293,4 @@ def exponential_search(sorted_collection: list[int], item: int) -> int:
417293 timeit .timeit (
418294 f"{ name } (collection, 500)" , setup = setup , number = 5_000 , globals = globals ()
419295 ),
420- )
421-
422- user_input = input ("\n Enter numbers separated by comma: " ).strip ()
423- collection = sorted (int (item ) for item in user_input .split ("," ))
424- target = int (input ("Enter a single number to be found in the list: " ))
425- result = binary_search (sorted_collection = collection , item = target )
426- if result == - 1 :
427- print (f"{ target } was not found in { collection } ." )
428- else :
429- print (f"{ target } was found at position { result } of { collection } ." )
296+ )
0 commit comments