|
1 | 1 | """ |
| 2 | +https://en.wikipedia.org/wiki/Shellsort |
2 | 3 | https://en.wikipedia.org/wiki/Shellsort#Pseudocode |
3 | 4 | """ |
4 | 5 |
|
| 6 | +from typing import Any, Protocol |
| 7 | + |
| 8 | + |
| 9 | +class Comparable(Protocol): |
| 10 | + def __lt__(self, other: Any, /) -> bool: ... |
5 | 11 |
|
6 | | -def shell_sort(collection: list[int]) -> list[int]: |
7 | | - """ |
8 | | - Sort a list of integers using the Shell Sort algorithm. |
9 | 12 |
|
10 | | - Reference: |
11 | | - https://en.wikipedia.org/wiki/Shellsort |
| 13 | +def shell_sort[T: Comparable](collection: list[T]) -> list[T]: |
| 14 | + """Pure implementation of shell sort algorithm in Python. |
12 | 15 |
|
| 16 | + :param collection: Some mutable ordered collection with heterogeneous |
| 17 | + comparable items inside |
| 18 | + :return: the same collection ordered in ascending order |
| 19 | +
|
| 20 | + Examples: |
13 | 21 | >>> shell_sort([0, 5, 3, 2, 2]) |
14 | 22 | [0, 2, 2, 3, 5] |
15 | 23 | >>> shell_sort([]) |
16 | 24 | [] |
17 | 25 | >>> shell_sort([-2, -5, -45]) |
18 | 26 | [-45, -5, -2] |
| 27 | + >>> shell_sort(["c", "a", "b"]) |
| 28 | + ['a', 'b', 'c'] |
| 29 | + >>> shell_sort([2.5, -1.0, 0.0]) |
| 30 | + [-1.0, 0.0, 2.5] |
| 31 | + >>> shell_sort([0, 5, 3, 2, 2]) == sorted([0, 5, 3, 2, 2]) |
| 32 | + True |
| 33 | + >>> shell_sort(["c", "a", "b"]) == sorted(["c", "a", "b"]) |
| 34 | + True |
19 | 35 | """ |
| 36 | + # Marcin Ciura's gap sequence |
20 | 37 | gaps = [701, 301, 132, 57, 23, 10, 4, 1] |
21 | | - |
22 | 38 | for gap in gaps: |
23 | 39 | for i in range(gap, len(collection)): |
24 | 40 | insert_value = collection[i] |
25 | 41 | j = i |
26 | | - while j >= gap and collection[j - gap] > insert_value: |
| 42 | + while j >= gap and insert_value < collection[j - gap]: |
27 | 43 | collection[j] = collection[j - gap] |
28 | 44 | j -= gap |
29 | | - collection[j] = insert_value |
30 | | - |
| 45 | + if j != i: |
| 46 | + collection[j] = insert_value |
31 | 47 | return collection |
| 48 | + |
| 49 | + |
| 50 | +if __name__ == "__main__": |
| 51 | + from doctest import testmod |
| 52 | + |
| 53 | + testmod() |
| 54 | + user_input = input("Enter numbers separated by a comma:\n").strip() |
| 55 | + unsorted = [int(item) for item in user_input.split(",")] |
| 56 | + print(shell_sort(unsorted)) |
0 commit comments