[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