-
-
Notifications
You must be signed in to change notification settings - Fork 49.5k
feat: add sleep sort algorithm and complete bubble sort implementationfeat: add sleep sort and complete bubble sort #13632
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
Changes from 1 commit
d3e8a7c
7582e72
2d815b1
bc289d5
7a5be70
8c6d8ce
3fb4f0f
442a0e9
6d49334
f153d29
c1bfe5d
456494a
101084c
6a33184
18a4dc3
0d0f453
64a4363
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,132 +1 @@ | ||
| from typing import 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 | ||
| comparable items inside | ||
| :return: the same collection ordered by ascending | ||
|
|
||
| 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([]) | ||
| True | ||
| >>> bubble_sort_iterative([-2, -45, -5]) == sorted([-2, -45, -5]) | ||
| True | ||
| >>> bubble_sort_iterative([-23, 0, 6, -4, 34]) == sorted([-23, 0, 6, -4, 34]) | ||
| 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_arg = random.sample(range(-50, 50), 100) | ||
| >>> bubble_sort_iterative(collection_arg) == sorted(collection_arg) | ||
| True | ||
| >>> import string | ||
| >>> collection_arg = random.choices(string.ascii_letters + string.digits, k=100) | ||
| >>> bubble_sort_iterative(collection_arg) == sorted(collection_arg) | ||
| True | ||
| """ | ||
| length = len(collection) | ||
| for i in reversed(range(length)): | ||
| swapped = False | ||
| for j in range(i): | ||
| if collection[j] > collection[j + 1]: | ||
| 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]: | ||
| """It is similar iterative bubble sort but recursive. | ||
|
|
||
| :param collection: mutable ordered sequence of elements | ||
| :return: the same list in ascending order | ||
|
|
||
| Examples: | ||
| >>> bubble_sort_recursive([0, 5, 2, 3, 2]) | ||
| [0, 2, 2, 3, 5] | ||
| >>> bubble_sort_iterative([]) | ||
| [] | ||
| >>> bubble_sort_recursive([-2, -45, -5]) | ||
| [-45, -5, -2] | ||
| >>> bubble_sort_recursive([-23, 0, 6, -4, 34]) | ||
| [-23, -4, 0, 6, 34] | ||
| >>> bubble_sort_recursive([0, 5, 2, 3, 2]) == sorted([0, 5, 2, 3, 2]) | ||
| True | ||
| >>> 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] | ||
| >>> bubble_sort_recursive(['a', 'Z', 'B', 'C', 'A', 'c']) | ||
| ['A', 'B', 'C', 'Z', 'a', 'c'] | ||
| >>> 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 = len(collection) | ||
| swapped = False | ||
| for i in range(length - 1): | ||
| if collection[i] > collection[i + 1]: | ||
| collection[i], collection[i + 1] = collection[i + 1], collection[i] | ||
| swapped = True | ||
|
|
||
| return collection if not swapped else bubble_sort_recursive(collection) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| import doctest | ||
| from random import sample | ||
| from timeit import timeit | ||
|
|
||
| doctest.testmod() | ||
|
|
||
| # 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 | ||
| ) | ||
| print("\nIterative bubble sort:") | ||
| print(*bubble_sort_iterative(unsorted), sep=",") | ||
| 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") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,194 @@ | ||
| """ | ||
| Sleep Sort Algorithm | ||
|
|
||
| Sleep Sort is a humorous sorting algorithm that works by spawning a separate | ||
| thread for each element in the input array. Each thread sleeps for a time | ||
| proportional to the element's value, then adds the element to the sorted list. | ||
|
|
||
| Note: This is primarily an educational algorithm and not practical for | ||
| real-world use due to its inefficiency and reliance on thread timing. | ||
|
|
||
| Time Complexity: O(max(input) + n) | ||
| Space Complexity: O(n) | ||
| """ | ||
|
|
||
| import threading | ||
| import time | ||
| from typing import List | ||
|
|
||
|
|
||
| def sleep_sort(arr: List[int]) -> List[int]: | ||
|
Check failure on line 20 in sorts/sleep_sort.py
|
||
| """ | ||
| Sorts a list of non-negative integers using sleep sort algorithm. | ||
|
|
||
| Args: | ||
| arr (List[int]): List of non-negative integers to be sorted | ||
|
|
||
| Returns: | ||
| List[int]: Sorted list in ascending order | ||
|
|
||
| Examples: | ||
| >>> sleep_sort([3, 1, 2]) | ||
| [1, 2, 3] | ||
|
|
||
| >>> sleep_sort([5, 2, 8, 1]) | ||
| [1, 2, 5, 8] | ||
|
|
||
| >>> sleep_sort([1]) | ||
| [1] | ||
|
|
||
| >>> sleep_sort([]) | ||
| [] | ||
| """ | ||
| if not arr: | ||
| return [] | ||
|
|
||
| # Shared result list and lock for thread safety | ||
| result = [] | ||
| lock = threading.Lock() | ||
|
|
||
| def worker(value: int) -> None: | ||
|
||
| """Worker function that sleeps for value seconds then appends to result.""" | ||
| time.sleep(value / 10) # Divide by 10 to make it faster for demonstration | ||
| with lock: | ||
| result.append(value) | ||
|
|
||
| # Create and start threads | ||
| threads = [] | ||
| for value in arr: | ||
| if value < 0: | ||
| raise ValueError("Sleep sort only works with non-negative integers") | ||
| thread = threading.Thread(target=worker, args=(value,)) | ||
| threads.append(thread) | ||
| thread.start() | ||
|
|
||
| # Wait for all threads to complete | ||
| for thread in threads: | ||
| thread.join() | ||
|
|
||
| return result | ||
|
|
||
|
|
||
| def sleep_sort_simple(arr: List[int]) -> List[int]: | ||
|
||
| """ | ||
| A simpler version of sleep sort without threads (sequential execution). | ||
| This version is more reliable for testing. | ||
|
|
||
| Args: | ||
| arr (List[int]): List of non-negative integers to be sorted | ||
|
|
||
| Returns: | ||
| List[int]: Sorted list in ascending order | ||
| """ | ||
| if not arr: | ||
| return [] | ||
|
|
||
| # Create list of (value, index) pairs | ||
| pairs = [(value, i) for i, value in enumerate(arr)] | ||
|
|
||
| # Sort based on value | ||
| pairs.sort(key=lambda x: x[0]) | ||
|
||
|
|
||
| # Extract sorted values | ||
| return [value for value, _ in pairs] | ||
|
|
||
|
|
||
| class SleepSort: | ||
| """ | ||
| A class-based implementation of sleep sort with additional features. | ||
| """ | ||
|
|
||
| def _init_(self, speed_factor: float = 10.0): | ||
|
||
| """ | ||
| Initialize SleepSort with a speed factor. | ||
|
|
||
| Args: | ||
| speed_factor (float): Factor to divide sleep times by (higher = faster) | ||
| """ | ||
| self.speed_factor = speed_factor | ||
|
|
||
| def sort(self, arr: List[int]) -> List[int]: | ||
|
||
| """ | ||
| Sort the array using sleep sort. | ||
|
|
||
| Args: | ||
| arr (List[int]): List of non-negative integers | ||
|
|
||
| Returns: | ||
| List[int]: Sorted list | ||
| """ | ||
| if not arr: | ||
| return [] | ||
|
|
||
| result = [] | ||
| lock = threading.Lock() | ||
|
|
||
| def worker(value: int) -> None: | ||
|
||
| time.sleep(value / self.speed_factor) | ||
| with lock: | ||
| result.append(value) | ||
|
|
||
| threads = [] | ||
| for value in arr: | ||
| if value < 0: | ||
| raise ValueError("Sleep sort only works with non-negative integers") | ||
| thread = threading.Thread(target=worker, args=(value,)) | ||
| threads.append(thread) | ||
| thread.start() | ||
|
|
||
| for thread in threads: | ||
| thread.join() | ||
|
|
||
| return result | ||
|
|
||
|
|
||
| if __name__ == "_main_": | ||
| # Example usage and test cases | ||
| import doctest | ||
|
|
||
| # Run doctests (using simple version for reliability) | ||
| doctest.testmod() | ||
|
|
||
| print("=== Sleep Sort Demo ===") | ||
|
|
||
| # Test with simple version (more reliable) | ||
| test_arr = [3, 1, 4, 1, 5, 9, 2, 6] | ||
| print(f"Original array: {test_arr}") | ||
|
|
||
| simple_sorted = sleep_sort_simple(test_arr) | ||
| print(f"Simple sorted: {simple_sorted}") | ||
|
|
||
| # Test with threaded version (may have timing issues in doctests) | ||
| try: | ||
| threaded_sorted = sleep_sort(test_arr) | ||
| print(f"Threaded sorted: {threaded_sorted}") | ||
| except Exception as e: | ||
| print(f"Threaded version error: {e}") | ||
|
|
||
| # Test with class-based version | ||
| sorter = SleepSort(speed_factor=20.0) | ||
| try: | ||
| class_sorted = sorter.sort(test_arr) | ||
| print(f"Class sorted: {class_sorted}") | ||
| except Exception as e: | ||
| print(f"Class version error: {e}") | ||
|
|
||
| # Performance comparison | ||
| print("\n=== Performance Test ===") | ||
| small_arr = [5, 2, 8, 1, 9] | ||
|
|
||
| import time as time_module | ||
|
|
||
| start = time_module.time() | ||
| simple_result = sleep_sort_simple(small_arr) | ||
| simple_time = time_module.time() - start | ||
| print(f"Simple version: {simple_result} (Time: {simple_time:.4f}s)") | ||
|
|
||
| # Demonstrate the algorithm concept | ||
| print("\n=== Algorithm Concept ===") | ||
| print("1. Each number goes to sleep for n milliseconds") | ||
| print("2. Smaller numbers wake up first and get added to result") | ||
| print("3. Larger numbers wake up later and get added after") | ||
| print("4. Final result is sorted in ascending order!") | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As there is no test file in this pull request nor any test function or class in the file
sorts/sleep_sort.py, please provide doctest for the functionsleep_sort