Skip to content

Instantly share code, notes, and snippets.

@tom-tan
Last active December 20, 2015 02:59
Show Gist options
  • Save tom-tan/6060324 to your computer and use it in GitHub Desktop.
Save tom-tan/6060324 to your computer and use it in GitHub Desktop.
Another implementation of std.algorithm.cartesianProduct
/**
* 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));
}
}
@tom-tan
Copy link
Author

tom-tan commented Oct 16, 2014

Bug #10693 is solved in HEAD.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment