Tell us what’s happening:
Hello there
My idea for solving this project was to use a recursive solution. It’s a mess and definitely not the optimal solution, but it actually works at this point (!), kind of. It passes the tests with the initial cid values, then it hits the tests where the cid values are changed (so it’s only one penny in the register and the price is 19.5), and then it fails.
The thing is, I’ve tried to actually change the cid array values in my editor to be what the test uses and then it works and correctly outputs INSUFFICIENT_FUNDS. If I click the run tests button after manually changing cid to only have one penny, then it passes all the tests where cid is supposed to have one penny, but not the previous tests with the initial cid array values.
So I think the problem is with how the cid is being changed when it’s being tested. Does anyone know how to fix that? To fix this I’ve tried:
- Spreading cid into a new array when reversing it
- Adding a counter that counts how many tests have been run that then changes the cid array after a certain amount. But this doesn’t work, so I assume the tests are resetting the code after every test. But then spreading the cid into a new array wouldn’t be necessary right?
I don’t understand what’s happening. Please help.
Your code so far
WARNING
The challenge seed code and/or your solution exceeded the maximum length we can port over from the challenge.
You will need to take an additional step here so the code you wrote presents in an easy to read format.
Please copy/paste all the editor code showing in the challenge from where you just linked.
const cashInput = document.getElementById("cash");
const changeDueDiv = document.getElementById('change-due');
const purchaseBtn = document.getElementById('purchase-btn');
let price = 1.87;
let cid = [
["PENNY", 1.01],
["NICKEL", 2.05],
["DIME", 3.1],
["QUARTER", 4.25],
["ONE", 90],
["FIVE", 55],
["TEN", 20],
["TWENTY", 60],
["ONE HUNDRED", 100],
];
// The one-penny tests work if I manually set cid to this:
/* let cid = [
["PENNY", 0.01],
["NICKEL", 0],
["DIME", 0],
["QUARTER", 0],
["ONE", 0],
["FIVE", 0],
["TEN", 0],
["TWENTY", 0],
["ONE HUNDRED", 0]
]; */
const reversedCid = [...cid].reverse();
// Round to two decimals
const round = num => {
return Math.round(num * 100) / 100;
}
// Sum values in register
let totalCurrInRegister = round(cid.map((curr) => curr[1]).reduce((idk, curr) => idk + curr, 0));
const currencyValues = [
{ value: 0.01, symbol: "PENNY" },
{ value: 0.05, symbol: "NICKEL" },
{ value: 0.1, symbol: "DIME" },
{ value: 0.25, symbol: "QUARTER" },
{ value: 1, symbol: "ONE" },
{ value: 5, symbol: "FIVE" },
{ value: 10, symbol: "TEN" },
{ value: 20, symbol: "TWENTY" },
{ value: 100, symbol: "ONE HUNDRED" }
];
const cashCombination = (inNum) => {
// G: base case:
if (inNum < 0.01) {
return [];
}
// B: What is the highest (usable) currency that you have in the register? If the value of that currency in cid is greater than 0 it means you have it in the register && the item's name ([0]) in the currencyvalues arr translates to an increment that is <= inNum.
const highestUsableCurr = reversedCid.find((item) => item[1] > 0 && currencyValues.find((obj) => obj.symbol === item[0]).value <= inNum)[0];
console.log(`highestUsableCurr: ${highestUsableCurr}`)
// C: takes that value's key and searches for it in the map of currency units
// to find out what the currency (key) is worth. like for example 'TWENTY' is 20
const incrementOfHighestUsableCurr = currencyValues.find((obj) => obj.symbol === highestUsableCurr).value;
console.log(`incrementOfHighestUsableCurr: ${incrementOfHighestUsableCurr}`)
// D: now you have the increment - that currency's value (the highest currency's value)
// E: Subtract the increment from total register amount
totalCurrInRegister = round(totalCurrInRegister) - round(incrementOfHighestUsableCurr);
// F: Subtract the increment from the value of the cid currency that is highest usable
// Same as highestUsableCurr, just the value, instead
const inRegOfHighestUsableCurrBefore = reversedCid.find((item) => item[1] > 0 && currencyValues.find((obj) => obj.symbol === item[0]).value <= inNum)[1];
console.log("inRegOfHighestUsableCurrBefore:", inRegOfHighestUsableCurrBefore);
// Decrement highest usable currency in register by that currency's increment
// reversedCid.find((item) => item[1] > 0 && currencyValues.find((obj) => obj.symbol === item[0]).value <= inNum)[1] -= incrementOfHighestUsableCurr;
// This is the decrement function.
reversedCid.find((item) => item[0] === highestUsableCurr)[1] = round(reversedCid.find((item) => item[0] === highestUsableCurr)[1] - incrementOfHighestUsableCurr)
const inRegOfHighestUsableCurrAfter = reversedCid.find((item) => item[1] > 0 && currencyValues.find((obj) => obj.symbol === item[0]).value <= inNum)[1];
console.log("inRegOfHighestUsableCurrAfter:", inRegOfHighestUsableCurrAfter);
// G: Do recursive call with n - highestCurrencyKey.increment, + (or concat) key name.
// - this call hits the base case, which is an array, and thus every currency unit you subtracted by gets added into that array. i'll figure out what to do with this later
// trying to round this so it doesn't thing
const newInNum = round(inNum - incrementOfHighestUsableCurr);
console.log("inNum:", inNum)
console.log("newInNum:", newInNum)
// The recursive call
return cashCombination(newInNum).concat(highestUsableCurr);
}
purchaseBtn.addEventListener('click', () => {
// Line so console.logs look cleaner
console.log("------------");
// Clear the text on every purchase
changeDueDiv.textContent = "";
const cash = round(cashInput.value);
console.log("cash:", cash);
// Amount you have to return to the customer
const leftoverCash = round(cash) - round(price);
console.log("leftoverCash:", leftoverCash)
// These ifs could be done with leftoverCash
if (round(cash) === round(price)) {
changeDueDiv.textContent = "No change due - customer paid with exact cash";
return;
}
if (round(cash) < round(price)) {
alert("Customer does not have enough money to purchase the item");
return;
}
console.log("round(cash) - round(price:", round(cash) - round(price))
console.log("totalCurrInRegister", totalCurrInRegister)
if (round(cash) - round(price) > totalCurrInRegister) {
changeDueDiv.textContent = "Status: INSUFFICIENT_FUNDS";
return;
}
// For testing:
const whatYouGetFromCashCombinationReversed = cashCombination(leftoverCash).reverse()
const outputArray = whatYouGetFromCashCombinationReversed;
console.log("outputArray:", outputArray)
console.log("cid:", cid)
// H: now you just need to make the output clean.
// First do count of each currency unit in the output.
const calculateTotalValueByCurrency = (currencyArray) => {
// Object to hold the count of each currency
const currencyCount = {};
// Add to currencyCount with each time you use a currency
// If the current item in currencyArray is in currencyCount, increase it, else, add it
currencyArray.forEach(currency => {
if (currencyCount[currency]) {
currencyCount[currency] += 1;
} else {
currencyCount[currency] = 1;
}
});
// Convert the counts to an array with total value
const resultArray = Object.entries(currencyCount).map(([currency, count]) => {
// Find the value of the currency
const currencyValue = round(currencyValues.find(obj => obj.symbol === currency).value);
console.log("currencyValue:", currencyValue)
// Calculate the total value for this currency
const totalValue = '$' + round(currencyValue * count);
console.log("totalValue:", totalValue)
return [currency, totalValue];
});
return resultArray;
}
const totalValuesByCurrency = calculateTotalValueByCurrency(outputArray)
const outputString = totalValuesByCurrency.map(pair => pair.join(": ")).join(" ");
changeDueDiv.textContent += `Status: OPEN ${outputString}`;
console.log("OPEN:", calculateTotalValueByCurrency(outputArray))
})
Your browser information:
User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
Challenge Information:
Build a Cash Register Project - Build a Cash Register