Cash register - Help!?

Tell us what’s happening:

Anybody is able to spot the bug? I have been trying for a few days now with some refactoring also to no avail… thanks.

Your code so far


function checkCashRegister(price, cash, cid) {
let result = { status: "", change: [cid] };
let changeDue = parseFloat(cash - price).toFixed(2);
let changeAvailable = getChangeAvailable(cid);
result.status = getRegisterStatus(changeDue, changeAvailable);

if (changeDue < 0) return "Cash not sufficient ma'am!";

if (result.status === "INSUFFICIENT_FUNDS") {
  result.change = [];
  return result;
}

result.change = getCustomerChange(changeDue, cid);

return result;
}

function getChangeAvailable(changeInDrawer) {
let total = 0;
let length = changeInDrawer.length;
for (let i = 0; i < length; i++) {
  total += changeInDrawer[i][1];
}
return total.toFixed(2);
}

function getRegisterStatus(changeDue, changeAvailable) {
if (changeDue > changeAvailable) {
  return "INSUFFICIENT_FUNDS";
}

if (changeDue < changeAvailable) {
  return "OPEN";
}

return "CLOSED";
}

function getCustomerChange(changeDue, changeInDrawer) {
const change = [];
const units = [
  ["PENNY", 0.01],
  ["NICKEL", 0.05],
  ["DIME", 0.1],
  ["QUARTER", 0.25],
  ["ONE", 1.0],
  ["FIVE", 5.0],
  ["TEN", 10.0],
  ["TWENTY", 20.0],
  ["ONE HUNDRED", 100.0],
];

const length = changeInDrawer.length;
for (let i = length - 1; i >= 0; i--) {
  const currencyName = changeInDrawer[i][0];
  const currencyTotalAvailable = changeInDrawer[i][1];
  const currencyUnitValue = units[i][1];
  let currencyAmountAvailable = (
    currencyTotalAvailable / currencyUnitValue
  ).toFixed(0);
  let currencyToReturn = 0;

  while (changeDue >= currencyUnitValue && currencyAmountAvailable > 0) {
    changeDue -= currencyUnitValue;
    changeDue = changeDue.toFixed(2);
    currencyAmountAvailable--;
    currencyToReturn++;
  }

  if (currencyToReturn > 0) {
    change.push([currencyName, currencyToReturn * currencyUnitValue]);
  }
}
return change;
}

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36.

Challenge: Cash Register

Link to the challenge:

Hi towerbrother,
could you give us a brief rundown of what you have observed so far? Any ideas about which areas likely work or don’t work?

Hi michaelsndr,
Thanks for your message. In summary, it fails certain test cases. The easiest way is to show you which cases fails.

Case 1 - not sure why it does not pick up on the fact that there are not sufficient funds while it does on other cases.

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: []}

Case 2 - I believe the fCC result is wrong as it should not return all the currencies with 0 value?? So I think this is actually not a problem with my code??

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]]}

I amended my code slightly, updated version below:

const resultStatus = {
  open: "OPEN",
  closed: "CLOSED",
  insufficientFunds: "INSUFFICIENT_FUNDS",
};

function getChangeAvailable(changeInDrawer) {
  let total = 0;
  let length = changeInDrawer.length;
  for (let i = 0; i < length; i++) {
    total += changeInDrawer[i][1];
  }
  return total.toFixed(2);
}

function getRegisterStatus(changeDue, changeAvailable) {
  if (Number(changeDue) > Number(changeAvailable)) {
    return "INSUFFICIENT_FUNDS";
  }

  if (Number(changeDue) < Number(changeAvailable)) {
    return "OPEN";
  }

  return "CLOSED";
}

function getCustomerChange(changeDue, changeInDrawer) {
  const change = [];
  const units = [
    ["PENNY", 0.01],
    ["NICKEL", 0.05],
    ["DIME", 0.1],
    ["QUARTER", 0.25],
    ["ONE", 1.0],
    ["FIVE", 5.0],
    ["TEN", 10.0],
    ["TWENTY", 20.0],
    ["ONE HUNDRED", 100.0],
  ];

  const length = changeInDrawer.length;
  for (let i = length - 1; i >= 0; i--) {
    const currencyName = changeInDrawer[i][0];
    const currencyTotalAvailable = changeInDrawer[i][1];
    const currencyUnitValue = units[i][1];
    let currencyAmountAvailable = currencyTotalAvailable / currencyUnitValue;
    let currencyToReturn = 0;

    while (changeDue >= currencyUnitValue && currencyAmountAvailable > 0) {
      changeDue -= currencyUnitValue;
      changeDue = changeDue.toFixed(2);
      currencyAmountAvailable--;
      currencyToReturn++;
    }

    if (currencyToReturn >= 0) {
      change.push([currencyName, currencyToReturn * currencyUnitValue]);
    }
  }
  return change;
}

