Skip to content

Commit fe865e3

Browse files
authored
Add knapsack exercise (#346)
* Add knapsack exercise * replace a POJO with a static class method
1 parent fa8814d commit fe865e3

File tree

8 files changed

+213
-0
lines changed

8 files changed

+213
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,14 @@
754754
"practices": [],
755755
"prerequisites": [],
756756
"difficulty": 5
757+
},
758+
{
759+
"slug": "knapsack",
760+
"name": "Knapsack",
761+
"uuid": "a385b861-22a5-4319-9fc0-c0228640ce26",
762+
"practices": [],
763+
"prerequisites": [],
764+
"difficulty": 6
757765
}
758766
]
759767
},
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Instructions
2+
3+
Your task is to determine which items to take so that the total value of his selection is maximized, taking into account the knapsack's carrying capacity.
4+
5+
Items will be represented as a list of items.
6+
Each item will have a weight and value.
7+
All values given will be strictly positive.
8+
Bob can take only one of each item.
9+
10+
For example:
11+
12+
```text
13+
Items: [
14+
{ "weight": 5, "value": 10 },
15+
{ "weight": 4, "value": 40 },
16+
{ "weight": 6, "value": 30 },
17+
{ "weight": 4, "value": 50 }
18+
]
19+
20+
Knapsack Maximum Weight: 10
21+
```
22+
23+
For the above, the first item has weight 5 and value 10, the second item has weight 4 and value 40, and so on.
24+
In this example, Bob should take the second and fourth item to maximize his value, which, in this case, is 90.
25+
He cannot get more than 90 as his knapsack has a weight limit of 10.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Introduction
2+
3+
Bob is a thief.
4+
After months of careful planning, he finally manages to crack the security systems of a fancy store.
5+
6+
In front of him are many items, each with a value and weight.
7+
Bob would gladly take all of the items, but his knapsack can only hold so much weight.
8+
Bob has to carefully consider which items to take so that the total value of his selection is maximized.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"glennj"
4+
],
5+
"files": {
6+
"solution": [
7+
"knapsack.coffee"
8+
],
9+
"test": [
10+
"knapsack.spec.coffee"
11+
],
12+
"example": [
13+
".meta/example.coffee"
14+
]
15+
},
16+
"blurb": "Given a knapsack that can only carry a certain weight, determine which items to put in the knapsack in order to maximize their combined value.",
17+
"source": "Wikipedia",
18+
"source_url": "https://en.wikipedia.org/wiki/Knapsack_problem"
19+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Algorithm taken from Wikipedia: https://en.wikipedia.org/wiki/Knapsack_problem
2+
3+
class Knapsack
4+
@maximumValue: ({maximumWeight, items}) ->
5+
return 0 if items.length is 0
6+
7+
m = Array.from({length: items.length + 1}, -> new Array(maximumWeight + 1))
8+
m[0].fill 0
9+
10+
for i in [1 .. items.length]
11+
{weight, value} = items[i - 1]
12+
for w in [0 .. maximumWeight]
13+
if weight > w
14+
m[i][w] = m[i - 1][w]
15+
else
16+
m[i][w] = Math.max m[i - 1][w], m[i - 1][w - weight] + value
17+
18+
m[items.length][maximumWeight]
19+
20+
module.exports = Knapsack
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[a4d7d2f0-ad8a-460c-86f3-88ba709d41a7]
13+
description = "no items"
14+
include = false
15+
16+
[3993a824-c20e-493d-b3c9-ee8a7753ee59]
17+
description = "no items"
18+
reimplements = "a4d7d2f0-ad8a-460c-86f3-88ba709d41a7"
19+
20+
[1d39e98c-6249-4a8b-912f-87cb12e506b0]
21+
description = "one item, too heavy"
22+
23+
[833ea310-6323-44f2-9d27-a278740ffbd8]
24+
description = "five items (cannot be greedy by weight)"
25+
26+
[277cdc52-f835-4c7d-872b-bff17bab2456]
27+
description = "five items (cannot be greedy by value)"
28+
29+
[81d8e679-442b-4f7a-8a59-7278083916c9]
30+
description = "example knapsack"
31+
32+
[f23a2449-d67c-4c26-bf3e-cde020f27ecc]
33+
description = "8 items"
34+
35+
[7c682ae9-c385-4241-a197-d2fa02c81a11]
36+
description = "15 items"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class Knapsack
2+
@maximumValue: (args) ->
3+
4+
module.exports = Knapsack
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
Knapsack = require './knapsack'
2+
3+
describe 'Knapsack', ->
4+
it 'no items', ->
5+
input = {
6+
maximumWeight: 100,
7+
items: []
8+
}
9+
expect(Knapsack.maximumValue input).toEqual 0
10+
11+
xit 'one item, too heavy', ->
12+
input = {
13+
maximumWeight: 10,
14+
items: [{ weight: 100, value: 1 }]
15+
}
16+
expect(Knapsack.maximumValue input).toEqual 0
17+
18+
xit 'five items (cannot be greedy by weight)', ->
19+
input = {
20+
maximumWeight: 10,
21+
items: [
22+
{ weight: 2, value: 5 },
23+
{ weight: 2, value: 5 },
24+
{ weight: 2, value: 5 },
25+
{ weight: 2, value: 5 },
26+
{ weight: 10, value: 21 }
27+
]
28+
}
29+
expect(Knapsack.maximumValue input).toEqual 21
30+
31+
xit 'five items (cannot be greedy by value)', ->
32+
input = {
33+
maximumWeight: 10,
34+
items: [
35+
{ weight: 2, value: 20 },
36+
{ weight: 2, value: 20 },
37+
{ weight: 2, value: 20 },
38+
{ weight: 2, value: 20 },
39+
{ weight: 10, value: 50 }
40+
]
41+
}
42+
expect(Knapsack.maximumValue input).toEqual 80
43+
44+
xit 'example knapsack', ->
45+
input = {
46+
maximumWeight: 10,
47+
items: [
48+
{ weight: 5, value: 10 },
49+
{ weight: 4, value: 40 },
50+
{ weight: 6, value: 30 },
51+
{ weight: 4, value: 50 }
52+
]
53+
}
54+
expect(Knapsack.maximumValue input).toEqual 90
55+
56+
xit '8 items', ->
57+
input = {
58+
maximumWeight: 104,
59+
items: [
60+
{ weight: 25, value: 350 },
61+
{ weight: 35, value: 400 },
62+
{ weight: 45, value: 450 },
63+
{ weight: 5, value: 20 },
64+
{ weight: 25, value: 70 },
65+
{ weight: 3, value: 8 },
66+
{ weight: 2, value: 5 },
67+
{ weight: 2, value: 5 }
68+
]
69+
}
70+
expect(Knapsack.maximumValue input).toEqual 900
71+
72+
xit '15 items', ->
73+
input = {
74+
maximumWeight: 750,
75+
items: [
76+
{ weight: 70, value: 135 },
77+
{ weight: 73, value: 139 },
78+
{ weight: 77, value: 149 },
79+
{ weight: 80, value: 150 },
80+
{ weight: 82, value: 156 },
81+
{ weight: 87, value: 163 },
82+
{ weight: 90, value: 173 },
83+
{ weight: 94, value: 184 },
84+
{ weight: 98, value: 192 },
85+
{ weight: 106, value: 201 },
86+
{ weight: 110, value: 210 },
87+
{ weight: 113, value: 214 },
88+
{ weight: 115, value: 221 },
89+
{ weight: 118, value: 229 },
90+
{ weight: 120, value: 240 }
91+
]
92+
}
93+
expect(Knapsack.maximumValue input).toEqual 1458

0 commit comments

Comments
 (0)