2

I am trying to create a javascript cash register function for the freeCodeCamp cash register project.

The description of how it should work is as follows:

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.

Example cash-in-drawer array:

[["PENNY", 1.01],
["NICKEL", 2.05],
["DIME", 3.1],
["QUARTER", 4.25],
["ONE", 90],
["FIVE", 55],
["TEN", 20],
["TWENTY", 60],
["ONE HUNDRED", 100]]

The checkCashRegister() function should always return an object with a status key and a change 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 the change key.

My code is passing all the tests at freeCodeCamp except one. 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]]}. But it is returning {change: [], status: "INSUFFICIENT_FUNDS"}.

Code:

function checkCashRegister(price, cash, cid) {
  var change = {};
  var changeDue = cash - price;
  var cidTotal = 0;
  for (let i = 0; i < cid.length; i++) {
    cidTotal += cid[i][1];
  }
  if (changeDue == cidTotal) {
    change.status = "CLOSED";
    change.change = cid;
    return change;
  }
  change.change = [];
  var denominations = [0.01, 0.05, 0.1, 0.25, 1, 5, 10, 20, 100];
  var remaining = changeDue;
  var units = ["PENNY", 'NICKEL', 'DIME', 'QUARTER', 'ONE', 'FIVE', 'TEN', 'TWENTY', 'ONE HUNDRED'];
  for (let i = cid.length - 1; i >= 0; i--) {
    let leastCount = denominations[i];
    let vid = cid[i][1]; //value in drawer for current denomination
    let n = 0;
    while (remaining >= leastCount && vid > 0) {
      vid -= leastCount;
      remaining -= leastCount;
      n ++;
    }
    if (n > 0) {
      change.change.push([units[i], n * leastCount]);
    }
  }
  console.log(change.change); //Console.log statement 1
  console.log(remaining); //Console.log statement 2
  if (remaining == 0) {
    change.status = "OPEN";
  } else {
    change.status = "INSUFFICIENT_FUNDS"
    change.change = [];
  }
  return change;
}


console.log(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]]));

My code is passing all the tests at freeCodeCamp except one. 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]]} But it is returning {change: [], status: "INSUFFICIENT_FUNDS"}.

Adding console.log(change.change) after the for loop displays [["TWENTY", 60], ["TEN", 20], ["FIVE", 15], ["ONE", 1], ["QUARTER", 0.5], ["DIME", 0.2], ["PENNY", 0.03]] instead of the expected result [["TWENTY", 60], ["TEN", 20], ["FIVE", 15], ["ONE", 1], ["QUARTER", 0.5], ["DIME", 0.2], ["PENNY", 0.04]].

Adding console.log(remaining) after the for loop displays 0.009999999999994869 instead of just 0.

Ayudh Khajne
  • 55
  • 1
  • 7
  • Possible duplicate of [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Thomas Jun 07 '19 at 12:09
  • Everything exists yet - there are libraries for arbitrary-precision decimals just found example this one https://mikemcl.github.io/decimal.js/ – Jan Jun 14 '19 at 08:26

1 Answers1

1

A bit of workaround, but what about multiplying by 100 to count with whole numbers ? In case you can represent all prices exactly, then this small modification works for me ;-) In case you are happy with, there is a accept button under voting buttons.

function checkCashRegister(price, cash, cid) {
  var change = {};
  var changeDue = (cash - price) * 100;
  var cidTotal = 0;
  for (let i = 0; i < cid.length; i++) {
    cidTotal += cid[i][1] * 100;
  }
  if (changeDue == cidTotal) {
    change.status = "CLOSED";
    change.change = cid;
    return change;
  }
  change.change = [];
  var denominations = [0.01, 0.05, 0.1, 0.25, 1, 5, 10, 20, 100];
  var remaining = changeDue;
  var units = ["PENNY", 'NICKEL', 'DIME', 'QUARTER', 'ONE', 'FIVE', 'TEN', 'TWENTY', 'ONE HUNDRED'];
  for (let i = cid.length - 1; i >= 0; i--) {
    let leastCount = denominations[i] * 100;
    let vid = cid[i][1] * 100; //value in drawer for current denomination
    let n = 0;
    while (remaining >= leastCount && vid > 0) {
      vid -= leastCount;
      remaining -= leastCount;
      n ++;
    }
    if (n > 0) {
      change.change.push([units[i], n * leastCount / 100]);
    }
  }
  console.log(change.change); //Console.log statement 1
  console.log(remaining); //Console.log statement 2
  if (remaining == 0) {
    change.status = "OPEN";
  } else {
    change.status = "INSUFFICIENT_FUNDS"
    change.change = [];
  }
  return change;
}


console.log(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]]));

Stupid sum test also looks promissing:

var nums = [];
var sum1 = 0, sum2 = 0, sum3 = 0;
for(var i=0;i<2556;i++) {
  sum1 += i;
  nums.push(i/100);
  sum2 += nums[i];
  sum3 += nums[i]*100;
}
console.log(sum1, sum2, sum3, nums);
//3265290 32652.899999999997 3265290
Jan
  • 2,178
  • 3
  • 14
  • 26
  • There is probably only 1 another option I found - string math, but does not look nicer, btw there are almost equal problems in C#, but there is a decimal type too, which can be used as replacement. Maybe using binary arrays, etc. it could be simulated in JS too, but you would write maybe more code comparing to your method size and there is no need to have floating points to represent cash sums. – Jan Jun 07 '19 at 17:48