I read and reread about recursion. I've seen so many videos and Stack Overflow posts, but I just don't get it. I've been going round and round for three hours on this recursion solution (BTW, yes, I know it's a greedy/unsafe solution)
Example: given coins
[10, 5, 1]
cents, find the minimum number of each coin to total18
cents. A solution is supposed to return the coin collection[10, 5, 1, 1, 1]
.
I can't get it to move past the first coin, 10
in the collection. What am I missing and why?
def r_change_money(total, denominations):
def collect_coins(total, denominations):
if total == 0:
return False
# fd (floor division)
fd = total // denominations[0]
addl_coins = [denominations[0]] * fd
total -= fd * denominations[0]
denominations.pop(0)
return addl_coins
# sort highest denom first
denominations.sort(reverse=True)
# holds coin collection
coins = []
coins += collect_coins(total, denominations)
return coins
# [10, 5, 1, 1, 1]
print(r_change_money(18, [1, 10, 5]))
# [6, 1, 1] (although safe answer is [4, 4])
print(r_change_money(8, [6, 1, 4]))
At least this solution isn't giving me errors anymore, but I am getting:
[10]
[6]
"Recursion" is when a function calls ITSELF. Your code is not doing any recursion. You have r_change_money
calling collect_coins
. The key here is that you need collect_coins
to call collect_coins
, to process the rest of the list.
For this to work, you need (a) to make sure the sequence WILL eventually finish, in this case by having the total go to 0, and (b) to provide a way to collect the answer. I do so here by passing the result list to the inner function.
Here is your example, modified to work correctly:
def r_change_money(total, denominations):
def collect_coins(answer, total, denominations):
if total == 0:
return False
coin = denominations[0]
fd = total // coin
answer.extend( [coin] * fd )
total -= fd * coin
collect_coins( answer, total, denominations[1:] )
denominations.sort(reverse=True) # sort highest denom first
coins = [] # holds coin collection
collect_coins( coins, total, denominations )
return coins
print(r_change_money(18, [1, 10, 5]))
print(r_change_money(8, [6, 1, 4]))
Output:
[10, 5, 1, 1, 1]
[6, 1, 1]
There are still problems with this code. It only works if there actually IS a combination that exactly meets the requirement. r_change_money(5, [2])
will fail.