|
5 | 5 |
|
6 | 6 | Normally the swaps in each set happen simultaneously, without that the algorithm |
7 | 7 | is no better than bubble sort. |
| 8 | +
|
| 9 | +For doctests run following command: |
| 10 | +python3 -m doctest -v odd_even_transposition_single_threaded.py |
| 11 | +
|
| 12 | +For manual testing run: |
| 13 | +python3 odd_even_transposition_single_threaded.py |
8 | 14 | """ |
9 | 15 |
|
| 16 | +from typing import Any, Protocol |
| 17 | + |
10 | 18 |
|
11 | | -def odd_even_transposition(arr: list) -> list: |
| 19 | +class Comparable(Protocol): |
| 20 | + def __lt__(self, other: Any, /) -> bool: ... |
| 21 | + |
| 22 | + |
| 23 | +def odd_even_transposition[T: Comparable](collection: list[T]) -> list[T]: |
12 | 24 | """ |
13 | | - >>> odd_even_transposition([5, 4, 3, 2, 1]) |
14 | | - [1, 2, 3, 4, 5] |
| 25 | + Sort a list in place using the odd-even transposition sort algorithm. |
| 26 | +
|
| 27 | + The algorithm alternates between comparing-and-swapping even-indexed and |
| 28 | + odd-indexed adjacent pairs until the collection is fully sorted. Because |
| 29 | + each pass compares a disjoint set of pairs, the passes can be parallelized; |
| 30 | + this implementation walks the pairs sequentially. |
15 | 31 |
|
16 | | - >>> odd_even_transposition([13, 11, 18, 0, -1]) |
17 | | - [-1, 0, 11, 13, 18] |
| 32 | + :param collection: a mutable ordered collection with comparable items |
| 33 | + :return: the same collection, sorted in ascending order |
18 | 34 |
|
19 | | - >>> odd_even_transposition([-.1, 1.1, .1, -2.9]) |
20 | | - [-2.9, -0.1, 0.1, 1.1] |
| 35 | + Examples: |
| 36 | + >>> odd_even_transposition([5, 4, 3, 2, 1]) |
| 37 | + [1, 2, 3, 4, 5] |
| 38 | + >>> odd_even_transposition([13, 11, 18, 0, -1]) == sorted([13, 11, 18, 0, -1]) |
| 39 | + True |
| 40 | + >>> odd_even_transposition([-.1, 1.1, .1, -2.9]) == sorted([-.1, 1.1, .1, -2.9]) |
| 41 | + True |
| 42 | + >>> odd_even_transposition([]) |
| 43 | + [] |
| 44 | + >>> odd_even_transposition([3, 3, 1, 2, 2, 1]) |
| 45 | + [1, 1, 2, 2, 3, 3] |
| 46 | + >>> odd_even_transposition(['c', 'a', 'b']) == sorted(['c', 'a', 'b']) |
| 47 | + True |
| 48 | + >>> odd_even_transposition([3.3, 1.1, 2.2]) == sorted([3.3, 1.1, 2.2]) |
| 49 | + True |
| 50 | + >>> values = [4, 2, 7, 1] |
| 51 | + >>> result = odd_even_transposition(values) |
| 52 | + >>> result is values |
| 53 | + True |
| 54 | + >>> values |
| 55 | + [1, 2, 4, 7] |
| 56 | + >>> import random |
| 57 | + >>> collection = random.sample(range(-50, 50), 100) |
| 58 | + >>> odd_even_transposition(collection) == sorted(collection) |
| 59 | + True |
| 60 | + >>> import string |
| 61 | + >>> collection = random.choices(string.ascii_letters + string.digits, k=100) |
| 62 | + >>> odd_even_transposition(collection) == sorted(collection) |
| 63 | + True |
| 64 | + >>> odd_even_transposition([1, "a"]) # doctest: +IGNORE_EXCEPTION_DETAIL |
| 65 | + Traceback (most recent call last): |
| 66 | + ... |
| 67 | + TypeError: '<' not supported between instances of 'str' and 'int' |
21 | 68 | """ |
22 | | - arr_size = len(arr) |
| 69 | + arr_size = len(collection) |
23 | 70 | for _ in range(arr_size): |
24 | 71 | for i in range(_ % 2, arr_size - 1, 2): |
25 | | - if arr[i + 1] < arr[i]: |
26 | | - arr[i], arr[i + 1] = arr[i + 1], arr[i] |
| 72 | + if collection[i + 1] < collection[i]: |
| 73 | + collection[i], collection[i + 1] = collection[i + 1], collection[i] |
27 | 74 |
|
28 | | - return arr |
| 75 | + return collection |
29 | 76 |
|
30 | 77 |
|
31 | 78 | if __name__ == "__main__": |
| 79 | + from doctest import testmod |
| 80 | + |
| 81 | + testmod() |
| 82 | + |
32 | 83 | arr = list(range(10, 0, -1)) |
33 | 84 | print(f"Original: {arr}. Sorted: {odd_even_transposition(arr)}") |
0 commit comments