Here is a faster version of your program. I've changed two things:
Implementation detail: all recursive programs can be re-written as equivalent iterative programs (in this case, using a for
and a while
loop). In most languages, the iterative version is faster as there is no need to maintain a stack.
Algorithm: I am using a greedy algorithm that starts off with the largest-value coins first, and then tries the smaller coins. This is not guaranteed to be optimal, as pointed out in other answers, but runs very fast (linear in the number of coins in the returned solution). Have a look at this page for an optimal (but slower) dynamic programming solution.
def min_coin_change2(n, d):
current_amount = 0
used_coins = []
for coin_value in sorted(d, reverse=True):
while n - current_amount >= coin_value:
current_amount += coin_value
used_coins.append(coin_value)
excuse = '' if current_amount == n else ', but that is not what you asked for'
return 'I can get to %d using %s%s' % (current_amount, used_coins, excuse)
Let's try it out:
print min_coin_change2(101, [50, 20, 10, 1])
Out[25]: 'I can get to 101 using [50, 50, 1]'
and again, when it is impossible to get the desired amount
print min_coin_change2(101, [50, 20, 10])
Out[26]: 'I can get to 100 using [50, 50], but that is not what you asked for'
and again, when the greedy algorithm finds a sub-optimal solution
print min_coin_change2(180, [100, 90, 20])
Out[2]: 'I can get to 180 using [100, 20, 20, 20, 20]'
but the optimal solution would have been [90, 90]