I created a "Cash Register" function for Freecodecamp but for some reason the last two tests aren't passing?
I created this function but the last two tests
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: []}.
checkCashRegister(19.5, 20, [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]) should return {status: "CLOSED", change: [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]}.
don't pass. What is wrong in my code?
The task is:
Design a cash register drawer function
checkCashRegister()
that accepts purchase price as the first argument (price
), payment as the second argument (cash
), and cash-in-drawer (cid
) as the third argument.
cid
is a 2D array listing available currency.The
checkCashRegister()
function should always return an object with astatus
key and achange
key.Return
{status: "INSUFFICIENT_FUNDS", change: []}
if cash-in-drawer is less than the change due, or if you cannot return the exact change.Return {status: "CLOSED", change: [...]} with cash-in-drawer as the value for the key
change
if it is equal to the change due.Otherwise, return
{status: "OPEN", change: [...]}
, with the change due in coins and bills, sorted in highest to lowest order, as the value of thechange
key.
My code:
const INSUFFICIENT_FUNDS = {
status: 'INSUFFICIENT_FUNDS',
change: []
};
const CLOSED_CID = {
status: 'CLOSED',
change: []
};
const POSITION_CID = [
['ONE HUNDRED', 100],
['TWENTY', 20],
['TEN', 10],
['FIVE', 5],
['ONE', 1],
['QUARTER', 0.25],
['DIME', 0.1],
['NICKEL', 0.05],
['PENNY', 0.01]
];
const add = (a, b) => a + b[1];
const checkCashRegister = (price, cash, cid) => {
let finalChange = [];
let changeDue = cash - price;
const cidSum = cid.reduce(add, 0).toFixed(2);
/*
If there is exactly enough money to provide change, the
status key is “CLOSED”, and the change key is our
cash-in-drawer(cid).
*/
if (cidSum == changeDue) {
return {
CLOSED_CID,
change: cid
};
}
/*
If there is not enough money to provide change, the status key
is “INSUFFICIENT_FUNDS” and the change key is an empty array.
*/
if (cidSum < changeDue) {
return INSUFFICIENT_FUNDS;
}
/*
If there is enough money to provide change with money still
left in the drawer, the change is then provided by going down
a list of currency units from high to low, pushing them to
the change array, and subtracting them from both the cash
owed and the cash-in-drawer(cid).
*/
let cidReverse = cid.reverse();
POSITION_CID.map((posCid, index) => {
const billValue = posCid[1];
while (changeDue >= billValue && cidReverse[index][1] >= billValue) {
changeDue -= billValue; // minus change due from bill value
changeDue = changeDue.toFixed(2); // fix rounding errors
const hasBillValueAlready = finalChange.filter(p => p[0] === cidReverse[index][0]);
if (hasBillValueAlready.length > 0) {
finalChange = finalChange.map(k => (k[0] === posCid[0] && [k[0], (k[1] += billValue)]) || [k[0], k[1]]);
} else {
finalChange.push([cidReverse[index][0], billValue]);
}
cidReverse[index][1] -= billValue; // minus bill value from cash-in-drawer
}
});
if (changeDue !== 0) {
return {
status: 'OPEN',
change: finalChange
};
} else {
return INSUFFICIENT_FUNDS;
}
};
const price = 19.5;
const cash = 200;
const cid = [
['PENNY', 1.01],
['NICKEL', 2.05],
['DIME', 3.1],
['QUARTER', 4.25],
['ONE', 90],
['FIVE', 55],
['TEN', 20],
['TWENTY', 60],
['ONE HUNDRED', 100]
];
// checkCashRegister(price, cash, cid);
console.log(
checkCashRegister(19.5, 20, [
["PENNY", 1.01],
["NICKEL", 2.05],
["DIME", 3.1],
["QUARTER", 4.25],
["ONE", 90],
["FIVE", 55],
["TEN", 20],
["TWENTY", 60],
["ONE HUNDRED", 100]
]),
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: []}`,
checkCashRegister(19.5, 20, [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]), "should return", `{status: "CLOSED", change: [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]}`)
Two issues to fix:
-
When the change due is exactly what is in the cash register, the code returns an object that does not have the right structure:
return { CLOSED_CID, change: cid };
This will create a property
CLOSED_CID
which has as value an object with a nestedstatus
andchange
property... and you add yet anotherchange
property at the parent level. Instead, you should just forget about the predefinedCLOSED_CID
object, and do this:return { status: "CLOSED", change: cid };
-
The decision whether to return the status
OPEN
orINSUFFICIENT_FUNDS
should be on the opposite condition. It is when you have attributed all of the change amount to bills that you should returnOPEN
. So change this:if (changeDue !== 0) { return { status: 'OPEN', change: finalChange }; } else { return INSUFFICIENT_FUNDS; }
to:
if (changeDue == 0) { // All change could be translated to available bills/coins return { status: 'OPEN', change: finalChange }; } else { // There is change remaining that cannot be covered by available bills/coins return INSUFFICIENT_FUNDS; }
As a remark: the toFixed
method returns a string. It would be better to explicitly convert the result back to number data type. There is currently no problem with it in your code, as that conversion happens implicitly when you do -=
and ==
, but for code maintenance reasons you'd better not rely on that. So add a unary +
whenever you call toFixed
:
const cidSum = +cid.reduce(add, 0).toFixed(2);
// ...
changeDue = +changeDue.toFixed(2);
I would however suggest to do all calculations in cents, so all calculations are done with integer values, which do not suffer from the imprecision you otherwise need to cope with.
I assume you already found solutions on the web, and there are many Q&A on Stack Overflow about this same challenge.