function checkCashRegister(price, cash, cid) {
  let result = { status: "", change: [] };
  let changeDue = parseFloat(cash - price).toFixed(2);
  let changeAvailable = getChangeAvailable(cid);
  result.status = getRegisterStatus(changeDue, changeAvailable);

  if (changeDue < 0) return "Cash not sufficient ma'am!";

  if (result.status === resultStatus.insufficientFunds) {
    return result;
  }

  result.change = getCustomerChange(changeDue, cid);

  return result;
}

Your function getRegisterStatus decides whether the funds are sufficient/insufficient based on the total amount of cash in the drawer. E.g. in the first case you need to give back 50 cents and you have a total amount of 1 dollar and something. As per the current getRegisterStatus that’s enough, but you need to base that decision on the specific bills you have in the drawer, since you can’t give 50 cents back with a 1 dollar coin …

Also, your function getCustomerChange pushes the bills that you need to give back 0 pieces of, which could be an additional reason some tests fail, comparing it with the test description …

Hi! Thanks for the advice, I now solved it but I believe there is a mistake in the fCC test (see below). We are always required to return the change excluding those coins and/or bills that are at 0 value… here though it seems to be different.

Do you know how to raise this to the fCC team?

My solution below the pic - SPOILER ALERT

const resultStatus = {

  open: "OPEN",

  closed: "CLOSED",

  insufficientFunds: "INSUFFICIENT_FUNDS",

};

function getChangeAvailable(changeInDrawer) {

  let total = 0;

  let length = changeInDrawer.length;

  for (let i = 0; i < length; i++) {

    total += changeInDrawer[i][1];

  }

  return total.toFixed(2);

}

function getOverallRegisterStatus(changeDue, changeAvailable) {

  if (Number(changeDue) > Number(changeAvailable)) {

    return "INSUFFICIENT_FUNDS";

  }

  if (Number(changeDue) < Number(changeAvailable)) {

    return "OPEN";

  }

  return "CLOSED";

}

function getCustomerChange(changeDue, changeInDrawer) {

  let change = [];

  const units = [

    ["PENNY", 0.01],

    ["NICKEL", 0.05],

    ["DIME", 0.1],

    ["QUARTER", 0.25],

    ["ONE", 1.0],

    ["FIVE", 5.0],

    ["TEN", 10.0],

    ["TWENTY", 20.0],

    ["ONE HUNDRED", 100.0],

  ];

  const length = changeInDrawer.length;

  for (let i = length - 1; i >= 0; i--) {

    const currencyName = changeInDrawer[i][0];

    const currencyTotalAvailable = changeInDrawer[i][1];

    const currencyUnitValue = units[i][1];

    let currencyAmountAvailable = currencyTotalAvailable / currencyUnitValue;

    let currencyToReturn = 0;

    while (changeDue >= currencyUnitValue && currencyAmountAvailable > 0) {

      changeDue -= currencyUnitValue;

      changeDue = Number(changeDue.toFixed(2));

      currencyAmountAvailable--;

      currencyToReturn++;

    }

    if (currencyToReturn > 0) {

      change.push([currencyName, currencyToReturn * currencyUnitValue]);

    }

  }

  if (changeDue != 0) {

    change = [];

    return change;

  }

  return change;

}

function checkCashRegister(price, cash, cid) {

  let result = { status: "", change: [] };

  let changeDue = parseFloat(cash - price).toFixed(2);

  let changeAvailable = getChangeAvailable(cid);

  if (changeDue < 0) return "Cash not sufficient ma'am!";

  result.status = getOverallRegisterStatus(changeDue, changeAvailable);

  if (result.status === resultStatus.insufficientFunds) {

    return result;

  }

  result.change = getCustomerChange(changeDue, cid);

  if (result.status === "OPEN" && result.change.length === 0) {

    result.status = resultStatus.insufficientFunds;

    return result;

  }

  return result;

}

Hey, congratulations on finishing!

Regarding the varying form requirements for the various statuses, I would argue that is by design, since the test descriptions spell it out and test for it. It adds a bit of complexity and it could be said that the different requirements are for a different views, when the register in closed/insufficient vs. open. An example for when it might make sense to get the whole list could be an illustration that shows a cash register on screen and the bills. It might be easier to get the whole list in such a case … In contrast, while the cashier is active and has to give out cash, it would make sense to show only the bills he needs to deal with …

Anyhow, just my two cents. (no pun intended :yum:) If you want to discuss improvements to the curriculum, there is a sub-forum for that: http://forum.freecodecamp.org/c/contributors/

Hey thanks for that! I guess it makes sense what you are saying but it still seems the test to not fully align, specifically, they use different standards for different tests… as you can see below… all these three should return either {… change: []} or {… change: full cid}

Nonetheless, most importantly I completed it, so I am good.