feat: use coin-change alongside subset-sum impl
This commit is contained in:
parent
2cb52a925d
commit
5de4e21b2e
2 changed files with 133 additions and 3 deletions
|
|
@ -1,6 +1,9 @@
|
|||
const _ = require('lodash/fp')
|
||||
const sumService = require('@haensl/subset-sum')
|
||||
|
||||
const logger = require('./logger')
|
||||
const cc = require('./coin-change')
|
||||
|
||||
const BILL_LIST_MODES = {
|
||||
LAST_UNIT_FIRST: 0,
|
||||
FIRST_UNIT_FIRST: 1,
|
||||
|
|
@ -103,7 +106,7 @@ const buildBillList = (units, mode) => {
|
|||
}
|
||||
}
|
||||
|
||||
const getSolution = (units, amount, mode) => {
|
||||
const getSolution_old = (units, amount, mode) => {
|
||||
const billList = buildBillList(units, mode)
|
||||
|
||||
if (_.sum(billList) < amount.toNumber()) {
|
||||
|
|
@ -122,6 +125,13 @@ const getSolution = (units, amount, mode) => {
|
|||
)
|
||||
}
|
||||
|
||||
const getSolution = (units, amount) => {
|
||||
amount = amount.toNumber()
|
||||
units = units.map(({ denomination, count }) => [denomination, count])
|
||||
const model = cc.model(units)
|
||||
return cc.solve(model, amount)
|
||||
}
|
||||
|
||||
const solutionToOriginalUnits = (solution, units) => {
|
||||
const billsToAssign = (count, left) => _.clamp(0, count)(_.isNaN(left) || _.isNil(left) ? 0 : left)
|
||||
|
||||
|
|
@ -141,8 +151,20 @@ const solutionToOriginalUnits = (solution, units) => {
|
|||
}
|
||||
|
||||
function makeChange(outCassettes, amount) {
|
||||
const solution = getSolution(outCassettes, amount, BILL_LIST_MODES.VALUE_ROUND_ROBIN)
|
||||
return solutionToOriginalUnits(solution, outCassettes)
|
||||
const ss_solution = getSolution_old(outCassettes, amount, BILL_LIST_MODES.VALUE_ROUND_ROBIN)
|
||||
const cc_solution = cc.solve(cc.model(outCassettes), amount.toNumber())
|
||||
|
||||
if (!!ss_solution === !!cc_solution) {
|
||||
logger.error(new Error(`subset-sum and coin-change don't agree on solvability -- subset-sum:${!!ss_solution} coin-change:${!!cc_solution}`))
|
||||
return solutionToOriginalUnits(ss_solution, outCassettes)
|
||||
}
|
||||
|
||||
if (!cc.check(cc_solution, amount.toNumber())) {
|
||||
logger.error(new Error("coin-change provided a bad solution"))
|
||||
return solutionToOriginalUnits(ss_solution, outCassettes)
|
||||
}
|
||||
|
||||
return solutionToOriginalUnits(cc_solution, outCassettes)
|
||||
}
|
||||
|
||||
module.exports = { makeChange }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue