From ef44a181c624efe056d85271ae50455e1f0345d8 Mon Sep 17 00:00:00 2001 From: Adam Ross <14985050+R055A@users.noreply.github.com> Date: Tue, 17 Oct 2023 19:18:43 +0200 Subject: [PATCH 1/5] Consolidate bubble sort iterative and recursive --- sorts/bubble_sort.py | 67 ++++++++++++++++++++++++++++------ sorts/recursive_bubble_sort.py | 42 --------------------- 2 files changed, 56 insertions(+), 53 deletions(-) delete mode 100644 sorts/recursive_bubble_sort.py diff --git a/sorts/bubble_sort.py b/sorts/bubble_sort.py index 7da4362a5b97..d3bbf11e19f6 100644 --- a/sorts/bubble_sort.py +++ b/sorts/bubble_sort.py @@ -1,7 +1,7 @@ from typing import Any -def bubble_sort(collection: list[Any]) -> list[Any]: +def bubble_sort_iterative(collection: list[Any]) -> list[Any]: """Pure implementation of bubble sort algorithm in Python :param collection: some mutable ordered collection with heterogeneous @@ -9,25 +9,25 @@ def bubble_sort(collection: list[Any]) -> list[Any]: :return: the same collection ordered by ascending Examples: - >>> bubble_sort([0, 5, 2, 3, 2]) + >>> bubble_sort_iterative([0, 5, 2, 3, 2]) [0, 2, 2, 3, 5] - >>> bubble_sort([0, 5, 2, 3, 2]) == sorted([0, 5, 2, 3, 2]) + >>> bubble_sort_iterative([0, 5, 2, 3, 2]) == sorted([0, 5, 2, 3, 2]) True - >>> bubble_sort([]) == sorted([]) + >>> bubble_sort_iterative([]) == sorted([]) True - >>> bubble_sort([-2, -45, -5]) == sorted([-2, -45, -5]) + >>> bubble_sort_iterative([-2, -45, -5]) == sorted([-2, -45, -5]) True - >>> bubble_sort([-23, 0, 6, -4, 34]) == sorted([-23, 0, 6, -4, 34]) + >>> bubble_sort_iterative([-23, 0, 6, -4, 34]) == sorted([-23, 0, 6, -4, 34]) True - >>> bubble_sort(['d', 'a', 'b', 'e', 'c']) == sorted(['d', 'a', 'b', 'e', 'c']) + >>> bubble_sort_iterative(['d', 'a', 'b', 'e']) == sorted(['d', 'a', 'b', 'e']) True >>> import random >>> collection = random.sample(range(-50, 50), 100) - >>> bubble_sort(collection) == sorted(collection) + >>> bubble_sort_iterative(collection) == sorted(collection) True >>> import string >>> collection = random.choices(string.ascii_letters + string.digits, k=100) - >>> bubble_sort(collection) == sorted(collection) + >>> bubble_sort_iterative(collection) == sorted(collection) True """ length = len(collection) @@ -42,6 +42,44 @@ def bubble_sort(collection: list[Any]) -> list[Any]: return collection +def bubble_sort_recursive(list_data: list, length: int = 0) -> list: + """ + It is similar is bubble sort but recursive. + :param list_data: mutable ordered sequence of elements + :param length: length of list data + :return: the same list in ascending order + + >>> bubble_sort_recursive([0, 5, 2, 3, 2], 5) + [0, 2, 2, 3, 5] + + >>> bubble_sort_recursive([], 0) + [] + + >>> bubble_sort_recursive([-2, -45, -5], 3) + [-45, -5, -2] + + >>> bubble_sort_recursive([-23, 0, 6, -4, 34], 5) + [-23, -4, 0, 6, 34] + + >>> bubble_sort_recursive([-23, 0, 6, -4, 34], 5) == sorted([-23, 0, 6, -4, 34]) + True + + >>> bubble_sort_recursive(['z','a','y','b','x','c'], 6) + ['a', 'b', 'c', 'x', 'y', 'z'] + + >>> bubble_sort_recursive([1.1, 3.3, 5.5, 7.7, 2.2, 4.4, 6.6]) + [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7] + """ + length = length or len(list_data) + swapped = False + for i in range(length - 1): + if list_data[i] > list_data[i + 1]: + list_data[i], list_data[i + 1] = list_data[i + 1], list_data[i] + swapped = True + + return list_data if not swapped else bubble_sort_recursive(list_data, length - 1) + + if __name__ == "__main__": import doctest import time @@ -50,6 +88,13 @@ def bubble_sort(collection: list[Any]) -> list[Any]: user_input = input("Enter numbers separated by a comma:").strip() unsorted = [int(item) for item in user_input.split(",")] + + print("Iterative bubble sort:") + start = time.process_time() + print(*bubble_sort_iterative(unsorted), sep=",") + print(f"Processing time (iterative): {(time.process_time() - start) % 1e9 + 7}") + + print("\nRecursive bubble sort:") start = time.process_time() - print(*bubble_sort(unsorted), sep=",") - print(f"Processing time: {(time.process_time() - start)%1e9 + 7}") + print(bubble_sort_recursive(unsorted, len(unsorted))) + print(f"Processing time (recursive): {(time.process_time() - start) % 1e9 + 7}") diff --git a/sorts/recursive_bubble_sort.py b/sorts/recursive_bubble_sort.py deleted file mode 100644 index 82af89593e5b..000000000000 --- a/sorts/recursive_bubble_sort.py +++ /dev/null @@ -1,42 +0,0 @@ -def bubble_sort(list_data: list, length: int = 0) -> list: - """ - It is similar is bubble sort but recursive. - :param list_data: mutable ordered sequence of elements - :param length: length of list data - :return: the same list in ascending order - - >>> bubble_sort([0, 5, 2, 3, 2], 5) - [0, 2, 2, 3, 5] - - >>> bubble_sort([], 0) - [] - - >>> bubble_sort([-2, -45, -5], 3) - [-45, -5, -2] - - >>> bubble_sort([-23, 0, 6, -4, 34], 5) - [-23, -4, 0, 6, 34] - - >>> bubble_sort([-23, 0, 6, -4, 34], 5) == sorted([-23, 0, 6, -4, 34]) - True - - >>> bubble_sort(['z','a','y','b','x','c'], 6) - ['a', 'b', 'c', 'x', 'y', 'z'] - - >>> bubble_sort([1.1, 3.3, 5.5, 7.7, 2.2, 4.4, 6.6]) - [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7] - """ - length = length or len(list_data) - swapped = False - for i in range(length - 1): - if list_data[i] > list_data[i + 1]: - list_data[i], list_data[i + 1] = list_data[i + 1], list_data[i] - swapped = True - - return list_data if not swapped else bubble_sort(list_data, length - 1) - - -if __name__ == "__main__": - import doctest - - doctest.testmod() From 1dacbec715f53f868d32d3120885240326f5babb Mon Sep 17 00:00:00 2001 From: Adam Ross <14985050+R055A@users.noreply.github.com> Date: Tue, 17 Oct 2023 20:58:07 +0200 Subject: [PATCH 2/5] Update sorts/bubble_sort.py Co-authored-by: Christian Clauss --- sorts/bubble_sort.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sorts/bubble_sort.py b/sorts/bubble_sort.py index d3bbf11e19f6..0fb59555411f 100644 --- a/sorts/bubble_sort.py +++ b/sorts/bubble_sort.py @@ -42,7 +42,7 @@ def bubble_sort_iterative(collection: list[Any]) -> list[Any]: return collection -def bubble_sort_recursive(list_data: list, length: int = 0) -> list: +def bubble_sort_recursive(collection: list[Any]), length: int = 0) -> list[Any]: """ It is similar is bubble sort but recursive. :param list_data: mutable ordered sequence of elements From c7ea86e4e45dc8d95fa437fee4e1d892940b3705 Mon Sep 17 00:00:00 2001 From: Adam Ross <14985050+R055A@users.noreply.github.com> Date: Tue, 17 Oct 2023 21:47:57 +0200 Subject: [PATCH 3/5] Refactor bubble sort func signature, doctest, timer --- sorts/bubble_sort.py | 99 +++++++++++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 34 deletions(-) diff --git a/sorts/bubble_sort.py b/sorts/bubble_sort.py index 0fb59555411f..70a4d8288af4 100644 --- a/sorts/bubble_sort.py +++ b/sorts/bubble_sort.py @@ -11,6 +11,12 @@ def bubble_sort_iterative(collection: list[Any]) -> list[Any]: Examples: >>> bubble_sort_iterative([0, 5, 2, 3, 2]) [0, 2, 2, 3, 5] + >>> bubble_sort_iterative([]) + [] + >>> bubble_sort_iterative([-2, -45, -5]) + [-45, -5, -2] + >>> bubble_sort_iterative([-23, 0, 6, -4, 34]) + [-23, -4, 0, 6, 34] >>> bubble_sort_iterative([0, 5, 2, 3, 2]) == sorted([0, 5, 2, 3, 2]) True >>> bubble_sort_iterative([]) == sorted([]) @@ -21,13 +27,19 @@ def bubble_sort_iterative(collection: list[Any]) -> list[Any]: True >>> bubble_sort_iterative(['d', 'a', 'b', 'e']) == sorted(['d', 'a', 'b', 'e']) True + >>> bubble_sort_iterative(['z', 'a', 'y', 'b', 'x', 'c']) + ['a', 'b', 'c', 'x', 'y', 'z'] + >>> bubble_sort_iterative([1.1, 3.3, 5.5, 7.7, 2.2, 4.4, 6.6]) + [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] >>> import random - >>> collection = random.sample(range(-50, 50), 100) - >>> bubble_sort_iterative(collection) == sorted(collection) + >>> collection_arg = random.sample(range(-50, 50), 100) + >>> bubble_sort_iterative(collection_arg) == sorted(collection_arg) True >>> import string - >>> collection = random.choices(string.ascii_letters + string.digits, k=100) - >>> bubble_sort_iterative(collection) == sorted(collection) + >>> collection_arg = random.choices(string.ascii_letters + string.digits, k=100) + >>> bubble_sort_iterative(collection_arg) == sorted(collection_arg) True """ length = len(collection) @@ -42,59 +54,78 @@ def bubble_sort_iterative(collection: list[Any]) -> list[Any]: return collection -def bubble_sort_recursive(collection: list[Any]), length: int = 0) -> list[Any]: - """ - It is similar is bubble sort but recursive. - :param list_data: mutable ordered sequence of elements - :param length: length of list data +def bubble_sort_recursive(collection: list[Any]) -> list[Any]: + """It is similar iterative bubble sort but recursive. + + :param collection: mutable ordered sequence of elements :return: the same list in ascending order - >>> bubble_sort_recursive([0, 5, 2, 3, 2], 5) + Examples: + >>> bubble_sort_recursive([0, 5, 2, 3, 2]) [0, 2, 2, 3, 5] - - >>> bubble_sort_recursive([], 0) + >>> bubble_sort_iterative([]) [] - - >>> bubble_sort_recursive([-2, -45, -5], 3) + >>> bubble_sort_recursive([-2, -45, -5]) [-45, -5, -2] - - >>> bubble_sort_recursive([-23, 0, 6, -4, 34], 5) + >>> bubble_sort_recursive([-23, 0, 6, -4, 34]) [-23, -4, 0, 6, 34] - - >>> bubble_sort_recursive([-23, 0, 6, -4, 34], 5) == sorted([-23, 0, 6, -4, 34]) + >>> bubble_sort_recursive([0, 5, 2, 3, 2]) == sorted([0, 5, 2, 3, 2]) True - - >>> bubble_sort_recursive(['z','a','y','b','x','c'], 6) + >>> bubble_sort_recursive([]) == sorted([]) + True + >>> bubble_sort_recursive([-2, -45, -5]) == sorted([-2, -45, -5]) + True + >>> bubble_sort_recursive([-23, 0, 6, -4, 34]) == sorted([-23, 0, 6, -4, 34]) + True + >>> bubble_sort_recursive(['d', 'a', 'b', 'e']) == sorted(['d', 'a', 'b', 'e']) + True + >>> bubble_sort_recursive(['z', 'a', 'y', 'b', 'x', 'c']) ['a', 'b', 'c', 'x', 'y', 'z'] - >>> bubble_sort_recursive([1.1, 3.3, 5.5, 7.7, 2.2, 4.4, 6.6]) [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] + >>> import random + >>> collection_arg = random.sample(range(-50, 50), 100) + >>> bubble_sort_recursive(collection_arg) == sorted(collection_arg) + True + >>> import string + >>> collection_arg = random.choices(string.ascii_letters + string.digits, k=100) + >>> bubble_sort_recursive(collection_arg) == sorted(collection_arg) + True """ - length = length or len(list_data) + length = len(collection) swapped = False for i in range(length - 1): - if list_data[i] > list_data[i + 1]: - list_data[i], list_data[i + 1] = list_data[i + 1], list_data[i] + if collection[i] > collection[i + 1]: + collection[i], collection[i + 1] = collection[i + 1], collection[i] swapped = True - return list_data if not swapped else bubble_sort_recursive(list_data, length - 1) + return collection if not swapped else bubble_sort_recursive(collection) if __name__ == "__main__": import doctest - import time + from timeit import timeit doctest.testmod() user_input = input("Enter numbers separated by a comma:").strip() - unsorted = [int(item) for item in user_input.split(",")] - - print("Iterative bubble sort:") - start = time.process_time() + unsorted = [int(item) if isinstance(item, int) else float(item) + for item in user_input.split(",")] + + num_runs = 1000 + timer_iterative = timeit('bubble_sort_iterative(unsorted[:])', + globals=globals(), + number=num_runs) + timer_recursive = timeit('bubble_sort_recursive(unsorted[:])', + globals=globals(), + number=num_runs) + + print("\nIterative bubble sort:") print(*bubble_sort_iterative(unsorted), sep=",") - print(f"Processing time (iterative): {(time.process_time() - start) % 1e9 + 7}") + print(f"Processing time (iterative): {timer_iterative:.5f} s for {num_runs} runs") print("\nRecursive bubble sort:") - start = time.process_time() - print(bubble_sort_recursive(unsorted, len(unsorted))) - print(f"Processing time (recursive): {(time.process_time() - start) % 1e9 + 7}") + print(*bubble_sort_recursive(unsorted), sep=",") + print(f"Processing time (recursive): {timer_recursive:.5f} s for {num_runs} runs") From 525d16147a67874d07e4bfceef70c7204f454eda Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 17 Oct 2023 19:48:51 +0000 Subject: [PATCH 4/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- sorts/bubble_sort.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sorts/bubble_sort.py b/sorts/bubble_sort.py index 70a4d8288af4..2b58bcfe8c97 100644 --- a/sorts/bubble_sort.py +++ b/sorts/bubble_sort.py @@ -111,16 +111,18 @@ def bubble_sort_recursive(collection: list[Any]) -> list[Any]: doctest.testmod() user_input = input("Enter numbers separated by a comma:").strip() - unsorted = [int(item) if isinstance(item, int) else float(item) - for item in user_input.split(",")] + unsorted = [ + int(item) if isinstance(item, int) else float(item) + for item in user_input.split(",") + ] num_runs = 1000 - timer_iterative = timeit('bubble_sort_iterative(unsorted[:])', - globals=globals(), - number=num_runs) - timer_recursive = timeit('bubble_sort_recursive(unsorted[:])', - globals=globals(), - number=num_runs) + timer_iterative = timeit( + "bubble_sort_iterative(unsorted[:])", globals=globals(), number=num_runs + ) + timer_recursive = timeit( + "bubble_sort_recursive(unsorted[:])", globals=globals(), number=num_runs + ) print("\nIterative bubble sort:") print(*bubble_sort_iterative(unsorted), sep=",") From b37d3bb5114ea67e19c1a1dadbde1daf3e39eb50 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 19 Oct 2023 22:40:02 +0200 Subject: [PATCH 5/5] Update bubble_sort.py --- sorts/bubble_sort.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/sorts/bubble_sort.py b/sorts/bubble_sort.py index 2b58bcfe8c97..bdf85c70dd35 100644 --- a/sorts/bubble_sort.py +++ b/sorts/bubble_sort.py @@ -106,28 +106,25 @@ def bubble_sort_recursive(collection: list[Any]) -> list[Any]: if __name__ == "__main__": import doctest + from random import sample from timeit import timeit doctest.testmod() - user_input = input("Enter numbers separated by a comma:").strip() - unsorted = [ - int(item) if isinstance(item, int) else float(item) - for item in user_input.split(",") - ] - - num_runs = 1000 + # Benchmark: Iterative seems slightly faster than recursive. + num_runs = 10_000 + unsorted = sample(range(-50, 50), 100) timer_iterative = timeit( "bubble_sort_iterative(unsorted[:])", globals=globals(), number=num_runs ) - timer_recursive = timeit( - "bubble_sort_recursive(unsorted[:])", globals=globals(), number=num_runs - ) - print("\nIterative bubble sort:") print(*bubble_sort_iterative(unsorted), sep=",") - print(f"Processing time (iterative): {timer_iterative:.5f} s for {num_runs} runs") + print(f"Processing time (iterative): {timer_iterative:.5f}s for {num_runs:,} runs") + unsorted = sample(range(-50, 50), 100) + timer_recursive = timeit( + "bubble_sort_recursive(unsorted[:])", globals=globals(), number=num_runs + ) print("\nRecursive bubble sort:") print(*bubble_sort_recursive(unsorted), sep=",") - print(f"Processing time (recursive): {timer_recursive:.5f} s for {num_runs} runs") + print(f"Processing time (recursive): {timer_recursive:.5f}s for {num_runs:,} runs")