# Post your Cash Register solutions here! (Fall 2022)

Hey everyone.

Congratulations on making it to the end of the Fall 2022 cohort of the free JavaScript Bootcamp. It’s always bittersweet to make it here, but I am proud of each and every one of you for making it this far.

With that said, let’s post our solutions!

Here’s mine:

``````const DENOMINATIONS = {
PENNY: 1,
NICKEL: 5,
DIME: 10,
QUARTER: 25,
ONE: 100,
FIVE: 500,
TEN: 1000,
TWENTY: 2000,
"ONE HUNDRED": 10000
}
function checkCashRegister(price, cash, cid) {
// calculate amount of change due
const changeDue = cash - price;
let changeDueCents = changeDue * 100;

const centsInCid = cid.reduce((acc, slot) => {
return acc + slot[1] * 100;
}, 0);

if (centsInCid === changeDueCents) {
return {status: "CLOSED", change: cid};
}

// cid like array
const changeInHand = cid.reverse().map(([name, valueInSlot]) => {
// Start accumulating amount of money we'll give worth of that money type
let total = 0;

// Look up the denomination
const denomination = DENOMINATIONS[name]

// Get the value in the slot in cents
let valueCents = valueInSlot * 100;

// Loop: while the change due is worth more than the denomination, and while we still have money of that type in the drawer
while(valueCents > 0 && denomination <= changeDueCents) {
// Add one worth of that denomination to the total
total += denomination;
// Subtract that amount from the change Due
changeDueCents -= denomination;
// Subtract that amount from the amount in the slot
valueCents -= denomination;
//console.log({name, total, changeDueCents, valueCents})
}
return [name, total / 100]
})
.filter(([, value]) => value > 0);

// If I still owe change, we don't have sufficient funds
if (changeDueCents > 0) {
return {status: "INSUFFICIENT_FUNDS", change: []}
}

return {status: "OPEN", change: changeInHand}
}

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

OMG! This is really tasking for me, but I came through with it.

here is my solution:

``````// create an object and multiply it by 100, because it is easier to work with integers
const currencyUnit = {
"PENNY": 1,
"NICKEL": 5,
"DIME": 10,
"QUARTER": 25,
"ONE": 100,
"FIVE": 500,
"TEN": 1000,
"TWENTY": 2000,
"ONE HUNDRED": 10000
}
function checkCashRegister(price, cash, cid) {
// calculate the difference between the cash and the accepted price
let myChange = cash * 100 - price * 100;
let  myChangeCheck = myChange
// initiate change to empty array and the status to empty string
let change = [];
let status = "";
// initiate the cidSum to 0 and filtered the cid
let cidSum = 0;
let cidFiltered = cid.filter(elem => elem[1] !== 0).reverse();
// using forEach to iterate through cidFiltered
cidFiltered.forEach(elem => {
// initiate currency to the element(array) and currency sum and multiply it by 100, so to work with whole number
let cur = elem[0];
let curSum = elem[1] * 100;
// add cidSum to currency sum
cidSum += curSum;
// initiate amount to 0
let amount = 0;
// loop through myChange and currency sum
while (myChange >= currencyUnit[cur] && curSum > 0) {
amount += currencyUnit[cur];
myChange -= currencyUnit[cur];
curSum -= currencyUnit[cur];
}
// if my amount is not equal to zero, then push change and divide amount with 100
if (amount !== 0) {
change.push([cur, amount / 100]);
}
});
// if myChange is more than 0, then, return to "INSUFFICIENT_FUNDS" and change to empty array
if (myChange > 0) {
return {status: "INSUFFICIENT_FUNDS", change: []}
} else if (myChange === 0 && myChangeCheck === cidSum) {
status = "CLOSED", change = cid
} else {
status = "OPEN"
}
//  return status and change
return {"status": status, "change": change};
}

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

I made it earlier and didn’t think about just multiplying everything with 100, so I used `.toFixed(2)`

