Cash Register Change Program

I just need some suggestions on how to start this program I wanted to work on for practice.
I want to make a cash register program that gives change and only works with $1's, $5's, $10's, and $20's (I might add cents in later for more practice).
Change should always be made with the largest available denominations.

Here's an example of the output I want it to do.

# Initialize the till with a two five dollar bills and five ones.
$ cashreg init 50 = 20 4 1 0 
  # Verify input for init (amounts don't match):
$ cashreg init 10 = 5 2 0 0 
  # Note, drawer hasn't changed
  # Purchase $38 with two $20s:
$ cashreg purchase 38 = 0 0 0 2
2 0 0 0
  # Change a five for 5 ones
$ cashreg change 0 1 = 5 
5 0 0 0
  # Change a 20 for a ten, five and five ones:
$ cashreg change 0 0 0 1 = 5 1 1 0
5 1 1 0 
  # Report the contents of the till
$ cashreg report
38 : 88 = 8 4 0 3

Do you think Python or Java would be easier to do this in? I was also thinking about AWK or Bash? I am a beginner in all these languages.

1 Like

I would use what you are most comfortable in, or even use this as practice for writing in them all. The key thing to get you logic documented so you can then write the code without having to think of the whole thing at the same time.

I would suggest that you write down a process using a flow chart or structure diagram that you would use manually and keep refining each step to more and more detail, including loops and conditions, to (for instance) try a $5 and work out how much is still required, loop round and try another $5 if you have one etc.

One question that you will need to answer for yourself is "How are you planning to store the cash?" Are you thinking of simple variables, arrays or even using a file perhaps?

I suppose convention might suggest putting the largest value denomination first, so your input/output would be in the form of twenties, tens, fives and ones, i.e.:-

$ cashreg init 50 = 0 1 4 20

$ cashreg purchase 38 = 2 0 0 0
0 0 0 2

I hope that this gives you a bit of a steer. Let us know how you get on. If you get stuck on specific coding, paste it to the thread and we will see if someone can help.

Kind regards,
Robin

1 Like

You might want to start with how do you make change. You can use a floor or truncate function with division to tell how much of a certain currency you will give as change. Subtract the value of that currency from the change that needs to be given and continue on with the next lower currency until you get to cents. Which is where you stop. So if you owe $61.97 in change see what steps you need to follow to give proper change. With SQL I would do the following:

SQL> select floor(61.97/20) number_of_twenties,
  2  61.97-(20*floor(61.97/20)) remaining_change from dual;

NUMBER_OF_TWENTIES REMAINING_CHANGE
------------------ ----------------
                 3             1.97
SQL> select floor(1.97/10) number_of_tens,
  2  1.97-(10*floor(1.97/10)) remaining_change from dual;

NUMBER_OF_TENS REMAINING_CHANGE
-------------- ----------------
             0             1.97
SQL> select floor(1.97/5) number_of_fives,
  2  1.97-(5*floor(1.97/5)) remaining_change from dual;

NUMBER_OF_FIVES REMAINING_CHANGE
--------------- ----------------
              0             1.97
SQL> select floor(1.97/1) number_of_ones,
  2  1.97-(1*floor(1.97/1)) remaining_change from dual;

NUMBER_OF_ONES REMAINING_CHANGE
-------------- ----------------
             1              .97
SQL> select floor(.97/.25) number_of_quarters,
  2  .97-(.25*floor(.97/.25)) remaining_change from dual;

NUMBER_OF_QUARTERS REMAINING_CHANGE
------------------ ----------------
                 3              .22

SQL> select floor(.22/.10) number_of_dimes,
  2  .22-(.1*floor(.22/.10)) remaining_change from dual;

NUMBER_OF_DIMES REMAINING_CHANGE
--------------- ----------------
              2              .02

SQL> select floor(.02/.05) number_of_nickels,
  2  .02-(.05*floor(.02/.05)) remaining_change from dual;

NUMBER_OF_NICKELS REMAINING_CHANGE
----------------- ----------------
                0              .02

At this point multiply by 100 for the number of pennies. Once you know the method of figuring out change, then figure out what language you can code it in. You might try Perl or Python this. You can use an array or set of arrays to store the currency and the proper order to do the computation with.

1 Like

Eventhough BASH is my currently my most favorite language, for (possibly) 'real' applications, specialy when it comes with numbers handling as in do math, i would choose something else... like python.

AFAIK, awk is no programing language, but a 'streaming/parsing' tool.
(simple said)

Me quite confused by your syntax.
There is:

init 50 = 0 1 4 20
purchase 38 = 2 0 0 0

But there is also

change 0 0 0 1 = 5 1 1 0
change 0 1 = 5 

To me this looks like you want to do 2 things at once, while the programing itself, would might be logical, think of what the cashier must do to enter this syntax!

Usualy the chashiers just type in the amount of cash the items costs, and the 'added up' amount the buyer pays. They do NOT count every single piece of cash, and enter 2x5$ 1x10$, 3x20$, etc...
They simply type: 78$ cost -> 80$ paid, returns -> 2$ returns.

