Last active
December 20, 2015 02:59
-
-
Save tom-tan/6060324 to your computer and use it in GitHub Desktop.
Another implementation of std.algorithm.cartesianProduct
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Another implementation of std.algorithm.cartesianProduct | |
* See_Also: $(LINK2 http://d.puremagic.com/issues/show_bug.cgi?id=10693, Issue 10693) | |
*/ | |
@safe auto cartesianProduct(RR...)(RR Rs) | |
{ | |
return CartesionProduct!RR(Rs); | |
} | |
@safe struct CartesionProduct(RR...) | |
{ | |
static assert(isInputRange!(typeof(this))); | |
immutable size_t length; | |
this(RR rs) pure | |
{ | |
rs_ = rs; | |
size_t tmp = 1; | |
foreach(r; rs_) | |
{ | |
tmp *= r.length; | |
} | |
length = tmp; | |
} | |
@property auto front() const pure | |
{ | |
alias ReturnType = Tuple!(staticMap!(ElementType, RR)); | |
ReturnType ret; | |
auto indices = idxFromIndices(); | |
foreach(i, r; rs_) | |
{ | |
ret[i] = r[indices[i]]; | |
} | |
return ret; | |
} | |
auto popFront() pure nothrow | |
{ | |
index++; | |
} | |
@property auto empty() const pure nothrow | |
{ | |
return index >= length; | |
} | |
private: | |
import std.typetuple; | |
import std.typecons; | |
import std.range; | |
auto idxFromIndices() const pure | |
{ | |
Unqual!(typeof(index)) idx = index; | |
size_t[] indices = []; | |
foreach(r; Reverse!(rs_)) | |
{ | |
indices ~= idx%r.length; | |
idx /= r.length; | |
} | |
indices.reverse; | |
return indices; | |
} | |
RR rs_; | |
size_t index; | |
} | |
unittest | |
{ | |
{ | |
auto cp = cartesianProduct([1,2,3], [4,5]); | |
assert(cp.length == 6); | |
assert(!cp.empty); | |
assert(cp.front == tuple(1, 4)); | |
cp.popFront(); | |
assert(!cp.empty); | |
assert(cp.front == tuple(1,5)); | |
} | |
{ | |
auto a = [1, 2, 3]; | |
auto b = [4, 5]; | |
auto c = ["foo", "bar", "buzz"]; | |
auto d = ['a', 'b', 'c']; | |
auto e = [1.1, 2.2, 3.3]; | |
auto cp = cartesianProduct(a, b, c, d, e); | |
pragma(msg, ElementType!(typeof(cp)).stringof); | |
assert(is(ElementType!(typeof(cp)) == Tuple!(int, int, string, dchar, double))); | |
assert(cp.length == 162); | |
assert(cp.front == tuple(1, 4, "foo", 'a', 1.1)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Bug #10693 is solved in HEAD.