Help w/ Cash Register, Stuck and can't seem to figure out easy solution

I’ve been working on this for a while and can’t seem to figure out the proper logic. I built the below code to help me visualize what to do next but it seems my code is growing with each step. Am I on the right track, or should I start over?

Link to Project:

Current Progress:

function checkCashRegister(price, cash, cid) {
var CidTextandAmounts = [];
function amounts (cid) {
    var changeOne = [];  
    for (var i = 0; i < cid.length; i++ ) {
     changeOne.push(cid[i][1]);
     CidTextandAmounts.push(cid[i]);
    } return changeOne;
  }

function add(total,num) {
  return total + num;
}
  
var CidAmounts = amounts(cid);


var totalcid = console.log("Total Cash in Draw: " + CidAmounts.reduce(add));
var changeDue = cash - price;
var values = [.01,.05,.1,.25,1,5,10,20,100];

function cidQuants (CidAmounts) {
var cidQuantity = [];

var cidParts=[];
var IdNote = [];// Note to multiply by

for (var i=0; i < values.length; i++ ) {
  cidQuantity.push(CidAmounts[i] / values[i]);
   cidParts.push(changeDue / values[i]);
    IdNote.push( changeDue * cidParts[i] * values[i] );
}
var newIdNote = [...new Set(IdNote)];
var mutiplyby = changeDue / newIdNote;

  console.log ("Number of Notes: " + cidQuantity);
  console.log("Note to multiply: " + newIdNote);
  console.log("Muliply by: " + mutiplyby);
  return CidTextandAmounts;
}

console.log("Change Due: " + changeDue);

console.log("Notes: " + values);
console.log("Value of Notes: " + CidAmounts);
console.log(cidQuants(CidAmounts));


  // Here is your change, ma'am.
  //return change;
}

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

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

You’re overthinking it. Write down the steps of your algorithm in pseudocode. Forget about javascript, forget about arrays. How would you solve this problem if you were working as a cashier IRL? You open the register, you look at the money that’s inside , you see the price of the item, you calculate the change that you need to give… and then what do you do???

3 Likes

As mentioned the user above, write a pseudocode about the steps that you need to take, then you worry about the code.

Thanks for all the tips! I’ll start again and write the steps and go from there. Appreciate it.

Good luck, get back to us with your success/failure.

I am closer than I was last time but haven’t had a breakthrough yet. I’m now using a for in loop that iterates through a Key/Value Object I created, and then am replacing that new Object’s property with the calculated change due, which is what we need to output. If there is nothing more to calculate, then end, otherwise I would need to subtract the change due from the existing CID amounts and divide by the next smallest quantity. This is where I’m stuck and feel like I’ll be here forever if I don’t look at the proper way to go about it. Thanks for your help on moving me along further than I was.

function checkCashRegister(price, cash, cid) {
  let cashRegister = { status: '', change: cid };
  const changeNeeded = parseFloat(cash - price).toFixed(2);
  const changeAvailable = getTotalCashRegisterChange(cid);
  
  let valueList = [];
  let keyValue = [];
  let valuesObj = { PENNY: .01, NICKEL: .05, DIME: .10,
    QUARTER: .25, ONE: 1, FIVE: 5, TEN: 10, HUNDRED: 100 };
  
  for (let prop in valuesObj ) {
    if ( valuesObj[prop] < 1  ) {
    valuesObj[prop] = changeNeeded;
    keyValue = [prop + ", " + valuesObj[prop] + " "];    
  }
  }

  console.log(keyValue);
  return change;
}
function getTotalCashRegisterChange(changeInDrawer) {
  let total = 0;
  for (let change of changeInDrawer) {
    let changeValue = change[1]; 
    total += change[1];
  }
  return total;
}

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

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

Ok, so I took another crack at it and this time around I got a lot further. I was almost done when I realized the challenge returns Test 3 differently than mine, which I would love clarification on. Test 3 outputs TWENTY : 60, etc…Why is the third challenge moving on from TWENTY at $60 rather than at 80$? Isn’t the objective to give as much change w/ highest denominator and then move on from there? The third test has Cash = $3 and CID = $100. The Change Due is $96.74, which TWENTY can go into 4 times but the third test has this at 3 times or $60 dollars. My solution codes for 4. See below.

Code so far. Please note, I have added a console log for the results I am getting and plan to clean up the NULL values in the other tests and a few other things:

