freeCodeCamp Challenge Guide: Cash Register

Cash Register


Problem Explanation

  • You have to create a program that will return an object containing a status key and a change key. The value of status is the string INSUFFICIENT_FUNDS, CLOSED, or OPEN, and the value of change is a 2D array of the change due.

Relevant Links


Hints

Hint 1

  • It is easier when you know how much money is in your register beforehand. For this it is recommended to have a function to assign this information to a variable. Then you can see if you have enough money to complete the transaction and return change, or if you should close the register.

Hint 2

  • This problem is easier when you know the value of each bill or coin you are working with, rather than just the sum of each in the register. For example, it’s useful to know that a nickel is worth .05, along with the fact that you have $2.05 worth of nickels in the cash register.

Hint 3

  • You will have to get as much change from one type of bill or coin before moving to the next, from greater to lesser value. Keep going until you have calculated all the change due.

Solutions

Solution 1 (Click to Show/Hide)
// Create an array of objects which hold the denominations and their values
var denom = [
  { name: "ONE HUNDRED", val: 100.0 },
  { name: "TWENTY", val: 20.0 },
  { name: "TEN", val: 10.0 },
  { name: "FIVE", val: 5.0 },
  { name: "ONE", val: 1.0 },
  { name: "QUARTER", val: 0.25 },
  { name: "DIME", val: 0.1 },
  { name: "NICKEL", val: 0.05 },
  { name: "PENNY", val: 0.01 }
];

function checkCashRegister(price, cash, cid) {
  var output = { status: null, change: [] };
  var change = cash - price;

  // Transform CID array into drawer object
  var register = cid.reduce(
    function(acc, curr) {
      acc.total += curr[1];
      acc[curr[0]] = curr[1];
      return acc;
    },
    { total: 0 }
  );

  // Handle exact change
  if (register.total === change) {
    output.status = "CLOSED";
    output.change = cid;
    return output;
  }

  // Handle obvious insufficient funds
  if (register.total < change) {
    output.status = "INSUFFICIENT_FUNDS";
    return output;
  }

  // Loop through the denomination array
  var change_arr = denom.reduce(function(acc, curr) {
    var value = 0;
    // While there is still money of this type in the drawer
    // And while the denomination is larger than the change remaining
    while (register[curr.name] > 0 && change >= curr.val) {
      change -= curr.val;
      register[curr.name] -= curr.val;
      value += curr.val;

      // Round change to the nearest hundreth deals with precision errors
      change = Math.round(change * 100) / 100;
    }
    // Add this denomination to the output only if any was used.
    if (value > 0) {
      acc.push([curr.name, value]);
    }
    return acc; // Return the current change_arr
  }, []); // Initial value of empty array for reduce

  // If there are no elements in change_arr or we have leftover change, return
  // the string "Insufficient Funds"
  if (change_arr.length < 1 || change > 0) {
    output.status = "INSUFFICIENT_FUNDS";
    return output;
  }

  // Here is your change, ma'am.
  output.status = "OPEN";
  output.change = change_arr;
  return output;
}

// test here
checkCashRegister(19.5, 20.0, [
  ["PENNY", 1.01],
  ["NICKEL", 2.05],
  ["DIME", 3.1],
  ["QUARTER", 4.25],
  ["ONE", 90.0],
  ["FIVE", 55.0],
  ["TEN", 20.0],
  ["TWENTY", 60.0],
  ["ONE HUNDRED", 100.0]
]);

Code Explanation

First, create an array of objects with the value of each denomination of bill or coin, along with an output object with the status and change keys. Next, transform the CID array into a drawer object. Then, handle the conditions of exact change and insufficient funds. Loop through the denom array and update the change and values while there is still money of each type in the drawer and while the denomination is larger than the change remaining. Add this denomination to the accumulator of change_arr if any of this type was used. After the loop, change_arr is a 2D array of the change due, sorted from highest to lowest denomination. If there are no elements in change_arr or you still owe change, return the output object with a status of INSUFFICIENT_FUNDS. Finally you can give the correct change. Return the output object with a status of OPEN and change_arr as the value of change.

Relevant Links

12 Likes

Here’s another way to solve it. It uses direct calculation instead of a while loop to calculate the change for each denomination.

