Collection Permutations/Combinations code?

Richard A. O'Keefe ok at cs.otago.ac.nz
Fri May 23 05:13:47 UTC 2003


"Joshua 'Schwa' Gargus" <schwa at cc.gatech.edu> asked:
	Does anyone have code that does something like:
	
	aCollection choose: 3 do: [:array | ...]
	
	where each possible unordered collection of 3 elements (ie:
	"n-choose-k", where n is the size of aCollection and k is here 3) is
	chosen from aCollection and passed as the argument to the block?
	
Well, I do, for Prolog.  But it's pretty rather than useful,
because n-choose-k gets big FAST.

Let's see how we might do this.

To choose k items out of n:
   If n < k, we can't do it.
   If k = 0 we are done.
   If k > 0, then
      Either we take item n and choose k-1 from n-1,
      or we choose k from n-1.

So here we go.  I'm going to put this in Array.

Array methods for 'enumerating'

    choose: k of: n into: workingArray do: aBlock
        n < k ifTrue: [^self].
        k = 0 ifTrue: [^aBlock value: workingArray].
        workingArray at: k put: (self at: n).
        self choose: k-1 of: n-1 into: workingArray do: aBlock.
        self choose: k of: n-1 into: workingArray do: aBlock.

    choose: k do: aBlock
	|workingArray|
	workingArray := Array new: k.
	self choose: k of: self size into: workingArray do: aBlock.

If you want this for other collections, stick

    choose: k do: aBlock
	self asArray choose: k do: aBlock

in Collection.

For example, #(a b c d) choose: 2 do: ... reports
#(c d), #(b d), #(a d), #(b c), #(a c), #(a b)
in that order.



More information about the Squeak-dev mailing list