mirror of
https://github.com/dlang/phobos.git
synced 2025-05-05 01:20:40 +03:00
Refactor: reduce global imports.
This commit is contained in:
parent
9dc4c34379
commit
5551facc2f
5 changed files with 206 additions and 24 deletions
|
@ -1,18 +1,12 @@
|
|||
// Written in the D programming language.
|
||||
module std.algorithm.comparison;
|
||||
|
||||
import std.algorithm : reverse; // FIXME: ugly hack
|
||||
import std.algorithm.iteration : filter, map;
|
||||
|
||||
// FIXME
|
||||
import std.functional; // : unaryFun, binaryFun;
|
||||
import std.range.primitives;
|
||||
|
||||
import std.traits;
|
||||
// FIXME
|
||||
import std.typecons; // : tuple, Tuple;
|
||||
// FIXME
|
||||
import std.typetuple; // : TypeTuple, staticMap, allSatisfy, anySatisfy;
|
||||
|
||||
/**
|
||||
Find $(D value) _among $(D values), returning the 1-based index
|
||||
|
@ -80,6 +74,8 @@ efficient search, but one that only supports matching on equality:
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.typetuple : TypeTuple;
|
||||
|
||||
if (auto pos = 3.among(1, 2, 3))
|
||||
assert(pos == 3);
|
||||
else
|
||||
|
@ -307,6 +303,7 @@ auto castSwitch(choices...)(Object switchObject)
|
|||
///
|
||||
unittest
|
||||
{
|
||||
import std.algorithm.iteration : map;
|
||||
import std.format : format;
|
||||
|
||||
class A
|
||||
|
@ -714,6 +711,7 @@ range of range (of range...) comparisons.
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.iteration : map;
|
||||
import std.math : approxEqual;
|
||||
import std.internal.test.dummyrange;
|
||||
|
||||
|
@ -879,6 +877,8 @@ struct Levenshtein(Range, alias equals, CostType = size_t)
|
|||
|
||||
EditOp[] path()
|
||||
{
|
||||
import std.algorithm : reverse; // FIXME
|
||||
|
||||
EditOp[] result;
|
||||
size_t i = rows - 1, j = cols - 1;
|
||||
// restore the path
|
||||
|
@ -1052,6 +1052,7 @@ size_t levenshteinDistance(alias equals = "a == b", Range1, Range2)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.iteration : filter;
|
||||
import std.uni : toUpper;
|
||||
|
||||
assert(levenshteinDistance("cat", "rat") == 1);
|
||||
|
|
|
@ -1,17 +1,10 @@
|
|||
// Written in the D programming language.
|
||||
module std.algorithm.iteration;
|
||||
|
||||
// FIXME
|
||||
import std.algorithm : algoFormat, copy, find;
|
||||
|
||||
import std.algorithm.comparison : equal, max, min;
|
||||
|
||||
// FIXME
|
||||
import std.functional; // : unaryFun, binaryFun;
|
||||
import std.range.primitives;
|
||||
import std.traits;
|
||||
// FIXME
|
||||
import std.typetuple; // : TypeTuple, staticMap, allSatisfy, anySatisfy;
|
||||
|
||||
/++
|
||||
$(D cache) eagerly evaluates $(D front) of $(D range)
|
||||
|
@ -54,6 +47,7 @@ if (isBidirectionalRange!Range)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.stdio, std.range;
|
||||
import std.typecons : tuple;
|
||||
|
||||
|
@ -108,6 +102,7 @@ same cost or side effects.
|
|||
+/
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range;
|
||||
int i = 0;
|
||||
|
||||
|
@ -124,6 +119,7 @@ same cost or side effects.
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range;
|
||||
auto a = [1, 2, 3, 4];
|
||||
assert(equal(a.map!"(a - 1)*a"().cache(), [ 0, 2, 6, 12]));
|
||||
|
@ -136,6 +132,8 @@ same cost or side effects.
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
//immutable test
|
||||
static struct S
|
||||
{
|
||||
|
@ -152,6 +150,8 @@ same cost or side effects.
|
|||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
//safety etc
|
||||
auto a = [1, 2, 3, 4];
|
||||
assert(equal(a.cache(), a));
|
||||
|
@ -192,6 +192,8 @@ private struct Cache(R, bool bidir)
|
|||
|
||||
private
|
||||
{
|
||||
import std.typetuple : TypeTuple;
|
||||
|
||||
alias E = ElementType!R;
|
||||
alias UE = Unqual!E;
|
||||
|
||||
|
@ -326,6 +328,8 @@ template map(fun...) if (fun.length >= 1)
|
|||
{
|
||||
auto map(Range)(Range r) if (isInputRange!(Unqual!Range))
|
||||
{
|
||||
import std.typetuple : staticMap;
|
||||
|
||||
alias AppliedReturnType(alias f) = typeof(f(r.front));
|
||||
|
||||
static if (fun.length > 1)
|
||||
|
@ -355,6 +359,7 @@ template map(fun...) if (fun.length >= 1)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : chain;
|
||||
int[] arr1 = [ 1, 2, 3, 4 ];
|
||||
int[] arr2 = [ 5, 6 ];
|
||||
|
@ -387,6 +392,7 @@ it separately:
|
|||
*/
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.conv : to;
|
||||
|
||||
alias stringize = map!(to!string);
|
||||
|
@ -504,6 +510,7 @@ private struct MapResult(alias fun, Range)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.conv : to;
|
||||
import std.functional : adjoin;
|
||||
|
||||
|
@ -525,6 +532,7 @@ private struct MapResult(alias fun, Range)
|
|||
|
||||
unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.internal.test.dummyrange;
|
||||
import std.ascii : toUpper;
|
||||
import std.range;
|
||||
|
@ -626,6 +634,7 @@ unittest
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range;
|
||||
auto LL = iota(1L, 4L);
|
||||
auto m = map!"a*a"(LL);
|
||||
|
@ -650,6 +659,7 @@ unittest
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range;
|
||||
//slicing infinites
|
||||
auto rr = iota(0, 5).cycle().map!"a * a"();
|
||||
|
@ -693,6 +703,7 @@ template filter(alias predicate) if (is(typeof(unaryFun!predicate)))
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.math : approxEqual;
|
||||
import std.range;
|
||||
|
||||
|
@ -767,6 +778,7 @@ private struct FilterResult(alias pred, Range)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.internal.test.dummyrange;
|
||||
import std.range;
|
||||
|
||||
|
@ -822,6 +834,8 @@ private struct FilterResult(alias pred, Range)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
int[] a = [ 3, 4 ];
|
||||
const aConst = a;
|
||||
auto r = filter!("a > 3")(aConst);
|
||||
|
@ -840,6 +854,7 @@ private struct FilterResult(alias pred, Range)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.functional : compose, pipe;
|
||||
|
||||
assert(equal(compose!(map!"2 * a", filter!"a & 1")([1,2,3,4,5]),
|
||||
|
@ -850,6 +865,8 @@ private struct FilterResult(alias pred, Range)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
int x = 10;
|
||||
int underX(int a) { return a < x; }
|
||||
const(int)[] list = [ 1, 2, 10, 11, 3, 4 ];
|
||||
|
@ -881,7 +898,9 @@ template filterBidirectional(alias pred)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range;
|
||||
|
||||
int[] arr = [ 1, 2, 3, 4, 5 ];
|
||||
auto small = filterBidirectional!("a < 3")(arr);
|
||||
static assert(isBidirectionalRange!(typeof(small)));
|
||||
|
@ -1045,6 +1064,7 @@ Group!(pred, Range) group(alias pred = "a == b", Range)(Range r)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ];
|
||||
|
@ -1054,6 +1074,7 @@ Group!(pred, Range) group(alias pred = "a == b", Range)(Range r)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.internal.test.dummyrange;
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
|
@ -1359,6 +1380,8 @@ auto groupBy(alias pred, EquivRelation equivRelation, Range)(Range r)
|
|||
/// Showing usage with binary predicate:
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
// Grouping by particular attribute of each element:
|
||||
auto data = [
|
||||
[1, 1],
|
||||
|
@ -1393,6 +1416,8 @@ auto groupBy(alias pred, EquivRelation equivRelation, Range)(Range r)
|
|||
/// Showing usage with unary predicate:
|
||||
pure @safe nothrow unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
// Grouping by particular attribute of each element:
|
||||
auto range =
|
||||
[
|
||||
|
@ -1436,6 +1461,8 @@ pure @safe nothrow unittest
|
|||
|
||||
pure @safe nothrow unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
struct Item { int x, y; }
|
||||
|
||||
// Force R to have only an input range API with reference semantics, so
|
||||
|
@ -1504,6 +1531,7 @@ pure @safe nothrow unittest
|
|||
// Issue 13595
|
||||
unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
auto r = [1, 2, 3, 4, 5, 6, 7, 8, 9].groupBy!((x, y) => ((x*y) % 3) == 0);
|
||||
assert(r.equal!equal([
|
||||
[1],
|
||||
|
@ -1698,6 +1726,7 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.conv : text;
|
||||
|
||||
debug(std_algorithm) scope(success)
|
||||
|
@ -1717,6 +1746,7 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR)
|
|||
|
||||
unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range.primitives;
|
||||
import std.range.interfaces;
|
||||
// joiner() should work for non-forward ranges too.
|
||||
|
@ -1726,6 +1756,7 @@ unittest
|
|||
|
||||
unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range;
|
||||
|
||||
// Related to issue 8061
|
||||
|
@ -1774,6 +1805,8 @@ unittest
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
// Transience correctness test
|
||||
struct TransientRange
|
||||
{
|
||||
|
@ -1909,6 +1942,7 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR))
|
|||
|
||||
unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range.interfaces;
|
||||
import std.range : repeat;
|
||||
|
||||
|
@ -1951,6 +1985,8 @@ unittest
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
struct TransientRange
|
||||
{
|
||||
@safe:
|
||||
|
@ -1993,6 +2029,9 @@ unittest
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm : algoFormat; // FIXME
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
struct TransientRange
|
||||
{
|
||||
@safe:
|
||||
|
@ -2069,6 +2108,8 @@ See_Also:
|
|||
+/
|
||||
template reduce(fun...) if (fun.length >= 1)
|
||||
{
|
||||
import std.typetuple : staticMap;
|
||||
|
||||
alias binfuns = staticMap!(binaryFun, fun);
|
||||
static if (fun.length > 1)
|
||||
import std.typecons : tuple, isTuple;
|
||||
|
@ -2195,6 +2236,7 @@ remarkable power and flexibility.
|
|||
*/
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : max, min;
|
||||
import std.math : approxEqual;
|
||||
import std.range;
|
||||
|
||||
|
@ -2249,6 +2291,7 @@ The number of seeds must be correspondingly increased.
|
|||
*/
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : max, min;
|
||||
import std.math : approxEqual, sqrt;
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
|
@ -2270,6 +2313,7 @@ The number of seeds must be correspondingly increased.
|
|||
|
||||
unittest
|
||||
{
|
||||
import std.algorithm.comparison : max, min;
|
||||
import std.exception : assertThrown;
|
||||
import std.range;
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
@ -2343,6 +2387,7 @@ unittest
|
|||
@safe unittest
|
||||
{
|
||||
// Issue #10408 - Two-function reduce of a const array.
|
||||
import std.algorithm.comparison : max, min;
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
const numbers = [10, 30, 20];
|
||||
|
@ -2387,6 +2432,7 @@ unittest
|
|||
int fun(int a, int b){return a + b + 1;}
|
||||
auto foo()
|
||||
{
|
||||
import std.algorithm.comparison : max;
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
auto a = reduce!(fun)([1, 2, 3]);
|
||||
|
@ -2404,6 +2450,7 @@ unittest
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : max, min;
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
//http://forum.dlang.org/thread/oghtttkopzjshsuflelk@forum.dlang.org
|
||||
|
@ -2419,6 +2466,7 @@ unittest
|
|||
|
||||
@safe unittest //12569
|
||||
{
|
||||
import std.algorithm.comparison : max, min;
|
||||
import std.typecons: tuple;
|
||||
dchar c = 'a';
|
||||
reduce!(min, max)(tuple(c, c), "hello"); // OK
|
||||
|
@ -2486,6 +2534,7 @@ auto splitter(alias pred = "a == b", Range, Separator)(Range r, Separator s)
|
|||
if (is(typeof(binaryFun!pred(r.front, s)) : bool)
|
||||
&& ((hasSlicing!Range && hasLength!Range) || isNarrowString!Range))
|
||||
{
|
||||
import std.algorithm : find; // FIXME
|
||||
import std.conv : unsigned;
|
||||
|
||||
static struct Result
|
||||
|
@ -2640,6 +2689,8 @@ if (is(typeof(binaryFun!pred(r.front, s)) : bool)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ]));
|
||||
int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
|
||||
int[][] w = [ [1, 2], [], [3], [4, 5], [] ];
|
||||
|
@ -2764,6 +2815,7 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
|
|||
&& isForwardRange!Separator
|
||||
&& (hasLength!Separator || isNarrowString!Separator))
|
||||
{
|
||||
import std.algorithm : find; // FIXME
|
||||
import std.conv : unsigned;
|
||||
|
||||
static struct Result
|
||||
|
@ -2916,6 +2968,8 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
assert(equal(splitter("hello world", " "), [ "hello", "world" ]));
|
||||
int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
|
||||
int[][] w = [ [1, 2], [3, 0, 4, 5, 0] ];
|
||||
|
@ -2928,6 +2982,7 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.typecons : Tuple;
|
||||
|
||||
alias C = Tuple!(int, "x", int, "y");
|
||||
|
@ -2937,6 +2992,7 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.conv : text;
|
||||
import std.array : split;
|
||||
|
||||
|
@ -2992,6 +3048,7 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
debug(std_algorithm) scope(success)
|
||||
writeln("unittest @", __FILE__, ":", __LINE__, " done.");
|
||||
auto s6 = ",";
|
||||
|
@ -3005,6 +3062,8 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
// Issue 10773
|
||||
auto s = splitter("abc", "");
|
||||
assert(s.equal(["a", "b", "c"]));
|
||||
|
@ -3012,6 +3071,8 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
// Test by-reference separator
|
||||
class RefSep {
|
||||
@safe:
|
||||
|
@ -3062,6 +3123,8 @@ if (isForwardRange!Range && is(typeof(unaryFun!isTerminator(input.front))))
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
assert(equal(splitter!"a == ' '"("hello world"), [ "hello", "", "world" ]));
|
||||
int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
|
||||
int[][] w = [ [1, 2], [], [3], [4, 5], [] ];
|
||||
|
@ -3076,6 +3139,7 @@ if (isForwardRange!Range && is(typeof(unaryFun!isTerminator(input.front))))
|
|||
|
||||
private struct SplitterResult(alias isTerminator, Range)
|
||||
{
|
||||
import std.algorithm : find; // FIXME
|
||||
enum fullSlicing = (hasLength!Range && hasSlicing!Range) || isSomeString!Range;
|
||||
|
||||
private Range _input;
|
||||
|
@ -3185,6 +3249,7 @@ private struct SplitterResult(alias isTerminator, Range)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : iota;
|
||||
|
||||
auto L = iota(1L, 10L);
|
||||
|
@ -3198,6 +3263,8 @@ private struct SplitterResult(alias isTerminator, Range)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm : algoFormat; // FIXME
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.internal.test.dummyrange;
|
||||
|
||||
debug(std_algorithm) scope(success)
|
||||
|
@ -3233,7 +3300,10 @@ private struct SplitterResult(alias isTerminator, Range)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm : algoFormat; // FIXME
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range;
|
||||
|
||||
struct Entry
|
||||
{
|
||||
int low;
|
||||
|
@ -3257,6 +3327,7 @@ private struct SplitterResult(alias isTerminator, Range)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.uni : isWhite;
|
||||
|
||||
//@@@6791@@@
|
||||
|
@ -3282,6 +3353,7 @@ Returns:
|
|||
auto splitter(C)(C[] s)
|
||||
if (isSomeChar!C)
|
||||
{
|
||||
import std.algorithm : find; // FIXME
|
||||
static struct Result
|
||||
{
|
||||
private:
|
||||
|
@ -3335,12 +3407,15 @@ if (isSomeChar!C)
|
|||
///
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
auto a = " a bcd ef gh ";
|
||||
assert(equal(splitter(a), ["a", "bcd", "ef", "gh"][]));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.typetuple : TypeTuple;
|
||||
foreach(S; TypeTuple!(string, wstring, dstring))
|
||||
{
|
||||
import std.conv : to;
|
||||
|
@ -3382,6 +3457,8 @@ if (isSomeChar!C)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm : algoFormat; // FIXME
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.conv : text;
|
||||
import std.array : split;
|
||||
|
||||
|
@ -3668,6 +3745,8 @@ if (isInputRange!Range && is(typeof(binaryFun!pred(r.front, r.front)) == bool))
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm : copy; // FIXME
|
||||
import std.algorithm.comparison : equal;
|
||||
int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ];
|
||||
assert(equal(uniq(arr), [ 1, 2, 3, 4, 5 ][]));
|
||||
|
||||
|
@ -3740,6 +3819,7 @@ private struct UniqResult(alias pred, Range)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.internal.test.dummyrange;
|
||||
import std.range;
|
||||
|
||||
|
|
|
@ -5913,7 +5913,8 @@ assert(arr == [ 1, 3, 4, 5, 4, 5, 2 ]);
|
|||
Specifies whether the output of certain algorithm is desired in sorted
|
||||
format.
|
||||
*/
|
||||
enum SortOutput {
|
||||
enum SortOutput
|
||||
{
|
||||
no, /// Don't sort output
|
||||
yes, /// Sort output
|
||||
}
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
// Written in the D programming language.
|
||||
module std.algorithm.setops;
|
||||
|
||||
// Ugly hack, while stuff still sits in package.d
|
||||
private import std.algorithm;
|
||||
|
||||
import std.range.primitives;
|
||||
|
||||
// FIXME
|
||||
import std.functional; // : unaryFun, binaryFun;
|
||||
import std.traits;
|
||||
// FIXME
|
||||
import std.typecons; // : tuple, Tuple;
|
||||
// FIXME
|
||||
import std.typetuple; // : TypeTuple, staticMap, allSatisfy, anySatisfy;
|
||||
|
||||
// cartesianProduct
|
||||
|
@ -36,11 +31,14 @@ auto cartesianProduct(R1, R2)(R1 range1, R2 range2)
|
|||
if (!allSatisfy!(isForwardRange, R1, R2) ||
|
||||
anySatisfy!(isInfinite, R1, R2))
|
||||
{
|
||||
import std.algorithm.iteration : map, joiner;
|
||||
|
||||
static if (isInfinite!R1 && isInfinite!R2)
|
||||
{
|
||||
static if (isForwardRange!R1 && isForwardRange!R2)
|
||||
{
|
||||
import std.range : zip, repeat, take, chain, sequence;
|
||||
|
||||
// This algorithm traverses the cartesian product by alternately
|
||||
// covering the right and bottom edges of an increasing square area
|
||||
// over the infinite table of combinations. This schedule allows us
|
||||
|
@ -75,7 +73,9 @@ auto cartesianProduct(R1, R2)(R1 range1, R2 range2)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm : canFind; // FIXME
|
||||
import std.range;
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto N = sequence!"n"(0); // the range of natural numbers
|
||||
auto N2 = cartesianProduct(N, N); // the range of all pairs of natural numbers
|
||||
|
@ -90,6 +90,9 @@ auto cartesianProduct(R1, R2)(R1 range1, R2 range2)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm : canFind; // FIXME
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto B = [ 1, 2, 3 ];
|
||||
auto C = [ 4, 5, 6 ];
|
||||
auto BC = cartesianProduct(B, C);
|
||||
|
@ -104,7 +107,10 @@ auto cartesianProduct(R1, R2)(R1 range1, R2 range2)
|
|||
@safe unittest
|
||||
{
|
||||
// Test cartesian product of two infinite ranges
|
||||
import std.algorithm : canFind; // FIXME
|
||||
import std.range;
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto Even = sequence!"2*n"(0);
|
||||
auto Odd = sequence!"2*n+1"(0);
|
||||
auto EvenOdd = cartesianProduct(Even, Odd);
|
||||
|
@ -125,7 +131,10 @@ auto cartesianProduct(R1, R2)(R1 range1, R2 range2)
|
|||
{
|
||||
// Test cartesian product of an infinite input range and a finite forward
|
||||
// range.
|
||||
import std.algorithm : canFind; // FIXME
|
||||
import std.range;
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto N = sequence!"n"(0);
|
||||
auto M = [100, 200, 300];
|
||||
auto NM = cartesianProduct(N,M);
|
||||
|
@ -160,6 +169,9 @@ auto cartesianProduct(R1, R2)(R1 range1, R2 range2)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm : canFind; // FIXME
|
||||
import std.typecons : tuple;
|
||||
|
||||
// Test cartesian product of two finite ranges.
|
||||
auto X = [1, 2, 3];
|
||||
auto Y = [4, 5, 6];
|
||||
|
@ -184,6 +196,11 @@ auto cartesianProduct(R1, R2)(R1 range1, R2 range2)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm : canFind; // FIXME
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.algorithm.iteration : map;
|
||||
import std.typecons : tuple;
|
||||
|
||||
import std.range;
|
||||
auto N = sequence!"n"(0);
|
||||
|
||||
|
@ -312,6 +329,7 @@ auto cartesianProduct(RR...)(RR ranges)
|
|||
}
|
||||
@property auto front()
|
||||
{
|
||||
import std.algorithm : algoFormat; // FIXME
|
||||
import std.range : iota;
|
||||
return mixin(algoFormat("tuple(%(current[%d].front%|,%))",
|
||||
iota(0, current.length)));
|
||||
|
@ -385,7 +403,10 @@ auto cartesianProduct(R1, R2, RR...)(R1 range1, R2 range2, RR otherRanges)
|
|||
* one level of tuples so that a ternary cartesian product, for example,
|
||||
* returns 3-element tuples instead of nested 2-element tuples.
|
||||
*/
|
||||
import std.algorithm : algoFormat; // FIXME
|
||||
import std.algorithm.iteration : map;
|
||||
import std.range : iota;
|
||||
|
||||
enum string denest = algoFormat("tuple(a[0], %(a[1][%d]%|,%))",
|
||||
iota(0, otherRanges.length+1));
|
||||
return map!denest(
|
||||
|
@ -395,7 +416,10 @@ auto cartesianProduct(R1, R2, RR...)(R1 range1, R2 range2, RR otherRanges)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm : canFind; // FIXME
|
||||
import std.range;
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
auto N = sequence!"n"(0);
|
||||
auto N3 = cartesianProduct(N, N, N);
|
||||
|
||||
|
@ -409,7 +433,10 @@ auto cartesianProduct(R1, R2, RR...)(R1 range1, R2 range2, RR otherRanges)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm : canFind; // FIXME
|
||||
import std.range;
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
auto N = sequence!"n"(0);
|
||||
auto N4 = cartesianProduct(N, N, N, N);
|
||||
|
||||
|
@ -425,6 +452,9 @@ auto cartesianProduct(R1, R2, RR...)(R1 range1, R2 range2, RR otherRanges)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto A = [ 1, 2, 3 ];
|
||||
auto B = [ 'a', 'b', 'c' ];
|
||||
auto C = [ "x", "y", "z" ];
|
||||
|
@ -459,6 +489,7 @@ pure @safe nothrow @nogc unittest
|
|||
// Issue 13935
|
||||
unittest
|
||||
{
|
||||
import std.algorithm.iteration : map;
|
||||
auto seq = [1, 2].map!(x => x);
|
||||
foreach (pair; cartesianProduct(seq, seq)) {}
|
||||
}
|
||||
|
@ -524,6 +555,8 @@ void largestPartialIntersection
|
|||
sorted);
|
||||
}
|
||||
|
||||
import std.algorithm : SortOutput; // FIXME
|
||||
|
||||
// largestPartialIntersectionWeighted
|
||||
/**
|
||||
Similar to $(D largestPartialIntersection), but associates a weight
|
||||
|
@ -557,6 +590,9 @@ void largestPartialIntersectionWeighted
|
|||
(alias less = "a < b", RangeOfRanges, Range, WeightsAA)
|
||||
(RangeOfRanges ror, Range tgt, WeightsAA weights, SortOutput sorted = SortOutput.no)
|
||||
{
|
||||
import std.algorithm.iteration : group;
|
||||
import std.algorithm.sorting : topNCopy;
|
||||
|
||||
if (tgt.empty) return;
|
||||
alias InfoType = ElementType!Range;
|
||||
bool heapComp(InfoType a, InfoType b)
|
||||
|
@ -569,6 +605,7 @@ void largestPartialIntersectionWeighted
|
|||
unittest
|
||||
{
|
||||
import std.conv : text;
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
debug(std_algorithm) scope(success)
|
||||
writeln("unittest @", __FILE__, ":", __LINE__, " done.");
|
||||
|
@ -592,6 +629,7 @@ unittest
|
|||
unittest
|
||||
{
|
||||
import std.conv : text;
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
debug(std_algorithm) scope(success)
|
||||
writeln("unittest @", __FILE__, ":", __LINE__, " done.");
|
||||
|
@ -612,6 +650,8 @@ unittest
|
|||
|
||||
unittest
|
||||
{
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
//scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done.");
|
||||
// Figure which number can be found in most arrays of the set of
|
||||
// arrays below, with specific per-element weights
|
||||
|
@ -634,6 +674,7 @@ unittest
|
|||
unittest
|
||||
{
|
||||
import std.container : Array;
|
||||
import std.typecons : Tuple;
|
||||
|
||||
alias T = Tuple!(uint, uint);
|
||||
const Array!T arrayOne = Array!T( [ T(1,2), T(3,4) ] );
|
||||
|
@ -681,6 +722,8 @@ struct NWayUnion(alias less, RangeOfRanges)
|
|||
|
||||
this(RangeOfRanges ror)
|
||||
{
|
||||
import std.algorithm : remove, SwapStrategy; // FIXME
|
||||
|
||||
// Preemptively get rid of all empty ranges in the input
|
||||
// No need for stability either
|
||||
_ror = remove!("a.empty", SwapStrategy.unstable)(ror);
|
||||
|
@ -723,6 +766,8 @@ NWayUnion!(less, RangeOfRanges) nWayUnion
|
|||
///
|
||||
unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
double[][] a =
|
||||
[
|
||||
[ 1, 4, 7, 8 ],
|
||||
|
@ -813,6 +858,8 @@ SetDifference!(less, R1, R2) setDifference(alias less = "a < b", R1, R2)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
int[] a = [ 1, 2, 4, 5, 7, 9 ];
|
||||
int[] b = [ 0, 1, 2, 4, 7, 8 ];
|
||||
assert(equal(setDifference(a, b), [5, 9][]));
|
||||
|
@ -821,6 +868,8 @@ SetDifference!(less, R1, R2) setDifference(alias less = "a < b", R1, R2)
|
|||
|
||||
@safe unittest // Issue 10460
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
int[] a = [1, 2, 3, 4, 5];
|
||||
int[] b = [2, 4];
|
||||
foreach (ref e; setDifference(a, b))
|
||||
|
@ -931,6 +980,8 @@ SetIntersection!(less, Rs) setIntersection(alias less = "a < b", Rs...)(Rs range
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
int[] a = [ 1, 2, 4, 5, 7, 9 ];
|
||||
int[] b = [ 0, 1, 2, 4, 7, 8 ];
|
||||
int[] c = [ 0, 1, 4, 5, 7, 8 ];
|
||||
|
@ -941,6 +992,9 @@ SetIntersection!(less, Rs) setIntersection(alias less = "a < b", Rs...)(Rs range
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.algorithm.iteration : filter;
|
||||
|
||||
int[] a = [ 1, 2, 4, 5, 7, 9 ];
|
||||
int[] b = [ 0, 1, 2, 4, 7, 8 ];
|
||||
int[] c = [ 0, 1, 4, 5, 7, 8 ];
|
||||
|
@ -1065,6 +1119,8 @@ setSymmetricDifference(alias less = "a < b", R1, R2)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
int[] a = [ 1, 2, 4, 5, 7, 9 ];
|
||||
int[] b = [ 0, 1, 2, 4, 7, 8 ];
|
||||
assert(equal(setSymmetricDifference(a, b), [0, 5, 8, 9][]));
|
||||
|
@ -1211,6 +1267,8 @@ SetUnion!(less, Rs) setUnion(alias less = "a < b", Rs...)
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
int[] a = [ 1, 2, 4, 5, 7, 9 ];
|
||||
int[] b = [ 0, 1, 2, 4, 7, 8 ];
|
||||
int[] c = [ 10 ];
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
// Written in the D programming language.
|
||||
module std.algorithm.sorting;
|
||||
|
||||
private import std.algorithm; // ugly hack for now
|
||||
|
||||
import std.algorithm : SortOutput, SwapStrategy; // FIXME
|
||||
import std.functional; // : unaryFun, binaryFun;
|
||||
import std.range.primitives;
|
||||
|
||||
// FIXME
|
||||
import std.range; // : SortedRange;
|
||||
import std.traits;
|
||||
// FIXME
|
||||
import std.typecons; // : tuple, Tuple;
|
||||
|
||||
// completeSort
|
||||
/**
|
||||
|
@ -26,6 +22,7 @@ void completeSort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable,
|
|||
Range1, Range2)(SortedRange!(Range1, less) lhs, Range2 rhs)
|
||||
if (hasLength!(Range2) && hasSlicing!(Range2))
|
||||
{
|
||||
import std.algorithm : bringToFront; // FIXME
|
||||
import std.range : chain, assumeSorted;
|
||||
// Probably this algorithm can be optimized by using in-place
|
||||
// merge
|
||||
|
@ -159,6 +156,7 @@ Range partition(alias predicate,
|
|||
if ((ss == SwapStrategy.stable && isRandomAccessRange!(Range))
|
||||
|| (ss != SwapStrategy.stable && isForwardRange!(Range)))
|
||||
{
|
||||
import std.algorithm : bringToFront, swap; // FIXME;
|
||||
alias pred = unaryFun!(predicate);
|
||||
if (r.empty) return r;
|
||||
static if (ss == SwapStrategy.stable)
|
||||
|
@ -236,6 +234,7 @@ Range partition(alias predicate,
|
|||
///
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm : count, find; // FIXME
|
||||
import std.conv : text;
|
||||
|
||||
auto Arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
|
@ -273,6 +272,7 @@ Range partition(alias predicate,
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm : rndstuff; // FIXME
|
||||
static bool even(int a) { return (a & 1) == 0; }
|
||||
|
||||
// test with random data
|
||||
|
@ -333,6 +333,10 @@ if (ss == SwapStrategy.unstable && isRandomAccessRange!Range
|
|||
// The algorithm is described in "Engineering a sort function" by
|
||||
// Jon Bentley et al, pp 1257.
|
||||
|
||||
import std.algorithm : swap, swapRanges; // FIXME
|
||||
import std.algorithm.comparison : min;
|
||||
import std.typecons : tuple;
|
||||
|
||||
alias lessFun = binaryFun!less;
|
||||
size_t i, j, k = r.length, l = k;
|
||||
|
||||
|
@ -449,6 +453,7 @@ makeIndex(
|
|||
if (isForwardRange!(Range) && isRandomAccessRange!(RangeIndex)
|
||||
&& is(ElementType!(RangeIndex) : ElementType!(Range)*))
|
||||
{
|
||||
import std.algorithm : addressOf; // FIXME
|
||||
import std.exception : enforce;
|
||||
|
||||
// assume collection already ordered
|
||||
|
@ -623,7 +628,9 @@ template multiSort(less...) //if (less.length > 1)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range;
|
||||
|
||||
static struct Point { int x, y; }
|
||||
auto pts1 = [ Point(5, 6), Point(1, 0), Point(5, 7), Point(1, 1), Point(1, 2), Point(0, 1) ];
|
||||
auto pts2 = [ Point(0, 1), Point(1, 0), Point(1, 1), Point(1, 2), Point(5, 6), Point(5, 7) ];
|
||||
|
@ -851,6 +858,7 @@ unittest
|
|||
|
||||
unittest
|
||||
{
|
||||
import std.algorithm : rndstuff; // FIXME
|
||||
import std.random : Random, unpredictableSeed, uniform;
|
||||
import std.uni : toUpper;
|
||||
|
||||
|
@ -910,6 +918,8 @@ unittest
|
|||
// Unstable sort should complete without an excessive number of predicate calls
|
||||
// This would suggest it's running in quadratic time
|
||||
|
||||
import std.algorithm : swapRanges; // FIXME
|
||||
|
||||
// Compilation error if predicate is not static, i.e. a nested function
|
||||
static uint comp;
|
||||
static bool pred(size_t a, size_t b)
|
||||
|
@ -929,6 +939,8 @@ unittest
|
|||
}
|
||||
|
||||
{
|
||||
import std.algorithm : swap; // FIXME
|
||||
|
||||
bool proxySwapCalled;
|
||||
struct S
|
||||
{
|
||||
|
@ -950,6 +962,7 @@ unittest
|
|||
//private
|
||||
void swapAt(R)(R r, size_t i1, size_t i2)
|
||||
{
|
||||
import std.algorithm : swap; // FIXME
|
||||
static if (is(typeof(&r[i1])))
|
||||
{
|
||||
swap(r[i1], r[i2]);
|
||||
|
@ -966,6 +979,9 @@ void swapAt(R)(R r, size_t i1, size_t i2)
|
|||
|
||||
private void quickSortImpl(alias less, Range)(Range r, size_t depth)
|
||||
{
|
||||
import std.algorithm : swap; // FIXME
|
||||
import std.algorithm.comparison : min;
|
||||
|
||||
alias Elem = ElementType!(Range);
|
||||
enum size_t optimisticInsertionSortGetsBetter = 25;
|
||||
static assert(optimisticInsertionSortGetsBetter >= 1);
|
||||
|
@ -1111,6 +1127,8 @@ private template TimSortImpl(alias pred, R)
|
|||
// Entry point for tim sort
|
||||
void sort(R range, T[] temp)
|
||||
{
|
||||
import std.algorithm.comparison : min;
|
||||
|
||||
// Do insertion sort on small range
|
||||
if (range.length <= minimalMerge)
|
||||
{
|
||||
|
@ -1202,6 +1220,8 @@ private template TimSortImpl(alias pred, R)
|
|||
}
|
||||
body
|
||||
{
|
||||
import std.algorithm : reverse; // FIXME
|
||||
|
||||
if (range.length < 2) return range.length;
|
||||
|
||||
size_t i = 2;
|
||||
|
@ -1225,6 +1245,8 @@ private template TimSortImpl(alias pred, R)
|
|||
}
|
||||
body
|
||||
{
|
||||
import std.algorithm : move; // FIXME
|
||||
|
||||
for (; sortedLen < range.length; ++sortedLen)
|
||||
{
|
||||
T item = moveAt(range, sortedLen);
|
||||
|
@ -1333,6 +1355,8 @@ private template TimSortImpl(alias pred, R)
|
|||
}
|
||||
body
|
||||
{
|
||||
import std.algorithm : copy; // FIXME
|
||||
|
||||
assert(mid <= range.length);
|
||||
assert(temp.length >= mid);
|
||||
|
||||
|
@ -1414,6 +1438,8 @@ private template TimSortImpl(alias pred, R)
|
|||
}
|
||||
body
|
||||
{
|
||||
import std.algorithm : copy; // FIXME
|
||||
|
||||
assert(mid <= range.length);
|
||||
assert(temp.length >= range.length - mid);
|
||||
|
||||
|
@ -1601,6 +1627,8 @@ unittest
|
|||
// Generates data especially for testing sorting with Timsort
|
||||
static E[] genSampleData(uint seed)
|
||||
{
|
||||
import std.algorithm : swap, swapRanges; // FIXME
|
||||
|
||||
auto rnd = Random(seed);
|
||||
|
||||
E[] arr;
|
||||
|
@ -1763,6 +1791,7 @@ schwartzSort(alias transform, alias less = "a < b",
|
|||
unittest
|
||||
{
|
||||
// issue 4909
|
||||
import std.typecons : Tuple;
|
||||
Tuple!(char)[] chars;
|
||||
schwartzSort!"a[0]"(chars);
|
||||
}
|
||||
|
@ -1770,12 +1799,14 @@ unittest
|
|||
unittest
|
||||
{
|
||||
// issue 5924
|
||||
import std.typecons : Tuple;
|
||||
Tuple!(char)[] chars;
|
||||
schwartzSort!((Tuple!(char) c){ return c[0]; })(chars);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
import std.algorithm.iteration : map;
|
||||
import std.math : log2;
|
||||
|
||||
debug(std_algorithm) scope(success)
|
||||
|
@ -1808,6 +1839,7 @@ unittest
|
|||
|
||||
unittest
|
||||
{
|
||||
import std.algorithm.iteration : map;
|
||||
import std.math : log2;
|
||||
|
||||
debug(std_algorithm) scope(success)
|
||||
|
@ -1889,6 +1921,7 @@ void topN(alias less = "a < b",
|
|||
Range)(Range r, size_t nth)
|
||||
if (isRandomAccessRange!(Range) && hasLength!Range)
|
||||
{
|
||||
import std.algorithm : swap; // FIXME
|
||||
import std.random : uniform;
|
||||
|
||||
static assert(ss == SwapStrategy.unstable,
|
||||
|
@ -1931,6 +1964,9 @@ void topN(alias less = "a < b",
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : max, min;
|
||||
import std.algorithm.iteration : reduce;
|
||||
|
||||
debug(std_algorithm) scope(success)
|
||||
writeln("unittest @", __FILE__, ":", __LINE__, " done.");
|
||||
//scope(failure) writeln(stderr, "Failure testing algorithm");
|
||||
|
@ -1979,6 +2015,8 @@ void topN(alias less = "a < b",
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : max, min;
|
||||
import std.algorithm.iteration : reduce;
|
||||
import std.random : uniform;
|
||||
|
||||
debug(std_algorithm) scope(success)
|
||||
|
@ -2116,6 +2154,7 @@ bool nextPermutation(alias less="a < b", BidirectionalRange)
|
|||
if (isBidirectionalRange!BidirectionalRange &&
|
||||
hasSwappableElements!BidirectionalRange)
|
||||
{
|
||||
import std.algorithm : find, reverse, swap; // FIXME
|
||||
import std.range : retro, takeExactly;
|
||||
// Ranges of 0 or 1 element have no distinct permutations.
|
||||
if (range.empty) return false;
|
||||
|
@ -2195,6 +2234,8 @@ bool nextPermutation(alias less="a < b", BidirectionalRange)
|
|||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
auto a1 = [1, 2, 3, 4];
|
||||
|
||||
assert(nextPermutation(a1));
|
||||
|
@ -2363,6 +2404,7 @@ bool nextEvenPermutation(alias less="a < b", BidirectionalRange)
|
|||
if (isBidirectionalRange!BidirectionalRange &&
|
||||
hasSwappableElements!BidirectionalRange)
|
||||
{
|
||||
import std.algorithm : find, reverse, swap; // FIXME
|
||||
import std.range : retro, takeExactly;
|
||||
// Ranges of 0 or 1 element have no distinct permutations.
|
||||
if (range.empty) return false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue