Wednesday, February 7, 2024

Python Change Maker (And Federal Tax Maker)

Today I was hit with this beauty in Python, and I'd like to go through the solution step by step:

"Given a dollar amount as a floating-point number, print out the smallest number (count) of coins and bills needed to make that amount.

The amount must be < $100.

Output should be printed, not returned.

Examples:

$1.05

1x $1 bill

1x nickel


$0.41

1x quarter

1x dime

1x nickel

1x penny"


This question is a class trap in control flow and will test how a person understands what the computer is doing step by step.

At first I started pedantically, thinking I was clever by starting with larger coins and working my way down:

quarters fire off at 25, 50, 75

dimes fire off at 10 20 30 35 40 45 50 60 70 80 90

nickels fire off at 5 15 25 35 45 55 65 75 85 95

hundredths place from 1-4 and 6-9 receive pennies 

(I'm so rusty at math I had to Google "hundredths place" lol)



Then I got a little frustrated, thinking about how I couldn't wrap my head around moving up in a direction. This is kind of how the thought process worked:

When able to / by 50, do that save quotient = bills

when able to / by 10, do that, save quotient = bills

"When the amount is 80 dollars and we've comitted to giving the 50. The amount 80 is greater than or equal to 50 and less than 100, then you only owe 30 dollars."


There's always a trick to coding and even in math, especially when it comes to "thinking backwards." Once you've unlocked that the secret to this problem is






subtraction



then there's no going back, and the rest, honestly, is pretty smooth. Or at least that's how it feels for me and my learning process. In layperson language, it's something like:

for each denomination, from highest to lowest:

     calculate how many of this denomination to give

     print out (or store to print later) that quantity

     subtract the change given from amount



As it looks in code:

def make_change(amount):

     if amount >= 100:

          raise Exception("YOU CAN'T DO THAT")

     if amount >= 50:

          print(f"{amount//50} Fifty")

          amount -= 50

     if amount > 19.99:

          print(f"{amount//20} Twenty")

          amount -= 20 * (amount//20)

      if amount > 9.99:

          print(f"{amount//10} Ten")

          amount -= 10 * (amount//10)

      if amount > 4.99:

          print(f"{amount//5} Five")

          amount -= 5 * (amount//5)

      if amount > 0.99:

          print(f"{amount//1} One")

          amount -= 1 * (amount//1)

make_change(36.41)

"""This will give the user one of each, and I used to love that at a cash register.


***Then you have figured it out, hurray, you're feeling good. But now you notice it's a long piece of code and it's just doing the same thing over and over. For each denomination you're applying the same rules, the only thing that's changing is the amount and denomination. You can start representing these things by iterating with your i count placeholder as shown below:

def make_change2(amount):

     denoms = [50, 20, 10, 5, 1, 0.25, 0.10, 0.05, 0.01]

     names = ["fifty", "twenty", "ten", "five", "one", "quarter", "dime", "nickel", "penny"]

         for i in range(0, len(denoms) - 1):

             if amount >= denoms[ i ]:

             qty = amount // denoms[ i ]

             print( f"{qty} {names[i]}" )

             amount -= denoms[ i ] * qty

make_change2(36.41)





Finally, another example using the IRS Federal Taxes, because this code makes the floor and tax rates easy to change:

def calc_tax(pay):

    rates = [0.37, 0.35, 0.32, 0.24, 0.22, 0.12, 0.1]

    floors = [578126, 231251, 182101, 95376, 44726, 11001, 0]

    tax = 0

    

    for i in range(0, len(rates)):

        if pay >= floors[ i ]: 

            tax = tax + (pay - floors[ i ]) * rates [ i ]

            pay = floors[i] - 1

            print(f"pay = {pay} floor = {floors[ i ]} rate = {rates[ i ]} tax = {tax}")

    return tax

        

calc_tax(100000)