Let me implement this in SequenceableCollection
for the sake of simplicity:
nextCombination09
| j |
j := self findLast: [:ai | ai < 9] ifAbsent: [^nil].
j + 1 to: self size do: [:i | self at: i put: 0].
self at: j put: (self at: j) + 1
The idea is the following: Use the lexicographic order to sort all combinations. In other words:
(a1, ..., an) < (b1, ..., bn)
if ai = bi
for all i
below some index j
where aj < bj
.
With this order the first combination is (0, ..., 0)
and the last one (9, ..., 9)
.
Moreover, given a combination (a1, ..., an)
the next one in this order is the one that adds 1
to the lowest preeminent index, this is the last index j
where aj < 9
. For example the next to (2, 3, 8, 9)
is (2, 3, 9, 9)
as there can't be anything in between.
Once we get to (9, ..., 9)
we are done, and answer with nil
.
Be aware that the method above modifies the receiver, which is why we have to copy
in the script below.
Here is the script that produces all combinations (n
is your N
)
n := <whatever>
array := Array new: n withAll: 0.
combinations := OrderedCollection new: (10 raisedTo: n).
[
combinations add: array copy.
array nextCombination09 notNil] whileTrue.
^combinations
ADDENDUM
The same technique can be used for other problems of similar nature.