``````function checkCashRegister(price, cash, cid) {

function isEmpty(remainingFunds) {
//checks whether every value in the object == 0
for (let item in remainingFunds) {
if (Number(remainingFunds[item].toFixed(2)) !== 0) {
return false;
}
}
return true;
}

function calculatePossibleChange(due, remainingFunds) {
let change = [];
const CURRENCY = [
["ONE HUNDRED", 100],
["TWENTY", 20],
["TEN", 10],
["FIVE", 5],
["ONE", 1],
["QUARTER", 0.25],
["DIME", 0.1],
["NICKEL", 2.05],
["PENNY", 0.01]
]

CURRENCY.forEach(([unit, value]) => {
let changeOfSlot = 0;
while (due >= value && remainingFunds[unit]) {
changeOfSlot += value;
due -= value;
due = due.toFixed(2);
remainingFunds[unit] -= value;
}
if (changeOfSlot !== 0) {
change.push([unit, changeOfSlot]);
}
})
return [change, due];
}

//make an object with the available funds
const remainingFunds = {};
cid.forEach(([unit, amount]) => remainingFunds[unit] = amount);

//calculate possible change
let [change, due] = calculatePossibleChange(cash - price, remainingFunds);
const finalChange = change.map(([_, value]) => [_, value]);

if (due > 0) {
//not enough money or units don't fit
return { status: "INSUFFICIENT_FUNDS", "change": [] };
}
else if (isEmpty(remainingFunds)) {
//enough money to give change out but no money remaining
return { status: "CLOSED", "change": cid }
}
else {
//enough money with rest
return { status: "OPEN", "change": finalChange }
}
}
``````
5 Likes

Nice one @Tzerio ,

Well done! I’ve never used

.toFixed

seems like a smart move. Pat Pat!

Happy coding!

1 Like

Hi Ramón and all!!!

This is the solution I submitted to get my certification, but I wanted to clean it up a bit, because it is too complex to read and also I know have to do better. It was my first solution.

I still didn’t have much time to get back to my projects, sorry. Anyway I hope it helps someone.

``````function checkCashRegister(price, cash, cid) {

const currencyInPenniesObj = {
"ONE HUNDRED": 10000,
"TWENTY": 2000,
"TEN": 1000,
"FIVE": 500,
"ONE": 100,
"QUARTER": 25,
"DIME": 10,
"NICKEL": 5,
"PENNY": 1
};

let returnedCashArray = [];

let cashDueInPennies = (cash - price) * 100;

const totalChangeInDrawerInPennies = cid.filter(withoutChange => withoutChange[1])
.map(currency => currency[1])
.reduce((sum, money) => ((sum + money)), 0)
.toFixed(2) * 100;

const arrayOfCents = cid
.filter(withoutChange => withoutChange[1])
.map(cash => [cash[0], cash[1] * 100])
.reverse();

if (totalChangeInDrawerInPennies === cashDueInPennies) { return { status: "CLOSED", change: cid }; }

if (totalChangeInDrawerInPennies < cashDueInPennies) { return { status: "INSUFFICIENT_FUNDS", change: [] }; };

for (let currency of arrayOfCents) {

let count = 0;
let cashName = currency[0];
let cashInDrawerSubarr = currency[1];
let currencyInPennies = currencyInPenniesObj[cashName];

if (cashDueInPennies - currencyInPennies < 0) { continue; };

while (cashDueInPennies - currencyInPennies >= 0 || currencyInPennies === 0) {
count += currencyInPennies;

cashInDrawerSubarr -= currencyInPennies;

cashDueInPennies -= currencyInPennies;

if (cashInDrawerSubarr === 0) { break; }

}

returnedCashArray.push([cashName, count / 100]);
}

if (cashDueInPennies > 0) { return { status: "INSUFFICIENT_FUNDS", change: [] } }

return { status: "OPEN", change: returnedCashArray };
}
``````

Keep the good work people!!!

1 Like

Well done Tzerio!!

It looks like you know what are you doing, eh?

Congrats, beautiful code too!!

and then I just came back to my solution and saw
`const finalChange = change.map(([_, value]) => [_, value]);`
and was like “wait wait wait was is this, isn’t this literally doing nothing relevant?”
But nobody else noticed, it’s fine, my past self surely had a reason for this

2 Likes

Hi @Tzerio

Ha ha ha, yeah I did not check yours, but I have something similar too, lol.

It means we are so good that we challenge ourself a bit more, just for fun.

Happy coding!!

1 Like

My solution is un-optimized, but here it is. If I have time I will come back and change it and re-post hopefully! The need to round off gave me some trouble, I improvised initially when I wrote my solution.

Michael

