2

I have been studying algorithms and data structures off https://runestone.academy/runestone/static/pythonds/index.html, and I got to the part about dynamic programming and the classic minimum number of coins problem. Given a sum we have to figure out what is the minimum number of coins required to change it into coins from various denominations.

In the code the book proposes to solve the problem there are 2 lines whose role I can't figure out even if my life depended on it.

The code is here:

def recMC(coinValueList,change):
   minCoins = change
   if change in coinValueList:
     return 1
   else:
      for i in [c for c in coinValueList if c <= change]:
         numCoins = 1 + recMC(coinValueList,change-i)
         if numCoins < minCoins:
            minCoins = numCoins
   return minCoins

print(recMC([1,5,10,25],63))

and I don't understand why we need this part:

         if numCoins < minCoins:
            minCoins = numCoins
   return minCoins

I tried replacing all 3 lines with a single statement

   return numCoins 

And it seems to work just fine, except for when change == 0. I don't think the way they wrote it in the book is meant to "protect" against an input of 0, since that can be handled even more trivially.

Why did they write it the way they did ?

ps: I am running it on python3.5 if it matters ...

cheers

d_darric
  • 387
  • 2
  • 15
  • try passing coins in reverse order. e.g print(recMC([25, ,5,1, 10],63)) – chandra Nov 05 '18 at 23:23
  • Thanks for the tip @chandra, it actually gives weird results... I am trying to debug it now. – d_darric Nov 06 '18 at 08:42
  • I'm sorry I am having trouble visualizing how this works... it seems to me we are comparing apples and oranges with numCoins < minCoins. Do you mind expanding a little bit ? thanks – d_darric Nov 06 '18 at 10:16

1 Answers1

0

As explained in the chapter,

If the amount does not match we have several options. What we want is the minimum of a penny plus the number of coins needed to make change for the original amount minus a penny, or a nickel plus the number of coins needed to make change for the original amount minus five cents, or a dime plus the number of coins needed to make change for the original amount minus ten cents, and so on. So the number of coins needed to make change for the original amount can be computed according to the following:

numCoins=min(1+numCoins(originalamount−1),
             1+numCoins(originalamount−5),
             1+numCoins(originalamount−10),
             1+numCoins(originalamount−25))

The below line in for loop is calculating each of the options for numCoins.

for i in [c for c in coinValueList if c <= change]:
     numCoins = 1 + recMC(coinValueList,change-i)

The next two lines in the loop are keeping track of the minimum value of numCoins:

if numCoins < minCoins:
        minCoins = numCoins

To make it easy to follow, you could rewrite the function as:

def recMC(coinValueList,change):
    if change in coinValueList:
        return 1
    else:
        return min([1 + recMC(coinValueList,change-c) for c in coinValueList if c < change])
chandra
  • 500
  • 4
  • 12
  • Thanks a lot man, I was able to figure it out in the end :) I got lost because it seemed weird to stock numCoins in minCoins but it actually did not matter since the parameter we are passing in the recursion is change... thx again. – d_darric Nov 08 '18 at 20:42
  • But I like the way you rewrote it more indeed, it think it is less ambiguous. – d_darric Nov 08 '18 at 20:48