Build a Cash Register Project - Build a Cash Register

I’ve been struggling with this problem for four days now, rewriting my code numerous times, but I keep running into issues with two specific test cases:18 and 19.

Your code so far

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cash Register</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="container">
        <h1>Cash Register</h1>
        <label for="price">Price:</label>
        <input type="number" id="price" value="19.5" disabled>
        
        <label for="cash">Cash Provided:</label>
        <input type="number" id="cash">

        <button id="purchase-btn">Purchase</button>
        
        <p id="change-due"></p>
    </div>

    <script src="script.js"></script>
</body>
</html>
let price = 0; // Global variable for price
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]
];

document.getElementById("purchase-btn").addEventListener("click", () => {
  const cashInput = parseFloat(document.getElementById("cash").value);
  const changeDiv = document.getElementById("change-due");

  if (isNaN(price) || isNaN(cashInput)) {
    alert("Please enter valid numbers for price and cash.");
    return;
  }

  if (cashInput < price) {
    alert("Customer does not have enough money to purchase the item");
    return;
  }

  if (cashInput === price) {
    changeDiv.textContent = "No change due - customer paid with exact cash";
    return;
  }

  const result = calculateChange(price, cashInput, cid);

  if (result.status === "INSUFFICIENT_FUNDS") {
    changeDiv.textContent = `Status: ${result.status}`;
  } else if (result.status === "CLOSED") {
    changeDiv.textContent = `Status: ${result.status} ${formatChange(result.change)}`;
  } else if (result.status === "OPEN") {
    changeDiv.textContent = `Status: ${result.status} ${formatChange(result.change)}`;
  }
});

function calculateChange(price, cash, cid) {
  let changeDue = cash - price;
  const changeArray = [];
  const currencyUnit = {
    "PENNY": 0.01,
    "NICKEL": 0.05,
    "DIME": 0.1,
    "QUARTER": 0.25,
    "ONE": 1,
    "FIVE": 5,
    "TEN": 10,
    "TWENTY": 20,
    "ONE HUNDRED": 100
  };

  // Calculate total cash in drawer
  let totalCid = cid.reduce((sum, [unit, amount]) => sum + amount, 0).toFixed(2);

  // Return CLOSED if totalCid equals changeDue
  if (parseFloat(totalCid) === changeDue) {
    return { status: "CLOSED", change: [...cid] };
  }

  // Return INSUFFICIENT_FUNDS if totalCid is less than changeDue
  if (parseFloat(totalCid) < changeDue) {
    return { status: "INSUFFICIENT_FUNDS", change: [] };
  }

  const reversedCid = [...cid].reverse();

  for (let [unit, amount] of reversedCid) {
    let value = 0;
    while (changeDue >= currencyUnit[unit] && amount > 0) {
      changeDue -= currencyUnit[unit];
      amount -= currencyUnit[unit];
      changeDue = Math.round(changeDue * 100) / 100; // Avoid floating-point errors
      value += currencyUnit[unit];
    }
    if (value > 0) {
      changeArray.push([unit, value]);
    }
  }

  // If unable to provide exact change, return INSUFFICIENT_FUNDS
  if (changeDue > 0) {
    return { status: "INSUFFICIENT_FUNDS", change: [] };
  }

  // Handle CLOSED status by summing up remaining cash
  const remainingTotal = reversedCid.reduce((sum, [unit, amount]) => sum + amount, 0).toFixed(2);
  if (parseFloat(remainingTotal) === 0) {
    return { status: "CLOSED", change: [...cid] };
  }

  return { status: "OPEN", change: changeArray };
}

// Function to format the change array into readable output
function formatChange(change) {
  return change.map(([unit, amount]) => `${unit}: $${amount.toFixed(2)}`).join(", ");
}
body {
    font-family: Arial, sans-serif;
    background-color: #f4f4f4;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
}

.container {
    background-color: white;
    padding: 20px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    border-radius: 5px;
}

h1 {
    margin-bottom: 20px;
}

label {
    display: block;
    margin-bottom: 5px;
}

input {
    width: 100%;
    padding: 10px;
    margin-bottom: 20px;
    border: 1px solid #ddd;
    border-radius: 5px;
}

button {
    width: 100%;
    padding: 10px;
    border: none;
    background-color: #5cb85c;
    color: white;
    border-radius: 5px;
    cursor: pointer;
}

button:hover {
    background-color: #4cae4c;
}

#change-due {
    margin-top: 20px;
}

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36

Challenge Information:

Build a Cash Register Project - Build a Cash Register

Welcome to the forum @hamdibenjarrar

The cid array should not be in the global scope.
It will reset each time the tests run.

Happy coding

it must be in the global scope instead, otherwise the tests can’t change it.
There is a different issue somewhere else

Your code is outputting Status: CLOSED PENNY: $0.50, NICKEL: $0.00, DIME: $0.00, QUARTER: $0.00, ONE: $0.00, FIVE: $0.00, TEN: $0.00, TWENTY: $0.00, ONE HUNDRED: $0.00
Why all those values with 0.00 in there?

2 Likes

Thank you so much for pointing that out! You were absolutely right—the issue was that all denominations, including those with a value of $0.00 , were being included in the output unnecessarily. After filtering out the denominations with a value of $0.00 before formatting the change, the output is now clean and accurate