feat: makeChange function supporting multiple cassettes

This commit is contained in:
Sérgio Salgado 2021-09-01 16:22:52 +01:00
parent 575235283a
commit 0a3b78f75e
3 changed files with 60 additions and 31 deletions

View file

@ -1,4 +1,5 @@
const uuid = require('uuid')
const _ = require('lodash')
// Custom algorith for two cassettes. For three or more denominations, we'll need
// to rethink this. Greedy algorithm fails to find *any* solution in some cases.
@ -10,28 +11,37 @@ exports.makeChange = function makeChange (cassettes, amount) {
// Note: Everything here is converted to primitive numbers,
// since they're all integers, well within JS number range,
// and this is way more efficient in a tight loop.
const small = cassettes[0]
const large = cassettes[1]
const largeDenom = large.denomination
const smallDenom = small.denomination
const largeBills = Math.min(large.count, Math.floor(amount / largeDenom))
const cassetteMap = _.map(cassettes, it => ({
denomination: it.denomination
}))
const amountNum = amount.toNumber()
for (let i = largeBills; i >= 0; i--) {
const remainder = amountNum - largeDenom * i
const sortedCassettes = _.orderBy(cassetteMap, ['denomination'], ['desc'])
if (remainder % smallDenom !== 0) continue
const finalDist = []
const smallCount = remainder / smallDenom
if (smallCount > small.count) continue
let mutableAmount = _.clone(amountNum)
return [
{provisioned: smallCount, denomination: small.denomination, id: uuid.v4()},
{provisioned: i, denomination: largeDenom, id: uuid.v4()}
]
while(mutableAmount >= 0) {
_.each(sortedCassettes, it => {
if (mutableAmount === 0) {
finalDist.push({provisioned: 0, denomination: it.denomination, id: uuid.v4()})
return
}
const remainder = mutableAmount % it.denomination
const amountToSub = mutableAmount - remainder
const numberOfBills = amountToSub / it.denomination
mutableAmount -= amountToSub
finalDist.push({provisioned: numberOfBills, denomination: it.denomination, id: uuid.v4()})
return
})
if (mutableAmount === 0) {
break
}
}
return null
return finalDist
}