feat: makeChange function supporting multiple cassettes
This commit is contained in:
parent
575235283a
commit
0a3b78f75e
3 changed files with 60 additions and 31 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue