Few things II

Oskar Linde oskar.lindeREM at OVEgmail.com
Thu Aug 16 02:43:25 PDT 2007


bearophile wrote:

> In the meantime I have found some problems translating lazy recursive generators from Py=>D, like this one, that yields the combinations of the given items, taking k distinct elements (this kind of code may look slow). You may help me:
> 
> def xcombinations(items, k):
>   if k:
>     for i in xrange(len(items) - k + 1):
>       for cc in xcombinations(items[i+1:], k-1):
>         yield [items[i]] + cc
>   else:
>     yield []
> 
> Usage example:
> xcombinations("abcd", 1) ==> "a" "b" "c" "d"
> xcombinations("abcd", 2) ==> "ab" "ac" "ad" "bc" "bd" "cd"
> xcombinations("abcd", 3) ==> "abc" "abd" "acd" "bcd"


As far as I can tell, the following should work. Maybe I am missing 
something fundamental, as this is just a straight forward implementation 
of the above. Note that yield(x) is:

{ auto tmp = x; if (auto r = dg(tmp)) return r; }

(Might be a nice macro in the future.)

Code:

struct XRange {
   int n;

   int opApply(int delegate(inout int v) dg) {
     for (int i = 0; i < n; i++)
       if (auto r = dg(i)) return r;
     return 0;
   }
}

XRange xrange(int n) { XRange r; r.n = n; return r; }

struct XCombinations(T) {
   T[] items;
   int k;
	
   int opApply(int delegate(inout T[] arr) dg) {
     if (k > 0)
       foreach (i; xrange(items.length - k + 1))
         foreach(cc; xcombinations(items[i+1..$], k-1)) {
           auto tmp = items[i] ~ cc; // must be an lvalue
           if (auto r = dg(tmp)) return r;
	}
     else {
       T[] tmp = null; // need an lvalue
       return dg(tmp);
     }
     return 0;
   }	
}

XCombinations!(T) xcombinations(T)(T[] items, int k) {
   XCombinations!(T) ret;
   ret.items = items;
   ret.k = k;
   return ret;
}



-- 
Oskar



More information about the Digitalmars-d mailing list