Skip to content

Commit 42ff4a8

Browse files
✨ feat(integerValuesKnapsackUnbounded): First draft.
1 parent 21699cb commit 42ff4a8

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

src/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
import integerValuesKnapsack from './integerValuesKnapsack';
2+
import integerValuesKnapsackUnbounded from './integerValuesKnapsackUnbounded';
23
import integerWeightsKnapsack from './integerWeightsKnapsack';
34
import integerWeightsKnapsackUnbounded from './integerWeightsKnapsackUnbounded';
45
import knapsackApprox from './knapsackApprox';
56

67
/* eslint import/no-anonymous-default-export: [2, {"allowObject": true}] */
78
export default {
89
integerValuesKnapsack,
10+
integerValuesKnapsackUnbounded,
911
integerWeightsKnapsack,
1012
integerWeightsKnapsackUnbounded,
1113
knapsackApprox,
1214
};
1315

1416
export {
1517
integerValuesKnapsack,
18+
integerValuesKnapsackUnbounded,
1619
integerWeightsKnapsack,
1720
integerWeightsKnapsackUnbounded,
1821
knapsackApprox,

src/integerValuesKnapsackUnbounded.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import assert from 'assert';
2+
import {increasing} from '@aureooms/js-compare';
3+
import {max, map, range} from '@aureooms/js-itertools';
4+
5+
const integerValuesKnapsackUnbounded = (
6+
v,
7+
w,
8+
n,
9+
W,
10+
V = Math.floor(
11+
W *
12+
max(
13+
increasing,
14+
map((i) => v[i] / w[i], range(n)),
15+
),
16+
),
17+
m = new w.constructor(V + 1).fill(W + 1),
18+
) => {
19+
assert(v.length === n);
20+
assert(w.length === n);
21+
assert(Number.isInteger(V) && V >= 0);
22+
assert(m.length >= V + 1);
23+
m[0] = 0;
24+
for (let j = 1; j <= V; ++j) {
25+
let temporary = m[j];
26+
for (let i = 0; i < n; ++i) {
27+
const wi = w[i];
28+
const vi = v[i];
29+
assert(Number.isInteger(vi) && vi >= 0);
30+
const k = j - vi;
31+
// TODO sort by value to avoid branching
32+
// from larger to smaller so that m is scanned
33+
// from left to right
34+
if (k >= 0) temporary = Math.min(temporary, m[k] + wi);
35+
}
36+
37+
m[j] = temporary;
38+
}
39+
40+
for (let j = V; j > 0; --j) {
41+
if (m[j] <= W) return j;
42+
}
43+
44+
return 0;
45+
};
46+
47+
export default integerValuesKnapsackUnbounded;

test/src/unbounded-knapsack-problem.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import test from 'ava';
22

33
import {all, map} from '@aureooms/js-itertools';
44

5-
import {integerWeightsKnapsackUnbounded} from '../../src';
5+
import {
6+
integerValuesKnapsackUnbounded,
7+
integerWeightsKnapsackUnbounded,
8+
} from '../../src';
69

710
const macro = (t, solve, _name, v, w, n, W, opt, approx) => {
811
t.is(n, v.length);
@@ -27,6 +30,10 @@ macro.title = (title, solve, name, v, w, n, W, opt, approx) =>
2730
)}, ${n}, ${W}) >= ${approx} * ${opt}`;
2831

2932
const solvers = [
33+
{
34+
solve: integerValuesKnapsackUnbounded,
35+
hypothesis: (v) => all(map((x) => Number.isInteger(x), v)),
36+
},
3037
{
3138
solve: integerWeightsKnapsackUnbounded,
3239
hypothesis: (_, w) => all(map((x) => Number.isInteger(x), w)),

0 commit comments

Comments
 (0)