|
1 | | -# Sleep sort (novelty) implementation |
2 | | -# This provides a fast simulated mode (default) plus an optional real threaded mode. |
3 | | - |
4 | 1 | from typing import List |
5 | 2 | import threading |
6 | 3 | import time |
7 | 4 |
|
8 | 5 |
|
9 | | -def sleep_sort(a: List[int], simulate: bool = True, scale: float = 0.01) -> None: |
| 6 | +def sleep_sort(numbers: List[int], simulate: bool = True, scale: float = 0.01) -> None: |
10 | 7 | """ |
11 | | - Sort the list a in-place using the sleep sort idea. |
| 8 | + Perform Sleep Sort on the given list of integers. |
| 9 | +
|
| 10 | + Sorts the list numbers in place using the Sleep Sort algorithm. |
12 | 11 |
|
13 | 12 | Behavior: |
14 | | - - Destructive: modifies list a. |
| 13 | + - Destructive: modifies the list numbers. |
15 | 14 | - Only accepts integers (positive, zero, or negative). |
16 | 15 | - Default simulate=True runs instantly by simulating timed wake-ups (safe for tests/CI). |
17 | | - - If simulate=False the function spawns one thread per element and uses time.sleep; |
18 | | - use that mode only for small inputs (and beware of real waiting). |
| 16 | + - If simulate=False, the function spawns one thread per element and uses time.sleep; |
| 17 | + this mode causes real waiting time proportional to element values. |
19 | 18 | - scale (seconds per unit) applies only when simulate=False. |
20 | 19 |
|
21 | | - >>> a = [3, 1, 2] |
22 | | - >>> b = sorted(a) |
23 | | - >>> sleep_sort(a) # simulated, fast |
24 | | - >>> a == b |
25 | | - True |
| 20 | + Examples |
| 21 | + -------- |
| 22 | + >>> nums = [3, 1, 2] |
| 23 | + >>> sleep_sort(nums) |
| 24 | + >>> nums |
| 25 | + [1, 2, 3] |
26 | 26 |
|
27 | | - >>> a = [0, 0, 1] |
28 | | - >>> sleep_sort(a) |
29 | | - >>> a |
| 27 | + >>> nums = [0, 0, 1] |
| 28 | + >>> sleep_sort(nums) |
| 29 | + >>> nums |
30 | 30 | [0, 0, 1] |
31 | 31 |
|
32 | | - >>> a = [-2, 1, 0] |
33 | | - >>> sleep_sort(a) |
34 | | - >>> a == sorted([-2, 1, 0]) |
35 | | - True |
| 32 | + >>> nums = [-2, 1, 0] |
| 33 | + >>> sleep_sort(nums) |
| 34 | + >>> nums |
| 35 | + [-2, 0, 1] |
36 | 36 |
|
37 | | - >>> sleep_sort([1.5, 2]) # non-integers not allowed |
38 | | - Traceback (most recent call last) |
| 37 | + >>> sleep_sort([1.5, 2]) |
| 38 | + Traceback (most recent call last): |
39 | 39 | ... |
40 | 40 | TypeError: integers only please |
41 | 41 | """ |
42 | | - # quick no-op for empty |
43 | | - if not a: |
| 42 | + if not numbers: |
44 | 43 | return |
45 | 44 |
|
46 | | - # type checks |
47 | | - if any(not isinstance(x, int) for x in a): |
| 45 | + if any(not isinstance(x, int) for x in numbers): |
48 | 46 | raise TypeError("integers only please") |
49 | 47 |
|
50 | | - # handle negatives by offsetting so all "sleep times" are non-negative |
51 | | - min_val = min(a) |
| 48 | + min_val = min(numbers) |
52 | 49 | offset = -min_val if min_val < 0 else 0 |
53 | 50 |
|
54 | 51 | if simulate: |
55 | | - # Simulated wake-up: bucket by wake time (value + offset), preserve original order |
| 52 | + # Simulated wake-up: bucket by wake time (value + offset), preserve order |
56 | 53 | buckets = {} |
57 | | - for idx, val in enumerate(a): |
| 54 | + for idx, val in enumerate(numbers): |
58 | 55 | wake = val + offset |
59 | 56 | buckets.setdefault(wake, []).append((idx, val)) |
60 | 57 | result: List[int] = [] |
61 | 58 | for wake in sorted(buckets.keys()): |
62 | | - # append in original order to make stable when values equal |
63 | 59 | for _, val in buckets[wake]: |
64 | 60 | result.append(val) |
65 | | - a[:] = result |
| 61 | + numbers[:] = result |
66 | 62 | return |
67 | 63 |
|
68 | | - # Real threaded mode (be careful: this actually sleeps) |
| 64 | + # Real threaded mode: causes actual delays proportional to element values |
69 | 65 | results: List[int] = [] |
70 | 66 | lock = threading.Lock() |
71 | 67 |
|
72 | 68 | def worker(value: int) -> None: |
73 | | - # sleep proportional to value (after offset), then append to results |
74 | 69 | time.sleep((value + offset) * scale) |
75 | 70 | with lock: |
76 | 71 | results.append(value) |
77 | 72 |
|
78 | 73 | threads: List[threading.Thread] = [] |
79 | | - for val in a: |
| 74 | + for val in numbers: |
80 | 75 | t = threading.Thread(target=worker, args=(val,)) |
81 | 76 | t.daemon = True |
82 | 77 | t.start() |
83 | 78 | threads.append(t) |
84 | 79 |
|
85 | | - # wait for threads to finish |
86 | 80 | for t in threads: |
87 | 81 | t.join() |
88 | 82 |
|
89 | | - # results is in the order threads woke up |
90 | | - a[:] = results |
91 | | - |
92 | | - |
93 | | -def main() -> None: |
94 | | - a = [8, 3, 2, 7, 4, 6, 8] |
95 | | - sleep_sort(a) # simulated (fast) |
96 | | - print("Sorted order is:", " ".join(map(str, a))) |
97 | | - |
98 | | - |
99 | | -if __name__ == "__main__": |
100 | | - main() |
| 83 | + numbers[:] = results |
0 commit comments