diff --git a/sorts/power_sort.py b/sorts/power_sort.py index da25e43d63fd..80cdc1200b9b 100644 --- a/sorts/power_sort.py +++ b/sorts/power_sort.py @@ -25,14 +25,12 @@ python power_sort.py """ -from __future__ import annotations - -from collections.abc import Callable +from collections.abc import Callable, Iterable from typing import Any -def _find_run( - arr: list, start: int, end: int, key: Callable[[Any], Any] | None = None +def _find_run[T]( + arr: list[T], start: int, end: int, key: Callable[[Any], Any] | None = None ) -> int: """ Detect a run (ascending or descending sequence) starting at 'start'. @@ -67,7 +65,7 @@ def _find_run( if start >= end - 1: return start + 1 - key_func = key if key else lambda element: element + key_func = key or (lambda element: element) run_end = start + 1 # Check if run is ascending or descending @@ -134,8 +132,8 @@ def _node_power(total_length: int, b1: int, n1: int, b2: int, n2: int) -> int: return power -def _merge( - arr: list, +def _merge[T]( + arr: list[T], start1: int, end1: int, end2: int, @@ -165,7 +163,7 @@ def _merge( >>> arr [1, 2, 3, 5, 6, 7] """ - key_func = key if key else lambda element: element + key_func = key or (lambda element: element) # Copy the runs to temporary storage left = arr[start1:end1] @@ -196,12 +194,12 @@ def _merge( k += 1 -def power_sort( - collection: list, +def power_sort[T]( + collection: Iterable[T], *, key: Callable[[Any], Any] | None = None, reverse: bool = False, -) -> list: +) -> list[T]: """ Sort a list using the PowerSort algorithm. @@ -243,26 +241,38 @@ def power_sort( ['apple', 'banana', 'cherry'] >>> power_sort([3.14, 2.71, 1.41, 1.73]) [1.41, 1.73, 2.71, 3.14] + >>> power_sort(value for value in [3, 1, 2]) # list + [1, 2, 3] + >>> power_sort(value for value in (3, 1, 2)) # tuple + [1, 2, 3] >>> power_sort([5, 2, 8, 1, 9], reverse=True) [9, 8, 5, 2, 1] + >>> power_sort(['apple', 'pie', 'a', 'longer']) + ['a', 'apple', 'longer', 'pie'] >>> power_sort(['apple', 'pie', 'a', 'longer'], key=len) ['a', 'pie', 'apple', 'longer'] + >>> power_sort(['apple', 'pie', 'a', 'longer'], reverse=True) + ['pie', 'longer', 'apple', 'a'] + >>> power_sort(['apple', 'pie', 'a', 'longer'], key=len, reverse=True) # Fix me! + ['a', 'pie', 'apple', 'longer'] >>> power_sort([(1, 'b'), (2, 'a'), (1, 'a')], key=lambda x: x[0]) [(1, 'b'), (1, 'a'), (2, 'a')] >>> power_sort([1, 2, 3, 2, 1, 2, 3, 4]) [1, 1, 2, 2, 2, 3, 3, 4] - >>> result = power_sort(list(range(100))) - >>> result == list(range(100)) + >>> power_sort(list(range(100))) == list(range(100)) True - >>> result = power_sort(list(reversed(range(50)))) - >>> result == list(range(50)) + >>> power_sort(list(reversed(range(50)))) == list(range(50)) True + >>> power_sort([1, "a"]) + Traceback (most recent call last): + ... + TypeError: '<' not supported between instances of 'str' and 'int' """ - if len(collection) <= 1: - return collection - - # Make a copy to avoid modifying the original if it's immutable + # Make a copy so any iterable is accepted and the original is not modified. arr = list(collection) + if len(arr) <= 1: + return arr + total_length = len(arr) # Adjust key function for reverse sorting diff --git a/tests/test_sorts.py b/tests/test_sorts.py index 88091d2809ed..5cfbacf30e6c 100644 --- a/tests/test_sorts.py +++ b/tests/test_sorts.py @@ -44,6 +44,7 @@ from sorts.odd_even_transposition_single_threaded import odd_even_transposition from sorts.pancake_sort import pancake_sort from sorts.patience_sort import patience_sort +from sorts.power_sort import power_sort from sorts.quick_sort import quick_sort from sorts.quick_sort_3_partition import three_way_radix_quicksort from sorts.recursive_insertion_sort import rec_insertion_sort @@ -117,6 +118,7 @@ def test_intro_sort_heap_fallback_preserves_surrounding_items(max_depth: int) -> odd_even_transposition, pancake_sort, patience_sort, + power_sort, quick_sort, recursive_quick_sort, reverse_selection_sort, @@ -198,6 +200,7 @@ def test_rec_insertion_sort(case) -> None: odd_even_transposition, pancake_sort, patience_sort, + power_sort, recursive_quick_sort, reverse_selection_sort, reversort,