Merge pull request #1783 from siiky/fix/lam-1296/coin-change

LAM-1296 fix: `coin-change`
This commit is contained in:
Rafael Taranto 2025-02-04 09:11:57 +00:00 committed by GitHub
commit 5dcbf7a60a
2 changed files with 10 additions and 32 deletions

View file

@ -116,14 +116,8 @@ const getSolution_old = (units, amount, mode) => {
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)
)
return Object.entries(solution)
.map(([denomination, provisioned]) => [_.toNumber(denomination), provisioned])
}
const getSolution = (units, amount) => {
@ -135,24 +129,13 @@ const getSolution = (units, amount) => {
const solutionToOriginalUnits = (solution, units) => {
const billsToAssign = (count, left) => _.clamp(0, count)(_.isNaN(left) || _.isNil(left) ? 0 : left)
const billsLeft = _.flow(
_.map(([denomination, provisioned]) => [BN(denomination), provisioned]),
_.reduce((acc, value) => {
acc[value[0]] = (acc[value[0]] || BN(0)).plus(value[1])
return acc
},
{}
)
)(solution)
return _.map(
const billsLeft = Object.fromEntries(solution)
return units.map(
({ count, name, denomination }) => {
const provisioned = billsToAssign(count, billsLeft[denomination])
billsLeft[denomination] -= provisioned
return { name, denomination, provisioned }
},
units
}
)
}
@ -160,13 +143,13 @@ function makeChange(outCassettes, amount) {
const ss_solution = getSolution_old(outCassettes, amount, BILL_LIST_MODES.VALUE_ROUND_ROBIN)
const cc_solution = getSolution(outCassettes, amount)
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}`))
if (!cc.check(cc_solution, amount.toNumber())) {
logger.error(new Error("coin-change provided a bad solution"))
return solutionToOriginalUnits(ss_solution, outCassettes)
}
if (!cc.check(cc_solution, amount.toNumber())) {
logger.error(new Error("coin-change provided a bad solution"))
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)
}

View file

@ -24,11 +24,6 @@ const prepare_denominations = denominations =>
const max_denomination_multiplicity = (denom, count, target) =>
Math.min(count, Math.floor(target / denom))
const has_divisor = (didx, denominations, target) =>
denominations
.slice(didx)
.some(({ denom }) => (target % denom) === 0)
/*
* @returns null if there's no solution set;
* false if there's no solution;
@ -78,7 +73,7 @@ const solve = (model, target) => {
* of the denominations, or if the target is not divisible by any of the
* denominations
*/
if (target > csum || !has_divisor(didx, denominations, target))
if (target > csum)
return memo_set(memo, target, denom, false)
let solution = memo_get(memo, target, denom)