I agree, it WOULD be a nice-to-have feature, but for the cashier its very unpractical to count the cash (not the value) each and every time, all day long, when there are 50 people at the register waiting..

Get my point? :wink:
In the end, a cash register is more like a big calculator, sure, it contains cash, but in the end, it just sums up the values, and not the counts of cash-items.
That is done at the evenings, manualy. (unless they have a cash counter- another device)

So my only suggestion is to make the syntax simpler.

Change only: VALUE
Pay: COST GIVEN
-> Returns: return/change

So you would only need to catch 2 arguments.

However, if you plan to do this as a 'backend', as in you then could make the GUI having fields to enter the amount of every single cash-item, which then, if there is something within the text field, pass this value as optional value to the script.
As in:
Pay: -twenty 1 -five 1 COST(22) paid(sumy up the textfield=25)
Returns: Return 3
(since there were optionas passed, show) Flow: +10 +5 -2 -1
While the italic text would be generated by the GUI, since there were only 2 (optional) textfield filled)

Hope this helps

EDIT:
Alternativly, you could expect:
Pay: COST / GIVEN
And simply split up the GIVEN to a possiblity of cash combinations.

1 Like

Thanks guys for all your suggestions. I decided to use Python and I am really stuck. I started to create classes but I am not sure if I even have to. I am not that great in programming and I want to know if I am starting this correctly.

#!/usr/bin/python

class CashRegister:

   ones = 1;
   fives = 5;
   tens = 10;
   twenties = 20;

   #Initializes drawer, using counts of bills provided
   def _init_(self, amt):
      self._amt = ones [fives [tens [twenties]]]

   def purchase_price(price, amount_tendered):

Here is what I am attempting to do for my first two commands:

-init amt = ones [fives [tens [twenties]]]

-Initialize drawer, using counts of bills provided
-If a drawer already exists, this will overwrite it.

-purchase price = amount_tendered

-price
-Integer
-amount_tendered
-Number and type of bills given to register
-amt = ones [fives [tens [twenties]]], where amounts are integers, counts
-Output will be a single line, if successful:
-change returned , where change returned has the same format: ones fives tens twenties

Example output for first two commands:

# Initialize the till with a two five dollar bills and five ones.
$ cashreg init 50 = 20 4 1 0 
  # Verify input for init (amounts don't match):
$ cashreg init 10 = 5 2 0 0 
  # Note, drawer hasn't changed
  # Purchase $38 with two $20s:
$ cashreg purchase 38 = 0 0 0 2
2 0 0 0

So do I make the classes and implement the commands? Then in main() just take the user input and call the functions?

@ totoro125
You give me all kinds of ideas. :slight_smile:

You could have two classes and keep transactions separated.

Class CashRegister
An accounting of the bills/coins that should be in your drawer.
date
ones = 1;
fives = 5;
tens = 10;
twenties = 20;
coins...

def bills - add/subtract

def coins - add/subtract

def report

Class Transaction
Keeping track of bills/coins recieved for each exchange.
record
transaction_id
date
sale_amount
tendered_amount
change_amount
tender
bills
coins
change
bills
coins

def update register

def calculate change

Figure out the largest bills/coins to give as change amount.
Update the register.
---------
To start (instantiate) a transaction you would give each a unique name -- something like...

tx1 = Transaction()
call the methods using the new instance name..
tx1.method(param)
...and then append them to a list
txList.append(tx1)

Do the register the same way...
regToday = CashRegister()

1 Like

Thank you! That helps a lot, but is how I started correct? And did I do the syntax correctly?

@ totoro125

I would make my class an empty template so I could use it over and over. Each time you use it you can initialize the values by passing parameters. The constructor should look something like this:

class CashRegister(object):
    """A class that makes big money."""
    def __init__(self, twenties, tens, fives, ones):
        self.twenties = twenties
        self.tens = tens
        self.fives = fives
        self.ones = ones

Make up some defs to test your classes while you are learning. Python has good error reporting built in.

    def description(self):
        print "I have %s twenties, %s tens and I have %s fives." % (self.twenties, self.tens, self.fives)

    def is_broke(self):
        if self.ones:
            print "Yep! I'm flush.\n"

        else:
            print "Please help me! I am broke.\n"

In the main body of your script is where you run the tests and other functions you built into the class.

Yesterday = CashRegister(4, 8, 16, 1)
Yesterday.description()
Yesterday.is_broke()

Today = CashRegister(5, 10, 20, False)
Today.description()
Today.is_broke()

okay, I have this so far:

