diff --git a/sorts/odd_even_transposition_single_threaded.py b/sorts/odd_even_transposition_single_threaded.py index f6cf7fba2a71..5055b0462edf 100644 --- a/sorts/odd_even_transposition_single_threaded.py +++ b/sorts/odd_even_transposition_single_threaded.py @@ -5,29 +5,80 @@ Normally the swaps in each set happen simultaneously, without that the algorithm is no better than bubble sort. + +For doctests run following command: +python3 -m doctest -v odd_even_transposition_single_threaded.py + +For manual testing run: +python3 odd_even_transposition_single_threaded.py """ +from typing import Any, Protocol + -def odd_even_transposition(arr: list) -> list: +class Comparable(Protocol): + def __lt__(self, other: Any, /) -> bool: ... + + +def odd_even_transposition[T: Comparable](collection: list[T]) -> list[T]: """ - >>> odd_even_transposition([5, 4, 3, 2, 1]) - [1, 2, 3, 4, 5] + Sort a list in place using the odd-even transposition sort algorithm. + + The algorithm alternates between comparing-and-swapping even-indexed and + odd-indexed adjacent pairs until the collection is fully sorted. Because + each pass compares a disjoint set of pairs, the passes can be parallelized; + this implementation walks the pairs sequentially. - >>> odd_even_transposition([13, 11, 18, 0, -1]) - [-1, 0, 11, 13, 18] + :param collection: a mutable ordered collection with comparable items + :return: the same collection, sorted in ascending order - >>> odd_even_transposition([-.1, 1.1, .1, -2.9]) - [-2.9, -0.1, 0.1, 1.1] + Examples: + >>> odd_even_transposition([5, 4, 3, 2, 1]) + [1, 2, 3, 4, 5] + >>> odd_even_transposition([13, 11, 18, 0, -1]) == sorted([13, 11, 18, 0, -1]) + True + >>> odd_even_transposition([-.1, 1.1, .1, -2.9]) == sorted([-.1, 1.1, .1, -2.9]) + True + >>> odd_even_transposition([]) + [] + >>> odd_even_transposition([3, 3, 1, 2, 2, 1]) + [1, 1, 2, 2, 3, 3] + >>> odd_even_transposition(['c', 'a', 'b']) == sorted(['c', 'a', 'b']) + True + >>> odd_even_transposition([3.3, 1.1, 2.2]) == sorted([3.3, 1.1, 2.2]) + True + >>> values = [4, 2, 7, 1] + >>> result = odd_even_transposition(values) + >>> result is values + True + >>> values + [1, 2, 4, 7] + >>> import random + >>> collection = random.sample(range(-50, 50), 100) + >>> odd_even_transposition(collection) == sorted(collection) + True + >>> import string + >>> collection = random.choices(string.ascii_letters + string.digits, k=100) + >>> odd_even_transposition(collection) == sorted(collection) + True + >>> odd_even_transposition([1, "a"]) # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + TypeError: '<' not supported between instances of 'str' and 'int' """ - arr_size = len(arr) + arr_size = len(collection) for _ in range(arr_size): for i in range(_ % 2, arr_size - 1, 2): - if arr[i + 1] < arr[i]: - arr[i], arr[i + 1] = arr[i + 1], arr[i] + if collection[i + 1] < collection[i]: + collection[i], collection[i + 1] = collection[i + 1], collection[i] - return arr + return collection if __name__ == "__main__": + from doctest import testmod + + testmod() + arr = list(range(10, 0, -1)) print(f"Original: {arr}. Sorted: {odd_even_transposition(arr)}") diff --git a/tests/test_sorts.py b/tests/test_sorts.py index 0081c0fdbd30..d18be1c22b83 100644 --- a/tests/test_sorts.py +++ b/tests/test_sorts.py @@ -37,6 +37,7 @@ from sorts.iterative_merge_sort import iter_merge_sort from sorts.merge_sort import merge_sort from sorts.odd_even_sort import odd_even_sort +from sorts.odd_even_transposition_single_threaded import odd_even_transposition from sorts.pancake_sort import pancake_sort from sorts.patience_sort import patience_sort from sorts.quick_sort import quick_sort @@ -74,6 +75,7 @@ def test_heap_sort() -> None: merge, merge_sort, odd_even_sort, + odd_even_transposition, pancake_sort, patience_sort, quick_sort, @@ -145,6 +147,7 @@ def test_rec_insertion_sort(case) -> None: merge, merge_sort, odd_even_sort, + odd_even_transposition, pancake_sort, reversort, selection_sort,