JavaScript Cash Register Challenge -- Not sure why this error persists

This isn’t a fully completed project, but I do have a solid idea of what I have left to do. The problem I’m facing is how to overcome a TypeError that occurs in the project.

My code is below:

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

// this will NOT change
const DENOMINATIONS = [
["PENNY", 1],
["NICKEL", 5],
["DIME", 10],
["QUARTER", 25],
["ONE", 100],
["FIVE", 500],
["TEN", 1000],
["TWENTY", 2000],
["ONE HUNDRED", 1000],
]

let priceInPennies = price * 100;
let cashInPennies = cash * 100;
let changeInPennies = Math.floor(cashInPennies - priceInPennies);

// This sets the cash in drawer amounts equal to values in pennies
let cidValues = cid
for (let i = 0; i < cidValues.length; i++) {
cidValues[i][1] *= 100
// console.log(cidValues[i][1])
}

//console.log(cidValues[4])

let change = []
while (changeInPennies > 0) {
for (let j = cidValues.length - 1; j >= 0; j--) {
console.log(cidValues[j][1])
let placeholder = [cidValues[j][0], 0]
// "while there is change in the drawer at the given currency and while a unit of the denomination can be subtracted from the change due..."
while ((cidValues[j][1] > 0) && (changeInPennies - DENOMINATIONS[j][1])) {
// subtract a unit of denomination from the change due
changeInPennies -= DENOMINATIONS[j][1]
// subtract a unit of denominations from the cash in drawer (values)
cidValues -= DENOMINATIONS[j][1]
// add a unit of denomination to the placeholder
placeholder[1] += DENOMINATIONS[j][1]
}
if (placeholder[1] > 0) {
change.append(placeholder)
}
}
}

}

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

and the error I get is:

``````TypeError: Cannot read property '1' of undefined
``````

When I copy/paste the code into Visual Studio Code, the editor specifies that the TypeError occurs on this line, specifically the `cidValues[j][1]` part:

``````while ((cidValues[j][1] > 0) && (changeInPennies - DENOMINATIONS[j][1])) {
``````

However, the `console.log(cidValues[j][1])` on the line immediately above it works fine. As it stands in the FCC editor, the code currently prints out the following:

``````0
0
0
0
0
0
0
0
1
TypeError: Cannot read property '1' of undefined
``````

I don’t necessarily need help solving this challenge (yet). I just have no clue why I’m getting this TypeError. Any help would be greatly appreciated.

I suspect that something weird is happening by trying to modify `cidValues` here.

``````        cidValues -= DENOMINATIONS[j][1]
``````
1 Like

That was it!! Wow, and you were quick. Thank you so, so much. I was looking for the error in the wrong place. I changed the line in question to:

``````cidValues[j][1] -= DENOMINATIONS[j][1]
``````

and the error disappeared. Now to fix the other errors, haha. Thanks again.

This probably doesn’t do what you think it does.

Hmm… my intention in that line is to store the value of `cid` into a new variable that I can take actions on without mutating `cid`. Doing `console.log(cid)` and `console.log(cidValues)` produces the same results. That said, I could be missing something.

That’s what I suspected. When you have an array or object, that won’t create a copy:

``````// Try to copy an array
const myArr = [1, 2, 3];
const myOtherArr = myArr;
console.log("Before:");
console.log(myArr);
console.log(myOtherArr);

// Change 'copy'
myOtherArr[0] = 42;
console.log("\nAfter:");
console.log(myArr);
console.log(myOtherArr);
``````

Ah, I see that now. Thank you for catching that. It looks like one way to prevent that problem is to do something like:

``````let cidValues = [...cid]
``````
1 Like

But, you have an array of arrays. Each array inside of your array has the same problem.

1 Like

Good catch again, thank you. Hmm… I suppose I could apply the same solution above to the nested array as well, but I might also try mutating the original `cid` value to do away with that issue entirely. Something like this:

``````const cid = [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]];
for (let i = 0; i < cid.length; i++) {
cid[i] = [cid[i][0], Math.round(cid[i][1] * 100)]
}
console.log(cid)
``````

which prints out:

``````[
[ 'PENNY', 101 ],
[ 'NICKEL', 205 ],
[ 'DIME', 310 ],
[ 'QUARTER', 425 ],
[ 'ONE', 9000 ],
[ 'FIVE', 5500 ],
[ 'TEN', 2000 ],
[ 'TWENTY', 6000 ],
[ 'ONE HUNDRED', 10000 ]
]
``````

Not sure if it’s best practice, but I’ll try tinkering with it that way, since the only purpose of `cidValues` is to have the penny values of each denomination in `cid`.

I wouldn’t mutate the input, personally. With some small changes, the loop to modify `cid` can also just make a copy of it.

Thanks for the insight – I’m sure it could be cleaner (I’m already spotting places where it could be cleaned up), but I got all the tests passing (!!) with this:

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

// this will NOT change
const DENOMINATIONS = [
["PENNY", 1],
["NICKEL", 5],
["DIME", 10],
["QUARTER", 25],
["ONE", 100],
["FIVE", 500],
["TEN", 1000],
["TWENTY", 2000],
["ONE HUNDRED", 10000],
]

let priceInPennies = price * 100;
let cashInPennies = cash * 100;
let changeInPennies = Math.floor(cashInPennies - priceInPennies);

// thanks to https://www.freecodecamp.org/news/how-to-clone-an-array-in-javascript-1d3183468f6a/
let cidValueInPennies = JSON.parse(JSON.stringify(cid))

// This sets the cash in drawer amounts equal to values in pennies
for (let i = 0; i < cid.length; i++) {
cidValueInPennies[i][1] = Math.round(cid[i][1] * 100)
}

let cidSum = 0
for (let h = 0; h < cidValueInPennies.length; h++) {
cidSum += cidValueInPennies[h][1]
}

if (cidSum == changeInPennies) {
return {
status: "CLOSED",
change: cid
}
}

let change = []
while (changeInPennies > 0) {
for (let j = cidValueInPennies.length - 1; j >= 0; j--) {
let placeholder = [cidValueInPennies[j][0], 0]
// "while there is change in the drawer at the given currency and while a unit of the denomination can be subtracted from the change due..."
while ((cidValueInPennies[j][1] > 0) && ((changeInPennies - DENOMINATIONS[j][1]) >= 0)) {
// subtract a unit of denomination from the change due
changeInPennies -= DENOMINATIONS[j][1]
// subtract a unit of denominations from the cash in drawer (values)
cidValueInPennies[j][1] -= DENOMINATIONS[j][1]
// add a unit of denomination to the placeholder
placeholder[1] += DENOMINATIONS[j][1]
}
if (placeholder[1] > 0) {
change.push(placeholder)
}
}
// Cannot return exact change, or not enough cash in drawer
if (changeInPennies > 0) {
return {
status: "INSUFFICIENT_FUNDS",
change: []
}
}
}
// This returns the values in pennies back to the original amounts
let finalChange = JSON.parse(JSON.stringify(change))
for (let m = 0; m < finalChange.length; m++) {
finalChange[m][1] = (finalChange[m][1] / 100)
}
return({
status: "OPEN",
change: finalChange
})
}
``````

Whew, learned a lot through this problem, that’s for sure.

1 Like

Nice work getting it running!

You can combine these two actually:

``````  // Copy drawer to cents
let drawer = cid
.map(denom => [denom[0], Math.round(denom[1] * 100)]);
``````

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