Pages

CodeEval Cash Register

Given in input the price of a certain item and the cash that the client has passed to us to get it, we have to provide to the cashier a list of what he has to get back. More details in the problem page on CodeEval.

We assume the register has an infinite amount of coins and bills in the given denominations:
'PENNY': .01,
'NICKEL': .05,
'DIME': .10,
'QUARTER': .25,
'HALF DOLLAR': .50,
'ONE': 1.00,
'TWO': 2.00,
'FIVE': 5.00,
'TEN': 10.00,
'TWENTY': 20.00,
'FIFTY': 50.00,
'ONE HUNDRED': 100.00
To better clarify what we should do, the first thing I have done is converting the given examples in a Python test case:
def test_provided_1(self):
    self.assertEqual('NICKEL,PENNY', solution(15.94, 16))

def test_provided_2(self):
    self.assertEqual('ERROR', solution(17, 16))

def test_provided_3(self):
    self.assertEqual('ZERO', solution(35, 35))

def test_provided_4(self):
    self.assertEqual('FIVE', solution(45, 50))
The first number passed to the function is the price, the second one is the amount given in.

It shouldn't be to difficult to get a working solution in Python. The core of the problem is looping on all the available denominations, starting from the highest one down to the smallest, selecting each denomination the maximum possible times.

Since working with floating point numbers when a currency is expected is rarely a good idea, I have decided to store in my dictionary of denomination the values as multiple of cents. Something like that:
DENOMINATIONS = {
    'PENNY': 1,
    'NICKEL': 5,

    # ...

    'FIFTY': 5000,
    'ONE HUNDRED': 10000
}
Besides, I payed attention in converting the floating point numbers in integers so to avoid truncation problems:
change = int(cash * 100) - int(price * 100)
However, the interesting part is the loop to check if a given denomination has to be used and how many times:
for name, value in sorted(DENOMINATIONS.items(), key=lambda x: x[1], reverse=True):
    # ...
I want to loop on all the items() in the DENOMINATIONS dictionary, to operate on its key and value - where the key represent the name of the denomination.

I can't rely on the order chosen by Python in scanning the dictionary, I must start from ONE HUNDRED, and proceed in sorted fashion down to the PENNY. So I sorted() it.

I don't want to sort them by the key, it won't make any sense, but by value. So I specify as key that I want to use the second component. I say that to Python using a lambda, that gets the current item in input and returns its second component (index 1, since we are 0 based).

As said above, I want to start from the highest value, that's way I specify that the sorting order is reversed.

The rest of the code should be quite simple to figure out. In any case, my full solution is on GitHub, both the test case and the actual python script.

No comments:

Post a Comment