diff --git a/sorts/cocktail_shaker_sort.py b/sorts/cocktail_shaker_sort.py index de126426d986..d658c8c4ddcd 100644 --- a/sorts/cocktail_shaker_sort.py +++ b/sorts/cocktail_shaker_sort.py @@ -4,8 +4,17 @@ https://en.wikipedia.org/wiki/Cocktail_shaker_sort """ +from typing import Protocol -def cocktail_shaker_sort(arr: list[int]) -> list[int]: + +class Comparable(Protocol): + def __lt__(self, other: object, /) -> bool: ... + + + + + +def cocktail_shaker_sort[T: Comparable](arr: list[T]) -> list[T]: """ Sorts a list using the Cocktail Shaker Sort algorithm. @@ -28,7 +37,12 @@ def cocktail_shaker_sort(arr: list[int]) -> list[int]: Traceback (most recent call last): ... TypeError: 'tuple' object does not support item assignment - """ + + >>> cocktail_shaker_sort(["elderberry", "banana", "date", "apple", "cherry"]) + ['apple', 'banana', 'cherry', 'date', 'elderberry'] + >>> cocktail_shaker_sort([3.2, -1.1, 2.4, 0.5]) + [-1.1, 0.5, 2.4, 3.2] +""" start, end = 0, len(arr) - 1 while start < end: diff --git a/sorts/comb_sort.py b/sorts/comb_sort.py index 72caeb9c7350..24d3068c4d35 100644 --- a/sorts/comb_sort.py +++ b/sorts/comb_sort.py @@ -18,8 +18,17 @@ python comb_sort.py """ +from typing import Protocol -def comb_sort(data: list) -> list: + +class Comparable(Protocol): + def __lt__(self, other: object, /) -> bool: ... + + + + + +def comb_sort[T: Comparable](data: list[T]) -> list[T]: """Pure implementation of comb sort algorithm in Python :param data: mutable collection with comparable items :return: the same collection in ascending order @@ -32,7 +41,12 @@ def comb_sort(data: list) -> list: [-15, -7, 0, 2, 3, 8, 45, 99] >>> comb_sort([2, 0, 3, 4, 5, 6, 1]) [0, 1, 2, 3, 4, 5, 6] - """ + + >>> comb_sort(["d", "a", "c", "b"]) + ['a', 'b', 'c', 'd'] + >>> comb_sort([2.5, -1.0, 0.0]) + [-1.0, 0.0, 2.5] +""" shrink_factor = 1.3 gap = len(data) completed = False diff --git a/sorts/cycle_sort.py b/sorts/cycle_sort.py index 7177c8ea110d..3fcafe3fd7fd 100644 --- a/sorts/cycle_sort.py +++ b/sorts/cycle_sort.py @@ -3,8 +3,17 @@ Source: https://en.wikipedia.org/wiki/Cycle_sort """ +from typing import Protocol -def cycle_sort(array: list) -> list: + +class Comparable(Protocol): + def __lt__(self, other: object, /) -> bool: ... + + + + + +def cycle_sort[T: Comparable](array: list[T]) -> list[T]: """ >>> cycle_sort([4, 3, 2, 1]) [1, 2, 3, 4] @@ -17,7 +26,12 @@ def cycle_sort(array: list) -> list: >>> cycle_sort([]) [] - """ + + >>> cycle_sort(["d", "a", "c", "b"]) + ['a', 'b', 'c', 'd'] + >>> cycle_sort([2.5, -1.0, 0.0]) + [-1.0, 0.0, 2.5] +""" array_len = len(array) for cycle_start in range(array_len - 1): item = array[cycle_start] diff --git a/sorts/double_sort.py b/sorts/double_sort.py index bd5fdca1e63c..969df90f00cc 100644 --- a/sorts/double_sort.py +++ b/sorts/double_sort.py @@ -1,44 +1,54 @@ -from typing import Any - - -def double_sort(collection: list[Any]) -> list[Any]: - """This sorting algorithm sorts an array using the principle of bubble sort, - but does it both from left to right and right to left. - Hence, it's called "Double sort" - :param collection: mutable ordered sequence of elements - :return: the same collection in ascending order - Examples: - >>> double_sort([-1 ,-2 ,-3 ,-4 ,-5 ,-6 ,-7]) - [-7, -6, -5, -4, -3, -2, -1] - >>> double_sort([]) - [] - >>> double_sort([-1 ,-2 ,-3 ,-4 ,-5 ,-6]) - [-6, -5, -4, -3, -2, -1] - >>> double_sort([-3, 10, 16, -42, 29]) == sorted([-3, 10, 16, -42, 29]) - True - """ - no_of_elements = len(collection) - for _ in range( - int(((no_of_elements - 1) / 2) + 1) - ): # we don't need to traverse to end of list as - for j in range(no_of_elements - 1): - # apply the bubble sort algorithm from left to right (or forwards) - if collection[j + 1] < collection[j]: - collection[j], collection[j + 1] = collection[j + 1], collection[j] - # apply the bubble sort algorithm from right to left (or backwards) - if collection[no_of_elements - 1 - j] < collection[no_of_elements - 2 - j]: - ( - collection[no_of_elements - 1 - j], - collection[no_of_elements - 2 - j], - ) = ( - collection[no_of_elements - 2 - j], - collection[no_of_elements - 1 - j], - ) - return collection - - -if __name__ == "__main__": - # allow the user to input the elements of the list on one line - unsorted = [int(x) for x in input("Enter the list to be sorted: ").split() if x] - print("the sorted list is") - print(f"{double_sort(unsorted) = }") + +from typing import Protocol + + +class Comparable(Protocol): + def __lt__(self, other: object, /) -> bool: ... + + +def double_sort[T: Comparable](collection: list[T]) -> list[T]: + """This sorting algorithm sorts an array using the principle of bubble sort, + but does it both from left to right and right to left. + Hence, it's called "Double sort" + :param collection: mutable ordered sequence of elements + :return: the same collection in ascending order + Examples: + >>> double_sort([-1 ,-2 ,-3 ,-4 ,-5 ,-6 ,-7]) + [-7, -6, -5, -4, -3, -2, -1] + >>> double_sort([]) + [] + >>> double_sort([-1 ,-2 ,-3 ,-4 ,-5 ,-6]) + [-6, -5, -4, -3, -2, -1] + >>> double_sort([-3, 10, 16, -42, 29]) == sorted([-3, 10, 16, -42, 29]) + True + + >>> double_sort(["d", "a", "c", "b"]) + ['a', 'b', 'c', 'd'] + >>> double_sort([2.5, -1.0, 0.0]) + [-1.0, 0.0, 2.5] +""" + no_of_elements = len(collection) + for _ in range( + int(((no_of_elements - 1) / 2) + 1) + ): # we don't need to traverse to end of list as + for j in range(no_of_elements - 1): + # apply the bubble sort algorithm from left to right (or forwards) + if collection[j + 1] < collection[j]: + collection[j], collection[j + 1] = collection[j + 1], collection[j] + # apply the bubble sort algorithm from right to left (or backwards) + if collection[no_of_elements - 1 - j] < collection[no_of_elements - 2 - j]: + ( + collection[no_of_elements - 1 - j], + collection[no_of_elements - 2 - j], + ) = ( + collection[no_of_elements - 2 - j], + collection[no_of_elements - 1 - j], + ) + return collection + + +if __name__ == "__main__": + # allow the user to input the elements of the list on one line + unsorted = [int(x) for x in input("Enter the list to be sorted: ").split() if x] + print("the sorted list is") + print(f"{double_sort(unsorted) = }") diff --git a/sorts/exchange_sort.py b/sorts/exchange_sort.py index 1ce78a9dc0cb..637bae2ebcb5 100644 --- a/sorts/exchange_sort.py +++ b/sorts/exchange_sort.py @@ -1,4 +1,11 @@ -def exchange_sort(numbers: list[int]) -> list[int]: +from typing import Protocol + + +class Comparable(Protocol): + def __lt__(self, other: object, /) -> bool: ... + + +def exchange_sort[T: Comparable](numbers: list[T]) -> list[T]: """ Uses exchange sort to sort a list of numbers. Source: https://en.wikipedia.org/wiki/Sorting_algorithm#Exchange_sort @@ -12,7 +19,12 @@ def exchange_sort(numbers: list[int]) -> list[int]: [-2, 0, 3, 5, 10] >>> exchange_sort([]) [] - """ + + >>> exchange_sort(["d", "a", "c", "b"]) + ['a', 'b', 'c', 'd'] + >>> exchange_sort([2.5, -1.0, 0.0]) + [-1.0, 0.0, 2.5] +""" numbers_length = len(numbers) for i in range(numbers_length): for j in range(i + 1, numbers_length): diff --git a/sorts/gnome_sort.py b/sorts/gnome_sort.py index 3002bc6a8b18..84dc6e414df5 100644 --- a/sorts/gnome_sort.py +++ b/sorts/gnome_sort.py @@ -12,8 +12,17 @@ python3 gnome_sort.py """ +from typing import Protocol -def gnome_sort(lst: list) -> list: + +class Comparable(Protocol): + def __lt__(self, other: object, /) -> bool: ... + + + + + +def gnome_sort[T: Comparable](lst: list[T]) -> list[T]: """ Pure implementation of the gnome sort algorithm in Python @@ -32,7 +41,12 @@ def gnome_sort(lst: list) -> list: >>> "".join(gnome_sort(list(set("Gnomes are stupid!")))) ' !Gadeimnoprstu' - """ + + >>> gnome_sort(["d", "a", "c", "b"]) + ['a', 'b', 'c', 'd'] + >>> gnome_sort([2.5, -1.0, 0.0]) + [-1.0, 0.0, 2.5] +""" if len(lst) <= 1: return lst diff --git a/tests/test_sorts.py b/tests/test_sorts.py index caa4b31cac81..8afa24e67582 100644 --- a/tests/test_sorts.py +++ b/tests/test_sorts.py @@ -17,6 +17,12 @@ import pytest from sorts.binary_insertion_sort import binary_insertion_sort +from sorts.cocktail_shaker_sort import cocktail_shaker_sort +from sorts.comb_sort import comb_sort +from sorts.cycle_sort import cycle_sort +from sorts.double_sort import double_sort +from sorts.exchange_sort import exchange_sort +from sorts.gnome_sort import gnome_sort from sorts.bubble_sort import bubble_sort_iterative, bubble_sort_recursive from sorts.circle_sort import circle_sort from sorts.cocktail_shaker_sort import cocktail_shaker_sort @@ -48,6 +54,12 @@ def test_heap_sort(): SORTS = ( binary_insertion_sort, + cocktail_shaker_sort, + comb_sort, + cycle_sort, + double_sort, + exchange_sort, + gnome_sort, bubble_sort_iterative, circle_sort, cocktail_shaker_sort, @@ -95,6 +107,12 @@ def test_sort_matches_builtin(sort, case): binary_insertion_sort, bubble_sort_iterative, bubble_sort_recursive, + cocktail_shaker_sort, + comb_sort, + cycle_sort, + double_sort, + exchange_sort, + gnome_sort, insertion_sort, ], ids=lambda f: f.__name__,