[Issue 7128] Cartesian product of ranges
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Sat Jan 10 15:45:44 PST 2015
https://issues.dlang.org/show_bug.cgi?id=7128
--- Comment #23 from bearophile_hugs at eml.cc ---
This doesn't use an efficient algorithm, but it shows the kind of API I was
thinking of (it can be a random access range):
struct CartesianPower(bool doCopy=true, T) {
T[] items;
uint repeat;
T[] row;
uint i, maxN;
this(T[] items_, in uint repeat_, T[] buffer) pure nothrow @safe @nogc {
this.items = items_;
this.repeat = repeat_;
row = buffer[0 .. repeat];
row[] = items[0];
maxN = items.length ^^ repeat;
}
static if (doCopy) {
@property T[] front() pure nothrow @safe @nogc {
return row.dup;
}
} else {
@property T[] front() pure nothrow @safe @nogc {
return row;
}
}
@property bool empty() pure nothrow @safe @nogc {
return i >= maxN;
}
void popFront() pure nothrow @safe @nogc {
i++;
if (empty)
return;
uint n = i;
size_t count = repeat - 1;
while (n) {
row[count] = items[n % items.length];
count--;
n /= items.length;
}
}
}
auto cartesianPower(bool doCopy=true, T)(T[] items, in uint repeat)
pure nothrow @safe {
return CartesianPower!(doCopy, T)(items, repeat, new T[repeat]);
}
auto cartesianPower(bool doCopy=true, T)(T[] items, in uint repeat, T[] buffer)
pure nothrow @safe @nogc {
if (buffer.length >= repeat) {
return CartesianPower!(doCopy, T)(items, repeat, buffer);
} else {
static immutable err = new Error("buffer.length < repeat");
throw err;
}
}
void main() @nogc {
import core.stdc.stdio;
int[3] items = [10, 20, 30];
int[4] buf;
foreach (p; cartesianPower!false(items, 4, buf))
printf("(%d, %d, %d, %d)\n", p[0], p[1], p[2], p[3]);
}
--
More information about the Digitalmars-d-bugs
mailing list