Timon Gehr:

> You lose vs haskell because haskell does not recompute the same PowerSet 
> multiple times.

Are you sure? I have tried with memoization, but now it's slower (about 5.8 
seconds).

Note: to use memoize I have had to add the opCall. Is this really necessary for 
memoization of a struct?


import std.stdio, std.array, std.range, std.functional;

struct PowerSet(T) {
    T[] items;

    static PowerSet opCall(T[] it) {
        PowerSet p;
        p.items = it;
        return p;
    }

    int opApply(int delegate(ref T[]) dg) {
        int result;
        T[] res;
        T[30] buf;

        if (!items.length) {
            result = dg(res);
        } else {
            outer:
            foreach (opt; [items[0..1], []]) {
                buf[0 .. opt.length] = opt[];
                alias memoize!PowerSet mPowerSet;
                foreach (r; mPowerSet(items[1..$])) {
                    buf[opt.length .. opt.length + r.length] = r[];
                    res = buf[0 .. (opt.length + r.length)];
                    result = dg(res);
                    if (result) break outer;
                }
            }
        }

        return result;
    }
}

void main() {
    size_t count;
    foreach (x; PowerSet!int(array(iota(22))))
        count++;
    writeln(count);
}


Bye,
bearophile

Reply via email to