``````function checkCashRegister(price, cash, cid) {
let change = [];
let totalDue = cash - price;
let cidSum = cid.reduce((sum, elem) => sum + elem[1], 0);

console.log(cidSum);

// if cash < price OR not enough money in the drawer return insufficient funds message
if (totalDue < 0 || totalDue > cidSum + 0.00001)
return {
status: 'INSUFFICIENT_FUNDS',
change: [],
};
// if cash equals price no change is due
else if (totalDue === 0)
return {
status: 'OPEN',
change,
};
// if total change due is equal to the cash in drawer, close drawer
else if (Math.abs(totalDue - cidSum) < 0.00001)
return {
status: 'CLOSED',
change: cid,
};

// now we know the change due is less than the cash in the register so we will
// try to make change
const denominations = [100, 50, 20, 10, 5, 1, 0.25, 0.1, 0.05, 0.01];
let denomIndex = 0;

// holds the 2-item array to be pushed onto the change array
let currentDenomChangeArr = [];

while (totalDue !== 0 && denomIndex <= 9) {
// check whether we can decrement the change still due by the denomination
if (totalDue > denominations[denomIndex]) {
//call first helper function that gets change array entry to be pushed
currentDenomChangeArr = getBillsOrCoinsAmount(
denominations[denomIndex],
totalDue,
cid
);

// push change entry
if (currentDenomChangeArr[1] !== 0) change.push(currentDenomChangeArr);

// subtract current amount out of the change still due
totalDue -= currentDenomChangeArr[1];
}
denomIndex++;
}

// check whether we were able to make the correct change bringing
// totalDue down to \$0.00
if (Math.abs(totalDue) < 0.01) {
return { status: 'OPEN', change: change };
} else {
// otherwise return unsuccessful change making activity
console.log(totalDue);
return {
status: 'INSUFFICIENT_FUNDS',
change: [],
};
}
}

// returns how much change of particular bill or coin should be allocated to
// make change
function getBillsOrCoinsAmount(denomination, amtStillDue, cid) {
let amount = 0;
let amountAvailableEntry;
let amountAvailable = 0;
switch (denomination) {
case 100:
return calculateAmount(denomination, 'ONE HUNDRED', amtStillDue, cid);
break;
case 50:
return calculateAmount(denomination, 'FIFTY', amtStillDue, cid);
break;
case 20:
return calculateAmount(denomination, 'TWENTY', amtStillDue, cid);
break;
case 10:
return calculateAmount(denomination, 'TEN', amtStillDue, cid);
break;
case 5:
return calculateAmount(denomination, 'FIVE', amtStillDue, cid);
break;
case 1:
return calculateAmount(denomination, 'ONE', amtStillDue, cid);
break;
case 0.25:
return calculateAmount(denomination, 'QUARTER', amtStillDue, cid);
break;
case 0.1:
return calculateAmount(denomination, 'DIME', amtStillDue, cid);
break;
case 0.05:
return calculateAmount(denomination, 'NICKEL', amtStillDue, cid);
break;
case 0.01:
return calculateAmount(denomination, 'PENNY', amtStillDue + 0.00001, cid);
break;
default:
return 'ERROR';
break;
}
}

function calculateAmount(denomination, denomString, amtStillDue, cid) {
let amount = 0;
let amountAvailableEntry;
let amountAvailable = 0;

amount = Math.floor(amtStillDue / denomination) * denomination;
amountAvailableEntry = cid.filter((e) => e[0] === denomString);
if (amountAvailableEntry.length > 0) {
amountAvailable = amountAvailableEntry[0][1];
amount = Math.min(amount, amountAvailable);
return [denomString, amount];
}
return [denomString, 0];
}

console.log(
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],
])
);
``````
1 Like

Hi again Michael

Remember that if you select all your code and hit the `</>` button on the top menu, it will improve the readability of your post. Thank you and good work!!

You are on fire!!

Well, I go there… eventually and with a code that probably owes more to Ramon than it does to me, but I managed it. I have just spent, oh… I guess about three hours trying to figure out why my INSUFFICIENT FUNDS bit wouldn’t work for me and then I realised that what was required was INSUFFICIENT_FUNDS. Oh well, such is life!

``````//MONEYVALS is an oject giving the value of the various denominations in cents
const MONEYVALS={
"ONE HUNDRED": 10000,
TWENTY: 2000,
TEN: 1000,
FIVE: 500,
ONE: 100,
QUARTER: 25,
DIME: 10,
NICKEL: 5,
PENNY: 1
}

