algorithm: import searching publically

This commit is contained in:
2019-03-20 07:30:47 +01:00
parent 20c7e47ff7
commit 0fe7308a22
28 changed files with 1468 additions and 2020 deletions

View File

@ -11,7 +11,7 @@
* All algorithms in this module are lazy, they request the next element of the
* original range on demand.
*
* Copyright: Eugene Wissner 2018.
* Copyright: Eugene Wissner 2018-2019.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
@ -26,7 +26,6 @@ import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range;
import tanya.typecons;
version (unittest) import tanya.test.stub;
private struct Take(R, bool exactly)
{
@ -49,21 +48,13 @@ private struct Take(R, bool exactly)
}
@property auto ref front()
in
{
assert(!empty);
}
do
in (!empty)
{
return this.source.front;
}
void popFront()
in
{
assert(!empty);
}
do
in (!empty)
{
this.source.popFront();
--this.length_;
@ -92,21 +83,13 @@ private struct Take(R, bool exactly)
static if (hasAssignableElements!R)
{
@property void front(ref ElementType!R value)
in
{
assert(!empty);
}
do
in (!empty)
{
this.source.front = value;
}
@property void front(ElementType!R value)
in
{
assert(!empty);
}
do
in (!empty)
{
this.source.front = move(value);
}
@ -122,31 +105,19 @@ private struct Take(R, bool exactly)
static if (isRandomAccessRange!R)
{
@property auto ref back()
in
{
assert(!empty);
}
do
in (!empty)
{
return this.source[this.length - 1];
}
void popBack()
in
{
assert(!empty);
}
do
in (!empty)
{
--this.length_;
}
auto ref opIndex(size_t i)
in
{
assert(i < length);
}
do
in (i < length)
{
return this.source[i];
}
@ -154,41 +125,25 @@ private struct Take(R, bool exactly)
static if (hasAssignableElements!R)
{
@property void back(ref ElementType!R value)
in
{
assert(!empty);
}
do
in (!empty)
{
this.source[length - 1] = value;
}
@property void back(ElementType!R value)
in
{
assert(!empty);
}
do
in (!empty)
{
this.source[length - 1] = move(value);
}
void opIndexAssign(ref ElementType!R value, size_t i)
in
{
assert(i < length);
}
do
in (i < length)
{
this.source[i] = value;
}
void opIndexAssign(ElementType!R value, size_t i)
in
{
assert(i < length);
}
do
in (i < length)
{
this.source[i] = move(value);
}
@ -198,12 +153,8 @@ private struct Take(R, bool exactly)
static if (!exactly && hasSlicing!R)
{
auto opSlice(size_t i, size_t j)
in
{
assert(i <= j);
assert(j <= length);
}
do
in (i <= j)
in (j <= length)
{
return typeof(this)(this.source[i .. j], length);
}
@ -322,18 +273,6 @@ if (isInputRange!R)
assert(t.empty);
}
// length is unknown when taking from a range without length
@nogc nothrow pure @safe unittest
{
static struct R
{
mixin InputRangeStub;
}
auto actual = take(R(), 100);
static assert(!hasLength!(typeof(actual)));
}
/**
* Takes exactly $(D_PARAM n) elements from $(D_PARAM range).
*
@ -428,32 +367,6 @@ if (isInputRange!R)
assert(t.empty);
}
// Takes minimum length if the range length > n
@nogc nothrow pure @safe unittest
{
auto range = take(cast(int[]) null, 8);
assert(range.length == 0);
}
@nogc nothrow pure @safe unittest
{
const int[9] range = [1, 2, 3, 4, 5, 6, 7, 8, 9];
{
auto slice = take(range[], 8)[1 .. 3];
assert(slice.length == 2);
assert(slice.front == 2);
assert(slice.back == 3);
}
{
auto slice = takeExactly(range[], 8)[1 .. 3];
assert(slice.length == 2);
assert(slice.front == 2);
assert(slice.back == 3);
}
}
// Reverse-access-order range returned by `retro`.
private struct Retro(Range)
{
@ -522,12 +435,8 @@ private struct Retro(Range)
alias opDollar = length;
auto opSlice(size_t i, size_t j)
in
{
assert(i <= j);
assert(j <= length);
}
do
in (i <= j)
in (j <= length)
{
return typeof(this)(this.source[$-j .. $-i]);
}
@ -615,41 +524,6 @@ if (isBidirectionalRange!Range)
assert(equal(actual, expected[]));
}
// Elements are accessible in reverse order
@nogc nothrow pure @safe unittest
{
const int[3] given = [1, 2, 3];
auto actual = retro(given[]);
assert(actual.back == given[].front);
assert(actual[0] == 3);
assert(actual[2] == 1);
actual.popBack();
assert(actual.back == 2);
assert(actual[1] == 2);
// Check slicing.
auto slice = retro(given[])[1 .. $];
assert(slice.length == 2 && slice.front == 2 && slice.back == 1);
}
// Elements can be assigned
@nogc nothrow pure @safe unittest
{
int[4] given = [1, 2, 3, 4];
auto actual = retro(given[]);
actual.front = 5;
assert(given[].back == 5);
actual.back = 8;
assert(given[].front == 8);
actual[2] = 10;
assert(given[1] == 10);
}
private struct SingletonByValue(E)
{
private Option!E element;
@ -807,49 +681,3 @@ auto singleton(E)(return ref E element)
singleChar.popFront();
assert(singleChar.empty);
}
// Singleton range is bidirectional and random-access
@nogc nothrow pure @safe unittest
{
static assert(isBidirectionalRange!(typeof(singleton('a'))));
static assert(isRandomAccessRange!(typeof(singleton('a'))));
assert({ char a; return isBidirectionalRange!(typeof(singleton(a))); });
assert({ char a; return isRandomAccessRange!(typeof(singleton(a))); });
}
@nogc nothrow pure @safe unittest
{
char a = 'a';
auto single = singleton(a);
assert(single.front == 'a');
assert(single.back == 'a');
assert(single[0] == 'a');
assert(single.length == 1);
assert(!single.empty);
}
// popFront makes SingletonByRef empty
@nogc nothrow pure @safe unittest
{
char a = 'a';
auto single = singleton(a);
single.popFront();
assert(single.empty);
assert(single.length == 0);
assert(single.empty);
}
// popBack makes SingletonByRef empty
@nogc nothrow pure @safe unittest
{
char a = 'b';
auto single = singleton(a);
single.popBack();
assert(single.empty);
assert(single.length == 0);
assert(single.empty);
}