function checkCashRegister(price, cash, cid) {
 var currency = [["PENNY", .01], ["NICKEL",.05], ["DIME",.10], ["QUARTER",.25], ["ONE",1], ["FIVE",5], ["TEN",10], ["TWENTY",20], ["ONE HUNDRED",100]];
  var change;
  // Here is your change, ma'am.
  let avail = []; 
  let availSum = avail.reduce((a, b) => a + b, 0); //will use later 
  let changeDue = cash - price;
    
    let words = [];
    let divisors = [];
    let finalDivisors = [];

//loop through currency array
    for (var j=currency.length-1;j>=0;j--) {
    //get divisors and words
        if (changeDue / currency[j][1] > 1) {
        divisors.push(currency[j][1]);
        words.push(currency[j][0]);
       
//first index of divisors
        if (divisors.indexOf(divisors[j]) === 0 )  {
                while (changeDue > .01) {
       //multiply divisor by changeDue divided by each divisor to get num it will be subtracted from  
                    var reduceDivisor = divisors[j] * Math.floor(changeDue / divisors[j]); 
                    changeDue -= reduceDivisor;          
                      finalDivisors.push(reduceDivisor );      
                      //remove current number     
                      divisors.shift();
                    }       
           //For last num in array. .01 decimal fix and replace
            var last = finalDivisors[finalDivisors.length -1];
            var lastNum = parseFloat((last + changeDue).toFixed(2));
            var replaced = finalDivisors.splice(-1, 1, lastNum);
        }  
    }
  }
//insert final numbers into words array
  let newfinal = [];
  for (var i=0;i<words.length;i++){
    newfinal.push([words[i],finalDivisors[i]]);
  }


console.log(newfinal);

}

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/cash-register

Nevermind. I just saw the reason. Will adjust the code to consider how much change is in the drawer for each currency.

Ok. Finally have a working solution. There are certainly places it can be improved and any critique and feedback welcomed, especially on finding a more elegant solution to accommodate 2nd to last challenge passed by first if statement at bottom.

function checkCashRegister(price, cash, cid) {
 var currency = [["PENNY", .01], ["NICKEL",.05], ["DIME",.10], 
["QUARTER",.25], ["ONE",1], ["FIVE",5], ["TEN",10], ["TWENTY",20], 
["ONE HUNDRED",100]];
  // Here is your change, ma'am.
  var cidSum = [];  var availCash = []; var changeDue = cash - price;
  var secondChangeDue = cash - price; var quantities = []; var words = []; var divisors = [];
  var finalDivisors = []; var newfinal = [];

    //loop through CID & push into arrays
    for (var i=cid.length-1;i>=0;i--) {
        if(cid[i][1] != 0 ) { availCash.push(cid[i][1]) }
        if (changeDue / cid[i][1] > 1) {
        quantities.push(cid[i][1]);
      }
    }
    //loop through currency array
    for (var j=currency.length-1;j>=0;j--) {
      
        //get divisors and words
        if (changeDue / currency[j][1] > 1) {
            divisors.push(currency[j][1]);
            words.push(currency[j][0]);        
       
        //first index of divisors
        if (divisors.indexOf(divisors[j]) === 0 )  {
            while (changeDue > .01) {
            //Crunch numbers and subtract result from change due until 0
            var multiplier = Math.floor(changeDue / divisors[j]);
            var reduceDivisor = divisors[j] * multiplier; 
            if (quantities[j] < reduceDivisor ) {
              reduceDivisor -= divisors[j];           
            }
                changeDue -= reduceDivisor;
                finalDivisors.push(reduceDivisor);  
                   
                //remove item in arrays to start w/ new number    
                quantities.shift();
                divisors.shift();              
              }       
           //.01 decimal fix and replace
            var last = finalDivisors[finalDivisors.length -1];
            var lastNum = parseFloat((last + changeDue).toFixed(2));
            var replaced = finalDivisors.splice(-1, 1, lastNum);
        }  
    }
  }
//insert final numbers into words array & remove entries w/ zero
  for (var i=0;i<words.length;i++){
    newfinal.push([words[i],finalDivisors[i]]);
    if(finalDivisors[i] == 0) {
        newfinal.splice(newfinal.indexOf(newfinal[i][1]), 1);
    }
    if(finalDivisors[i] == null) {
        newfinal.splice(newfinal.indexOf(newfinal[i]), 1);
    }
  } 

cidSum = availCash.reduce((a, b) => a + b, 0);
//Output results
for (var l=0;l<availCash.length;l++) {
   if ( cidSum < secondChangeDue || availCash[l] == 1 
|| availCash[l] == .25 || availCash[l] == .1 || availCash[l] == .05 
|| availCash[l] == .01) { 
       return {status: "INSUFFICIENT_FUNDS", change: []}   
    }
 }
   if ( cidSum === secondChangeDue  ) {  
      return {status: "CLOSED", change: cid}   
      }
      return {status: "OPEN", change: newfinal}
}

Link to Challenge