-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
115 lines (95 loc) · 3.59 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
type Item = {
weight: number;
cost: number;
name: string;
}
type Decision = {
items: Item[];
total_cost: number;
}
const getTotalCost = (items:Item[]) => items.reduce((acc, cur) => acc + cur.cost, 0);
const createKnapsackTable = (items_count: number, capacity: number):Item[][][] => new Array(items_count)
.fill(null)
.map(() => new Array(capacity)
.fill(null)
.map(() => ([])));
const EMPTY_RESULT:Decision = { items: [], total_cost: 0 };
function resolveKnapsack(items:Item[], capacity:number):Decision {
if (!items.length || capacity < 1) {
return EMPTY_RESULT;
}
const getLastMax = (i: number, j: number):Item[] | null => {
if (i === 0) {
// can not get last max result for the first item
return null;
}
return knapsack_table[i - 1][j];
}
const getCurrentResult = (i: number, j: number, current_item: Item, current_knapsack_size: number):Item[] => {
const diff = current_knapsack_size - current_item.weight;
if (!diff) {
return [current_item];
}
return [current_item, ...knapsack_table[i - 1][diff - 1]];
}
const knapsack_table = createKnapsackTable(items.length, capacity);
for (let i = 0; i < items.length; i++) {
for (let j = 0; j < capacity; j++) {
const current_item = items[i];
const current_knapsack_size = j + 1;
const last_max = getLastMax(i, j);
if (current_item.weight > current_knapsack_size) {
if (last_max) {
knapsack_table[i][j].push(...knapsack_table[i - 1][j])
}
continue;
}
if (current_item.weight <= current_knapsack_size) {
if (!last_max) {
knapsack_table[i][j].push(current_item);
continue;
}
const last_max_total_cost = getTotalCost(last_max);
const current_result = getCurrentResult(i, j, current_item, current_knapsack_size);
const current_result_total_cost = getTotalCost(current_result);
if (last_max_total_cost > current_result_total_cost) {
knapsack_table[i][j].push(...last_max);
} else {
knapsack_table[i][j].push(...current_result);
}
}
}
}
const result = knapsack_table[items.length - 1][ capacity - 1 ];
return {
items: result,
total_cost: getTotalCost(result),
}
}
const test1: Item[] = [
{ weight: 1, cost: 1500, name: 'мини-гитара' },
{ weight: 4, cost: 3000, name: 'бензопила' },
{ weight: 3, cost: 2000, name: 'ноутбук' },
];
const test2: Item[] = [
{ weight: 1, cost: 1500, name: 'мини-гитара' },
{ weight: 4, cost: 3000, name: 'бензопила' },
{ weight: 3, cost: 2000, name: 'ноутбук' },
{ weight: 1, cost: 2000, name: 'айфон' },
];
const test3: Item[] = [
{ weight: 4, cost: 3000, name: 'бензопила' },
{ weight: 3, cost: 2000, name: 'ноутбук' },
{ weight: 1, cost: 2000, name: 'айфон' },
]
const test4: Item[] = [
{ weight: 4, cost: 3000, name: 'бензопила' },
{ weight: 3, cost: 2000, name: 'ноутбук' },
]
console.log(resolveKnapsack(test1, 4));
console.log(resolveKnapsack(test2, 4));
console.log(resolveKnapsack(test2, 3));
console.log(resolveKnapsack(test2, 1));
console.log(resolveKnapsack(test2, 0));
console.log(resolveKnapsack(test3, 2));
console.log(resolveKnapsack(test4, 2));