Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bubble sort #19

Merged
merged 9 commits into from
Jan 8, 2025
67 changes: 67 additions & 0 deletions solutions/bubble_sort.py
emrebiyik marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
A module for sorting collection using bubble sort algorithm.

Module contents:
- bubble_sort: sort the collection in ascending order.

Created on 2024-01-02
Author: Oleksandr Maksymikhin
"""


# def bubble_sort(input_collection: list[int]) -> list[int]:
def bubble_sort(input_collection: list[any]) -> list[any]:
emrebiyik marked this conversation as resolved.
Show resolved Hide resolved
"""Sort collection using bubble sort algorithm.

Sort elements in collection by swapping and moving larger elements to the end of collection.

Parameters:
input_collection: list[any], collection of unsorted data of any homogeneous type.

Returns -> list[any], collection of sorted elements with any data type.

Raises:
AssertionError: if input is not a collection.
AssertionError: if collection contains elements of different data types (non-homogeneous).

Examples:
>>> bubble_sort([1])
[1]
>>> bubble_sort([1, 3, 2])
[1, 2, 3]
>>> bubble_sort([3, 2, 100500, 1])
[1, 2, 3, 100500]
"""

# defensive assertion to check that input is a collection list
assert isinstance(input_collection, list), "Input is not a collection"

# defensive assertion to check that collection is homogeneous
assert all(
isinstance(item, type(input_collection[0])) for item in input_collection
), "Input collection is not homogeneous"

# copy collection to avoid side effect
collection = input_collection.copy()
# define collection length
collection_length = len(collection)
# first loop to traverse the collection
for current_item_index in range(collection_length):
# flag to break if the last run didn't swap any item
already_sorted = True
# second loop to compare/swap item with adjacent one
for swap_index in range(collection_length - current_item_index - 1):
# swap items if the next adjacent item is smaller
if collection[swap_index] > collection[swap_index + 1]:
(collection[swap_index], collection[swap_index + 1]) = (
collection[swap_index + 1],
collection[swap_index],
)
already_sorted = False
# break loop if the last run didn't swap any item
if already_sorted:
break
# return sorted collection
return collection
89 changes: 89 additions & 0 deletions solutions/tests/test_bubble_sort.py
emrebiyik marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Test module for bubble_sort() function.

Test categories:
- Standard cases: lists of type int with different lengths
- Edge cases: empty lists, single element
- Different data types: char, string, bool
- Defensive tests:
- side effects protection
- input is not a collection
- different data types in the input collection (non-homogeneous)

Created on 2024-01-03
Author: Oleksandr Maksymikhin
"""

import unittest

from ..bubble_sort import bubble_sort


class TestBubbleSort(unittest.TestCase):
"""Test the bubble_sort function."""

def test_1_empty_list(self):
"""It should return [] for input []"""
actual = bubble_sort([])
expected = []
self.assertEqual(actual, expected)

def test_2_one_int_element_list(self):
"""It should return [1] for input [1]"""
actual = bubble_sort([1])
expected = [1]
self.assertEqual(actual, expected)

def test_3_two_int_elements_list(self):
"""It should return [1, 2] for input [2, 1]"""
actual = bubble_sort([2, 1])
expected = [1, 2]
self.assertEqual(actual, expected)

def test_4_three_int_elements_list(self):
"""It should return [1, 2, 3] for input [3, 2, 1]"""
actual = bubble_sort([3, 2, 1])
expected = [1, 2, 3]
self.assertEqual(actual, expected)

def test_5_four_int_elements_list_big_number(self):
"""It should return [1, 2, 3, 100500] for input [2, 3, 100500, 1]"""
actual = bubble_sort([2, 3, 100500, 1])
expected = [1, 2, 3, 100500]
self.assertEqual(actual, expected)

def test_6_char_elements_list(self):
"""It should return ["a", "b", "c"] for input ["b", "a", "c"]"""
actual = bubble_sort(["b", "a", "c"])
expected = ["a", "b", "c"]
self.assertEqual(actual, expected)

def test_7_string_elements_list(self):
"""It should return ["apple", "banana", "cabbage"] for input ["cabbage", "banana", "apple"]"""
actual = bubble_sort(["cabbage", "banana", "apple"])
expected = ["apple", "banana", "cabbage"]
self.assertEqual(actual, expected)

def test_8_bool_elements_list(self):
"""It should return [False, False, True, True] for input [True, False, True, False]"""
actual = bubble_sort([True, False, True, False])
expected = [False, False, True, True]
self.assertEqual(actual, expected)

def test_9_side_effect_protection(self):
"""It should return [3, 2, 1] of initial input"""
input_list = [3, 2, 1]
bubble_sort(input_list)
self.assertEqual(input_list, [3, 2, 1])

def test_10_non_collection_input(self):
"""It should raise an assertion error if the input is not a collection"""
with self.assertRaises(AssertionError):
bubble_sort("apple")

def test_11_non_homogeneous_collection_input(self):
"""It should raise an assertion error if the collection is non-homogeneous"""
with self.assertRaises(AssertionError):
bubble_sort([3, "two", 1])
emrebiyik marked this conversation as resolved.
Show resolved Hide resolved
Loading