std.algorithms: document public methods

This commit is contained in:
Sebastian Wilzbach 2016-05-12 17:48:51 +03:00
parent 80594b0b61
commit b8f17e2531
5 changed files with 244 additions and 197 deletions

View file

@ -1168,7 +1168,7 @@ size_t levenshteinDistance(alias equals = (a,b) => a == b, Range1, Range2)
assert(levenshteinDistance("cat"d, "rat"d) == 1); assert(levenshteinDistance("cat"d, "rat"d) == 1);
} }
// compat overload for alias this strings /// ditto
size_t levenshteinDistance(alias equals = (a,b) => a == b, Range1, Range2) size_t levenshteinDistance(alias equals = (a,b) => a == b, Range1, Range2)
(auto ref Range1 s, auto ref Range2 t) (auto ref Range1 s, auto ref Range2 t)
if (isConvertibleToString!Range1 || isConvertibleToString!Range2) if (isConvertibleToString!Range1 || isConvertibleToString!Range2)
@ -1240,7 +1240,7 @@ levenshteinDistanceAndPath(alias equals = (a,b) => a == b, Range1, Range2)
assert(levenshteinDistance("kitten", "sitting") == 3); assert(levenshteinDistance("kitten", "sitting") == 3);
} }
// compat overload for alias this strings /// ditto
Tuple!(size_t, EditOp[]) Tuple!(size_t, EditOp[])
levenshteinDistanceAndPath(alias equals = (a,b) => a == b, Range1, Range2) levenshteinDistanceAndPath(alias equals = (a,b) => a == b, Range1, Range2)
(auto ref Range1 s, auto ref Range2 t) (auto ref Range1 s, auto ref Range2 t)

View file

