From 3151d0e7c9116403b77f4bf546b0112679f1171d Mon Sep 17 00:00:00 2001 From: Rafael Taranto Date: Tue, 16 Dec 2025 16:11:51 +0000 Subject: [PATCH] fix: drop deprecated coin change lib --- packages/server/lib/bill-math.js | 137 +---------------------------- packages/server/lib/coin-change.js | 2 +- packages/server/package.json | 1 - pnpm-lock.yaml | 11 --- 4 files changed, 2 insertions(+), 149 deletions(-) diff --git a/packages/server/lib/bill-math.js b/packages/server/lib/bill-math.js index ff02051..4dc5dac 100644 --- a/packages/server/lib/bill-math.js +++ b/packages/server/lib/bill-math.js @@ -1,127 +1,7 @@ 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, - LOWEST_VALUE_FIRST: 2, - HIGHEST_VALUE_FIRST: 3, - UNIT_ROUND_ROBIN: 4, - VALUE_ROUND_ROBIN: 5, -} - -const buildBillList = (units, mode) => { - switch (mode) { - case BILL_LIST_MODES.LAST_UNIT_FIRST: - return _.reduce( - (acc, value) => { - acc.push(..._.times(_.constant(value.denomination), value.count)) - return acc - }, - [], - _.reverse(units), - ) - case BILL_LIST_MODES.FIRST_UNIT_FIRST: - return _.reduce( - (acc, value) => { - acc.push(..._.times(_.constant(value.denomination), value.count)) - return acc - }, - [], - units, - ) - case BILL_LIST_MODES.LOWEST_VALUE_FIRST: - return _.reduce( - (acc, value) => { - acc.push(..._.times(_.constant(value.denomination), value.count)) - return acc - }, - [], - _.orderBy(['denomination'], ['asc'])(units), - ) - case BILL_LIST_MODES.HIGHEST_VALUE_FIRST: - return _.reduce( - (acc, value) => { - acc.push(..._.times(_.constant(value.denomination), value.count)) - return acc - }, - [], - _.orderBy(['denomination'], ['desc'])(units), - ) - case BILL_LIST_MODES.UNIT_ROUND_ROBIN: { - const amountOfBills = _.reduce( - (acc, value) => acc + value.count, - 0, - units, - ) - - const _units = _.filter(it => it.count > 0)(_.cloneDeep(units)) - const bills = [] - - for (let i = 0; i < amountOfBills; i++) { - const idx = i % _.size(_units) - if (_units[idx].count > 0) { - bills.push(_units[idx].denomination) - _units[idx].count-- - } - - if (_units[idx].count === 0) { - _units.splice(idx, 1) - } - } - - return bills - } - case BILL_LIST_MODES.VALUE_ROUND_ROBIN: { - const amountOfBills = _.reduce( - (acc, value) => acc + value.count, - 0, - units, - ) - - const _units = _.flow([ - _.filter(it => it.count > 0), - _.orderBy(['denomination'], ['asc']), - ])(_.cloneDeep(units)) - const bills = [] - - for (let i = 0; i < amountOfBills; i++) { - const idx = i % _.size(_units) - if (_units[idx].count > 0) { - bills.push(_units[idx].denomination) - _units[idx].count-- - } - - if (_units[idx].count === 0) { - _units.splice(idx, 1) - } - } - - return bills - } - default: - throw new Error(`Invalid mode: ${mode}`) - } -} - -const getSolution_old = (units, amount, mode) => { - const billList = buildBillList(units, mode) - - if (_.sum(billList) < amount.toNumber()) { - return [] - } - - const solver = sumService.subsetSum(billList, amount.toNumber()) - const solution = _.countBy(Math.floor, solver.next().value) - return Object.entries(solution).map(([denomination, provisioned]) => [ - _.toNumber(denomination), - provisioned, - ]) -} - const getSolution = (units, amount) => { amount = amount.toNumber() units = Object.entries( @@ -147,25 +27,10 @@ const solutionToOriginalUnits = (solution, units) => { } function makeChange(outCassettes, amount) { - const ss_solution = getSolution_old( - outCassettes, - amount, - BILL_LIST_MODES.VALUE_ROUND_ROBIN, - ) const cc_solution = getSolution(outCassettes, amount) if (!cc.check(cc_solution, amount.toNumber())) { - logger.error(new Error('coin-change provided a bad solution')) - return solutionToOriginalUnits(ss_solution, outCassettes) - } - - 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) + throw new Error('coin-change provided a bad solution') } return solutionToOriginalUnits(cc_solution, outCassettes) diff --git a/packages/server/lib/coin-change.js b/packages/server/lib/coin-change.js index d90b46c..5b13a89 100644 --- a/packages/server/lib/coin-change.js +++ b/packages/server/lib/coin-change.js @@ -41,7 +41,7 @@ const memo_set = (memo, target, denom, solution) => { } const check = (solution, target) => - !solution || + solution && target === solution.reduce((sum, [denom, provisioned]) => sum + denom * provisioned, 0) diff --git a/packages/server/package.json b/packages/server/package.json index 53bd724..01a659f 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -18,7 +18,6 @@ "@graphql-tools/merge": "^9.0.22", "@graphql-tools/schema": "^10.0.21", "@graphql-tools/utils": "^10.8.4", - "@haensl/subset-sum": "^3.0.5", "@lamassu/coins": "v1.6.1", "@simplewebauthn/server": "^3.0.0", "@vonage/auth": "1.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c29663c..a1398f9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -240,9 +240,6 @@ importers: '@graphql-tools/utils': specifier: ^10.8.4 version: 10.8.6(graphql@16.11.0) - '@haensl/subset-sum': - specifier: ^3.0.5 - version: 3.0.7 '@lamassu/coins': specifier: v1.6.1 version: 1.6.1 @@ -1261,10 +1258,6 @@ packages: peerDependencies: graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@haensl/subset-sum@3.0.7': - resolution: {integrity: sha512-67zH9BEaRPXrPeQviZpKuFOavcgx6PMK3BnvTgwhsTUePhf1PncysxLNA6G100fekvxbNrV3cGPVi8qj8DOTmQ==} - engines: {node: '>=10.12.0'} - '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -8456,10 +8449,6 @@ snapshots: dependencies: graphql: 16.11.0 - '@haensl/subset-sum@3.0.7': - dependencies: - '@babel/runtime': 7.27.1 - '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6':