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);
}
// compat overload for alias this strings
/// ditto
size_t levenshteinDistance(alias equals = (a,b) => a == b, Range1, Range2)
(auto ref Range1 s, auto ref Range2 t)
if (isConvertibleToString!Range1 || isConvertibleToString!Range2)
@ -1240,7 +1240,7 @@ levenshteinDistanceAndPath(alias equals = (a,b) => a == b, Range1, Range2)
assert(levenshteinDistance("kitten", "sitting") == 3);
}
// compat overload for alias this strings
/// ditto
Tuple!(size_t, EditOp[])
levenshteinDistanceAndPath(alias equals = (a,b) => a == b, Range1, Range2)
(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
the number of its repetitions.
@ -1423,6 +1346,89 @@ Group!(pred, Range) group(alias pred = "a == b", Range)(Range 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
{
@ -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)
if (isRandomAccessRange!Range && hasLength!Range)
{
size_t[] indices, state;
Range r;
///
this(Range r)
{
import std.range : iota;
@ -4892,14 +4916,17 @@ struct Permutations(Range)
empty = r.length == 0;
}
///
bool empty;
///
@property auto front()
{
import std.range : indexed;
return r.indexed(indices);
}
///
void popFront()
{
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
{

View file

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

View file

@ -321,6 +321,7 @@ is ignored.
}
public:
///
this(Range needle)
{
if (!needle.length) return;
@ -347,6 +348,7 @@ public:
}
}
///
Range beFound(Range haystack)
{
import std.algorithm.comparison : max;
@ -368,11 +370,13 @@ public:
return haystack[$ .. $];
}
///
@property size_t length()
{
return needle.length;
}
///
alias opDollar = length;
}
@ -1776,8 +1780,7 @@ if (isForwardRange!R1 && isForwardRange!R2
assert(equal(r, SList!int(2, 5, 7, 3)[]));
}
// Specialization for searching a random-access range for a
// bidirectional range
/// ditto
R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if (isRandomAccessRange!R1 && isBidirectionalRange!R2
&& is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool))
@ -1786,9 +1789,7 @@ if (isRandomAccessRange!R1 && isBidirectionalRange!R2
const needleLength = walkLength(needle.save);
if (needleLength > haystack.length)
{
// @@@BUG@@@
//return haystack[$ .. $];
return haystack[haystack.length .. haystack.length];
return haystack[$ .. $];
}
// @@@BUG@@@
// auto needleBack = moveBack(needle);
@ -1848,8 +1849,7 @@ if (isRandomAccessRange!R1 && isBidirectionalRange!R2
//assert(find!"a == b"("abc", "bc").length == 2);
}
// Leftover specialization: searching a random-access range for a
// non-bidirectional forward range
/// ditto
R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if (isRandomAccessRange!R1 && isForwardRange!R2 && !isBidirectionalRange!R2 &&
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)
}
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
$(D pred(e, sentinel)) is true.
@ -3987,6 +3897,104 @@ until(alias pred, Range)
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
{

View file

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