Cash Register Problem to finish JS Cert

My solution here is a little convoluted. I used a method similar / building off of a method I found online to do the Roman Numeral Conversion. My ‘table’ is a reference table.
leftInRegisterObj and changeDue are initially objects that I convert to arrays for purpose of the output.

A little explanation:

  • quantity: number of coins/bills needed
  • diff: the sum value of change due to the customer (used for calculations)
  • amount: the same value as diff, only used in the end for a condition
  • leftInRegisterObj: object with the value of each denomination remaining in register
  • changeDue: object of change in each denomination, taken out of register to be given to customer

In VSCode I am getting the correct output for:

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

the expected output being:

{ status: 'OPEN', change: [ [ 'QUARTER', 0.5 ] ] }

which is an object. However, the FCC interpreter is not recognising this as either an object nor the correct output.
Please Help!!

function checkCashRegister(price, cash, cid) {
  let table = {
    'ONE HUNDRED': 100,
    TWENTY: 20,
    TEN: 10,
    FIVE: 5,
    ONE: 1,
    QUARTER: 0.25,
    DIME: 0.1,
    NICKEL: 0.05,
    PENNY: 0.01
  }

  // variable declaration
  cid = cid.reverse();
  let diff = cash - price;          // diff and amount are same value. diff is used for calculations, and is changed
  let amount = cash - price;
  let leftInRegisterObj = Object.fromEntries(cid.map(([a, b]) => [a, b]));
  let changeDue = {};
  let registerInitialSum = cid.reduce((sum,val) => sum + val[1] ,0);

  // helper func to make obj into arrays for output         USEFUL FUNCTION
  const objectToArray = (obj = {}) => {
    const res = [];
    const keys = Object.keys(obj);
    for(key of keys){
        res.push([
          key, obj[key]
        ]);
    };
    return res;
  };

  // conditions to check if CID is enough for required change
  if (registerInitialSum < diff) {
    return {status: "INSUFFICIENT_FUNDS", change: []};
  } else {
    while (diff > 0) {
      for (let i of Object.keys(table)) {
        let quantity = Math.floor(diff/table[i]);

        let val = quantity * table[i];
        leftInRegisterObj[i] -= val;
        diff -= val;
        if (quantity != 0) {
          changeDue[i] = val;
        };
      };
    };
  };

  // sum values of leftInRegisterObj before next conditions
  let registerFinalSum = Object.values(leftInRegisterObj).reduce((a, b) => a + b, 0);

  // Convert changeDue and leftInRegisterObj objects into 2D arrays for returning
  changeDue = objectToArray(changeDue);
  leftInRegisterObj = objectToArray(leftInRegisterObj);
  //console.log('left in register', leftInRegisterObj, '\n change returned', changeDue);

  if (amount == registerFinalSum){
    return {status: "CLOSED", change: [...leftInRegisterObj]};
  } else if (amount < registerFinalSum) {
    return {status: "OPEN", change: [...changeDue]};
  };
};

Well it seems the reason is that there is a error being produced by the code (not sure why VSCode doesn’t see it) here:

You never declared key.

Once you fix that, there are still errors with the output though.

Edit: I put in a lot of console.logs and I can see for eg. that for this case:

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

You are allowing the register to go into negatives. At one point you have this
res = ONE HUNDRED,0,TWENTY,0,TEN,0,FIVE,0,ONE,1,QUARTER,-0.5,DIME,0,NICKEL,0,PENNY,0.01
Notice the quarter field is -0.5 (I printed out the res from your objectToArray)
So I would add a lot more logging and start figuring this out, one test case at a time.

I have made some rearrangements and cleaned up the code a bit. I haven’t yet console.logged anything or addressed infinite loops… Just updating here with what im currently working with:

@hbar1st thanks for your help on this so far
@camperextraordinaire good advice

function checkCashRegister(price, cash, cid) {
    let table = {
      'ONE HUNDRED': 100,
      TWENTY: 20,
      TEN: 10,
      FIVE: 5,
      ONE: 1,
      QUARTER: 0.25,
      DIME: 0.1,
      NICKEL: 0.05,
      PENNY: 0.01
    }
  
    // variable declaration
    cid = cid.reverse();
    let diff = cash - price;          // diff and amount are same value. diff is used for calculations, and is changed
    let amount = cash - price;
    let leftInRegisterObj = Object.fromEntries(cid.map(([a, b]) => [a, b]));
    let changeDue = {};
    let registerInitialSum = cid.reduce((sum,val) => sum + val[1] ,0);
  
    // helper func to make obj into arrays for output         USEFUL FUNCTION
    const objectToArray = (obj = {}) => {
      const res = [];
      const keys = Object.keys(obj);
      for(let key of keys){
          res.push([
            key, obj[key]
          ]);
      }
      return res;
    }
    
    while (diff > 0) {
        for (let i of Object.keys(table)) {
            let quantity = Math.floor(diff/table[i]);

            let val = quantity * table[i];
            leftInRegisterObj[i] -= val;
            diff -= val;
            if (quantity != 0) {
            changeDue[i] = val;
            }
        }
    }

    // sum values of leftInRegisterObj before next conditions
    let registerFinalSum = Object.values(leftInRegisterObj).reduce((a, b) => a + b, 0);
    let changeDueSum = Object.values(changeDue).reduce((a,b) => a+b,0);

    // Convert changeDue and leftInRegisterObj objects into 2D arrays for returning
    changeDue = objectToArray(changeDue);
    leftInRegisterObj = objectToArray(leftInRegisterObj);

    if (amount > registerInitialSum || (amount != changeDueSum && amount < registerFinalSum) ) {
        return {status: "INSUFFICIENT_FUNDS", change: []};
    } else if (amount == changeDueSum && registerFinalSum == 0){
        return {status: "CLOSED", change: [...leftInRegisterObj]};
    } else if (amount == changeDueSum || registerFinalSum > 0 ) {
        return {status: "OPEN", change: [...changeDue]};
    }
  }
1 Like

Rounding to nearest 100th seems to have solved the infinite loop as well as the negatives, I believe. What remains seems to be the conditional statement logic at the end.

Here is the updated while loop:

    while (diff > 0) {
        for (let i of Object.keys(table)) {
            let quantity = Math.floor(diff/table[i]);
            let val = quantity * table[i];
            val = Math.round(val/100)*100;

            leftInRegisterObj[i] -= val;
            diff -= val;
            diff = Math.round(diff/100)*100;

            if (quantity != 0) {
            changeDue[i] = val;
            }
        }
    }

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.