function checkCashRegister(price, cash, cid) {
  // All amounts are multiplied by 100 until the final result to avoid errors with floating point math
  const denominations = { "PENNY": 1, "NICKEL": 5, "DIME": 10, "QUARTER": 25, "ONE": 100, "FIVE": 500, "TEN": 1000, "TWENTY": 2000, "ONE HUNDRED": 10000 }
  let changeDue = (cash * 100 - price * 100);
  const register = cid.reverse().map(el => [el[0], Math.round(el[1]*100)]);
  const registerTotal = register.reduce((sum, elem) => (sum + elem[1]), 0);
  
  if (changeDue > registerTotal ) return "Insufficient Funds";
  if (changeDue === registerTotal ) return "Closed";

  let partial;
  let change = register.reduce((acc, elem) => {
        // for each denomination calculate the lesser of (a) the amount that could be paid with that
        // denomination without going over the amount owed, and (b) the actual amount of that denomination in 
        // the register. Denominations not used to make change are excluded from the resulting array.
        partial = Math.min(elem[1], Math.floor(changeDue / denominations[elem[0]]) * denominations[elem[0]]);
        if ( partial > 0 ) {
          changeDue -= partial;
          acc.push([elem[0], partial / 100]);
        } return acc;
    }, [])
      
  // If the correct change could not be made from what was in the register.
  if (changeDue > 0 ) return "Insufficient Funds"

  return change;
}
13 Likes

Actually, I don’t see much value from converting the ‘cid’ array into an object for this task. Below’s my approach just with arrays. It also tests at the very beginning if enough cash is in the drawer before doing any computations. I think the structure is cleaner as the current “Beginner Code Solution”. Take a look:

/*jshint esversion: 6 */

function checkCashRegister(price, cash, cid) {
  //declare and initialize variables
  var change = Math.round((cash - price) * 100);
  var value = 0;
  var changeRecord = [];
  var currency = [1, 5, 10, 25, 100, 500, 1000, 2000, 10000];
  //convert all floats to integers due to floating point number issue
  cid.forEach(el => el[1] = Math.round(el[1] * 100));
  //helper function to check if sufficient cash for change is in the drawer
  function enoughFund(cid) {
    var sum = cid.filter((el, i) => change >= currency[i]);
    return sum.reduce((a, b) => {
      return a + b[1];
    }, 0);
  }

  //Actual program/control flow starts here
  if (enoughFund(cid) < change)
    return "Insufficient Funds";
  else if (enoughFund(cid) === change)
    return "Closed";
  else {
    for (var i = cid.length - 1; i > -1; i--) {
      value = 0;
      while (cid[i][1] > 0 && change >= currency[i]) {
        //update everything as long as condition is true
        change -= currency[i];
        cid[i][1] -= currency[i];
        //value keeps track of the amount of each currency unit as change
        value += currency[i];
      }
      if (value)
        changeRecord.push([cid[i][0], value]);
    }
  }
  //divide each array by 100 to display a proper money format
  changeRecord.forEach(el => el[1] = (el[1] / 100));
  return changeRecord;
}
17 Likes

The result of this code for check #5 is “[[“TWENTY”,80],[“TEN”,10],[“FIVE”,5],[“ONE”,1],[“QUARTER”,0.5],[“DIME”,0.2],[“PENNY”,0.04]]”, whereas the expected answer for check #5 has been “[[“TWENTY”, 60.00], [“TEN”, 20.00], [“FIVE”, 15.00], [“ONE”, 1.00], [“QUARTER”, 0.50], [“DIME”, 0.20], [“PENNY”, 0.04]]”. There seems to be a bug in this challenge scenario. This is what I have:

function checkCashRegister(price, cash, cid) {
var changeValue=cash-price;
var flattened = [].concat.apply([], cid);
var numbersOnly = flattened.filter(function(element) {return !isNaN(parseFloat(element)) && isFinite(element);});
var registerValue=numbersOnly.reduce((a, b) => a + b, 0).toFixed(2);
var change=[];
var smallChange=(changeValue%1).toFixed(2);
var coinsValue=0;

for (i=0;i<4;i++){
coinsValue+=numbersOnly[i];
}

if (registerValue==changeValue) return “Closed”;
if (registerValue>changeValue){
if (changeValue>=100) change.push([“ONE HUNDRED”,100Math.floor(changeValue/100)]); changeValue=changeValue%100;
if (changeValue>=20) change.push([“TWENTY”,20
Math.floor(changeValue/20)]); changeValue=changeValue%20;
if (changeValue>=10) change.push([“TEN”,10Math.floor(changeValue/10)]); changeValue=changeValue%10;
if (changeValue>=5) change.push([“FIVE”,5
Math.floor(changeValue/5)]); changeValue=changeValue%5;
if (changeValue>=1) change.push([“ONE”,1Math.floor(changeValue)]); changeValue=changeValue%1;
if (changeValue>=0.25) { change.push([“QUARTER”,0.25
Math.floor(changeValue/0.25)]); changeValue=changeValue%0.25; }
if (changeValue>=0.10){ change.push([“DIME”,0.10Math.floor(changeValue/0.10)]); changeValue=changeValue%0.1;}
if (changeValue>=0.05){ change.push([“NICKEL”,0.05
Math.floor(changeValue/0.05)]); changeValue=changeValue%0.05;}
if (changeValue>=0.01){ change.push([“PENNY”,0.01*Math.ceil(changeValue/0.01)]);}
} else {return “Insufficient Funds”;}
if (coinsValue<smallChange) return “Insufficient Funds”;

return change;
}

