Skip to content
Closed
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
23 changes: 18 additions & 5 deletions sorts/bubble_sort.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
from typing import Any
from typing import Protocol


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



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 @@ -50,6 +55,10 @@ def bubble_sort_iterative(collection: list[Any]) -> list[Any]:
[1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7]
>>> bubble_sort_iterative([1, 3.3, 5, 7.7, 2, 4.4, 6])
[1, 2, 3.3, 4.4, 5, 6, 7.7]
>>> bubble_sort_iterative([1, "a"])
Traceback (most recent call last):
...
TypeError: '<' not supported between instances of 'str' and 'int'
>>> import random
>>> collection_arg = random.sample(range(-50, 50), 100)
>>> bubble_sort_iterative(collection_arg) == sorted(collection_arg)
Expand All @@ -63,15 +72,15 @@ def bubble_sort_iterative(collection: list[Any]) -> list[Any]:
for i in reversed(range(length)):
swapped = False
for j in range(i):
if collection[j] > collection[j + 1]:
if collection[j + 1] < collection[j]:
swapped = True
collection[j], collection[j + 1] = collection[j + 1], collection[j]
if not swapped:
break # Stop iteration if the collection is sorted.
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 @@ -114,6 +123,10 @@ def bubble_sort_recursive(collection: list[Any]) -> list[Any]:
[1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7]
>>> bubble_sort_recursive([1, 3.3, 5, 7.7, 2, 4.4, 6])
[1, 2, 3.3, 4.4, 5, 6, 7.7]
>>> bubble_sort_recursive([1, "a"])
Traceback (most recent call last):
...
TypeError: '<' not supported between instances of 'str' and 'int'
>>> bubble_sort_recursive(['a', 'Z', 'B', 'C', 'A', 'c'])
['A', 'B', 'C', 'Z', 'a', 'c']
>>> import random
Expand All @@ -128,7 +141,7 @@ def bubble_sort_recursive(collection: list[Any]) -> list[Any]:
length = len(collection)
swapped = False
for i in range(length - 1):
if collection[i] > collection[i + 1]:
if collection[i + 1] < collection[i]:
collection[i], collection[i + 1] = collection[i + 1], collection[i]
swapped = True

Expand Down
8 changes: 7 additions & 1 deletion 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 @@ -92,3 +92,9 @@ def test_sort_matches_builtin(sort, case):
def test_binary_insertion_sort_rejects_non_comparable_items():
with pytest.raises(TypeError):
binary_insertion_sort([1, "a"])


@pytest.mark.parametrize("sort", [bubble_sort_iterative, bubble_sort_recursive])
def test_bubble_sort_rejects_non_comparable_items(sort):
with pytest.raises(TypeError):
sort([1, "a"])