The goal is to compute the number of different ways to change a dollar into
an arbitrary number of 50, 25, 10, 5 and 1 cent coins.
(I.e. one solution would be: 50 + 25 + 10 + 5 + 5 + 1 + 1 + 1 + 1 + 1)
|f coins solutions|
coins := #(50 25 10 5 1).
f := [:coinsAlreadyTaken :amount|
|solutions t|
amount == 0 ifTrue:[
Array with: coinsAlreadyTaken
] ifFalse:[
solutions := Set new.
coins do:[:cn |
cn <= amount ifTrue:[
solutions
addAll:
(f
value:(coinsAlreadyTaken copy add:cn; yourself)
value:amount-cn)
]
].
solutions
]
].
solutions := f value:#() asBag value:100.
solutions size
this algorithm works and returns the correct number of solutions (292);
|solutionForAmountAndCoins f coins solutions|
coins := #(50 25 10 5 1).
solutionForAmountAndCoins := Dictionary new.
f := [:coinsAlready :amount|
|solutions t|
amount == 0 ifTrue:[
{ coinsAlready }
] ifFalse:[
t := solutionForAmountAndCoins at:amount ifAbsentPut:[Dictionary new].
solutions := t at:coinsAlready ifAbsent:nil.
solutions isNil ifTrue:[
solutions := Set new.
coins do:[:cn |
cn <= amount ifTrue:[
solutions
addAll:
(f
value:(coinsAlready copy add:cn; yourself)
value:amount-cn)
]
].
t at:coinsAlready put:solutions.
].
solutions
]
].
solutions := f value:#() asBag value:100.
solutions size
|numberOfSolutions valOfCoin cc|
valOfCoin := #(1 5 10 25 50).
cc := [:amount :kinds |
amount == 0
ifTrue:[ 1 ]
ifFalse:[
amount < 0
ifTrue:[ 0 ]
ifFalse:[
kinds == 0
ifTrue:[0]
ifFalse:[
(cc value:amount value:(kinds - 1))
+
(cc value:(amount - (valOfCoin at:kinds))
value:kinds)
]
]
]
].
numberOfSolutions := cc value:100 value:5.
numberOfSolutions
Copyright © Claus Gittinger Development & Consulting
Copyright © eXept Software AG
<cg@exept.de>