1 Like

I’ve fixed my own chicken scratch. Although I’ve also realized that this challenge is to help one with learning the skills of object oriented programming, I’ve proceeded to solve the puzzle with sequential coding. Thus, this following snippet probably qualifies as a very basic-level solution:

function checkCashRegister(price, cash, cid) {
var changeValue=cash-price;
var flattened = [].concat.apply([], cid);
var numbersOnly = flattened.filter(function(element) {return !isNaN(parseFloat(element)) && isFinite(element);}).reverse();
var registerValue=numbersOnly.reduce((a, b) => a + b, 0).toFixed(2);
var change=[];
var smallChange=(changeValue%1).toFixed(2);
var coinsValue=0;
var grab=0;

for (i=0;i<4;i++){
coinsValue+=numbersOnly[i];
}

if (registerValue==changeValue) return “Closed”;
if (registerValue>changeValue){

// Let's deal with HUNDREDs
if (changeValue>=100){ 
  grab=100*Math.floor(changeValue/100) > numbersOnly[0]? numbersOnly[0] : 100*Math.floor(changeValue/100);
  change.push(["ONE HUNDRED",grab]);
  changeValue-=grab; }

// TWENTIES
if (changeValue>=20){ 
  grab=20*Math.floor(changeValue/20) > numbersOnly[1]? numbersOnly[1] : 20*Math.floor(changeValue/20);
  change.push(["TWENTY",grab]); 
  changeValue-=grab; }

// TENs
if (changeValue>=10){
  grab=10*Math.floor(changeValue/10) > numbersOnly[2]? numbersOnly[2] : 10*Math.floor(changeValue/10);
  change.push(["TEN",grab]);
  changeValue-=grab;}

// FIVEs
if (changeValue>=5){ 
  grab=5*Math.floor(changeValue/5) > numbersOnly[3]? numbersOnly[3] : 5*Math.floor(changeValue/5);
  change.push(["FIVE",grab]); 
  changeValue-=grab;}

// ONEs
if (changeValue>=1){
  grab=changeValue > numbersOnly[4]? numbersOnly[4] : Math.ceil(changeValue%1);
  change.push(["ONE",grab]); 
  changeValue-=grab;
}

if (changeValue>=0.25) {

// return changeValue;
grab=changeValue > numbersOnly[5]? numbersOnly[5] : 0.25*Math.floor(changeValue/0.25);
change.push([“QUARTER”,grab]);
changeValue-=grab;
}

if (changeValue>=0.10){ 
  grab=changeValue > numbersOnly[6]? numbersOnly[6] : 0.1*Math.floor(changeValue/0.1);
  change.push(["DIME",grab]);
  changeValue-=grab;}

if (changeValue>=0.05){ 
  grab=changeValue > numbersOnly[7]? numbersOnly[7] : 0.05*Math.floor(changeValue/0.05);
  change.push(["NICKEL",grab]);
  changeValue-=grab;}

if (changeValue>=0.01){ 
  change.push(["PENNY",Math.round(changeValue*100)/100]);
  }

} else {return “Insufficient Funds”;}
if (coinsValue<smallChange) return “Insufficient Funds”;

return change;
}

This is the first working solution I came up with.
Feedback always welcome:

function checkCashRegister(price, cash, cid) {
    var change = cash - price;
    var currencyValues = { 0: 100, 1: 20, 2: 10, 3: 5, 4: 1, 5: 0.25, 6: 0.10, 7: 0.05, 8: 0.01 };
    console.log(totalInDrawer(cid));
    if (change > totalInDrawer(cid) || enoughCurrencyValue(cid, change, currencyValues) === false) {
        return 'Insufficient Funds';
    } else if (change == totalInDrawer(cid)) {
        return 'Closed';
    }
    var ticket = createTicket(cid, change, currencyValues);
    // Here is your change, ma'am.
    return ticket;
}

