removed final from variable declarations

This commit is contained in:
Walter Bright 2008-01-28 07:06:00 +00:00
parent c3d2ffdf9b
commit e5c065b46e
4 changed files with 442 additions and 440 deletions

View file

@ -1,439 +1,439 @@
// Written in the D programming language.
/**
This module is a port of a growing fragment of the $(D_PARAM
algorithm) header in Alexander Stepanov's
$(LINK2 http://www.sgi.com/tech/stl/,Standard Template Library).
Macros:
WIKI = Phobos/StdAlgorithm
Author:
Andrei Alexandrescu
*/
/*
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
* Written by Andrei Alexandrescu, www.erdani.org
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
module std.algorithm;
private import std.stdio;
private import std.math;
private import std.random;
private import std.date;
private import std.functional;
/* The iterator-related part below is undocumented and might
* change in future releases. Do NOT rely on it.
*/
template IteratorType(T : U[], U)
{
alias U* IteratorType;
}
template ElementType(T : U[], U)
{
alias U ElementType;
}
IteratorType!(T[]) begin(T)(T[] range)
{
return range.ptr;
}
ElementType!(T[]) front(T)(T[] range)
{
assert(range.length);
return *range.ptr;
}
bool isEmpty(T)(T[] range)
{
return !range.length;
}
IteratorType!(T[]) end(T)(T[] range)
{
return range.ptr + range.length;
}
void next(T)(ref T[] range)
{
range = range.ptr[1 .. range.length];;
}
IteratorType!(R) adjacentFind(R, E)(R range)
{
if (range.isEmpty()) return range.end();
auto result = range.begin();
range.next();
if (range.isEmpty()) return range.end();
for (; !range.isEmpty(); range.next())
{
auto next = range.begin();
if (*result == *next) return result;
result = next;
}
return range.end();
}
IteratorType!(Range) find(Range, E)(Range haystack, E needle)
{
ElementType!(Range) e;
for (; !isEmpty(haystack); next(haystack))
{
if (front(haystack) == needle) break;
}
return begin(haystack);
}
unittest
{
int[] a = ([ 1, 2, 3 ]).dup;
assert(find(a, 5) == a.ptr + a.length);
assert(find(a, 2) == &a[1]);
}
/**
Swaps $(D_PARAM lhs) and $(D_PARAM rhs).
*/
void swap(T)(ref T lhs, ref T rhs)
{
final t = lhs;
lhs = rhs;
rhs = t;
}
/**
Implements C.A.R. Hoare's
$(LINK2 http://en.wikipedia.org/wiki/Selection_algorithm#Partition-based_general_selection_algorithm,
partition) algorithm. Specifically, reorders the range [$(D_PARAM
left), $(D_PARAM right)$(RPAREN) such that everything strictly smaller
(according to the predicate $(D_PARAM compare)) than $(D_PARAM *mid)
is to the left of the returned pointer, and everything else is at the
right of the returned pointer.
Precondition:
$(D_PARAM left == mid && mid == right
||
left <= mid && mid < right).
Returns:
If $(D_PARAM left == right), returns $(D_PARAM left). Otherwise,
return a value $(D_PARAM p) such that the following three conditions
are simultaneously true:
$(OL
$(LI $(D_PARAM *p == *mid))
$(LI $(D_PARAM compare(*p1, *p)) for all $(D_PARAM p1) in [$(D_PARAM
left), $(D_PARAM p)$(RPAREN))
$(LI $(D_PARAM !compare(*p2, *p)) for all $(D_PARAM p2) in [$(D_PARAM p),
$(D_PARAM right)$(RPAREN)))
Example:
----
auto a = [3, 3, 2].dup;
p = partition!(less)(a.ptr, a.ptr, a.ptr + a.length);
assert(p == a.ptr + 1 && a == [2, 3, 3]);
----
*/
template partition(alias compare)
{
///
T partition(T)(T left, T mid, T right)
{
if (left == right) return left;
assert(left <= mid && mid < right);
auto pivot = *mid;
--right;
swap(*mid, *right); // Move pivot to end
auto result = left;
for (auto i = left; i != right; ++i) {
if (!compare(*i, pivot)) continue;
swap(*result, *i);
++result;
}
swap(*right, *result); // Move pivot to its final place
assert(*result == pivot);
return result;
}
}
unittest
{
int[] a = null;
auto p = partition!(less)(a.ptr, a.ptr, a.ptr + a.length);
assert(p is null);
a = [2].dup;
p = partition!(less)(a.ptr, a.ptr, a.ptr + a.length);
assert(p == a.ptr);
a = [2, 2].dup;
p = partition!(less)(a.ptr, a.ptr, a.ptr + a.length);
assert(p == a.ptr);
p = partition!(less)(a.ptr, a.ptr + 1, a.ptr + a.length);
assert(p == a.ptr);
a = [3, 3, 2].dup;
p = partition!(less)(a.ptr, a.ptr, a.ptr + a.length);
assert(p == a.ptr + 1);
}
/**
Reorders the range [$(D_PARAM b), $(D_PARAM e)$(RPAREN) such that
$(D_PARAM nth) points to the element that would fall there if the
range were fully sorted. Effectively, it finds the nth smallest
(according to $(D_PARAM compare)) element in the range [$(D_PARAM b),
$(D_PARAM e)$(RPAREN).
Example:
----
auto v = ([ 25, 7, 9, 2, 0, 5, 21 ]).dup;
auto n = 4;
nthElement!(less)(v.ptr, v.ptr + n, v.ptr + v.length);
assert(v[n] == 9);
----
*/
template nthElement(alias compare)
{
///
void nthElement(T)(T b, T nth, T e)
{
assert(b <= nth && nth < e);
for (;;) {
auto pivot = b + (e - b) / 2;
pivot = partition!(compare)(b, pivot, e);
if (pivot == nth) return;
if (pivot < nth) b = pivot + 1;
else e = pivot;
}
}
}
unittest
{
scope(failure) writeln(stderr, "Failure testing algorithm");
auto v = ([ 25, 7, 9, 2, 0, 5, 21 ]).dup;
auto n = 4;
nthElement!(less)(v.ptr, v.ptr + n, v.ptr + v.length);
assert(v[n] == 9);
//
v = ([3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5]).dup;
n = 3;
nthElement!(less)(v.ptr, v.ptr + n, v.ptr + v.length);
assert(v[n] == 3);
//
v = ([3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5]).dup;
n = 1;
nthElement!(less)(v.ptr, v.ptr + n, v.ptr + v.length);
assert(v[n] == 2);
//
v = ([3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5]).dup;
n = v.length - 1;
nthElement!(less)(v.ptr, v.ptr + n, v.ptr + v.length);
assert(v[n] == 7);
//
v = ([3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5]).dup;
n = 0;
nthElement!(less)(v.ptr, v.ptr + n, v.ptr + v.length);
assert(v[n] == 1);
}
/**
Reverses $(D_PARAM range) in-place.
*/
void reverse(T)(T range)
{
auto len = range.length;
final limit = len / 2;
--len;
for (uint i = 0; i != limit; ++i)
{
final t = range[i];
range[i] = range[len - i];
range[len - i] = t;
}
}
unittest
{
int[] range = null;
reverse(range);
range = [ 1 ].dup;
reverse(range);
assert(range == [1]);
range = [1, 2].dup;
reverse(range);
assert(range == [2, 1]);
range = [1, 2, 3].dup;
reverse(range);
assert(range == [3, 2, 1]);
}
/**
Sorts a random-access range according to predicate $(D_PARAM comp),
which must be a function name.
Example:
----
int[] array = ([ 1, 2, 3, 4 ]).dup;
sort!(greater)(array);
assert(array == [ 4, 3, 2, 1 ]);
bool myComp(int x, int y) { return x < y; }
sort!(myComp)(array);
assert(array == [ 1, 2, 3, 4 ]);
----
*/
template sort(alias comp)
{
void sort(Range)(Range r)
{
static if (is(typeof(comp(*begin(r), *end(r))) == bool))
{
sortImpl!(comp)(begin(r), end(r));
assert(isSorted!(comp)(r));
}
else
{
static assert(false, typeof(&comp).stringof);
}
}
}
/**
Sorts a random-access range according to predicate $(D_PARAM comp),
expressed as a string. The string can use the names "a" and "b" for
the two elements being compared.
Example:
----
int[] array = ([ 1, 2, 3, 4 ]).dup;
sort!("a > b")(array);
assert(array == [ 4, 3, 2, 1 ]);
----
*/
template sort(string comp)
{
void sort(Range)(Range r)
{
alias typeof(*begin(r)) ElementType;
static ElementType a, b;
alias typeof(mixin(comp)) ResultType;
static ResultType compFn(ElementType a, ElementType b)
{
return mixin(comp);
}
.sort!(compFn)(r);
}
}
unittest
{
// sort using delegate
int a[] = new int[100];
auto rnd = Random(getUTCtime);
foreach (ref e; a) {
e = uniform!(int)(rnd, -100, 100);
}
int i = 0;
bool greater2(int a, int b) { return a + i > b + i; }
bool delegate(int, int) greater = &greater2;
sort!(greater)(a);
assert(isSorted!(greater)(a));
// sort using string
sort!("a < b")(a);
assert(isSorted!(less)(a));
// sort using function; all elements equal
foreach (ref e; a) {
e = 5;
}
sort!(less)(a);
assert(isSorted!(less)(a));
// sort using ternary predicate
//sort!("b - a")(a);
//assert(isSorted!(less)(a));
}
/*private*/ template getPivot(alias compare)
{
Iter getPivot(Iter)(Iter b, Iter e)
{
final r = b + (e - b) / 2;
return r;
}
}
/*private*/ template sortImpl(alias comp)
{
void sortImpl(Iter)(Iter b, Iter e)
{
while (e - b > 1)
{
auto m = partition!(comp)(b, getPivot!(comp)(b, e), e);
assert(b <= m && m < e);
.sortImpl!(comp)(b, m);
b = ++m;
}
}
}
/**
Checks whether a random-access range is sorted according to the
comparison operation $(D_PARAM comp).
Example:
----
int[] arr = ([4, 3, 2, 1]).dup;
assert(!isSorted!(less)(arr));
sort!(less)(arr);
assert(isSorted!(less)(arr));
----
*/
template isSorted(alias comp)
{
bool isSorted(Range)(Range r)
{
auto b = begin(r), e = end(r);
if (e - b <= 1) return true;
auto next = b + 1;
for (; next < e; ++b, ++next) {
if (comp(*next, *b)) return false;
}
return true;
}
}
// Written in the D programming language.
/**
This module is a port of a growing fragment of the $(D_PARAM
algorithm) header in Alexander Stepanov's
$(LINK2 http://www.sgi.com/tech/stl/,Standard Template Library).
Macros:
WIKI = Phobos/StdAlgorithm
Author:
Andrei Alexandrescu
*/
/*
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
* Written by Andrei Alexandrescu, www.erdani.org
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
module std.algorithm;
private import std.stdio;
private import std.math;
private import std.random;
private import std.date;
private import std.functional;
/* The iterator-related part below is undocumented and might
* change in future releases. Do NOT rely on it.
*/
template IteratorType(T : U[], U)
{
alias U* IteratorType;
}
template ElementType(T : U[], U)
{
alias U ElementType;
}
IteratorType!(T[]) begin(T)(T[] range)
{
return range.ptr;
}
ElementType!(T[]) front(T)(T[] range)
{
assert(range.length);
return *range.ptr;
}
bool isEmpty(T)(T[] range)
{
return !range.length;
}
IteratorType!(T[]) end(T)(T[] range)
{
return range.ptr + range.length;
}
void next(T)(ref T[] range)
{
range = range.ptr[1 .. range.length];;
}
IteratorType!(R) adjacentFind(R, E)(R range)
{
if (range.isEmpty()) return range.end();
auto result = range.begin();
range.next();
if (range.isEmpty()) return range.end();
for (; !range.isEmpty(); range.next())
{
auto next = range.begin();
if (*result == *next) return result;
result = next;
}
return range.end();
}
IteratorType!(Range) find(Range, E)(Range haystack, E needle)
{
ElementType!(Range) e;
for (; !isEmpty(haystack); next(haystack))
{
if (front(haystack) == needle) break;
}
return begin(haystack);
}
unittest
{
int[] a = ([ 1, 2, 3 ]).dup;
assert(find(a, 5) == a.ptr + a.length);
assert(find(a, 2) == &a[1]);
}
/**
Swaps $(D_PARAM lhs) and $(D_PARAM rhs).
*/
void swap(T)(ref T lhs, ref T rhs)
{
auto t = lhs;
lhs = rhs;
rhs = t;
}
/**
Implements C.A.R. Hoare's
$(LINK2 http://en.wikipedia.org/wiki/Selection_algorithm#Partition-based_general_selection_algorithm,
partition) algorithm. Specifically, reorders the range [$(D_PARAM
left), $(D_PARAM right)$(RPAREN) such that everything strictly smaller
(according to the predicate $(D_PARAM compare)) than $(D_PARAM *mid)
is to the left of the returned pointer, and everything else is at the
right of the returned pointer.
Precondition:
$(D_PARAM left == mid && mid == right
||
left <= mid && mid < right).
Returns:
If $(D_PARAM left == right), returns $(D_PARAM left). Otherwise,
return a value $(D_PARAM p) such that the following three conditions
are simultaneously true:
$(OL
$(LI $(D_PARAM *p == *mid))
$(LI $(D_PARAM compare(*p1, *p)) for all $(D_PARAM p1) in [$(D_PARAM
left), $(D_PARAM p)$(RPAREN))
$(LI $(D_PARAM !compare(*p2, *p)) for all $(D_PARAM p2) in [$(D_PARAM p),
$(D_PARAM right)$(RPAREN)))
Example:
----
auto a = [3, 3, 2].dup;
p = partition!(less)(a.ptr, a.ptr, a.ptr + a.length);
assert(p == a.ptr + 1 && a == [2, 3, 3]);
----
*/
template partition(alias compare)
{
///
T partition(T)(T left, T mid, T right)
{
if (left == right) return left;
assert(left <= mid && mid < right);
auto pivot = *mid;
--right;
swap(*mid, *right); // Move pivot to end
auto result = left;
for (auto i = left; i != right; ++i) {
if (!compare(*i, pivot)) continue;
swap(*result, *i);
++result;
}
swap(*right, *result); // Move pivot to its final place
assert(*result == pivot);
return result;
}
}
unittest
{
int[] a = null;
auto p = partition!(less)(a.ptr, a.ptr, a.ptr + a.length);
assert(p is null);
a = [2].dup;
p = partition!(less)(a.ptr, a.ptr, a.ptr + a.length);
assert(p == a.ptr);
a = [2, 2].dup;
p = partition!(less)(a.ptr, a.ptr, a.ptr + a.length);
assert(p == a.ptr);
p = partition!(less)(a.ptr, a.ptr + 1, a.ptr + a.length);
assert(p == a.ptr);
a = [3, 3, 2].dup;
p = partition!(less)(a.ptr, a.ptr, a.ptr + a.length);
assert(p == a.ptr + 1);
}
/**
Reorders the range [$(D_PARAM b), $(D_PARAM e)$(RPAREN) such that
$(D_PARAM nth) points to the element that would fall there if the
range were fully sorted. Effectively, it finds the nth smallest
(according to $(D_PARAM compare)) element in the range [$(D_PARAM b),
$(D_PARAM e)$(RPAREN).
Example:
----
auto v = ([ 25, 7, 9, 2, 0, 5, 21 ]).dup;
auto n = 4;
nthElement!(less)(v.ptr, v.ptr + n, v.ptr + v.length);
assert(v[n] == 9);
----
*/
template nthElement(alias compare)
{
///
void nthElement(T)(T b, T nth, T e)
{
assert(b <= nth && nth < e);
for (;;) {
auto pivot = b + (e - b) / 2;
pivot = partition!(compare)(b, pivot, e);
if (pivot == nth) return;
if (pivot < nth) b = pivot + 1;
else e = pivot;
}
}
}
unittest
{
scope(failure) writeln(stderr, "Failure testing algorithm");
auto v = ([ 25, 7, 9, 2, 0, 5, 21 ]).dup;
auto n = 4;
nthElement!(less)(v.ptr, v.ptr + n, v.ptr + v.length);
assert(v[n] == 9);
//
v = ([3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5]).dup;
n = 3;
nthElement!(less)(v.ptr, v.ptr + n, v.ptr + v.length);
assert(v[n] == 3);
//
v = ([3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5]).dup;
n = 1;
nthElement!(less)(v.ptr, v.ptr + n, v.ptr + v.length);
assert(v[n] == 2);
//
v = ([3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5]).dup;
n = v.length - 1;
nthElement!(less)(v.ptr, v.ptr + n, v.ptr + v.length);
assert(v[n] == 7);
//
v = ([3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5]).dup;
n = 0;
nthElement!(less)(v.ptr, v.ptr + n, v.ptr + v.length);
assert(v[n] == 1);
}
/**
Reverses $(D_PARAM range) in-place.
*/
void reverse(T)(T range)
{
auto len = range.length;
const limit = len / 2;
--len;
for (uint i = 0; i != limit; ++i)
{
auto t = range[i];
range[i] = range[len - i];
range[len - i] = t;
}
}
unittest
{
int[] range = null;
reverse(range);
range = [ 1 ].dup;
reverse(range);
assert(range == [1]);
range = [1, 2].dup;
reverse(range);
assert(range == [2, 1]);
range = [1, 2, 3].dup;
reverse(range);
assert(range == [3, 2, 1]);
}
/**
Sorts a random-access range according to predicate $(D_PARAM comp),
which must be a function name.
Example:
----
int[] array = ([ 1, 2, 3, 4 ]).dup;
sort!(greater)(array);
assert(array == [ 4, 3, 2, 1 ]);
bool myComp(int x, int y) { return x < y; }
sort!(myComp)(array);
assert(array == [ 1, 2, 3, 4 ]);
----
*/
template sort(alias comp)
{
void sort(Range)(Range r)
{
static if (is(typeof(comp(*begin(r), *end(r))) == bool))
{
sortImpl!(comp)(begin(r), end(r));
assert(isSorted!(comp)(r));
}
else
{
static assert(false, typeof(&comp).stringof);
}
}
}
/**
Sorts a random-access range according to predicate $(D_PARAM comp),
expressed as a string. The string can use the names "a" and "b" for
the two elements being compared.
Example:
----
int[] array = ([ 1, 2, 3, 4 ]).dup;
sort!("a > b")(array);
assert(array == [ 4, 3, 2, 1 ]);
----
*/
template sort(string comp)
{
void sort(Range)(Range r)
{
alias typeof(*begin(r)) ElementType;
static ElementType a, b;
alias typeof(mixin(comp)) ResultType;
static ResultType compFn(ElementType a, ElementType b)
{
return mixin(comp);
}
.sort!(compFn)(r);
}
}
unittest
{
// sort using delegate
int a[] = new int[100];
auto rnd = Random(getUTCtime);
foreach (ref e; a) {
e = uniform!(int)(rnd, -100, 100);
}
int i = 0;
bool greater2(int a, int b) { return a + i > b + i; }
bool delegate(int, int) greater = &greater2;
sort!(greater)(a);
assert(isSorted!(greater)(a));
// sort using string
sort!("a < b")(a);
assert(isSorted!(less)(a));
// sort using function; all elements equal
foreach (ref e; a) {
e = 5;
}
sort!(less)(a);
assert(isSorted!(less)(a));
// sort using ternary predicate
//sort!("b - a")(a);
//assert(isSorted!(less)(a));
}
/*private*/ template getPivot(alias compare)
{
Iter getPivot(Iter)(Iter b, Iter e)
{
auto r = b + (e - b) / 2;
return r;
}
}
/*private*/ template sortImpl(alias comp)
{
void sortImpl(Iter)(Iter b, Iter e)
{
while (e - b > 1)
{
auto m = partition!(comp)(b, getPivot!(comp)(b, e), e);
assert(b <= m && m < e);
.sortImpl!(comp)(b, m);
b = ++m;
}
}
}
/**
Checks whether a random-access range is sorted according to the
comparison operation $(D_PARAM comp).
Example:
----
int[] arr = ([4, 3, 2, 1]).dup;
assert(!isSorted!(less)(arr));
sort!(less)(arr);
assert(isSorted!(less)(arr));
----
*/
template isSorted(alias comp)
{
bool isSorted(Range)(Range r)
{
auto b = begin(r), e = end(r);
if (e - b <= 1) return true;
auto next = b + 1;
for (; next < e; ++b, ++next) {
if (comp(*next, *b)) return false;
}
return true;
}
}