| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| import std.range : assumeSorted; | |
| int[] a = [ 1, 2, 3 ]; | |
| int[] b = [ 4, 0, 6, 5 ]; | |
| completeSort(assumeSorted(a), b); | |
| assert(a == [ 0, 1, 2 ]); | |
| assert(b == [ 3, 4, 5, 6 ]); | |
| } | |
| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| assert([1, 1, 2].isSorted); | |
| // strictly monotonic doesn't allow duplicates | |
| assert(![1, 1, 2].isStrictlyMonotonic); | |
| int[] arr = [4, 3, 2, 1]; | |
| assert(!isSorted(arr)); | |
| assert(!isStrictlyMonotonic(arr)); | |
| assert(isSorted!"a > b"(arr)); | |
| assert(isStrictlyMonotonic!"a > b"(arr)); | |
| sort(arr); | |
| assert(isSorted(arr)); | |
| assert(isStrictlyMonotonic(arr)); | |
| } | |
| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| assert(ordered(42, 42, 43)); | |
| assert(!strictlyOrdered(43, 42, 45)); | |
| assert(ordered(42, 42, 43)); | |
| assert(!strictlyOrdered(42, 42, 43)); | |
| assert(!ordered(43, 42, 45)); | |
| // Ordered lexicographically | |
| assert(ordered("Jane", "Jim", "Joe")); | |
| assert(strictlyOrdered("Jane", "Jim", "Joe")); | |
| // Incidentally also ordered by length decreasing | |
| assert(ordered!((a, b) => a.length > b.length)("Jane", "Jim", "Joe")); | |
| // ... but not strictly so: "Jim" and "Joe" have the same length | |
| assert(!strictlyOrdered!((a, b) => a.length > b.length)("Jane", "Jim", "Joe")); | |
| } | |
| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| import std.algorithm.mutation : SwapStrategy; | |
| import std.algorithm.searching : count, find; | |
| import std.conv : text; | |
| import std.range.primitives : empty; | |
| auto Arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; | |
| auto arr = Arr.dup; | |
| static bool even(int a) { return (a & 1) == 0; } | |
| // Partition arr such that even numbers come first | |
| auto r = partition!(even)(arr); | |
| // Now arr is separated in evens and odds. | |
| // Numbers may have become shuffled due to instability | |
| assert(r == arr[5 .. $]); | |
| assert(count!(even)(arr[0 .. 5]) == 5); | |
| assert(find!(even)(r).empty); | |
| // Can also specify the predicate as a string. | |
| // Use 'a' as the predicate argument name | |
| arr[] = Arr[]; | |
| r = partition!(q{(a & 1) == 0})(arr); | |
| assert(r == arr[5 .. $]); | |
| // Now for a stable partition: | |
| arr[] = Arr[]; | |
| r = partition!(q{(a & 1) == 0}, SwapStrategy.stable)(arr); | |
| // Now arr is [2 4 6 8 10 1 3 5 7 9], and r points to 1 | |
| assert(arr == [2, 4, 6, 8, 10, 1, 3, 5, 7, 9] && r == arr[5 .. $]); | |
| // In case the predicate needs to hold its own state, use a delegate: | |
| arr[] = Arr[]; | |
| int x = 3; | |
| // Put stuff greater than 3 on the left | |
| bool fun(int a) { return a > x; } | |
| r = partition!(fun, SwapStrategy.semistable)(arr); | |
| // Now arr is [4 5 6 7 8 9 10 2 3 1] and r points to 2 | |
| assert(arr == [4, 5, 6, 7, 8, 9, 10, 2, 3, 1] && r == arr[7 .. $]); | |
| } | |
| @safe nothrow unittest | |
| { | |
| import std.algorithm.sorting; | |
| int[] a = [5, 3, 2, 6, 4, 1, 3, 7]; | |
| size_t pivot = pivotPartition(a, a.length / 2); | |
| import std.algorithm.searching : all; | |
| assert(a[0 .. pivot].all!(x => x <= a[pivot])); | |
| assert(a[pivot .. $].all!(x => x >= a[pivot])); | |
| } | |
| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| int[] r = [ 1, 3, 5, 7, 8, 2, 4, ]; | |
| assert(isPartitioned!"a & 1"(r)); | |
| } | |
| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| auto a = [ 8, 3, 4, 1, 4, 7, 4 ]; | |
| auto pieces = partition3(a, 4); | |
| assert(pieces[0] == [ 1, 3 ]); | |
| assert(pieces[1] == [ 4, 4, 4 ]); | |
| assert(pieces[2] == [ 8, 7 ]); | |
| } | |
| @system unittest | |
| { | |
| import std.algorithm.sorting; | |
| immutable(int[]) arr = [ 2, 3, 1, 5, 0 ]; | |
| // index using pointers | |
| auto index1 = new immutable(int)*[arr.length]; | |
| makeIndex!("a < b")(arr, index1); | |
| assert(isSorted!("*a < *b")(index1)); | |
| // index using offsets | |
| auto index2 = new size_t[arr.length]; | |
| makeIndex!("a < b")(arr, index2); | |
| assert(isSorted! | |
| ((size_t a, size_t b){ return arr[a] < arr[b];}) | |
| (index2)); | |
| } | |
| @safe pure nothrow unittest | |
| { | |
| import std.algorithm.sorting; | |
| import std.algorithm.comparison : equal; | |
| import std.range : retro; | |
| int[] a = [1, 3, 5]; | |
| int[] b = [2, 3, 4]; | |
| assert(a.merge(b).equal([1, 2, 3, 3, 4, 5])); | |
| assert(a.merge(b).retro.equal([5, 4, 3, 3, 2, 1])); | |
| } | |
| @safe pure nothrow unittest | |
| { | |
| import std.algorithm.sorting; | |
| import std.algorithm.comparison : equal; | |
| import std.range : retro; | |
| import std.traits : CommonType; | |
| alias S = short; | |
| alias I = int; | |
| alias D = double; | |
| S[] a = [1, 2, 3]; | |
| I[] b = [50, 60]; | |
| D[] c = [10, 20, 30, 40]; | |
| auto m = merge(a, b, c); | |
| static assert(is(typeof(m.front) == CommonType!(S, I, D))); | |
| assert(equal(m, [1, 2, 3, 10, 20, 30, 40, 50, 60])); | |
| assert(equal(m.retro, [60, 50, 40, 30, 20, 10, 3, 2, 1])); | |
| m.popFront(); | |
| assert(equal(m, [2, 3, 10, 20, 30, 40, 50, 60])); | |
| m.popBack(); | |
| assert(equal(m, [2, 3, 10, 20, 30, 40, 50])); | |
| m.popFront(); | |
| assert(equal(m, [3, 10, 20, 30, 40, 50])); | |
| m.popBack(); | |
| assert(equal(m, [3, 10, 20, 30, 40])); | |
| m.popFront(); | |
| assert(equal(m, [10, 20, 30, 40])); | |
| m.popBack(); | |
| assert(equal(m, [10, 20, 30])); | |
| m.popFront(); | |
| assert(equal(m, [20, 30])); | |
| m.popBack(); | |
| assert(equal(m, [20])); | |
| m.popFront(); | |
| assert(m.empty); | |
| } | |
| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| import std.algorithm.mutation : SwapStrategy; | |
| static struct Point { int x, y; } | |
| auto pts1 = [ Point(0, 0), Point(5, 5), Point(0, 1), Point(0, 2) ]; | |
| auto pts2 = [ Point(0, 0), Point(0, 1), Point(0, 2), Point(5, 5) ]; | |
| multiSort!("a.x < b.x", "a.y < b.y", SwapStrategy.unstable)(pts1); | |
| assert(pts1 == pts2); | |
| } | |
| @safe pure nothrow unittest | |
| { | |
| import std.algorithm.sorting; | |
| int[] array = [ 1, 2, 3, 4 ]; | |
| // sort in descending order | |
| array.sort!("a > b"); | |
| assert(array == [ 4, 3, 2, 1 ]); | |
| // sort in ascending order | |
| array.sort(); | |
| assert(array == [ 1, 2, 3, 4 ]); | |
| // sort with reusable comparator and chain | |
| alias myComp = (x, y) => x > y; | |
| assert(array.sort!(myComp).release == [ 4, 3, 2, 1 ]); | |
| } | |
| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| // Showcase stable sorting | |
| import std.algorithm.mutation : SwapStrategy; | |
| string[] words = [ "aBc", "a", "abc", "b", "ABC", "c" ]; | |
| sort!("toUpper(a) < toUpper(b)", SwapStrategy.stable)(words); | |
| assert(words == [ "a", "aBc", "abc", "ABC", "b", "c" ]); | |
| } | |
| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| // Sorting floating-point numbers in presence of NaN | |
| double[] numbers = [-0.0, 3.0, -2.0, double.nan, 0.0, -double.nan]; | |
| import std.algorithm.comparison : equal; | |
| import std.math.operations : cmp; | |
| import std.math.traits : isIdentical; | |
| sort!((a, b) => cmp(a, b) < 0)(numbers); | |
| double[] sorted = [-double.nan, -2.0, -0.0, 0.0, 3.0, double.nan]; | |
| assert(numbers.equal!isIdentical(sorted)); | |
| } | |
| @safe pure unittest | |
| { | |
| import std.algorithm.sorting; | |
| import std.algorithm.iteration : map; | |
| import std.numeric : entropy; | |
| auto lowEnt = [ 1.0, 0, 0 ], | |
| midEnt = [ 0.1, 0.1, 0.8 ], | |
| highEnt = [ 0.31, 0.29, 0.4 ]; | |
| auto arr = new double[][3]; | |
| arr[0] = midEnt; | |
| arr[1] = lowEnt; | |
| arr[2] = highEnt; | |
| schwartzSort!(entropy, "a > b")(arr); | |
| assert(arr[0] == highEnt); | |
| assert(arr[1] == midEnt); | |
| assert(arr[2] == lowEnt); | |
| assert(isSorted!("a > b")(map!(entropy)(arr))); | |
| } | |
| @system unittest | |
| { | |
| import std.algorithm.sorting; | |
| int[] a = [ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ]; | |
| partialSort(a, 5); | |
| assert(a[0 .. 5] == [ 0, 1, 2, 3, 4 ]); | |
| } | |
| @system unittest | |
| { | |
| import std.algorithm.sorting; | |
| int[] a = [5, 7, 2, 6, 7]; | |
| int[] b = [2, 1, 5, 6, 7, 3, 0]; | |
| partialSort(a, b); | |
| assert(a == [0, 1, 2, 2, 3]); | |
| } | |
| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| int[] v = [ 25, 7, 9, 2, 0, 5, 21 ]; | |
| topN!"a < b"(v, 100); | |
| assert(v == [ 25, 7, 9, 2, 0, 5, 21 ]); | |
| auto n = 4; | |
| topN!((a, b) => a < b)(v, n); | |
| assert(v[n] == 9); | |
| } | |
| @system unittest | |
| { | |
| import std.algorithm.sorting; | |
| int[] a = [ 5, 7, 2, 6, 7 ]; | |
| int[] b = [ 2, 1, 5, 6, 7, 3, 0 ]; | |
| topN(a, b); | |
| sort(a); | |
| assert(a == [0, 1, 2, 2, 3]); | |
| } | |
| @system unittest | |
| { | |
| import std.algorithm.sorting; | |
| import std.typecons : Yes; | |
| int[] a = [ 10, 16, 2, 3, 1, 5, 0 ]; | |
| int[] b = new int[3]; | |
| topNCopy(a, b, Yes.sortOutput); | |
| assert(b == [ 0, 1, 2 ]); | |
| } | |
| @system unittest | |
| { | |
| import std.algorithm.sorting; | |
| import std.typecons : Yes; | |
| // Construct index to top 3 elements using numerical indices: | |
| int[] a = [ 10, 2, 7, 5, 8, 1 ]; | |
| int[] index = new int[3]; | |
| topNIndex(a, index, Yes.sortOutput); | |
| assert(index == [5, 1, 3]); // because a[5]==1, a[1]==2, a[3]==5 | |
| // Construct index to top 3 elements using pointer indices: | |
| int*[] ptrIndex = new int*[3]; | |
| topNIndex(a, ptrIndex, Yes.sortOutput); | |
| assert(ptrIndex == [ &a[5], &a[1], &a[3] ]); | |
| } | |
| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| // Step through all permutations of a sorted array in lexicographic order | |
| int[] a = [1,2,3]; | |
| assert(nextPermutation(a) == true); | |
| assert(a == [1,3,2]); | |
| assert(nextPermutation(a) == true); | |
| assert(a == [2,1,3]); | |
| assert(nextPermutation(a) == true); | |
| assert(a == [2,3,1]); | |
| assert(nextPermutation(a) == true); | |
| assert(a == [3,1,2]); | |
| assert(nextPermutation(a) == true); | |
| assert(a == [3,2,1]); | |
| assert(nextPermutation(a) == false); | |
| assert(a == [1,2,3]); | |
| } | |
| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| // Step through permutations of an array containing duplicate elements: | |
| int[] a = [1,1,2]; | |
| assert(nextPermutation(a) == true); | |
| assert(a == [1,2,1]); | |
| assert(nextPermutation(a) == true); | |
| assert(a == [2,1,1]); | |
| assert(nextPermutation(a) == false); | |
| assert(a == [1,1,2]); | |
| } | |
| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| // Step through even permutations of a sorted array in lexicographic order | |
| int[] a = [1,2,3]; | |
| assert(nextEvenPermutation(a) == true); | |
| assert(a == [2,3,1]); | |
| assert(nextEvenPermutation(a) == true); | |
| assert(a == [3,1,2]); | |
| assert(nextEvenPermutation(a) == false); | |
| assert(a == [1,2,3]); | |
| } | |
| @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| import std.math.algebraic : sqrt; | |
| // Print the 60 vertices of a uniform truncated icosahedron (soccer ball) | |
| enum real Phi = (1.0 + sqrt(5.0)) / 2.0; // Golden ratio | |
| real[][] seeds = [ | |
| [0.0, 1.0, 3.0*Phi], | |
| [1.0, 2.0+Phi, 2.0*Phi], | |
| [Phi, 2.0, Phi^^3] | |
| ]; | |
| size_t n; | |
| foreach (seed; seeds) | |
| { | |
| // Loop over even permutations of each seed | |
| do | |
| { | |
| // Loop over all sign changes of each permutation | |
| size_t i; | |
| do | |
| { | |
| // Generate all possible sign changes | |
| for (i=0; i < seed.length; i++) | |
| { | |
| if (seed[i] != 0.0) | |
| { | |
| seed[i] = -seed[i]; | |
| if (seed[i] < 0.0) | |
| break; | |
| } | |
| } | |
| n++; | |
| } while (i < seed.length); | |
| } while (nextEvenPermutation(seed)); | |
| } | |
| assert(n == 60); | |
| } | |
| pure @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| auto src = [0, 1, 2, 3, 4, 5, 6]; | |
| auto rslt = [4, 0, 6, 2, 1, 3, 5]; | |
| src = nthPermutation(src, 2982); | |
| assert(src == rslt); | |
| } | |
| pure @safe unittest | |
| { | |
| import std.algorithm.sorting; | |
| auto src = [0, 1, 2, 3, 4, 5, 6]; | |
| auto rslt = [4, 0, 6, 2, 1, 3, 5]; | |
| bool worked = nthPermutationImpl(src, 2982); | |
| assert(worked); | |
| assert(src == rslt); | |
| } | |