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
|