forked from TheAlgorithms/Python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dutch_national_flag_sort.py
98 lines (85 loc) · 3.58 KB
/
dutch_national_flag_sort.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
"""
A pure implementation of Dutch national flag (DNF) sort algorithm in Python.
Dutch National Flag algorithm is an algorithm originally designed by Edsger Dijkstra.
It is the most optimal sort for 3 unique values (eg. 0, 1, 2) in a sequence. DNF can
sort a sequence of n size with [0 <= a[i] <= 2] at guaranteed O(n) complexity in a
single pass.
The flag of the Netherlands consists of three colors: white, red, and blue.
The task is to randomly arrange balls of white, red, and blue in such a way that balls
of the same color are placed together. DNF sorts a sequence of 0, 1, and 2's in linear
time that does not consume any extra space. This algorithm can be implemented only on
a sequence that contains three unique elements.
1) Time complexity is O(n).
2) Space complexity is O(1).
More info on: https://en.wikipedia.org/wiki/Dutch_national_flag_problem
For doctests run following command:
python3 -m doctest -v dutch_national_flag_sort.py
For manual testing run:
python dnf_sort.py
"""
# Python program to sort a sequence containing only 0, 1 and 2 in a single pass.
red = 0 # The first color of the flag.
white = 1 # The second color of the flag.
blue = 2 # The third color of the flag.
colors = (red, white, blue)
def dutch_national_flag_sort(sequence: list) -> list:
"""
A pure Python implementation of Dutch National Flag sort algorithm.
:param data: 3 unique integer values (e.g., 0, 1, 2) in an sequence
:return: The same collection in ascending order
>>> dutch_national_flag_sort([])
[]
>>> dutch_national_flag_sort([0])
[0]
>>> dutch_national_flag_sort([2, 1, 0, 0, 1, 2])
[0, 0, 1, 1, 2, 2]
>>> dutch_national_flag_sort([0, 1, 1, 0, 1, 2, 1, 2, 0, 0, 0, 1])
[0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2]
>>> dutch_national_flag_sort("abacab")
Traceback (most recent call last):
...
ValueError: The elements inside the sequence must contains only (0, 1, 2) values
>>> dutch_national_flag_sort("Abacab")
Traceback (most recent call last):
...
ValueError: The elements inside the sequence must contains only (0, 1, 2) values
>>> dutch_national_flag_sort([3, 2, 3, 1, 3, 0, 3])
Traceback (most recent call last):
...
ValueError: The elements inside the sequence must contains only (0, 1, 2) values
>>> dutch_national_flag_sort([-1, 2, -1, 1, -1, 0, -1])
Traceback (most recent call last):
...
ValueError: The elements inside the sequence must contains only (0, 1, 2) values
>>> dutch_national_flag_sort([1.1, 2, 1.1, 1, 1.1, 0, 1.1])
Traceback (most recent call last):
...
ValueError: The elements inside the sequence must contains only (0, 1, 2) values
"""
if not sequence:
return []
if len(sequence) == 1:
return list(sequence)
low = 0
high = len(sequence) - 1
mid = 0
while mid <= high:
if sequence[mid] == colors[0]:
sequence[low], sequence[mid] = sequence[mid], sequence[low]
low += 1
mid += 1
elif sequence[mid] == colors[1]:
mid += 1
elif sequence[mid] == colors[2]:
sequence[mid], sequence[high] = sequence[high], sequence[mid]
high -= 1
else:
msg = f"The elements inside the sequence must contains only {colors} values"
raise ValueError(msg)
return sequence
if __name__ == "__main__":
import doctest
doctest.testmod()
user_input = input("Enter numbers separated by commas:\n").strip()
unsorted = [int(item.strip()) for item in user_input.split(",")]
print(f"{dutch_national_flag_sort(unsorted)}")