Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions sorts/bubble_sort.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
from typing import Any
from typing import Any, Protocol, TypeVar


def bubble_sort_iterative(collection: list[Any]) -> list[Any]:
class Comparable(Protocol):
def __lt__(self, other: Any, /) -> bool: ...


T = TypeVar("T", bound=Comparable)


def bubble_sort_iterative[T: Comparable](collection: list[T]) -> list[T]:
"""Pure implementation of the bubble sort algorithm in Python (iterative).

Bubble sort works by repeatedly stepping through the collection,
Expand Down Expand Up @@ -58,6 +65,10 @@ def bubble_sort_iterative(collection: list[Any]) -> list[Any]:
>>> collection_arg = random.choices(string.ascii_letters + string.digits, k=100)
>>> bubble_sort_iterative(collection_arg) == sorted(collection_arg)
True
>>> bubble_sort_iterative([1, "a"]) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
TypeError: '<' not supported between instances of 'str' and 'int'
"""
length = len(collection)
for i in reversed(range(length)):
Expand All @@ -71,7 +82,7 @@ def bubble_sort_iterative(collection: list[Any]) -> list[Any]:
return collection


def bubble_sort_recursive(collection: list[Any]) -> list[Any]:
def bubble_sort_recursive[T: Comparable](collection: list[T]) -> list[T]:
"""Pure implementation of the bubble sort algorithm in Python (recursive).

Functionally identical to the iterative version: each call makes a
Expand Down Expand Up @@ -124,6 +135,10 @@ def bubble_sort_recursive(collection: list[Any]) -> list[Any]:
>>> collection_arg = random.choices(string.ascii_letters + string.digits, k=100)
>>> bubble_sort_recursive(collection_arg) == sorted(collection_arg)
True
>>> bubble_sort_recursive([1, "a"]) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
TypeError: '<' not supported between instances of 'str' and 'int'
"""
length = len(collection)
swapped = False
Expand Down
16 changes: 13 additions & 3 deletions tests/test_sorts.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import pytest

from sorts.binary_insertion_sort import binary_insertion_sort
from sorts.bubble_sort import bubble_sort_iterative
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
from sorts.comb_sort import comb_sort
Expand Down Expand Up @@ -89,6 +89,16 @@ def test_sort_matches_builtin(sort, case):
assert list(sort(list(case))) == sorted(case)


def test_binary_insertion_sort_rejects_non_comparable_items():
@pytest.mark.parametrize(
"sort",
[
binary_insertion_sort,
bubble_sort_iterative,
bubble_sort_recursive,
insertion_sort,
],
ids=lambda f: f.__name__,
)
def test_sort_rejects_non_comparable_items(sort):
with pytest.raises(TypeError):
binary_insertion_sort([1, "a"])
sort([1, "a"])
Loading