Skip to content
34 changes: 29 additions & 5 deletions sorts/cyclic_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
python -m doctest -v cyclic_sort.py
or
python3 -m doctest -v cyclic_sort.py

For manual testing run:
python cyclic_sort.py
or
Expand All @@ -27,20 +28,42 @@ def cyclic_sort(nums: list[int]) -> list[int]:
[]
>>> cyclic_sort([3, 5, 2, 1, 4])
[1, 2, 3, 4, 5]

>>> cyclic_sort([1, 2, 2])
Traceback (most recent call last):
...
ValueError: All numbers must be unique, got 2

>>> cyclic_sort([1, 5])
Traceback (most recent call last):
...
ValueError: All numbers must be in range 1 to 2, got 5
"""

# Input validation
seen = set()
n = len(nums)

for num in nums:
if num in seen:
message = f"All numbers must be unique, got {num}"
raise ValueError(message)

if num < 1 or num > n:
message = f"All numbers must be in range 1 to {n}, got {num}"
raise ValueError(message)

seen.add(num)

# Perform cyclic sort
index = 0
while index < len(nums):
# Calculate the correct index for the current element
correct_index = nums[index] - 1
# If the current element is not at its correct position,
# swap it with the element at its correct index

if index != correct_index:
nums[index], nums[correct_index] = nums[correct_index], nums[index]

else:
# If the current element is already in its correct position,
# move to the next element
index += 1

return nums
Expand All @@ -50,6 +73,7 @@ def cyclic_sort(nums: list[int]) -> list[int]:
import doctest

doctest.testmod()

user_input = input("Enter numbers separated by a comma:\n").strip()
unsorted = [int(item) for item in user_input.split(",")]
print(*cyclic_sort(unsorted), sep=",")