how to do nested loops of variable depth?

Stephan Rudlof sr at evolgo.de
Fri Dec 21 03:52:02 UTC 2001


This thread has motivated me for making yet another iterative solution
(resulting in the tupels):

| collectionCombinatorBlock arrays |

collectionCombinatorBlock _ [:collections | | tupels sizeOfTupel tupel
collStreams pos activeStream |
  tupels _ OrderedCollection new.
  sizeOfTupel _ collections size.
  tupel _ Array new: sizeOfTupel.
  collStreams _ collections collect: [:coll | ReadStream on: coll].

  pos _ 1.
  activeStream _ collStreams at: pos.

  [activeStream atEnd] whileFalse: [
    tupel at: pos put: activeStream next.
    pos = sizeOfTupel
      ifTrue: ["tupel finished"
        tupels addLast: tupel copy.
        [pos > 1 and: [activeStream atEnd]] whileTrue: [
          "reset and search back for next tupel pos to 'increment'"
          activeStream reset.
          pos _ pos - 1.
          activeStream _ collStreams at: pos.
        ]
      ]
      ifFalse: ["next tupel position"
        pos _ pos + 1.
        activeStream _ collStreams at: pos.
      ].
  ].
  tupels.
].

arrays := OrderedCollection new.
arrays add: #(#a #b);
     add: #(1 2 3 4);
     add: #('w' 'x' 'y' 'z').
collectionCombinatorBlock value: arrays.


It's interesting how many ways there are to solve a problem...


Greetings,

Stephan


Chris Muller wrote:
> 
> I see you already have a solution.  Here is mine that
> does not use any recursion, minimizes allocation and,
> like Boris', values each combination as-you-go.  This
> one will work in a workspace.  Just supply the doBlock
> with the correct number of arguments and away you go!
> 
>         | anArrayOfArrays doBlock numberOfCombinations args |
>         anArrayOfArrays _ OrderedCollection new
>                 add: #('eat' 'wear');
>                 add: #('green' 'blue' 'orange');
>                 add: #('apples' 'oranges' 'cherries');
>                 yourself.
>         doBlock _
>                 [ :eachVerb :eachColor :eachFruit | Transcript cr;
> show: eachVerb, eachColor, eachFruit ].
>         numberOfCombinations :=
>                 anArrayOfArrays
>                         inject: 1
>                         into: [ :prod :each | each size * prod ].
>         args := Array new: anArrayOfArrays size.
>         1
>                 to: numberOfCombinations
>                 do:
>                         [ :elementIndex |
>                         1
>                                 to: anArrayOfArrays size
>                                 do:
>                                         [ :innerIndex | | eachInnerArray radix |
>                                         eachInnerArray := anArrayOfArrays at: innerIndex.
>                                         radix := 1.
>                                         1
>                                                 to: innerIndex - 1
>                                                 do: [ :eachOrder | radix := radix *
> (anArrayOfArrays at: eachOrder) size ].
>                                         args
>                                                 at: innerIndex
>                                                 put: (eachInnerArray at: (elementIndex // radix
> \\ eachInnerArray size + 1)) ].
>                         doBlock valueWithArguments: args ]
> 
> __________________________________________________
> Do You Yahoo!?
> Check out Yahoo! Shopping and Yahoo! Auctions for all of
> your unique holiday gifts! Buy at http://shopping.yahoo.com
> or bid at http://auctions.yahoo.com

-- 
Stephan Rudlof (sr at evolgo.de)
   "Genius doesn't work on an assembly line basis.
    You can't simply say, 'Today I will be brilliant.'"
    -- Kirk, "The Ultimate Computer", stardate 4731.3




More information about the Squeak-dev mailing list