Add min/max algorithms
This commit is contained in:
parent
e8222123e6
commit
86053de8c9
source/tanya/algorithm
195
source/tanya/algorithm/comparison.d
Normal file
195
source/tanya/algorithm/comparison.d
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Algorithms for comparing values.
|
||||||
|
*
|
||||||
|
* Copyright: Eugene Wissner 2018.
|
||||||
|
* 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)
|
||||||
|
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/algorithm/comparison.d,
|
||||||
|
* tanya/algorithm/comparison.d)
|
||||||
|
*/
|
||||||
|
module tanya.algorithm.comparison;
|
||||||
|
|
||||||
|
import tanya.meta.trait;
|
||||||
|
import tanya.range.array;
|
||||||
|
import tanya.range.primitive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the smallest element in the argument list or a range.
|
||||||
|
*
|
||||||
|
* The function should take at least one argument.
|
||||||
|
*
|
||||||
|
* If a range is passed, $(D_PSYMBOL min) returns a range of the same type,
|
||||||
|
* whose front element is the smallest in the range. If more than one element
|
||||||
|
* fulfills this condition, the front of the returned range points to
|
||||||
|
* the first one found.
|
||||||
|
* If $(D_PARAM range) is empty, the original range is returned.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* Args = Types of the arguments. All arguments should have the same type.
|
||||||
|
* Range = Forward range type.
|
||||||
|
* args = Argument list.
|
||||||
|
* range = Forward range.
|
||||||
|
*
|
||||||
|
* Returns: The smallest element.
|
||||||
|
*/
|
||||||
|
Args[0] min(Args...)(Args args)
|
||||||
|
if (Args.length > 0 && isOrderingComparable!(Args[0]) && allSameType!Args)
|
||||||
|
{
|
||||||
|
return min!Args(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ditto
|
||||||
|
ref Args[0] min(Args...)(ref Args args)
|
||||||
|
if (Args.length > 0 && isOrderingComparable!(Args[0]) && allSameType!Args)
|
||||||
|
{
|
||||||
|
auto actual = (() @trusted => &args[0])();
|
||||||
|
|
||||||
|
foreach (arg; args[1 .. $])
|
||||||
|
{
|
||||||
|
if (arg < *actual)
|
||||||
|
{
|
||||||
|
actual = (() @trusted => &arg)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
assert(min(1) == 1);
|
||||||
|
static assert(!is(typeof(min(1, 1UL))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ditto
|
||||||
|
Range min(Range)(Range range)
|
||||||
|
if (isForwardRange!Range && isOrderingComparable!(ElementType!Range))
|
||||||
|
{
|
||||||
|
if (range.empty)
|
||||||
|
{
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
auto actual = range.save;
|
||||||
|
|
||||||
|
range.popFront();
|
||||||
|
for (; !range.empty; range.popFront())
|
||||||
|
{
|
||||||
|
if (range.front < actual.front)
|
||||||
|
{
|
||||||
|
actual = range.save;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
assert(min(1, 2) == 1);
|
||||||
|
assert(min(3, 2) == 2);
|
||||||
|
assert(min(3, 1, 2) == 1);
|
||||||
|
|
||||||
|
int[4] range = [3, 1, 1, 2];
|
||||||
|
auto minElement = min(range[]);
|
||||||
|
assert(minElement.front == 1);
|
||||||
|
assert(minElement.length == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
assert(min(cast(ubyte[]) []).empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the largest element in the argument list or a range.
|
||||||
|
*
|
||||||
|
* The function should take at least one argument.
|
||||||
|
*
|
||||||
|
* If a range is passed, $(D_PSYMBOL max) returns a range of the same type,
|
||||||
|
* whose front element is the largest in the range. If more than one element
|
||||||
|
* fulfills this condition, the front of the returned range points to
|
||||||
|
* the first one found.
|
||||||
|
* If $(D_PARAM range) is empty, the original range is returned.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* Args = Types of the arguments. All arguments should have the same type.
|
||||||
|
* Range = Forward range type.
|
||||||
|
* args = Argument list.
|
||||||
|
* range = Forward range.
|
||||||
|
*
|
||||||
|
* Returns: The largest element.
|
||||||
|
*/
|
||||||
|
Args[0] max(Args...)(Args args)
|
||||||
|
if (Args.length > 0 && isOrderingComparable!(Args[0]) && allSameType!Args)
|
||||||
|
{
|
||||||
|
return max!Args(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ditto
|
||||||
|
ref Args[0] max(Args...)(ref Args args)
|
||||||
|
if (Args.length > 0 && isOrderingComparable!(Args[0]) && allSameType!Args)
|
||||||
|
{
|
||||||
|
auto actual = (() @trusted => &args[0])();
|
||||||
|
|
||||||
|
foreach (arg; args[1 .. $])
|
||||||
|
{
|
||||||
|
if (arg > *actual)
|
||||||
|
{
|
||||||
|
actual = (() @trusted => &arg)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
assert(max(1) == 1);
|
||||||
|
static assert(!is(typeof(max(1, 1UL))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ditto
|
||||||
|
Range max(Range)(Range range)
|
||||||
|
if (isForwardRange!Range && isOrderingComparable!(ElementType!Range))
|
||||||
|
{
|
||||||
|
if (range.empty)
|
||||||
|
{
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
auto actual = range.save;
|
||||||
|
|
||||||
|
range.popFront();
|
||||||
|
for (; !range.empty; range.popFront())
|
||||||
|
{
|
||||||
|
if (range.front > actual.front)
|
||||||
|
{
|
||||||
|
actual = range.save;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
assert(max(1, 2) == 2);
|
||||||
|
assert(max(3, 2) == 3);
|
||||||
|
assert(max(1, 3, 2) == 3);
|
||||||
|
|
||||||
|
int[4] range = [1, 5, 5, 2];
|
||||||
|
auto maxElement = max(range[]);
|
||||||
|
assert(maxElement.front == 5);
|
||||||
|
assert(maxElement.length == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
assert(max(cast(ubyte[]) []).empty);
|
||||||
|
}
|
@ -14,4 +14,5 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.algorithm;
|
module tanya.algorithm;
|
||||||
|
|
||||||
|
public import tanya.algorithm.comparison;
|
||||||
public import tanya.algorithm.mutation;
|
public import tanya.algorithm.mutation;
|
||||||
|
Loading…
Reference in New Issue
Block a user