function enoughCurrencyValue(cid, change, values) {
    var lower = cid.reverse().filter(function(item, index) {
        if(values[index] <= change || (item[1] >= change && values[index] <= change)) return item;
    }, []);
    return totalInDrawer(lower) >= change;
}

function createTicket(cid, change, currencyValues) {
    
    var ticket = cid.filter(function (current, index) {
        let changeAcc = 0;
        while (current[1] >= currencyValues[index] && current[1] >= 0 && currencyValues[index] <= change && change > 0) {
            if (enoughCurrency(currencyValues[index], current[1])) {
                change = change.toFixed(2);
                change -= currencyValues[index];
                current[1] -= currencyValues[index];
                changeAcc += currencyValues[index];
            }
        }
        if (changeAcc > 0) {
            current[1] = changeAcc;
            return current;
        }
    });
    return ticket;
}

function enoughCurrency(value, available) {
    return available >= value ? true : false;
}

function totalInDrawer(array) {
    return array.reduce(function (prev, curr) {
        return prev + curr[1];
    }, 0);
}
2 Likes

My solution uses two 2D arrays: inDrawer (denominations and cash) and changeArray (output)
inDrawer = [ [denomination value, current value ], … ];
changeArray = [ [denominatin name, current change ], … ]

    function checkCashRegister(price, cash, cid) {

  var change = cash - price,
  cashInDrawer = 0,
  // Part of cashInDrawer, which currency is  equal or less than change
  possibleChange = 0,
  // Part of change in one denomination
  giveChange = 0,
  inDrawer = [[100], [20], [10], [5], [1], [0.25], [0.10], [0.05], [0.01]],
  changeArray = [];

  cid.reverse();
  // Counts all cash in drawer,
  // Comletes inDrawer (denominations) with appropriate cash
  // Pushes each name of denominations into  changeArray
  for (var i = cid.length-1; i >= 0; i--) {
    cashInDrawer += cid[i][1];
    inDrawer[i].push(cid[i][1]);
    changeArray.push([cid[i][0]]);
  }

  changeArray.reverse();

  if (change > cashInDrawer) {
    return "Insufficient Funds";
  } else if (change === cashInDrawer) {
    return "Closed";
  } else {
// ----------- count change START ----------- //
    for (var k = 0; k < inDrawer.length; k++) {
      // Counts change of each denomination type ...
      while (change >= inDrawer[k][0] && inDrawer[k][1] > 0) {
        giveChange += inDrawer[k][0];
        inDrawer[k][1] -= inDrawer[k][0];
        change -= inDrawer[k][0];
        change = Math.round(change * 100) / 100;
      }
      // ... and pushes it to appropriate denomination name
      if (giveChange > 0) {
        changeArray[k].push(Math.round(giveChange * 100) / 100);
      }
      // counts possibleChange
      if (cash - price >= inDrawer[k][0]) {
        possibleChange += inDrawer[k][1];
      }
      // Assign giveChange to 0 for next k-iteration
      giveChange = 0;
    }
// ----------- count change END ----------- //
  }
  // Second case, when change returning is impossible
  if (cash - price > possibleChange) {
    return "Insufficient Funds";
  }
   // Filters out items with 2 elements (denomination name and appropriate cash)
  return changeArray.filter(function(item) {
    return item.length === 2;
  });
}

console.log(checkCashRegister(19.50, 20.00, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.10], ["QUARTER", 4.25], ["ONE", 90.00], ["FIVE", 55.00], ["TEN", 20.00], ["TWENTY", 60.00], ["ONE HUNDRED", 100.00]]));
1 Like
function checkCashRegister(price, cash, cid) {

var obj = {“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};
var returnVal;
var change=[];
var diff = parseFloat(cash-price).toFixed(2);
for (var i=cid.length-1;i>=0;i–){
var accumilator=0;
var money = cid[i][1];
var currencyName = cid[i][0];
var objDivid = obj[cid[i][0]];

while(money/objDivid>=1&&diff>=objDivid){
accumilator +=objDivid;
money=  parseFloat(money-objDivid).toFixed(2);
diff=parseFloat(diff-objDivid).toFixed(2);
   }
  if(accumilator>0)change.push([currencyName,accumilator]);

}
// Here is your change, ma’am.
if(diff==0)returnVal=change;
if(diff>0)returnVal=“Insufficient Funds”;
if(diff==0&&cid[0][1]<1)returnVal=“Closed”;
return returnVal;
}