@ -1319,83 +1319,6 @@ private struct FilterBidiResult(alias pred, Range)
} }
} }
// group
struct Group(alias pred, R) if (isInputRange!R)
{
import std.typecons : Rebindable, tuple, Tuple;
private alias comp = binaryFun!pred;
private alias E = ElementType!R;
static if ((is(E == class) || is(E == interface)) &&
(is(E == const) || is(E == immutable)))
{
private alias MutableE = Rebindable!E;
}
else static if (is(E : Unqual!E))
{
private alias MutableE = Unqual!E;
}
else
{
private alias MutableE = E;
}
private R _input;
private Tuple!(MutableE, uint) _current;
this(R input)
{
_input = input;
if (!_input.empty) popFront();
}
void popFront()
{
if (_input.empty)
{
_current[1] = 0;
}
else
{
_current = tuple(_input.front, 1u);
_input.popFront();
while (!_input.empty && comp(_current[0], _input.front))
{
++_current[1];
_input.popFront();
}
}
}
static if (isInfinite!R)
{
enum bool empty = false; // Propagate infiniteness.
}
else
{
@property bool empty()
{
return _current[1] == 0;
}
}
@property auto ref front()
{
assert(!empty);
return _current;
}
static if (isForwardRange!R) {
@property typeof(this) save() {
typeof(this) ret = this;
ret._input = this._input.save;
ret._current = this._current;
return ret;
}
}
}
/** /**
Groups consecutively equivalent elements into a single tuple of the element and Groups consecutively equivalent elements into a single tuple of the element and
the number of its repetitions. the number of its repetitions.
@ -1423,6 +1346,89 @@ Group!(pred, Range) group(alias pred = "a == b", Range)(Range r)
return typeof(return)(r); return typeof(return)(r);
} }
/// ditto
struct Group(alias pred, R) if (isInputRange!R)
{
import std.typecons : Rebindable, tuple, Tuple;
private alias comp = binaryFun!pred;
private alias E = ElementType!R;
static if ((is(E == class) || is(E == interface)) &&
(is(E == const) || is(E == immutable)))
{
private alias MutableE = Rebindable!E;
}
else static if (is(E : Unqual!E))
{
private alias MutableE = Unqual!E;
}
else
{
private alias MutableE = E;
}
private R _input;
private Tuple!(MutableE, uint) _current;
///
this(R input)
{
_input = input;
if (!_input.empty) popFront();
}
///
void popFront()
{
if (_input.empty)
{
_current[1] = 0;
}
else
{
_current = tuple(_input.front, 1u);
_input.popFront();
while (!_input.empty && comp(_current[0], _input.front))
{
++_current[1];
_input.popFront();
}
}
}
static if (isInfinite!R)
{
///
enum bool empty = false; // Propagate infiniteness.
}
else
{
///
@property bool empty()
{
return _current[1] == 0;
}
}
///
@property auto ref front()
{
assert(!empty);
return _current;
}
static if (isForwardRange!R) {
///
@property typeof(this) save() {
typeof(this) ret = this;
ret._input = this._input.save;
ret._current = this._current;
return ret;
}
}
}
/// ///
@safe unittest @safe unittest
{ {
@ -4874,13 +4880,31 @@ private struct UniqResult(alias pred, Range)
} }
} }
// permutations /**
Lazily computes all _permutations of $(D r) using $(WEB
en.wikipedia.org/wiki/Heap%27s_algorithm, Heap's algorithm).
Returns:
A forward range the elements of which are an $(XREF range,
indexed) view into $(D r).
See_Also:
$(XREF_PACK algorithm,sorting,nextPermutation).
*/
Permutations!Range permutations(Range)(Range r)
if (isRandomAccessRange!Range && hasLength!Range)
{
return typeof(return)(r);
}
/// ditto
struct Permutations(Range) struct Permutations(Range)
if (isRandomAccessRange!Range && hasLength!Range) if (isRandomAccessRange!Range && hasLength!Range)
{ {
size_t[] indices, state; size_t[] indices, state;
Range r; Range r;
///
this(Range r) this(Range r)
{ {
import std.range : iota; import std.range : iota;
@ -4892,14 +4916,17 @@ struct Permutations(Range)
empty = r.length == 0; empty = r.length == 0;
} }
///
bool empty; bool empty;
///
@property auto front() @property auto front()
{ {
import std.range : indexed; import std.range : indexed;
return r.indexed(indices); return r.indexed(indices);
} }
///
void popFront() void popFront()
{ {
void next(int n) void next(int n)
@ -4928,23 +4955,6 @@ struct Permutations(Range)
} }
} }
/**
Lazily computes all _permutations of $(D r) using $(WEB
en.wikipedia.org/wiki/Heap%27s_algorithm, Heap's algorithm).
Returns:
A forward range the elements of which are an $(XREF range,
indexed) view into $(D r).
See_Also:
$(XREF_PACK algorithm,sorting,nextPermutation).
*/
Permutations!Range permutations(Range)(Range r)
if (isRandomAccessRange!Range && hasLength!Range)
{
return typeof(return)(r);
}
/// ///
unittest unittest
{ {

View file

@ -1667,7 +1667,7 @@ if (s != SwapStrategy.stable
return range; return range;
} }
// Ditto /// Ditto
Range remove Range remove
(SwapStrategy s = SwapStrategy.stable, Range, Offset...) (SwapStrategy s = SwapStrategy.stable, Range, Offset...)
(Range range, Offset offset) (Range range, Offset offset)
@ -2380,8 +2380,9 @@ unittest
swap(b1, b2); swap(b1, b2);
} }
// Not yet documented /// ditto
void swap(T)(ref T lhs, ref T rhs) if (is(typeof(lhs.proxySwap(rhs)))) void swap(T)(ref T lhs, ref T rhs)
if (is(typeof(lhs.proxySwap(rhs))))
{ {
lhs.proxySwap(rhs); lhs.proxySwap(rhs);
} }

View file

