Skip to content

Commit 6fd4c61

Browse files
committed
#481 fair_partition
1 parent 71133a2 commit 6fd4c61

4 files changed

Lines changed: 79 additions & 0 deletions

File tree

src/solutions/chapter7/__init__.py

Whitespace-only changes.

src/solutions/chapter7/section1/__init__.py

Whitespace-only changes.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from book.data_structures import Array
2+
from book.data_structures import CT
3+
from util import range_of
4+
5+
6+
def fair_partition(A: Array[CT], p: int, r: int) -> int:
7+
"""Partitions an array into two subarrays, the low side and the high side, such that each element in the low side of
8+
the partition is less than or equal to the pivot value, which is, in turn, less than or equal to each element in the
9+
high side. Distributes elements equal to the pivot value evenly to the low side and to the high side.
10+
11+
Implements:
12+
Fair-Partition
13+
14+
Args:
15+
A: an Array to partition
16+
p: the lower index of the subarray to partition
17+
r: the upper index of the subarray to partition
18+
19+
Returns:
20+
The index q, such that each element in A[p:q - 1] is less than or equal to A[q], and that A[q] is less than or
21+
equal to each element in A[q + 1:r]. If all the elements in A[p:r] are equal, returns q = (p + r) // 2.
22+
"""
23+
x = A[r]
24+
i = p - 1
25+
low = False
26+
for j in range_of(p, to=r - 1):
27+
if A[j] < x:
28+
i += 1
29+
A[i], A[j] = A[j], A[i]
30+
elif A[j] == x:
31+
if low:
32+
i += 1
33+
A[i], A[j] = A[j], A[i]
34+
low = not low
35+
A[i + 1], A[r] = A[r], A[i + 1]
36+
return i + 1
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import math
2+
3+
from hypothesis import given
4+
from hypothesis import strategies as st
5+
from hypothesis.strategies import integers
6+
from hypothesis.strategies import just
7+
from hypothesis.strategies import lists
8+
9+
from solutions.chapter7.section1.exercise2 import fair_partition
10+
from test_case import ClrsTestCase
11+
from test_util import create_array
12+
from util import range_of
13+
14+
15+
class TestChapter7(ClrsTestCase):
16+
17+
@given(st.data())
18+
def test_fair_partition(self, data):
19+
elements = data.draw(lists(integers(), min_size=1))
20+
A = create_array(elements)
21+
n = len(elements)
22+
23+
actual_split_index = fair_partition(A, 1, n)
24+
25+
left_max = -math.inf
26+
right_min = math.inf
27+
for i in range_of(1, to=actual_split_index):
28+
left_max = max(left_max, A[i])
29+
for i in range_of(actual_split_index + 1, to=n):
30+
right_min = min(right_min, A[i])
31+
self.assertLessEqual(left_max, right_min)
32+
self.assertArrayPermuted(A, elements, end=n)
33+
34+
@given(st.data())
35+
def test_fair_partition_all_values_equal(self, data):
36+
value = data.draw(integers())
37+
elements = data.draw(lists(just(value), min_size=1))
38+
A = create_array(elements)
39+
n = len(elements)
40+
41+
actual_split_index = fair_partition(A, 1, n)
42+
43+
self.assertEqual(actual_split_index, (n + 1) // 2)

0 commit comments

Comments
 (0)