1

the program works fine, except that the "change" array has many duplicates, summing the duplicates is supposed to be easy, except it gives wrong sums! ex: summing 3 twenties should give 60, instead it gives 80! i noticed that the error only happens with the odd duplicates! another thing that i cant figure out is why the "change" array is changing when i sum the duplicates? i copied the change array to a different array so if anything happens to the 2nd array it shouldnt affect "change" array!

the program works well until i get to the part where i need to sum the duplicates (sumDuplicates() function works fine on its own, but not with my code)

function checkCashRegister(price, cash, cid) {
  var change = [];
  let difference = cash - price;
  let level = 0;
  let currency = [
    ["PENNY", 0.01],
    ["NICKEL", 0.05],
    ["DIME", 0.1],
    ["QUARTER", 0.25],
    ["ONE", 1],
    ["FIVE", 5],
    ["TEN", 10],
    ["TWENTY", 20],
    ["ONE HUNDRED", 100]
  ]
  //sum all money in register
  let totalFunds = cid.reduce((r, [key, value]) => {
    return r + value
  }, 0)

  //function to match the difference to appropriate currency
  function findLevel(dif) {
    for (let i = currency.length - 1; i >= 0; i--) {
      //our change must be the highest availabe currency
      if (dif >= currency[i][1] && cid[i][1] != 0) {
        //console.log(currency[i])
        return i
      }
    }
  }
  //function to subtract
  function subtractor(dif, lvl) {
    if (cid[lvl][1] != 0) {
      dif = dif.toFixed(2)
      dif = dif - currency[lvl][1]
      cid[lvl][1] -= currency[lvl][1]
      change.push(currency[lvl])
      return dif
    }
  }
  //if no change needed
  if (difference == 0) {
    return {
      status: "CLOSED",
      change: []
    }
  }
  //if we dont have enough money to pay back
  if (totalFunds < difference) {
    return {
      status: "INSUFFICIENT_FUNDS",
      change: []
    }
  }
  //if we need to pay change AND we have enough money
  if (difference > 0 && totalFunds >= difference) {
    while (difference >= 0.01) {
      level = findLevel(difference)
      difference = subtractor(difference, level)
      //console.log(difference)
    }
  }

  //to sum duplicate elements in the "change" array, this is the problem!!!
  function sumDuplicates(arr1) {
    let arr = [...arr1]
    let sums = arr.reduce((sums, item) => {
      let found = sums.find(([key]) => key === item[0]);
      //console.log(found)
      if (found)
        found[1] += item[1];
      else
        sums.push(item);
      // console.log(item)
      return sums;
    }, []);
    return sums;
  }
  let sums = sumDuplicates(change)
  console.log(sums);
  return {
    status: "OPEN",
    change: sums
  };
}

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]
]);

I expect [[twenties,60]] instead I get [[twenties,80]]

2
  • @Bosco The code was already indented using the snippet editor's Tidy function. Why did you need to remove the snippet to fix the indentation? Commented Jun 28, 2019 at 21:36
  • The edit happened simultaneously. needs to roll back or repeat Commented Jun 28, 2019 at 21:38

1 Answer 1

3

You need to be careful with pushing references into arrays, because they don't make copies. You do it in an couple places and in your sum function you end up modifying the original array which changes the values in your lookup table.

if (found)
     found[1] += item[1]; // <-- now modifying your original currency lookup!
else
     sums.push(item);     // <-- your pushing a ref to your original currency lookup!

A quick fix is to push a copy instead in your sum function:

 sums.push([...item])

A (probably better alternative) is to push a copy into the change array:

function subtractor(dif, lvl) {
  if (cid[lvl][1] != 0) {
      dif = dif.toFixed(2)
      dif = dif - currency[lvl][1]
      cid[lvl][1] -= currency[lvl][1]
      change.push([...currency[lvl]]) // < push a copy not the original ref
      return dif
   }
 }

function checkCashRegister(price, cash, cid) {
  var change = [];
  let difference = cash - price;
  let level = 0;
  let currency = [
    ["PENNY", 0.01],
    ["NICKEL", 0.05],
    ["DIME", 0.1],
    ["QUARTER", 0.25],
    ["ONE", 1],
    ["FIVE", 5],
    ["TEN", 10],
    ["TWENTY", 20],
    ["ONE HUNDRED", 100]
  ]
  //sum all money in register
  let totalFunds = cid.reduce((r, [key, value]) => {
    return r + value
  }, 0)

  //function to match the difference to appropriate currency
  function findLevel(dif) {
    for (let i = currency.length - 1; i >= 0; i--) {
      //our change must be the highest availabe currency
      if (dif >= currency[i][1] && cid[i][1] != 0) {
        //console.log(currency[i])
        return i
      }
    }
  }
  //function to subtract
  function subtractor(dif, lvl) {
    if (cid[lvl][1] != 0) {
      dif = dif.toFixed(2)
      dif = dif - currency[lvl][1]
      cid[lvl][1] -= currency[lvl][1]
      change.push([...currency[lvl]])  //< -- PUSH A COPY!
      return dif
    }
  }
  //if no change needed
  if (difference == 0) {
    return {
      status: "CLOSED",
      change: []
    }
  }
  //if we dont have enough money to pay back
  if (totalFunds < difference) {
    return {
      status: "INSUFFICIENT_FUNDS",
      change: []
    }
  }
  //if we need to pay change AND we have enough money
  if (difference > 0 && totalFunds >= difference) {
    while (difference >= 0.01) {
      level = findLevel(difference)
      difference = subtractor(difference, level)
      //console.log(difference)
    }
  }

  //to sum duplicate elements in the "change" array, this is the problem!!!
  function sumDuplicates(arr1) {
    let arr = [...arr1]
    let sums = arr.reduce((sums, item) => {
      let found = sums.find(([key]) => key === item[0]);
      //console.log(found)
      if (found)
        found[1] += item[1];
      else
        sums.push(item);  
      // console.log(item)
      return sums;
    }, []);
    return sums;
  }
  let sums = sumDuplicates(change)
  console.log(sums);
  return {
    status: "OPEN",
    change: sums
  };
}

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.