Skip to content

Commit

Permalink
Merge pull request #4110 from wilzbach/is_strictly_sorted
Browse files Browse the repository at this point in the history
add isStrictlyMonotonic for ranges
  • Loading branch information
Hackerpilot committed Apr 20, 2016
2 parents a01b985 + 95cb575 commit a102024
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 5 deletions.
2 changes: 2 additions & 0 deletions changelog.dd
Expand Up @@ -21,6 +21,8 @@ $(BUGSTITLE Library Changes,
arguments.)
$(LI $(XREF range, iota)'s `.length` property is fixed to `size_t` instead
of the type being iterated)
$(LI $(XREF algorithm, sorting, isStrictlyMonotonic) which doesn't allow
equal values was added.)
)

$(BUGSTITLE Library Changes,
Expand Down
1 change: 1 addition & 0 deletions std/algorithm/package.d
Expand Up @@ -87,6 +87,7 @@ $(TR $(TDNW Sorting)
$(SUBREF sorting, completeSort)
$(SUBREF sorting, isPartitioned)
$(SUBREF sorting, isSorted)
$(SUBREF sorting, isStrictlyMonotonic)
$(SUBREF sorting, ordered)
$(SUBREF sorting, strictlyOrdered)
$(SUBREF sorting, makeIndex)
Expand Down
79 changes: 74 additions & 5 deletions std/algorithm/sorting.d
Expand Up @@ -19,6 +19,8 @@ $(T2 isPartitioned,
afterwards.)
$(T2 isSorted,
$(D isSorted([1, 1, 2, 3])) returns $(D true).)
$(T2 isStrictlyMonotonic,
$(D isStrictlyMonotonic([1, 1, 2, 3])) returns $(D false).)
$(T2 ordered,
$(D ordered(1, 1, 2, 3)) returns $(D true).)
$(T2 strictlyOrdered,
Expand Down Expand Up @@ -136,11 +138,20 @@ Checks whether a forward range is sorted according to the comparison
operation $(D less). Performs $(BIGOH r.length) evaluations of $(D
less).
Unlike $(LREF isSorted), $(LREF isStrictlyMonotonic) does not allow for equal values,
i.e. values for which both `less(a, b)` and `less(b, a)` are false.
With either function, the predicate must be a strict ordering just like with
$(LREF isSorted). For example, using `"a <= b"` instead of `"a < b"` is
incorrect and will cause failed assertions.
Params:
less = Predicate the range should be sorted by.
r = Forward range to check for sortedness.
Returns: true if the range is sorted, false otherwise.
Returns:
`true` if the range is sorted, false otherwise. $(LREF isSorted) allows
duplicates, $(LREF isStrictlyMonotonic) not.
*/
bool isSorted(alias less = "a < b", Range)(Range r) if (isForwardRange!(Range))
{
Expand Down Expand Up @@ -182,12 +193,20 @@ bool isSorted(alias less = "a < b", Range)(Range r) if (isForwardRange!(Range))
///
@safe unittest
{
assert([1, 1, 2].isSorted);
// strictly monotonic doesn't allow duplicates
assert(![1, 1, 2].isStrictlyMonotonic);

int[] arr = [4, 3, 2, 1];
assert(!isSorted(arr));
assert(!isStrictlyMonotonic(arr));

assert(isSorted!"a > b"(arr));
assert(isStrictlyMonotonic!"a > b"(arr));

sort(arr);
assert(isSorted(arr));
sort!("a > b")(arr);
assert(isSorted!("a > b")(arr));
assert(isStrictlyMonotonic(arr));
}

@safe unittest
Expand All @@ -205,13 +224,63 @@ bool isSorted(alias less = "a < b", Range)(Range r) if (isForwardRange!(Range))
int[] b = [1, 3, 2];
assert(!isSorted(b));

// ignores duplicates
int[] c = [1, 1, 2];
assert(isSorted(c));

dchar[] ds = "コーヒーが好きです"d.dup;
sort(ds);
string s = to!string(ds);
assert(isSorted(ds)); // random-access
assert(isSorted(s)); // bidirectional
}

@nogc @safe nothrow pure unittest
{
static immutable a = [1, 2, 3];
assert(a.isSorted);
}

/// ditto
bool isStrictlyMonotonic(alias less = "a < b", Range)(Range r)
if (isForwardRange!Range)
{
import std.algorithm.searching : findAdjacent;
return findAdjacent!((a,b) => !binaryFun!less(a,b))(r).empty;
}

@safe unittest
{
import std.conv : to;

assert("abcd".isStrictlyMonotonic);
assert(!"aacd".isStrictlyMonotonic);
assert(!"acb".isStrictlyMonotonic);

assert([1, 2, 3].isStrictlyMonotonic);
assert(![1, 3, 2].isStrictlyMonotonic);
assert(![1, 1, 2].isStrictlyMonotonic);

// ー occurs twice -> can't be strict
dchar[] ds = "コーヒーが好きです"d.dup;
sort(ds);
string s = to!string(ds);
assert(!isStrictlyMonotonic(ds)); // random-access
assert(!isStrictlyMonotonic(s)); // bidirectional

dchar[] ds2 = "コーヒが好きです"d.dup;
sort(ds2);
string s2 = to!string(ds2);
assert(isStrictlyMonotonic(ds2)); // random-access
assert(isStrictlyMonotonic(s2)); // bidirectional
}

@nogc @safe nothrow pure unittest
{
static immutable a = [1, 2, 3];
assert(a.isStrictlyMonotonic);
}

/**
Like $(D isSorted), returns $(D true) if the given $(D values) are ordered
according to the comparison operation $(D less). Unlike $(D isSorted), takes values
Expand All @@ -221,8 +290,8 @@ $(D ordered) allows repeated values, e.g. $(D ordered(1, 1, 2)) is $(D true). To
that the values are ordered strictly monotonically, use $(D strictlyOrdered);
$(D strictlyOrdered(1, 1, 2)) is $(D false).
With either function, the predicate must be a strict ordering just like with $(D isSorted). For
example, using $(D "a <= b") instead of $(D "a < b") is incorrect and will cause failed
With either function, the predicate must be a strict ordering. For example,
using $(D "a <= b") instead of $(D "a < b") is incorrect and will cause failed
assertions.
Params:
Expand Down

0 comments on commit a102024

Please sign in to comment.