Help: Cash Register won't pass final case

I’ve really struggled with this project so far. Took me a while to realize why I was getting errors with rounding(ie: floating points). I’ve managed to make all but the last case pass and I’m at my wits end here. Seems like I should just scratch it all, restart and convert all numbers to full integers. Should I do that or can this code be modified to work?

Behold, the beast:

function checkCashRegister(price, cash, cid) {
  //initialize two arrays, one with total cash in drawer and one with currency units
  let currency = [
    ["PENNY", 0.01],
    ["NICKEL", 0.05],
    ["DIME", 0.10],
    ["QUARTER", 0.25],
    ["ONE", 1.00],
    ["FIVE", 5.00],
    ["TEN", 10.00],
    ["TWENTY", 20.00],
    ["ONE HUNDRED", 100.00],
  ];
  let drawer = [...cid];
  
  //find total money in drawer
  let countChange = function(arr){
    let count = 0;
    for(let i = 0; i < arr.length; i++){
      count += arr[i][1];
    }
    return count.toFixed(2);
  }
  
  //find change owed
  let changeOwed = cash - price;

  let changeArray = [];
  for(let i = drawer.length - 1; i >= 0; i--){
    let changeReturned = 0;
    
    //if the current $ amount in the drawer is more than zero and the currency unit is less than whats owed, while this is all true, add currency units to changeReturned and subtract them from the drawer and the amount owed until no longer true
    if(drawer[i][1] > 0 && currency[i][1] <= changeOwed && changeOwed > 0){
      while(drawer[i][1] > 0 && currency[i][1] <= changeOwed && changeOwed > 0){
        changeReturned += currency[i][1];
        drawer[i][1] -= currency[i][1];
        drawer[i][1] = drawer[i][1].toFixed(2);
        changeOwed = changeOwed.toFixed(2)
        changeOwed -= currency[i][1];
      }
      //add the drawer array to change array then mutate it to the amount returned. set changeReturned back to 0 and continue to the next drawer item in the for loop
      changeArray.push(drawer[i]);
      drawer[i][1] = changeReturned;
      changeReturned = 0;
    };
  };
  
  //use if statements to handle cases and when change is due loop through the cid array and return change starting with the highest bills/coins
  if(cash - price  == countChange(cid)){
    return {status: "CLOSED", change: [...cid]}
  }
  if(changeOwed < countChange(cid)){
    if(countChange(changeArray) == cash - price){
      return {status: "OPEN", change: [...changeArray]}
    } else {
      return {status: "INSUFFICIENT_FUNDS", change: []}
    }
  }
  if(changeOwed > countChange(cid)){
    return {status: "INSUFFICIENT_FUNDS", change: []}
  }
  
} //end function

console.log(checkCashRegister(19.5, 20, [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]));

TEST CASES

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]]) should return an object.

Passed
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]]) should return {status: "OPEN", change: [["QUARTER", 0.5]]}.

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

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

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

Thank you.

You wouldn’t need to scrap everything to use integer numbers of cents. You’d only need to multiply by 100 and then at the end divide out that 100. To me, integer numbers of cents is the most straightforward way to fix this.

1 Like

You can use the toFixed method which works as such

n = 1.234;
n.toFixed(2) //returns the string "1.23"

the method toFixed takes a number as an argument for how many decimal places deep you wan to be. toFixed returns a string not a number so be careful of that, and it also does some slight rounding of its own.

Another approach you can take is just to see if a value is less than 0.01 and if it is just set it to 0 as that is less than any valid denomination.

1 Like

Thank you both for your help. I tried messing around with toFixed for a bit but kept coming up with type errors and couldn’t get to the root of the problem. In the end I scrapped a lot of what I had and tried an approach in whole integers and it worked out. I was definitely over complicating things. Thanks again. :slightly_smiling_face: