# Cash Register : Can't figure out one case

Hi there !

I’ve tried multiple solutions, thinking about a precision problem but I’m not sure anymore. I pass all tests except one. I would like a little hint on my mistake.

Oh and my code construction is pretty messy, I’m sorry for that but if you have any tips to improve, feebacks are welcome !

``````function checkCashRegister(price, cash, cid) {
var change = cash - price;
let ticket = {status: "", change: []};
const values = [1, 5, 10, 25, 100, 500, 1000, 2000, 10000];

function howMuchDrawer(array) {
return array.reduce((acc, current) => {
return acc + current[1];
}, 0);
}

// Basics solutions, no enough money or exact change
if (change > howMuchDrawer(cid)) {
ticket.status = "INSUFFICIENT_FUNDS";
} else if (change == howMuchDrawer(cid)) {
ticket.status = "CLOSED";
ticket.change = cid;

// Actual problem. I've tried to *100 in case of a precision mistake, but the behavior didn't change.
} else {
change = Math.round((cash - price) * 100);
cid.forEach(el => el[1] = Math.round(el[1] * 100));
for (var i = cid.length - 1; i >= 0; i--) {
var dueChange = 0;
// Here is the problem, my algo think that I can return money for the 5th test.
while (cid[i][1] > 0 && change >= values[i]) {
change -= values[i];
cid[i][1] -= values[i];
dueChange += values[i];
}
if (dueChange) {
ticket.status = "OPEN";
ticket.change.push([cid[i][0], dueChange]);
}
}
ticket.change.forEach(el => el[1] = (el[1] / 100));
}
return ticket;

}
``````

It looks like you are tracking a decimal value of dollars. You will always have problems with precision when using floating point numbers because its not possible for your computer to accurately store decimal numbers without roundoff.

I recommend using an integer number of cents instead.

I tried another approach, by directly putting the cents in integers.
My problem is that I can’t seem to tell my program “If you don’t have the perfect amount of change to give change, then you return {status:” INSUFFICIENT_FUNDS ", change: }

It returns the only value it is able to return (0.01) before stopping. I don’t know how to add the condition “If dueChange == initialChange” stay OPEN, else return INSUFFICIENT_FUNDS

I am not sure that I am clear, or even that I understand my mistake.

``````function checkCashRegister(price, cash, cid) {
var change = Math.round((cash - price) * 100);
let ticket = {status: "", change: []};
const values = [1, 5, 10, 25, 100, 500, 1000, 2000, 10000];
cid.forEach(el => el[1] = Math.round(el[1] * 100));

function howMuchDrawer(array) {
return array.reduce((acc, current) => {
return acc + current[1];
}, 0);
}

// Basics solutions, no enough money or exact change
if (change > howMuchDrawer(cid)) {
ticket.status = "INSUFFICIENT_FUNDS";
} else if (change == howMuchDrawer(cid)) {
ticket.status = "CLOSED";
ticket.change = cid;

// Actual problem. I've tried to *100 in case of a precision mistake, but the behavior didn't change.
} else {
for (var i = cid.length - 1; i >= 0; i--) {
var dueChange = 0;
// Here is the problem, my algo think that I can return money for the 5th test.
while (cid[i][1] > 0 && change >= values[i]) {
change -= values[i];
cid[i][1] -= values[i];
dueChange += values[i];
}
if (dueChange) {
ticket.status = "OPEN";
ticket.change.push([cid[i][0], dueChange]);
}
}
}
ticket.change.forEach(el => el[1] = (el[1] / 100));

return ticket;
}
``````

`checkCashRegister(19.5, 20, [["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 1], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]])` should return `{status: "INSUFFICIENT_FUNDS", change: [ ]}`

And it return :
`{ status: 'OPEN', change: [ [ 'PENNY', 0.01 ] ] }`

Okay, I believe I see the error in the logic here.

So it iterates (backwards) through your `cid` array. It sees there are 0 “ONE HUNDRED” and moves to “TWENTY”, sees that there are 0 “TWENTY” and moves to “TEN”, and so on. It hits “ONE”, sees that there is 100 in “ONE”, but change is only “50” so it moves on.

Then it hits “PENNY” and sees there is 1. 1 is greater than 0, and `change` is 50 so the while loop runs. It takes the `1` out of 50 and out of “PENNY”, pushes to `dueChange`, and the `for` loop ends.

Now your `ticket.status` is OPEN and you have the penny in your change, so this gets returned. You want to check if `dueChange == initialChange` but I think that is the incorrect approach. Instead, after you’ve gone through your `for` loop and calculated your change, check if `dueChange` is `0`. If it IS, you have enough cash to return the customer’s change. But if it is NOT, then you have `INSUFFICIENT_FUNDS` to return the change.

I’ve tried a simple `console.log(dueChange)` right after the `for` loop. Now `dueChange` is then worth 1. If I try with this test :

`checkCashRegister(3.26, 100, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]])` should return `{status: "OPEN", change: [["TWENTY", 60], ["TEN", 20], ["FIVE", 15], ["ONE", 1], ["QUARTER", 0.5], ["DIME", 0.2], ["PENNY", 0.04]]}` .

Then, `console.log(dueChange)` return 4 even if I have enough cash.

If you are checking the value of `dueChange` after the `for` loop, it makes sense that you would see `4`. `dueChange` holds the value of the change being returned in the current denomination - your loop ends with pennies, which if you look at the expected return in that test you see 4 pennies.

I made an error in my previous post, I think - instead of checking `dueChange == 0`, I meant to check `change == 0`.

1 Like

Alright, you’re completely right ! Thank you again for your help and for your precise explanations !
I’ll have to rework this challenge 'til being able to found a solution by myself.

1 Like

Glad I was able to help!

It can be fun to rework your solutions - I just rebuilt this one myself yesterday.