Skip to content

Commit

Permalink
Completed solution. Limited functionality to process data types (int,…
Browse files Browse the repository at this point in the history
… float, string, bool)
  • Loading branch information
oleksandr-maksymikhin committed Jan 6, 2025
1 parent 9652dd2 commit d30c5b3
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 36 deletions.
24 changes: 20 additions & 4 deletions solutions/merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
"""
A module for merging of two sorted collection into one sorted collection.
Processed data types: int, float, string, bool.
Module contents:
- merge: merge two sorted collections into one sorted collection.
Expand All @@ -17,17 +18,17 @@ def merge(left: list[any], right: list[any]) -> list[any]:
Combine two sorted homogeneous collections into one sorted collection
Parameters:
left: list[any], first sorted collection of type any.
right: list[any], second sorted collection of type any.
left: list[any], first sorted collection of data types (int, float, string, bool).
right: list[any], second sorted collection of data types (int, float, string, bool).
Returns -> list[any], collection of sorted elements with type any.
Returns -> list[any], sorted collection of data types (int, float, string, bool).
Raises:
AssertionError: left is not a collection.
AssertionError: right is not a collection.
AssertionError: left collection contains elements of different data types (non-homogeneous).
AssertionError: right collection contains elements of different data types (non-homogeneous).
AssertionError: data of left and right collections have different types (non-homogeneous).
AssertionError: left and right contain elements of different data types(non-homogeneous).
Examples:
>>> merge([2], [1])
Expand All @@ -37,6 +38,21 @@ def merge(left: list[any], right: list[any]) -> list[any]:
>>> merge([2, 5, 100500], [1, 9])
[1, 2, 5, 9, 100500]
"""
# defensive assertion to check that input is a collections are lists
assert isinstance(left, list), "Input left is not a collection"
assert isinstance(right, list), "Input right is not a collection"

# defensive assertion to check that input collections are homogeneous
assert all(
isinstance(item, type(left[0])) for item in left
), "Input left is not homogeneous"
assert all(
isinstance(item, type(right[0])) for item in right
), "Input right is not homogeneous"
assert isinstance(
left[0], type(right[0])
), "Input left and right are not homogeneous"

# check if left or right collection is empty
if len(left) == 0:
return right
Expand Down
32 changes: 28 additions & 4 deletions solutions/merge_sort.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
A module for sorting collection using merge sort algorithm.
A module for sorting non empty collection of build-in elementary Python data types
(int, float, string, bool) using merge sort algorithm.
Splitting and sorting function.
Module contents:
- merge_sort: splitting the collection and launching the merge.
- merge_sort: function that splits the collection and launching the merge.
Created on 2024-01-05
Author: Oleksandr Maksymikhin
Expand All @@ -20,12 +21,14 @@ def merge_sort(input_collection: list[any]) -> list[any]:
Sort elements in collection by splitting the collection in two parts and launching the merge.
Parameters:
input_collection: list[any], collection of unsorted data type any.
input_collection: list[any], collection of unsorted data of data types (int, float, string, bool).
Returns -> list[any], collection of sorted elements with type any.
Returns -> list[any], collection of sorted elements of data types (int, float, string, bool).
Raises:
AssertionError: if input is not a collection.
AssertionError: if input collection is empty.
AssertionError: if input is not a data type processed by module (int, float, string, bool).
AssertionError: if collection contains elements of different data types (non-homogeneous).
Examples:
Expand All @@ -36,6 +39,27 @@ def merge_sort(input_collection: list[any]) -> list[any]:
>>> merge_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 input collection is not empty
assert len(input_collection) > 0, "Collection is empty"

# defensive assertion to check that input data types are any of (int, float, string, bool)
assert (
isinstance(input_collection[0], int)
or isinstance(input_collection[0], float)
or isinstance(input_collection[0], str)
or isinstance(input_collection[0], bool)
), "Input data types is not processed. Processed data types (int, float, string, bool)"

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

# copy collection to avoid side effect
collection = input_collection.copy()
if len(collection) < 2:
return input_collection
Expand Down
60 changes: 32 additions & 28 deletions solutions/tests/test_merge_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
Test categories:
- Standard cases: lists of type int with different lengths
- Edge cases: empty lists, single element
- Different data type: char, string, bool
- Edge cases: single element
- Different data type: string, bool
- Defensive tests:
- side effects protection
- input is not a collection
- input of empty collection
- different data types in the input collection (non-homogeneous)
- input data types are not processed by module
Created on 2024-01-05
Author: Oleksandr Maksymikhin
Expand All @@ -24,69 +26,71 @@
class TestMergeSort(unittest.TestCase):
"""Test the merge_sort function."""

# Uncomment for predictive stepping
# test_1 = merge_sort([])
# test_2 = merge_sort([1])
# test_3 = merge_sort([2, 1])
# test_4 = merge_sort([3, 2, 1])
# test_5 = merge_sort([2, 3, 100500, 1])
# test_6 = merge_sort(["b", "a", "c"])
# test_7 = merge_sort(["daikon", "cabbage", "banana", "apple"])
# test_8 = merge_sort([True, False, True, False])
# test_10 = merge_sort("apple")
# test_11 = merge_sort([3, "two", 1])

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

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

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

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

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

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

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

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

def test_9_side_effect_protection(self):
def test_8_side_effect_protection(self):
"""It should return [3, 2, 1] of initial input"""
input_list = [3, 2, 1, 100500]
copy_for_sorting = input_list.copy()
merge_sort(copy_for_sorting)
self.assertEqual(input_list, [3, 2, 1, 100500])

def test_9_non_collection_input(self):
"""It should raise an assertion error if the input is not a collection"""
with self.assertRaises(AssertionError):
merge_sort("banana")

def test_10_non_homogeneous_collection_input(self):
"""It should raise an assertion error if the collection is non-homogeneous"""
with self.assertRaises(AssertionError):
merge_sort([3, 2, "one"])

def test_11_input_of_empty_collection(self):
"""It should raise an assertion error if the input data type is out of processed type"""
with self.assertRaises(AssertionError):
merge_sort([])

def test_12_input_of_non_processed_data_type(self):
"""It should raise an assertion error if the input data type is out of processed type"""
with self.assertRaises(AssertionError):
merge_sort([{1, "one"}, {2, "two"}])

0 comments on commit d30c5b3

Please sign in to comment.