Skip to content

Commit c07fe10

Browse files
💥 refactor(isPartitioned)!: Handle multiple pivots.
This fixes #65. BREAKING CHANGE: This changes the API.
1 parent 5d3ec6f commit c07fe10

File tree

7 files changed

+39
-17
lines changed

7 files changed

+39
-17
lines changed

src/utils/firstInversion.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,32 @@
66
* @param {ArrayLike} array
77
* @param {number} left
88
* @param {number} right
9-
* @param {number} p
9+
* @param {number[]} pivots
10+
* @param {number} pi
11+
* @param {number} pj
1012
* @return {number}
1113
*/
12-
const firstInversion = (compare, array, left, right, p) => {
14+
const firstInversion = (compare, array, left, right, pivots, pi, pj) => {
15+
let p = pivots[pi];
16+
let x = array[p];
1317
for (let k = left; k < p; ++k) {
14-
if (compare(array[k], array[p]) > 0) return k;
18+
if (compare(array[k], x) > 0) return k;
19+
}
20+
21+
while (++pi < pj) {
22+
const q = pivots[pi];
23+
const y = array[q];
24+
for (let k = p + 1; k < q; ++k) {
25+
if (compare(array[k], x) < 0) return k;
26+
if (compare(array[k], y) > 0) return k;
27+
}
28+
29+
p = q;
30+
x = y;
1531
}
1632

1733
for (let k = p + 1; k < right; ++k) {
18-
if (compare(array[k], array[p]) < 0) return k;
34+
if (compare(array[k], x) < 0) return k;
1935
}
2036

2137
return right;

src/utils/isPartitioned.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import firstInversion from './firstInversion.js';
88
* @param {ArrayLike} array
99
* @param {number} left
1010
* @param {number} right
11-
* @param {number} p
11+
* @param {number[]} pivots
12+
* @param {number} pi
13+
* @param {number} pj
1214
* @return {boolean}
1315
*/
14-
const isPartitioned = (compare, array, left, right, p) =>
15-
firstInversion(compare, array, left, right, p) === right;
16+
const isPartitioned = (compare, array, left, right, pivots, pi, pj) =>
17+
firstInversion(compare, array, left, right, pivots, pi, pj) === right;
1618

1719
export default isPartitioned;

test/src/isPartitioned.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ import {isPartitioned, firstInversion} from '../../src/index.js';
77
const macro = (t, array, left, right, p, k1, k2) => {
88
const n = array.length;
99

10-
t.true(firstInversion(increasing, array, left, right, p) === k1);
10+
t.is(firstInversion(increasing, array, left, right, [p], 0, 1), k1);
1111
if (k1 === right) {
12-
t.true(isPartitioned(increasing, array, left, right, p));
12+
t.true(isPartitioned(increasing, array, left, right, [p], 0, 1));
1313
}
1414

15-
t.true(firstInversion(decreasing, array, left, right, p) === k2);
15+
t.is(firstInversion(decreasing, array, left, right, [p], 0, 1), k2);
1616
if (k2 === right) {
17-
t.true(isPartitioned(decreasing, array, left, right, p));
17+
t.true(isPartitioned(decreasing, array, left, right, [p], 0, 1));
1818
}
1919

2020
t.is(array.length, n);
@@ -36,3 +36,9 @@ test(macro, [5, 4, 4, 5], 0, 4, 1, 0, 3);
3636
test(macro, [5, 4, 4, 5], 0, 4, 2, 0, 3);
3737
test(macro, [1, 0, 1, 1, 2, 3, 1, 0, 1], 3, 6, 4, 6, 3);
3838
test(macro, [1, 0, 1, 1, 2, 3, 1, 0, 1], 0, 9, 4, 6, 0);
39+
40+
test('multi', (t) => {
41+
const array = [0, 0, 0, 2, 2, 2, 4, 1, 3, 3, 3, 4];
42+
t.is(firstInversion(increasing, array, 0, array.length, [4, 9], 0, 2), 6);
43+
t.is(firstInversion(increasing, array, 0, array.length, [6, 9], 0, 2), 7);
44+
});

test/src/partition1.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function check(partitionname, method, ctor, n, comparename, compare) {
2828

2929
// TEST PREDICATE
3030

31-
t.true(isPartitioned(compare, a, 0, n, p), 'check partitioned');
31+
t.true(isPartitioned(compare, a, 0, n, [p], 0, 1), 'check partitioned');
3232
t.is(a.length, n, 'check length a');
3333
});
3434
}

test/src/partition2.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ function check(partitionname, method, ctor, n, comparename, compare) {
3232
// TEST PREDICATE
3333

3434
t.true(p <= q, 'check p <= q');
35-
t.true(isPartitioned(compare, a, 0, n, p), 'check partitioned p');
36-
t.true(isPartitioned(compare, a, 0, n, q), 'check partitioned q');
35+
t.true(isPartitioned(compare, a, 0, n, [p, q], 0, 2), 'check partitioned');
3736
t.is(a.length, n, 'check length a');
3837
});
3938
}

test/src/whole1.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function check(partitionname, method, ctor, n, comparename, compare) {
3030

3131
// TEST PREDICATE
3232

33-
t.true(isPartitioned(compare, a, 0, n, p), 'check partitioned');
33+
t.true(isPartitioned(compare, a, 0, n, [p], 0, 1), 'check partitioned');
3434
t.is(a.length, n, 'check length a');
3535
});
3636
}

test/src/whole2.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ function check(partitionname, method, ctor, n, comparename, compare) {
3434
// TEST PREDICATE
3535

3636
t.true(p <= q, 'check p <= q');
37-
t.true(isPartitioned(compare, a, 0, n, p), 'check partitioned p');
38-
t.true(isPartitioned(compare, a, 0, n, q), 'check partitioned q');
37+
t.true(isPartitioned(compare, a, 0, n, [p, q], 0, 2), 'check partitioned');
3938
t.is(a.length, n, 'check length a');
4039
});
4140
}

0 commit comments

Comments
 (0)