Hello there!
I would like to post here my solution to the cash register algorithm hoping for someone to give me some feedback.
This time I have placed a lot of verbose and kept a bunch o console logs for whoever wants to see how the function builds upon every call.
I left comments as well in the code.
Thanks in advance =)
function checkCashRegister(price, cash, cid) {
const currencyRef = [
["PENNY", 0.01],
["NICKEL", 0.05],
["DIME", 0.1],
["QUARTER", 0.25],
["ONE", 1],
["FIVE", 5],
["TEN", 10],
["TWENTY", 20],
["ONE HUNDRED", 100]
];
//create an object to manage the register
const managedStock = currencyRef.map(val => ({
id: val[0],
unitaryValue: val[1],
stockValue: cid.find(stockItem => stockItem[0] === val[0])[1] / val[1],
changeApplied: 0
}));
const change = (cash - price)
const bankNoteFinder = (change, array, cidStatus) => {
let fixedChange;
//small hack to ensure that we will not get floating initial numbers
if (change.toString().match(/[0-9]{3,}/g)) {
fixedChange = change.toFixed(2);
console.log("fixed change", fixedChange);
} else { fixedChange = change; }
//if the change is not 0 exec logic
if (fixedChange !== 0) {
console.log("change", fixedChange);
//check for the closest bank note / coin
const closestBankNote = array.reduce((a, b) => {
return {
unitaryValue:
b.unitaryValue > fixedChange ? a.unitaryValue : b.unitaryValue
};
});
console.log("result of bank note finder", closestBankNote);
//do we have funds for the closest bank note / coin?
const closestBankNoteHasFunds =
array.find(
stock => stock.unitaryValue === closestBankNote.unitaryValue
).stockValue > 0;
console.log("check if we have funds", closestBankNoteHasFunds);
//in case we do not have funds for the given bank note / coin
if (!closestBankNoteHasFunds) {
//let´s slice the array of notes for the next recursion, excluding the note we tried to use
const indexOfClosestBankNote = array.indexOf(
array.find(v => v.unitaryValue === closestBankNote.unitaryValue)
);
//slice and call the recursion while the index is higher then 0
if (indexOfClosestBankNote - 1 >= 0) {
const slicedArrayForRecursion = array.slice(
0,
indexOfClosestBankNote
);
return bankNoteFinder(
fixedChange,
slicedArrayForRecursion,
cidStatus
);
//stop slicing once we get to Index 0 and still have change to give
} else {
cidStatus = { status: "INSUFFICIENT_FUNDS", change: [] };
}
}
//if we have funds for the given bank note
if (closestBankNoteHasFunds) {
//how many notes do we need?
const numberOfNotesNeeded = Math.trunc(
fixedChange / closestBankNote.unitaryValue
);
console.log("number of notes needed", numberOfNotesNeeded);
//how many notes can we use?
const howManyNotesAvailable = array.find(
note => note.unitaryValue === closestBankNote.unitaryValue
).stockValue;
//Oh, this is the amount of notes that will be used
const amountOfNotesThatWillBeUsed =
numberOfNotesNeeded > howManyNotesAvailable
? howManyNotesAvailable
: numberOfNotesNeeded;
console.log("amount of notes that will be used",amountOfNotesThatWillBeUsed);
// get the desired note info and total deduction to prepare array of change
const getNeededNote = array.find(
note => note.unitaryValue === closestBankNote.unitaryValue
);
const totalDedution = amountOfNotesThatWillBeUsed * getNeededNote.unitaryValue;
//start building the array of the change
cidStatus.push([getNeededNote.id, totalDedution]);
const noteToBeMutatedInstance = array.indexOf(
array.find(note => note.id === getNeededNote.id)
);
//deduce the amount of available bank notes / coins and it´s total deduction
//from the total in the management control
array[noteToBeMutatedInstance].stockValue = howManyNotesAvailable - amountOfNotesThatWillBeUsed;
array[noteToBeMutatedInstance].changeApplied = totalDedution;
return bankNoteFinder(fixedChange - totalDedution, array, cidStatus);
}
}
//managed to give out all of the needed change
if (fixedChange === 0) {
console.log("change is ZERO!");
console.log("we've used all of our money?", managedStock.every(note => note.stockValue === 0));
//in case there is no money left in the register
if (managedStock.every(note => note.stockValue === 0)) {
cidStatus = {
status: "CLOSED",
change: [...managedStock.map(note => [note.id, note.changeApplied])]
};
}
//in case there is still some money left
if (managedStock.some(note => note.stockValue > 0)) {
cidStatus = { status: "OPEN", change: [...cidStatus] };
}
}
return cidStatus;
};
return bankNoteFinder(change, managedStock, [], {});
}
console.log( checkCashRegister(19.5, 20, [
["PENNY", 0.5],
["NICKEL", 0],
["DIME", 0],
["QUARTER", 0],
["ONE", 0],
["FIVE", 0],
["TEN", 0],
["TWENTY", 0],
["ONE HUNDRED", 0]
])
);