Skip to content

Commit 35e74cb

Browse files
committed
### Summary
Add `sort/sleep_sort.py`: a novelty sleep-sort implementation with a simulated mode (safe for CI) and an optional real threaded mode. ### Files added - sort/sleep_sort.py ### Notes - File name is snake_case. - Includes doctests; tested with `python -m doctest -v sort/sleep_sort.py`. - Follows repository style. If this addresses an issue, add: `Fixes #<issue-number>`
1 parent f13ad5d commit 35e74cb

1 file changed

Lines changed: 100 additions & 0 deletions

File tree

sorts/sleep_sort.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Sleep sort (novelty) implementation
2+
# This provides a fast simulated mode (default) plus an optional real threaded mode.
3+
4+
from typing import List
5+
import threading
6+
import time
7+
8+
9+
def sleep_sort(a: List[int], simulate: bool = True, scale: float = 0.01) -> None:
10+
"""
11+
Sort the list a in-place using the sleep sort idea.
12+
13+
Behavior:
14+
- Destructive: modifies list a.
15+
- Only accepts integers (positive, zero, or negative).
16+
- 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).
19+
- scale (seconds per unit) applies only when simulate=False.
20+
21+
>>> a = [3, 1, 2]
22+
>>> b = sorted(a)
23+
>>> sleep_sort(a) # simulated, fast
24+
>>> a == b
25+
True
26+
27+
>>> a = [0, 0, 1]
28+
>>> sleep_sort(a)
29+
>>> a
30+
[0, 0, 1]
31+
32+
>>> a = [-2, 1, 0]
33+
>>> sleep_sort(a)
34+
>>> a == sorted([-2, 1, 0])
35+
True
36+
37+
>>> sleep_sort([1.5, 2]) # non-integers not allowed
38+
Traceback (most recent call last)
39+
...
40+
TypeError: integers only please
41+
"""
42+
# quick no-op for empty
43+
if not a:
44+
return
45+
46+
# type checks
47+
if any(not isinstance(x, int) for x in a):
48+
raise TypeError("integers only please")
49+
50+
# handle negatives by offsetting so all "sleep times" are non-negative
51+
min_val = min(a)
52+
offset = -min_val if min_val < 0 else 0
53+
54+
if simulate:
55+
# Simulated wake-up: bucket by wake time (value + offset), preserve original order
56+
buckets = {}
57+
for idx, val in enumerate(a):
58+
wake = val + offset
59+
buckets.setdefault(wake, []).append((idx, val))
60+
result: List[int] = []
61+
for wake in sorted(buckets.keys()):
62+
# append in original order to make stable when values equal
63+
for _, val in buckets[wake]:
64+
result.append(val)
65+
a[:] = result
66+
return
67+
68+
# Real threaded mode (be careful: this actually sleeps)
69+
results: List[int] = []
70+
lock = threading.Lock()
71+
72+
def worker(value: int) -> None:
73+
# sleep proportional to value (after offset), then append to results
74+
time.sleep((value + offset) * scale)
75+
with lock:
76+
results.append(value)
77+
78+
threads: List[threading.Thread] = []
79+
for val in a:
80+
t = threading.Thread(target=worker, args=(val,))
81+
t.daemon = True
82+
t.start()
83+
threads.append(t)
84+
85+
# wait for threads to finish
86+
for t in threads:
87+
t.join()
88+
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()

0 commit comments

Comments
 (0)