function checkCashRegister(price, cash, cid) {
//these lines are used by the whole function
// work out the amount of change required in cents
let change = (cash - price) * 100;
//reverse cid so as to have it in the same order as MONEYVALS
const REVARR = cid.reverse();
//find out how much money is in the till both in total and in each denomination
let tillAmount = REVARR.reduce((acc, money) => {
return acc + money[1] * 100
},0);

//this is the final part although it appears at the beginning

if (tillAmount === change) {

//reverse cid again so that the required format for the question is realised

cid.reverse()
return {status: "CLOSED", change: cid};
}

//this part only works with the insufficient funds and the open categories

//work out the amount of change due in each denomination
//by mapping the name and amount from REVARR

const changeDue = REVARR.map(([name,amount])=>{

//Set up a variable total to hold the amount of change required

let total=0

//nameValue holds each value in turn from the MONEYVALS array

let nameValue = MONEYVALS[name];

//amountCents multiplies the amount in the map function by 100 (note that this cannot be done within the function

let amountCents = amount*100

//we now need a while loop to calculate how much we can take out of each denomination starting at 100 and working down
//for the while loop to be triggered we need the amountCents variable to be greater than 0 and name value to be <= the
//value of change

while (amountCents > 0 && nameValue <= change){

//we then add our nameValue to the total

total += nameValue;

//subtract it from change and

change -= nameValue;

//subtract it from the amountCents variable until the while loop is no longer triggered

amountCents -= nameValue;

}
return [name,total/100]; //we then return the name of the denomination and the amount in dollars and cents

//We run a filter to take away any denomination and amount that is 0 to satisfy the answer requirements

}).filter(([,amount]) => amount > 0);

//if our change at the end of the above process has not reached zero we are unable to give change and so
//we return insufficient funds

if (change > 0) {
return {status:"INSUFFICIENT_FUNDS",change:[]};

//but if it has reached zero we are able to open the cash register and give the required amount of change

}
return {status:"OPEN",change: changeDue}

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

Ramon, thanks for the course buddy.

I am now working on web development learning HTML and CSS.

Cheers everybody,

Bill

2 Likes

Well done William!!

Keep the good work. Nicely done

Thank you Carlos, I just boxed my code like you suggested. You were such a valuable resource to everyone in this course Carlos! Pat pat

Michael

1 Like

Pat pat Michael!! Thank you very much.

1 Like

Thank you so much Carlos, good luck to you in your future!

1 Like

And, here is my solution.
Not really efficient but seems to serve the purpose. Thanks, Ramon, for the guidance and the encouragement!

``````function checkCashRegister(price, cash, cid) {

//Declaring denomination object to take care of different currency denominations
const denomination = {
'PENNY':  1,
'NICKEL': 5,
'DIME':   10,
'QUARTER':  25,
'ONE': 100,
'FIVE': 500,
'TEN':  1000,
'TWENTY': 2000,
'ONE HUNDRED':  10000
};

//Initializing temp variables
let status = '';
let change = [];

//Calculating change to be returned
let changeToBeReturned = cash - price;
let changeToBeReturnedInCents = changeToBeReturned * 100;

//Calculating cash available in drawer
let availableCashInCents = 0;
for (let k of cid){
availableCashInCents += k[1] * 100;
}

//CLOSED case: Cash available in drawer is equal to the cash to be returned
if (changeToBeReturnedInCents === availableCashInCents){
status = 'CLOSED';
change.length = 0;
change = [...cid];

//OPEN case: More cash is available in drawer than is required to be returned
}else {
const cidReversed = [...cid].reverse();

while (changeToBeReturnedInCents > 0){
for (let j in cidReversed){
let key = cidReversed[j][0];
if(denomination[key] <= changeToBeReturnedInCents){
let noOfCoins = Math.min(Math.floor(changeToBeReturnedInCents/denomination[key]), (cidReversed[j][1] * 100)/denomination[key]);
changeToBeReturnedInCents -= (noOfCoins * denomination[key]);
const arrTemp = [];
arrTemp.push(key, noOfCoins * (denomination[key]/100));
status ='OPEN';
change.push(arrTemp);
}
}

//INSUFFICIENT FUNDS case: Not enough cash is available in the drawer
if (changeToBeReturnedInCents > 0){
status ='INSUFFICIENT_FUNDS';
change.length = 0;
}
break;
}
}

//Collecting and returning result
const resultObj = {
status: status,
change: change
};

return resultObj;
}

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]]);
``````
1 Like

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