class CashRegister(object):
    def __init__(self, drawer):
        self.drawer = self.formatMoney(drawer)
    ## Purchase function
    def purchase(self, price, amount_tendered):
        change_required = self.sumMoney(self.formatMoney(amount_tendered)) - price
        if change_required == 0:
            return [0, 0, 0, 0]
        if change_required > self.sumMoney(self.drawer):
            return 3
        if self.sumMoney(self.formatMoney(amount_tendered)) < price:
            return 2
        ret = {'ones': 0, 'fives': 0, 'tens': 0, 'twenties': 0}
        if change_required >= 20:
            ret['twenties'] = change_required / 20
            change_required = change_required % 20
        if change_required >= 10:
            ret['tens'] = change_required / 10
            change_required = change_required % 10
        if change_required >= 5:
            ret['fives'] = change_required / 5
            change_required = change_required % 5
        ret['ones'] = change_required
        return ret
    ## Helper function
    def sumMoney(self, l):
        s = 0
        s += l['ones']
        s += l['fives'] * 5
        s += l['tens'] * 10
        s += l['twenties'] * 20
        return s
    def formatMoney(self, l):
        return {'ones': l[0], 'fives': l[1], 'tens': l[2], 'twenties': l[3]}

How can I change part of this so I can test it by typing:
$ Cashregister purchase 38 = 0 0 0 2
on the command line?

You've been busy. :slight_smile:
For something as advanced as this it would help you to no end to learn more about Python containers; dictionaries, tuples, lists, etc.
You are passing around lists of numbers here and you need to manage them as groups.

I liked this part, the rest I doctored a little.

def sumMoney(self, l):
        s = 0
        s += l['ones']
        s += l['fives'] * 5
        s += l['tens'] * 10
        s += l['twenties'] * 20
        return s

Not bad so far. We're still a ways from running from the command line though.
Keep pluggin'.

There are people out here better qualified than me, and there's probably many different ways to do this stuff, but here's what I've come up with; based on my understanding of what you want to do. You might have to work out a few bugs.

# You dont want function calls in __init__ because the functions haven't been
# initialized yet.  Use __init__ to assign values and such
# from the arguments you provide when you create an instance of the class.
class CashRegister(object):
    def __init__(self, ones, fives, tens, twenties):
        self.drawer = {'ones': ones, 'fives': fives, 'tens': tens, 'twenties': twenties}
        self.tender = {'ones': 0, 'fives': 0, 'tens': 0, 'twenties': 0}
        self.cash = {'ones': 0, 'fives': 0, 'tens': 0, 'twenties': 0}


## Purchase function
    def purchase(self, price, ones, fives, tens, twenties):
        self.tender = {'ones': ones, 'fives': fives, 'tens': tens, 'twenties': twenties}
        change_required = self.sum_tendered() - price

        if change_required == 0:
            return "err0" # distinguish error numbers from dollars

        if self.sum_tendered() < price:
            return "err2"

        # if change_required > self.sumMoney(self.drawer):
        if change_required > self.sum_drawer():
            return "err3"

        return change_required
 
## Helper functions
    def formatMoney(self, amount):
        self.cash = {'ones': 0, 'fives': 0, 'tens': 0, 'twenties': 0}
        if amount >= 20:
            self.cash['twenties'] = amount / 20
            amount = amount % 20

        if amount >= 10:
            self.cash['tens'] = amount / 10
            amount = amount % 10

        if amount >= 5:
            self.cash['fives'] = amount / 5
            amount = amount % 5
        self.cash['ones'] = amount

        return self.cash

    def sumMoney(self, fmt):
        self.cash = fmt
        s = 0
        s += self.cash['ones']
        s += self.cash['fives'] * 5
        s += self.cash['tens'] * 10
        s += self.cash['twenties'] * 20
        return s

    def cash_drawer(self):
        return self.drawer
    def cash_tendered(self):
        return self.tender
    def sum_drawer(self):
        return self.sumMoney(self.drawer)
    def sum_tendered(self):
        return self.sumMoney(self.tender)

############
# some random testing
############

d1 = {}
reg = CashRegister(20, 20, 10, 10)

change = reg.purchase(38, 0, 0, 0, 2)
d1 = reg.cash_tendered()
tender = reg.sum_tendered()
print 'tendered:$%s = %s, %s, %s, %s' % (tender, d1['ones'], d1['fives'], d1['tens'], d1['twenties'])
d1 = reg.formatMoney(change)
print 'change:$%s = %s, %s, %s, %s' % (change, d1['ones'], d1['fives'], d1['tens'], d1['twenties'])
d1 = reg.cash_drawer()
drawer = reg.sum_drawer()
print 'drawer:$%s = %s, %s, %s, %s' % (drawer, d1['ones'], d1['fives'], d1['tens'], d1['twenties'])

--------- Post updated at 08:18 PM ---------- Previous update was at 01:36 AM ----------

EDIT:
Found some ugly bugs.
Did some renaming because vars were getting clobbered in the Helper functions.
Errors 0, 2, 3 were causing confusion with dollar output.
Added a few helper functions to ease the use of the class in a progamming sense.
Made several other changes and reposted the code.

The above tests now produce decent output.

Code:
tendered:$40 = 0, 0, 0, 2 change:$2 = 2, 0, 0, 0 drawer:$420 = 20, 20, 10, 10