Skip to content

Commit bff5fe7

Browse files
committed
Make bubble sort support comparable items
1 parent d0f9b6e commit bff5fe7

2 files changed

Lines changed: 27 additions & 6 deletions

File tree

sorts/bubble_sort.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
from typing import Any
1+
from typing import Protocol, TypeVar
22

33

4-
def bubble_sort_iterative(collection: list[Any]) -> list[Any]:
4+
class Comparable(Protocol):
5+
def __lt__(self, other: object, /) -> bool: ...
6+
7+
8+
T = TypeVar("T", bound=Comparable)
9+
10+
11+
def bubble_sort_iterative(collection: list[T]) -> list[T]:
512
"""Pure implementation of the bubble sort algorithm in Python (iterative).
613
714
Bubble sort works by repeatedly stepping through the collection,
@@ -50,6 +57,10 @@ def bubble_sort_iterative(collection: list[Any]) -> list[Any]:
5057
[1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7]
5158
>>> bubble_sort_iterative([1, 3.3, 5, 7.7, 2, 4.4, 6])
5259
[1, 2, 3.3, 4.4, 5, 6, 7.7]
60+
>>> bubble_sort_iterative([1, "a"])
61+
Traceback (most recent call last):
62+
...
63+
TypeError: '<' not supported between instances of 'str' and 'int'
5364
>>> import random
5465
>>> collection_arg = random.sample(range(-50, 50), 100)
5566
>>> bubble_sort_iterative(collection_arg) == sorted(collection_arg)
@@ -63,15 +74,15 @@ def bubble_sort_iterative(collection: list[Any]) -> list[Any]:
6374
for i in reversed(range(length)):
6475
swapped = False
6576
for j in range(i):
66-
if collection[j] > collection[j + 1]:
77+
if collection[j + 1] < collection[j]:
6778
swapped = True
6879
collection[j], collection[j + 1] = collection[j + 1], collection[j]
6980
if not swapped:
7081
break # Stop iteration if the collection is sorted.
7182
return collection
7283

7384

74-
def bubble_sort_recursive(collection: list[Any]) -> list[Any]:
85+
def bubble_sort_recursive(collection: list[T]) -> list[T]:
7586
"""Pure implementation of the bubble sort algorithm in Python (recursive).
7687
7788
Functionally identical to the iterative version: each call makes a
@@ -114,6 +125,10 @@ def bubble_sort_recursive(collection: list[Any]) -> list[Any]:
114125
[1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7]
115126
>>> bubble_sort_recursive([1, 3.3, 5, 7.7, 2, 4.4, 6])
116127
[1, 2, 3.3, 4.4, 5, 6, 7.7]
128+
>>> bubble_sort_recursive([1, "a"])
129+
Traceback (most recent call last):
130+
...
131+
TypeError: '<' not supported between instances of 'str' and 'int'
117132
>>> bubble_sort_recursive(['a', 'Z', 'B', 'C', 'A', 'c'])
118133
['A', 'B', 'C', 'Z', 'a', 'c']
119134
>>> import random
@@ -128,7 +143,7 @@ def bubble_sort_recursive(collection: list[Any]) -> list[Any]:
128143
length = len(collection)
129144
swapped = False
130145
for i in range(length - 1):
131-
if collection[i] > collection[i + 1]:
146+
if collection[i + 1] < collection[i]:
132147
collection[i], collection[i + 1] = collection[i + 1], collection[i]
133148
swapped = True
134149

tests/test_sorts.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import pytest
1818

1919
from sorts.binary_insertion_sort import binary_insertion_sort
20-
from sorts.bubble_sort import bubble_sort_iterative
20+
from sorts.bubble_sort import bubble_sort_iterative, bubble_sort_recursive
2121
from sorts.circle_sort import circle_sort
2222
from sorts.cocktail_shaker_sort import cocktail_shaker_sort
2323
from sorts.comb_sort import comb_sort
@@ -92,3 +92,9 @@ def test_sort_matches_builtin(sort, case):
9292
def test_binary_insertion_sort_rejects_non_comparable_items():
9393
with pytest.raises(TypeError):
9494
binary_insertion_sort([1, "a"])
95+
96+
97+
@pytest.mark.parametrize("sort", [bubble_sort_iterative, bubble_sort_recursive])
98+
def test_bubble_sort_rejects_non_comparable_items(sort):
99+
with pytest.raises(TypeError):
100+
sort([1, "a"])

0 commit comments

Comments
 (0)