@ -321,6 +321,7 @@ is ignored.
} }
public: public:
///
this(Range needle) this(Range needle)
{ {
if (!needle.length) return; if (!needle.length) return;
@ -347,6 +348,7 @@ public:
} }
} }
///
Range beFound(Range haystack) Range beFound(Range haystack)
{ {
import std.algorithm.comparison : max; import std.algorithm.comparison : max;
@ -368,11 +370,13 @@ public:
return haystack[$ .. $]; return haystack[$ .. $];
} }
///
@property size_t length() @property size_t length()
{ {
return needle.length; return needle.length;
} }
///
alias opDollar = length; alias opDollar = length;
} }
@ -1776,8 +1780,7 @@ if (isForwardRange!R1 && isForwardRange!R2
assert(equal(r, SList!int(2, 5, 7, 3)[])); assert(equal(r, SList!int(2, 5, 7, 3)[]));
} }
// Specialization for searching a random-access range for a /// ditto
// bidirectional range
R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle) R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if (isRandomAccessRange!R1 && isBidirectionalRange!R2 if (isRandomAccessRange!R1 && isBidirectionalRange!R2
&& is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool)) && is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool))
@ -1786,9 +1789,7 @@ if (isRandomAccessRange!R1 && isBidirectionalRange!R2
const needleLength = walkLength(needle.save); const needleLength = walkLength(needle.save);
if (needleLength > haystack.length) if (needleLength > haystack.length)
{ {
// @@@BUG@@@ return haystack[$ .. $];
//return haystack[$ .. $];
return haystack[haystack.length .. haystack.length];
} }
// @@@BUG@@@ // @@@BUG@@@
// auto needleBack = moveBack(needle); // auto needleBack = moveBack(needle);
@ -1848,8 +1849,7 @@ if (isRandomAccessRange!R1 && isBidirectionalRange!R2
//assert(find!"a == b"("abc", "bc").length == 2); //assert(find!"a == b"("abc", "bc").length == 2);
} }
// Leftover specialization: searching a random-access range for a /// ditto
// non-bidirectional forward range
R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle) R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if (isRandomAccessRange!R1 && isForwardRange!R2 && !isBidirectionalRange!R2 && if (isRandomAccessRange!R1 && isForwardRange!R2 && !isBidirectionalRange!R2 &&
is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool)) is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool))
@ -3861,96 +3861,6 @@ enum OpenRight
yes /// Interval is open to the right (last element is not included) yes /// Interval is open to the right (last element is not included)
} }
struct Until(alias pred, Range, Sentinel) if (isInputRange!Range)
{
private Range _input;
static if (!is(Sentinel == void))
private Sentinel _sentinel;
// mixin(bitfields!(
// OpenRight, "_openRight", 1,
// bool, "_done", 1,
// uint, "", 6));
// OpenRight, "_openRight", 1,
// bool, "_done", 1,
OpenRight _openRight;
bool _done;
static if (!is(Sentinel == void))
this(Range input, Sentinel sentinel,
OpenRight openRight = OpenRight.yes)
{
_input = input;
_sentinel = sentinel;
_openRight = openRight;
_done = _input.empty || openRight && predSatisfied();
}
else
this(Range input, OpenRight openRight = OpenRight.yes)
{
_input = input;
_openRight = openRight;
_done = _input.empty || openRight && predSatisfied();
}
@property bool empty()
{
return _done;
}
@property auto ref front()
{
assert(!empty);
return _input.front;
}
private bool predSatisfied()
{
static if (is(Sentinel == void))
return cast(bool) unaryFun!pred(_input.front);
else
return cast(bool) startsWith!pred(_input, _sentinel);
}
void popFront()
{
assert(!empty);
if (!_openRight)
{
_done = predSatisfied();
_input.popFront();
_done = _done || _input.empty;
}
else
{
_input.popFront();
_done = _input.empty || predSatisfied();
}
}
static if (isForwardRange!Range)
{
static if (!is(Sentinel == void))
@property Until save()
{
Until result = this;
result._input = _input.save;
result._sentinel = _sentinel;
result._openRight = _openRight;
result._done = _done;
return result;
}
else
@property Until save()
{
Until result = this;
result._input = _input.save;
result._openRight = _openRight;
result._done = _done;
return result;
}
}
}
/** /**
Lazily iterates $(D range) _until the element $(D e) for which Lazily iterates $(D range) _until the element $(D e) for which
$(D pred(e, sentinel)) is true. $(D pred(e, sentinel)) is true.
@ -3987,6 +3897,104 @@ until(alias pred, Range)
return typeof(return)(range, openRight); return typeof(return)(range, openRight);
} }
/// ditto
struct Until(alias pred, Range, Sentinel) if (isInputRange!Range)
{
private Range _input;
static if (!is(Sentinel == void))
private Sentinel _sentinel;
// mixin(bitfields!(
// OpenRight, "_openRight", 1,
// bool, "_done", 1,
// uint, "", 6));
// OpenRight, "_openRight", 1,
// bool, "_done", 1,
OpenRight _openRight;
bool _done;
static if (!is(Sentinel == void))
///
this(Range input, Sentinel sentinel,
OpenRight openRight = OpenRight.yes)
{
_input = input;
_sentinel = sentinel;
_openRight = openRight;
_done = _input.empty || openRight && predSatisfied();
}
else
///
this(Range input, OpenRight openRight = OpenRight.yes)
{
_input = input;
_openRight = openRight;
_done = _input.empty || openRight && predSatisfied();
}
///
@property bool empty()
{
return _done;
}
///
@property auto ref front()
{
assert(!empty);
return _input.front;
}
private bool predSatisfied()
{
static if (is(Sentinel == void))
return cast(bool) unaryFun!pred(_input.front);
else
return cast(bool) startsWith!pred(_input, _sentinel);
}
///
void popFront()
{
assert(!empty);
if (!_openRight)
{
_done = predSatisfied();
_input.popFront();
_done = _done || _input.empty;
}
else
{
_input.popFront();
_done = _input.empty || predSatisfied();
}
}
static if (isForwardRange!Range)
{
static if (!is(Sentinel == void))
///
@property Until save()
{
Until result = this;
result._input = _input.save;
result._sentinel = _sentinel;
result._openRight = _openRight;
result._done = _done;
return result;
}
else
///
@property Until save()
{
Until result = this;
result._input = _input.save;
result._openRight = _openRight;
result._done = _done;
return result;
}
}
}
/// ///
@safe unittest @safe unittest
{ {

View file

@ -788,6 +788,8 @@ struct NWayUnion(alias less, RangeOfRanges)
private alias ElementType = .ElementType!(.ElementType!RangeOfRanges); private alias ElementType = .ElementType!(.ElementType!RangeOfRanges);
private alias comp = binaryFun!less; private alias comp = binaryFun!less;
private RangeOfRanges _ror; private RangeOfRanges _ror;
///
static bool compFront(.ElementType!RangeOfRanges a, static bool compFront(.ElementType!RangeOfRanges a,
.ElementType!RangeOfRanges b) .ElementType!RangeOfRanges b)
{ {
@ -796,6 +798,7 @@ struct NWayUnion(alias less, RangeOfRanges)
} }
BinaryHeap!(RangeOfRanges, compFront) _heap; BinaryHeap!(RangeOfRanges, compFront) _heap;
///
this(RangeOfRanges ror) this(RangeOfRanges ror)
{ {
import std.algorithm.mutation : remove, SwapStrategy; import std.algorithm.mutation : remove, SwapStrategy;
@ -807,13 +810,16 @@ struct NWayUnion(alias less, RangeOfRanges)
_heap.acquire(_ror); _heap.acquire(_ror);
} }
///
@property bool empty() { return _ror.empty; } @property bool empty() { return _ror.empty; }
///
@property auto ref front() @property auto ref front()
{ {
return _heap.front.front; return _heap.front.front;
} }
///
void popFront() void popFront()
{ {
_heap.removeFront(); _heap.removeFront();
@ -900,6 +906,7 @@ private:
} }
public: public:
///
this(R1 r1, R2 r2) this(R1 r1, R2 r2)
{ {
this.r1 = r1; this.r1 = r1;
@ -908,12 +915,14 @@ public:
adjustPosition(); adjustPosition();
} }
///
void popFront() void popFront()
{ {
r1.popFront(); r1.popFront();
adjustPosition(); adjustPosition();
} }
///
@property auto ref front() @property auto ref front()
{ {
assert(!empty); assert(!empty);
@ -922,6 +931,7 @@ public:
static if (isForwardRange!R1 && isForwardRange!R2) static if (isForwardRange!R1 && isForwardRange!R2)
{ {
///
@property typeof(this) save() @property typeof(this) save()
{ {
auto ret = this; auto ret = this;
@ -931,6 +941,7 @@ public:
} }
} }
///
@property bool empty() { return r1.empty; } @property bool empty() { return r1.empty; }
} }
@ -1010,6 +1021,7 @@ private:
} }
public: public:
///
this(Rs input) this(Rs input)
{ {
this._input = input; this._input = input;
@ -1017,6 +1029,7 @@ public:
adjustPosition(); adjustPosition();
} }
///
@property bool empty() @property bool empty()
{ {
foreach (ref r; _input) foreach (ref r; _input)
@ -1026,6 +1039,7 @@ public:
return false; return false;
} }
///
void popFront() void popFront()
{ {
assert(!empty); assert(!empty);
@ -1042,6 +1056,7 @@ public:
adjustPosition(); adjustPosition();
} }
///
@property ElementType front() @property ElementType front()
{ {
assert(!empty); assert(!empty);
@ -1050,6 +1065,7 @@ public:
static if (allSatisfy!(isForwardRange, Rs)) static if (allSatisfy!(isForwardRange, Rs))
{ {
///
@property SetIntersection save() @property SetIntersection save()
{ {
auto ret = this; auto ret = this;
@ -1158,6 +1174,7 @@ private:
} }
public: public:
///
this(R1 r1, R2 r2) this(R1 r1, R2 r2)
{ {
this.r1 = r1; this.r1 = r1;
@ -1166,6 +1183,7 @@ public:
adjustPosition(); adjustPosition();
} }
///
void popFront() void popFront()
{ {
assert(!empty); assert(!empty);
@ -1187,6 +1205,7 @@ public:
adjustPosition(); adjustPosition();
} }
///
@property auto ref front() @property auto ref front()
{ {
assert(!empty); assert(!empty);
@ -1197,6 +1216,7 @@ public:
static if (isForwardRange!R1 && isForwardRange!R2) static if (isForwardRange!R1 && isForwardRange!R2)
{ {
///
@property typeof(this) save() @property typeof(this) save()
{ {
auto ret = this; auto ret = this;
@ -1206,8 +1226,10 @@ public:
} }
} }
///
ref auto opSlice() { return this; } ref auto opSlice() { return this; }
///
@property bool empty() { return r1.empty && r2.empty; } @property bool empty() { return r1.empty && r2.empty; }
} }
@ -1300,17 +1322,20 @@ public:
static assert(!is(CommonType!(staticMap!(.ElementType, Rs)) == void), static assert(!is(CommonType!(staticMap!(.ElementType, Rs)) == void),
typeof(this).stringof ~ ": incompatible element types."); typeof(this).stringof ~ ": incompatible element types.");
///
this(Rs rs) this(Rs rs)
{ {
this._r = rs; this._r = rs;
adjustPosition(); adjustPosition();
} }
///
@property bool empty() @property bool empty()
{ {
return _crt == _crt.max; return _crt == _crt.max;
} }
///
void popFront() void popFront()
{ {
// Assumes _crt is correct // Assumes _crt is correct
@ -1327,6 +1352,7 @@ public:
assert(false); assert(false);
} }
///
@property auto ref ElementType front() @property auto ref ElementType front()
{ {
assert(!empty); assert(!empty);
@ -1342,6 +1368,7 @@ public:
static if (allSatisfy!(isForwardRange, Rs)) static if (allSatisfy!(isForwardRange, Rs))
{ {
///
@property auto save() @property auto save()
{ {
auto ret = this; auto ret = this;
@ -1355,6 +1382,7 @@ public:
static if (allSatisfy!(hasLength, Rs)) static if (allSatisfy!(hasLength, Rs))
{ {
///
@property size_t length() @property size_t length()
{ {
size_t result; size_t result;