On 09/12/2011 06:57 PM, bearophile wrote:
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

std.functional.memoize uses AAs internally, so that is very slow.

Haskell builds a linked data structure, if you have

result: [...,[2,3],[1,2,3]]

then the [2,3] part is exactly the same for both. Also, if you only look at the length, the haskell code probably does not fully evaluate the power set.






Reply via email to