46 lines
1.4 KiB
JavaScript
46 lines
1.4 KiB
JavaScript
const _ = require('lodash/fp')
|
|
const sumService = require('@haensl/subset-sum')
|
|
|
|
const getSolution = (units, amount) => {
|
|
const billList = _.reduce(
|
|
(acc, value) => {
|
|
acc.push(..._.times(_.constant(value.denomination), value.count))
|
|
return acc
|
|
},
|
|
[],
|
|
units
|
|
)
|
|
|
|
const solver = sumService.subsetSum(billList, amount.toNumber())
|
|
const solution = _.countBy(Math.floor, solver.next().value)
|
|
return _.reduce(
|
|
(acc, value) => {
|
|
acc.push({ denomination: _.toNumber(value), provisioned: solution[value] })
|
|
return acc
|
|
},
|
|
[],
|
|
_.keys(solution)
|
|
)
|
|
}
|
|
|
|
const solutionToOriginalUnits = (solution, units) => {
|
|
const billsLeft = _.clone(_.fromPairs(_.map(it => [it.denomination, it.provisioned])(solution)))
|
|
return _.reduce(
|
|
(acc, value) => {
|
|
const unit = units[value]
|
|
const billsToAssign = _.clamp(0, unit.count)(_.isNaN(billsLeft[unit.denomination]) || _.isNil(billsLeft[unit.denomination]) ? 0 : billsLeft[unit.denomination])
|
|
acc.push({ name: unit.name, denomination: unit.denomination, provisioned: billsToAssign })
|
|
billsLeft[unit.denomination] -= billsToAssign
|
|
return acc
|
|
},
|
|
[],
|
|
_.range(0, _.size(units))
|
|
)
|
|
}
|
|
|
|
function makeChange(outCassettes, amount) {
|
|
const solution = getSolution(outCassettes, amount)
|
|
return solutionToOriginalUnits(solution, outCassettes)
|
|
}
|
|
|
|
module.exports = { makeChange }
|