1 Like

I can’t pass the #5 tests because of JS’s DEMICAL BUG.
I tried to multiply every demical to 100 and divide it by 100 but the bug is still there.
So I just put my code here hope that someone could fix this for me.Meanwhile I’d have to copy one of yours to pass the god damn test :frowning:

function checkCashRegister(price, cash, cid) {
   // Here is your change, ma'am.
  var funds=(cid.reduce(function(acc,val){
    return acc+val[1]*100;
  },0))/100;
  var newArr=cid.reduce(function(acc,val){
      acc.push(val.slice());
    return acc;
    },[]);
 
  for(i=0;i<newArr.length;i++){
    switch(newArr[i][0]){
      case "PENNY":newArr[i][0]=0.01;break;
      case "NICKEL":newArr[i][0]=0.05;break;
      case "DIME":newArr[i][0]=0.10;break;
      case "QUARTER":newArr[i][0]=0.25;break;
      case "ONE":newArr[i][0]=1;break;
      case "FIVE":newArr[i][0]=5;break;
      case "TEN":newArr[i][0]=10;break;
      case "TWENTY":newArr[i][0]=20;break;
      case "ONE HUNDRED":newArr[i][0]=100;break;
    }
  }
  
 //return newArr;
  //return cid;
 
  if(cash-price>funds){
    return "Insufficient Funds";
  }
  else if(cash-price===funds){
    return "Closed";
  }
  else{
    var list=[];
    var change=cash-price;
   for(i=8;i>=0;i--){
     if(change>=cid[i][1]){
       change=(change*100-cid[i][1]*100)/100;
       list.push(cid[i]);
     }
     else if(change>=newArr[i][0]){
       list.push([cid[i][0],Math.floor(change/newArr[i][0])*newArr[i][0]]);
       change=(change*100-newArr[i][0]*100*Math.floor((change*100)/(newArr[i][0]*100)))/100;
       
     }
    
   }
    
   if(change!==0){
     return"Insufficient Funds";
   }
   else{
    return list;
      }
  }
  
}



checkCashRegister(3.26, 100.00, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.10], ["QUARTER", 4.25], ["ONE", 90.00], ["FIVE", 55.00], ["TEN", 20.00], ["TWENTY", 60.00], ["ONE HUNDRED", 100.00]]) ;

why do you divide by a hundred before you finish operations? Doesn’t that defeat the purpose of multiplying by a 100 to began with? You end up doing a lot of your operations in float anyway, just with a redundant *100/100. Why not multiply by 100, do all the math operations, then divide by 100?

My approach first checks if there is enough cash in the drawer to satisfy the required change. Then it loops through the cash in drawer (cid) array, starting with the largest denomination. Each iteration checks if that denomination is smaller than the amount of change remaining and if there is actually any of that denomination in the cid. If not, it moves to the next denomination. If there is, it subtracts that denomination from the change and the cid, then adds that amount to changeArr.


function checkCashRegister(price, cash, cid) {
  var worth = [0.01, 0.05, 0.10, 0.25, 1.00, 5.00, 10.00, 20.00, 100.00];
  var changeArr = [];
  var change = cash - price;
  var cashDrawer = 0;
  var changeAvail = 0;
  for(i = 0; i < cid.length; i++) {
    cashDrawer += cid[i][1];
  }
  cashDrawer = cashDrawer.toFixed(2);
  if(cashDrawer < cash - price) { // Is there not enough cash in the drawer?
    return "Insufficient Funds";
  } else if(cashDrawer == cash - price) { // Is there exactly enough cash in the drawer?
    return "Closed";
  } else {
    for(i = 8; i > -1; i--) {
      //Create a copy of the cid array to prevent unwanted changes to it
      var cidCopy = [];
      for (var k = 0; k < cid.length; k++) {
        cidCopy[k] = cid[i].slice();
      }
      var x = worth[i];
      var y = cidCopy[i];
      var z = cidCopy[i][0];
      // If there is cash in the drawer of that denomination,
      // and if that denomination is smaller than the change remaining:
      if(change >= x && cidCopy[i][1] > 0) {
        change -= x;
        change = Number(change.toFixed(2)); // Round change to nearest hundredth
        cid[i][1] -= x;
        if(!changeArr.length) {
          changeArr.unshift(y);
          changeArr[0][1] = x;
        } else if(changeArr[0][0] == z) {
          changeArr[0][1] += x;
        } else {
          changeArr.unshift(y);
          changeArr[0][1] = x;
        }
        i++;
      }
    }

  }  
  // Here is your change, ma'am.
  for(j = 0; j < changeArr.length; j++) {
    changeAvail += changeArr[j][1];
  }
  if(changeAvail < cash - price) {
    return "Insufficient Funds";
  } else {
    return changeArr.reverse();
  }
}


1 Like

I used:
change = Number(change.toFixed(2));

The toFixed method actually returns a string, so I had to convert it back to a number. But this seems to do the trick pretty well.

See my code to see it in action. I only had to use it in one line to fix the problem.

1 Like

Here’s my current solution.

function checkCashRegister(price, cash, cid) {
  const values = [1,5,10,25,100,500,1000,2000,10000];
  let change = cash*100 - price*100; 
  let allCash = true;

  let moneyback = cid.reduceRight(function(p,c,i){
      let out = Math.min(change-change%values[i], c[1]*100);
      change -= out;
      if (out !== c[1]*100) { allCash = false; }
      return out ? p.concat([[c[0], out/100]]) : p;
    },[]);

  return change > 0 ? "Insufficient Funds" : allCash ? "Closed" : moneyback;
}
16 Likes

forkerino, I tryed this test:

checkCashRegister(19.70, 20.00, [[“PENNY”, 0], [“NICKEL”, 0], [“DIME”, 0.5], [“QUARTER”, 0.5], [“ONE”, 0], [“FIVE”, 0], [“TEN”, 0], [“TWENTY”, 0], [“ONE HUNDRED”, 100.00]]);

And got:

“Insufficient Funds”

Hi, thanks for catching that one. It seems to be a situation that is not tested for in any of the provided test-cases (the change can be given only by skipping one of the denomenations, in this case the quarters). I suspect most other solutions on this page have the same problem, at least as far as I can see from skimming the code… I also don’t see an easy way to solve this based on my current solution, but it’s definitely an interesting case to think about.

Here is my advanced solution:

function checkCashRegister(price, cash, cid) {
    let mNames = ['PENNY', 'NICKEL', 'DIME', 'QUARTER', 'ONE', 'FIVE', 'TEN', 'TWENTY', 'ONE HUNDRED'],
        mValues = [1, 5, 10, 25, 100, 500, 1000, 2000, 10000],
        mAmount = [];

    let goal = cash * 100 - price * 100;
    
    for(let i = 0; i < cid.length; i++) {
        let sum = Math.round(cid[i][1] * 100);
        mAmount[i] =  Math.floor(sum / mValues[i]); 
    }
    
    console.log('mAmount:');
    console.log(mAmount);
    
    let hRes = h(goal, 8);
    
    if(hRes) { 
        let res = [],
            flag = 0;

        for(let i = hRes.length - 1; i >= 0; i--) {
            let sum = ((hRes[i] * mValues[i]) / 100 ).toFixed(2);
            let have = (cid[i][1]).toFixed(2); 
          
            if(have == sum) {
                flag++;
            }
            
            if(sum > 0) {
                sum = Number(sum);
                res.push([mNames[i], sum]);    
            } 
        }
        
        if(flag === 9) {
            return 'Closed';
        } else {
            return res;
        }  
    } else {
        return 'Insufficient Funds';
    }
  
    function h(goal, i) {
        if(i < 0) {
            return false;
        }
        
        console.log(`goal: ${goal}`);
        console.log(`coin: ${mValues[i]}`);
        console.log(`i: ${i}`);
        
        let value = mValues[i],
            amount = mAmount[i];
        
        let div = Math.floor(goal / value);
        let n = Math.min(div, amount);
        
        if(goal - n * value == 0) {
            let coins = [0,0,0,0,0,0,0,0,0];
            coins[i] = n;
            return coins;
        } else {
            while(n >= 0) {
                let newGoal = goal - n * value;
                let hRes = h(newGoal, i-1);
                
                if(hRes) {
                    hRes[i] = n;
                    return hRes;
                }
                
                n--;
            }
    
            return false;
        } 
    }
}
1 Like

forkerino, if you interested, check my solution above

Thanks for sharing. I haven’t had time to look at it, but will do later.