Knapsack problem/Bounded: Difference between revisions

m
m (→‎{{header|Wren}}: Minor tidy)
 
(44 intermediate revisions by 23 users not shown)
Line 11:
 
This is the list:
:::::{| style="text-align: left; width: 8055%;" border="4" cellpadding="2" cellspacing="2"
|+ Table of potential knapsack items
|- style="background-color: rgb(255, 204, 255);"
Line 78:
*   [[Knapsack problem/0-1]]
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">V items = [
‘sandwich’ = (50, 60, 2),
‘map’ = (9, 150, 1),
‘compass’ = (13, 35, 1),
‘water’ = (153, 200, 3),
‘glucose’ = (15, 60, 2),
‘tin’ = (68, 45, 3),
‘banana’ = (27, 60, 3),
‘apple’ = (39, 40, 3),
‘cheese’ = (23, 30, 1),
‘beer’ = (52, 10, 3),
‘suntan cream’ = (11, 70, 1),
‘camera’ = (32, 30, 1),
‘t-shirt’ = (24, 15, 2),
‘trousers’ = (48, 10, 2),
‘umbrella’ = (73, 40, 1),
‘w-trousers’ = (42, 70, 1),
‘w-overcoat’ = (43, 75, 1),
‘note-case’ = (22, 80, 1),
‘sunglasses’ = (7, 20, 1),
‘towel’ = (18, 12, 2),
‘socks’ = (4, 50, 1),
‘book’ = (30, 10, 2)
]
 
V item_keys = items.keys()
 
[(Int, Int) = (Int, [(Int, String)])] cache
 
F choose_item(weight, idx)
[(Int, String)] best_list
I idx < 0
R (0, best_list)
V k = (weight, idx)
V? c = :cache.find(k)
I c != N
R c
V name = :item_keys[idx]
V (w, v, qty) = :items[name]
V best_v = 0
 
L(i) 0..qty
V wlim = weight - i * w
I wlim < 0
L.break
V (val, taken) = choose_item(wlim, idx - 1)
I val + i * v > best_v
best_v = val + i * v
best_list = copy(taken)
best_list.append((i, name))
:cache[k] = (best_v, best_list)
R (best_v, best_list)
 
V (v, lst) = choose_item(400, items.len - 1)
V w = 0
L(cnt, name) lst
I cnt > 0
print(cnt‘ ’name)
w += items[name][0] * cnt
 
print(‘Total weight: ’w‘ Value: ’v)</syntaxhighlight>
 
{{out}}
<pre>
3 banana
1 cheese
1 compass
2 glucose
1 map
1 note-case
1 socks
1 sunglasses
1 suntan cream
1 w-overcoat
1 water
Total weight: 396 Value: 1010
</pre>
 
=={{header|AutoHotkey}}==
iterative dynamic programming solution
<langsyntaxhighlight AutoHotkeylang="autohotkey">Item = map,compass,water,sandwich,glucose,tin,banana,apple,cheese,beer,suntan cream
,camera,tshirt,trousers,umbrella,waterproof trousers,waterproof overclothes,notecase
,sunglasses,towel,socks,book
Line 117 ⟶ 198:
}
 
MsgBox % "Value = " m%N%_%W% "`nWeight = " s "`n`n" t</langsyntaxhighlight>
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat">(knapsack=
( things
= (map.9.150.1)
Line 193 ⟶ 274:
);
 
!knapsack;</langsyntaxhighlight>
{{out}}
<pre> 1010
Line 210 ⟶ 291:
=={{header|C}}==
 
<langsyntaxhighlight Clang="c">#include <stdio.h>
#include <stdlib.h>
 
Line 294 ⟶ 375:
return 0;
}
</syntaxhighlight>
</lang>
 
{{output}}
Line 309 ⟶ 390:
socks 1 4 50
count, weight, value: 14 396 1010</pre>
 
=={{header|C sharp|C#}}==
Similar to Knapsack/0-1.
<syntaxhighlight lang="csharp">using System; // 4790@3.6
class program
{
static void Main()
{
knapSack(40);
var sw = System.Diagnostics.Stopwatch.StartNew();
Console.Write(knapSack(400) + "\n" + sw.Elapsed); // 51 µs
Console.Read();
}
 
static string knapSack(uint w1)
{
init(); change();
uint n = (uint)w.Length; var K = new uint[n + 1, w1 + 1];
for (uint vi, wi, w0, x, i = 0; i < n; i++)
for (vi = v[i], wi = w[i], w0 = 1; w0 <= w1; w0++)
{
x = K[i, w0];
if (wi <= w0) x = max(vi + K[i, w0 - wi], x);
K[i + 1, w0] = x;
}
string str = "";
for (uint v1 = K[n, w1]; v1 > 0; n--)
if (v1 != K[n - 1, w1])
{
v1 -= v[n - 1]; w1 -= w[n - 1]; str += items[n - 1] + "\n";
}
return str;
}
 
static uint max(uint a, uint b) { return a > b ? a : b; }
 
static byte[] w, v; static string[] items;
 
static byte[] p = { 1, 1, 2, 2, 2, 3, 3, 3, 1, 3, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 1, 2 };
 
static void init()
{
w = new byte[] { 9, 13, 153, 50, 15, 68, 27, 39, 23, 52, 11,
32, 24, 48, 73, 42, 43, 22, 7, 18, 4, 30 };
 
v = new byte[] { 150, 35, 200, 60, 60, 45, 60, 40, 30, 10, 70,
30, 15, 10, 40, 70, 75, 80, 20, 12, 50, 10 };
 
items = new string[] {"map","compass","water","sandwich","glucose","tin",
"banana","apple","cheese","beer","suntan cream",
"camera","T-shirt","trousers","umbrella",
"waterproof trousers","waterproof overclothes",
"note-case","sunglasses","towel","socks","book"};
}
 
static void change()
{
int n = w.Length, s = 0, i, j, k; byte xi;
for (i = 0; i < n; i++) s += p[i];
{
byte[] x = new byte[s];
for (k = i = 0; i < n; i++)
for (xi = w[i], j = p[i]; j > 0; j--) x[k++] = xi;
w = x;
}
{
byte[] x = new byte[s];
for (k = i = 0; i < n; i++)
for (xi = v[i], j = p[i]; j > 0; j--) x[k++] = xi;
v = x;
}
string[] pItems = new string[s]; string itemI;
for (k = i = 0; i < n; i++)
for (itemI = items[i], j = p[i]; j > 0; j--) pItems[k++] = itemI;
items = pItems;
}
}</syntaxhighlight>
 
=={{header|C++}}==
C++ DP solution. Initially taken from C but than fixed and refactored.<br>
Remark: The above comment implies there is a bug in the C code, but refers to a much older and very different version [[User:Petelomax|Pete Lomax]] ([[User talk:Petelomax|talk]]) 19:28, 20 March 2017 (UTC)
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <vector>
#include <algorithm>
Line 548 ⟶ 706:
cout << "Weight: " << solution.w << " Value: " << solution.v << endl;
return 0;
}</langsyntaxhighlight>
 
=={{header|Clojure}}==
We convert the problem to a Knapsack-0/1 problem by replacing (n-max item) vith n-max identical occurences of 1 item.
Adapted Knapsack-0/1 problem solution from [https://www.rosettacode.org/wiki/Knapsack_problem/0-1#Clojure]
<langsyntaxhighlight lang="lisp">(ns knapsack
(:gen-class))
 
Line 613 ⟶ 771:
(println "Total value:" value)
(println "Total weight:" (reduce + (map (comp :weight items) indexes))))
</syntaxhighlight>
</lang>
{{Output}}
<pre>
Line 631 ⟶ 789:
Total weight: 396
</pre>
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">;;; memoize
(defmacro mm-set (p v) `(if ,p ,p (setf ,p ,v)))
 
Line 665 ⟶ 824:
(T-shirt 24 15 2) (trousers 48 10 2) (umbrella 73 40 1)
(trousers 42 70 1) (overclothes 43 75 1) (notecase 22 80 1)
(glasses 7 20 1) (towel 18 12 2) (socks 4 50 1) (book 30 10 2))))</langsyntaxhighlight>
 
=={{header|Crystal}}==
 
==== Branch and Bound solution ====
<syntaxhighlight lang="ruby">record Item, name : String, weight : Int32, value : Int32, count : Int32
 
record Selection, mask : Array(Int32), cur_index : Int32, total_value : Int32
 
class Knapsack
@threshold_value = 0
@threshold_choice : Selection?
getter checked_nodes = 0
 
def knapsack_step(taken, items, remaining_weight)
if taken.total_value > @threshold_value
@threshold_value = taken.total_value
@threshold_choice = taken
end
candidate_index = items.index(taken.cur_index) { |item| item.weight <= remaining_weight }
return nil unless candidate_index
@checked_nodes += 1
candidate = items[candidate_index]
# candidate is a best of available items, so if we fill remaining value with
# and still don't reach the threshold, the branch is wrong
return nil if taken.total_value + 1.0 * candidate.value / candidate.weight * remaining_weight < @threshold_value
# now recursively check all variants (from taking maximum count to taking nothing)
max_count = {candidate.count, remaining_weight // candidate.weight}.min
(0..max_count).reverse_each do |n|
mask = taken.mask.clone
mask[candidate_index] = n
knapsack_step Selection.new(mask, candidate_index + 1, taken.total_value + n*candidate.value), items, remaining_weight - n*candidate.weight
end
end
 
def select(items, max_weight)
@checked_variants = 0
# sort by descending relative value
list = items.sort_by { |item| -1.0 * item.value / item.weight }
nothing = Selection.new(Array(Int32).new(items.size, 0), 0, 0)
@threshold_value = 0
@threshold_choice = nothing
knapsack_step(nothing, list, max_weight)
selected = @threshold_choice.not_nil!
result = Hash(Item, Int32).new(0)
selected.mask.each_with_index { |v, i| result[list[i]] = v if v > 0 }
result
end
end
 
possible = [
Item.new("map", 9, 150, 1),
Item.new("compass", 13, 35, 1),
Item.new("water", 153, 200, 2),
Item.new("sandwich", 50, 60, 2),
Item.new("glucose", 15, 60, 2),
Item.new("tin", 68, 45, 3),
Item.new("banana", 27, 60, 3),
Item.new("apple", 39, 40, 3),
Item.new("cheese", 23, 30, 1),
Item.new("beer", 52, 10, 3),
Item.new("suntan cream", 11, 70, 1),
Item.new("camera", 32, 30, 1),
Item.new("T-shirt", 24, 15, 2),
Item.new("trousers", 48, 10, 2),
Item.new("umbrella", 73, 40, 1),
Item.new("waterproof trousers", 42, 70, 1),
Item.new("waterproof overclothes", 43, 75, 1),
Item.new("note-case", 22, 80, 1),
Item.new("sunglasses", 7, 20, 1),
Item.new("towel", 18, 12, 2),
Item.new("socks", 4, 50, 1),
Item.new("book", 30, 10, 2),
]
 
solver = Knapsack.new
used = solver.select(possible, 400)
puts "optimal choice: #{used.map { |item, count| count == 1 ? item.name : "#{count}x #{item.name}" }.join(", ")}"
puts "total weight #{used.sum { |item, count| item.weight*count }}"
puts "total value #{used.sum { |item, count| item.value*count }}"
puts "checked nodes: #{solver.checked_nodes}"</syntaxhighlight>
{{out}}
<pre>optimal choice: map, socks, suntan cream, 2x glucose, note-case, sunglasses, compass, 3x banana, waterproof overclothes, water, cheese
total weight 396
total value 1010
checked nodes: 1185
</pre>
 
==== Dynamic programming solution ====
{{trans|Ruby}}
<syntaxhighlight lang="ruby"># Item struct to represent each item in the problem
record Item, name : String, weight : Int32, value : Int32, count : Int32
 
def choose_item(items, weight, id, cache)
return 0, ([] of Int32) if id < 0
 
k = {weight, id}
cache = cache || {} of Tuple(Int32, Int32) => Tuple(Int32, Array(Int32))
return cache[k] if cache[k]?
value = items[id].value
best_v = 0
best_list = [] of Int32
(items[id].count + 1).times do |i|
wlim = weight - i * items[id].weight
break if wlim < 0
val, taken = choose_item(items, wlim, id - 1, cache)
if val + i * value > best_v
best_v = val + i * value
best_list = taken + [i]
end
end
cache[k] = {best_v, best_list}
return {best_v, best_list}
end
 
items = [
Item.new("map", 9, 150, 1),
Item.new("compass", 13, 35, 1),
Item.new("water", 153, 200, 2),
Item.new("sandwich", 50, 60, 2),
Item.new("glucose", 15, 60, 2),
Item.new("tin", 68, 45, 3),
Item.new("banana", 27, 60, 3),
Item.new("apple", 39, 40, 3),
Item.new("cheese", 23, 30, 1),
Item.new("beer", 52, 10, 3),
Item.new("suntan cream", 11, 70, 1),
Item.new("camera", 32, 30, 1),
Item.new("T-shirt", 24, 15, 2),
Item.new("trousers", 48, 10, 2),
Item.new("umbrella", 73, 40, 1),
Item.new("waterproof trousers", 42, 70, 1),
Item.new("waterproof overclothes", 43, 75, 1),
Item.new("note-case", 22, 80, 1),
Item.new("sunglasses", 7, 20, 1),
Item.new("towel", 18, 12, 2),
Item.new("socks", 4, 50, 1),
Item.new("book", 30, 10, 2),
]
 
val, list = choose_item(items, 400, items.size - 1, nil)
w = 0
list.each_with_index do |cnt, i|
if cnt > 0
print "#{cnt} #{items[i].name}\n"
w += items[i].weight * cnt
end
end
 
p "Total weight: #{w}, Value: #{val}"</syntaxhighlight>
 
=={{header|D}}==
{{trans|Python}}
Solution with memoization.
<langsyntaxhighlight lang="d">import std.stdio, std.typecons, std.functional;
 
immutable struct Item {
Line 726 ⟶ 1,034:
 
writeln("Total weight: ", w, " Value: ", v_lst[0]);
}</langsyntaxhighlight>
{{out}}
<pre>1 map
Line 743 ⟶ 1,051:
=={{header|EchoLisp}}==
We convert the problem to a Knapsack-0/1 problem by replacing (n-max item) vith n-max identical occurences of 1 item.
<langsyntaxhighlight lang="scheme">
(lib 'struct)
(lib 'sql)
Line 799 ⟶ 1,107:
(name i))))
 
</syntaxhighlight>
</lang>
{{out}}
<langsyntaxhighlight lang="scheme">
(define goodies
'((map 9 150 1) (compass 13 35 1)(water 153 200 3)
Line 821 ⟶ 1,129:
(length (hash-keys H))
→ 10827 ;; # of entries in cache
</syntaxhighlight>
</lang>
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">#define PesoMax 400
#define items 22
#define Tabu Chr(9)
 
Type Knapsack
articulo As String*22
peso As Integer
valor As Integer
pieza As Integer
End Type
Dim item(1 To 22) As Knapsack => { _
("map ", 9, 150, 0), ("compass ", 13, 35, 0), _
("water ", 153, 200, 0), ("sandwich ", 50, 160, 0), _
("glucose ", 15, 60, 0), ("tin ", 68, 45, 0), _
("banana ", 27, 60, 0), ("apple ", 39, 40, 0), _
("cheese ", 23, 30, 0), ("beer ", 52, 10, 0), _
("suntan cream ", 11, 70, 0), ("camera ", 32, 30, 0), _
("T-shirt ", 24, 15, 0), ("trousers ", 48, 10, 0), _
("umbrella ", 73, 40, 0), ("waterproof trousers ", 42, 70, 0), _
("waterproof overclothes", 43, 75, 0), ("note-case ", 22, 80, 0), _
("sunglasses ", 7, 20, 0), ("towel ", 18, 12, 0), _
("socks ", 4, 50, 0), ("book ", 30, 10, 0)}
 
Dim As Integer i, tot = 0, TValor = 0
For i =1 To Ubound(item)
tot += item(i).peso
Next i
 
Dim As Integer TPeso = tot-PesoMax
Dim As String pr = ""
Dim As Integer c = 0, v, w, k
 
Do
v = 1e9 : w = 0 : k = 0
For i = 1 To items
If item(i).pieza = 0 Then
w = 1000 * item(i).valor / item(i).peso
If w < v Then v = w : k = i
End If
Next i
If k Then
TPeso -= item(k).peso
item(k).pieza = 1
If TPeso <= 0 Then Exit Do
End If
c += 1
Loop Until c>= items
 
Print "Knapsack contents: "
For i = 1 To items
If item(i).pieza = 0 Then
Print item(i).articulo & Tabu & item(i).peso & Tabu & item(i).valor
TValor += item(i).valor
End If
Next i
 
Print !"\nTotal value: "; TValor
Print "Total weight: "; PesoMax + TPeso
Sleep</syntaxhighlight>
{{out}}
<pre>Knapsack contents:
map 9 150
compass 13 35
water 153 200
sandwich 50 160
glucose 15 60
banana 27 60
suntan cream 11 70
waterproof trousers 42 70
waterproof overclothes 43 75
note-case 22 80
sunglasses 7 20
socks 4 50
 
Total value: 1030
Total weight: 396</pre>
 
=={{header|Go}}==
Solution with caching.
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 923 ⟶ 1,311:
}
fmt.Printf("Value: %d; weight: %d\n", v, w)
}</langsyntaxhighlight>
(A simple test and benchmark used while making changes to make sure performance wasn't sacrificed is available at [[/Go_test]].)
{{out}}
Line 942 ⟶ 1,330:
=={{header|Groovy}}==
Solution: dynamic programming
<langsyntaxhighlight lang="groovy">def totalWeight = { list -> list.collect{ it.item.weight * it.count }.sum() }
def totalValue = { list -> list.collect{ it.item.value * it.count }.sum() }
 
Line 959 ⟶ 1,347:
}
m[n][400]
}</langsyntaxhighlight>
Test:
<langsyntaxhighlight lang="groovy">def items = [
[name:"map", weight: 9, value:150, pieces:1],
[name:"compass", weight: 13, value: 35, pieces:1],
Line 996 ⟶ 1,384:
printf (' item: %-22s weight:%4d value:%4d count:%2d\n',
it.item.name, it.item.weight, it.item.value, it.count)
}</langsyntaxhighlight>
{{out}}
<pre>Elapsed Time: 0.603 s
Line 1,015 ⟶ 1,403:
=={{header|Haskell}}==
Directly lifted from 1-0 problem:
<langsyntaxhighlight lang="haskell">inv = [("map",9,150,1), ("compass",13,35,1), ("water",153,200,2), ("sandwich",50,60,2),
("glucose",15,60,2), ("tin",68,45,3), ("banana",27,60,3), ("apple",39,40,3),
("cheese",23,30,1), ("beer",52,10,3), ("cream",11,70,1), ("camera",32,30,1),
Line 1,029 ⟶ 1,417:
new = map (\(val,itms)->(val + v * i, (name,i):itms)) old
 
main = print $ (knapsack inv) !! 400</langsyntaxhighlight>
{{out}}
 
Line 1,036 ⟶ 1,424:
</pre>
The above uses merging lists for cache. It's faster, and maybe easier to understand when some constant-time lookup structure is used for cache (same output):
<langsyntaxhighlight lang="haskell">import Data.Array
 
-- snipped the item list; use the one from above
Line 1,046 ⟶ 1,434:
prepend (x,n) (y,s) = (x+y,n:s)
 
main = do print $ knapsack inv 400</langsyntaxhighlight>
 
=={{header|J}}==
Brute force solution:
<langsyntaxhighlight lang="j">'names numbers'=:|:".;._2]0 :0
'map'; 9 150 1
'compass'; 13 35 1
Line 1,099 ⟶ 1,487:
 
bestCombo''
978832641</langsyntaxhighlight>
Interpretation of answer:
<langsyntaxhighlight lang="j"> decode 978832641
1 1 1 0 2 0 3 0 1 0 1 0 0 0 0 0 1 1 1 0 1 0
(0<decode 978832641) # (":,.decode 978832641),.' ',.names
Line 1,118 ⟶ 1,506:
396
values +/ .* decode 978832641
1010</langsyntaxhighlight>
Dynamic programming solution (faster):
<langsyntaxhighlight lang="j">dyn=:3 :0
m=. 0$~1+400,+/pieces NB. maximum value cache
b=. m NB. best choice cache
Line 1,146 ⟶ 1,534:
 
dyn''
1 1 1 0 2 0 3 0 1 0 1 0 0 0 0 0 1 1 1 0 1 0</langsyntaxhighlight>
Note: the brute force approach would return multiple "best answers" if more than one combination of choices would satisfy the "best" constraint. The dynamic approach arbitrarily picks one of those choices. That said, with this particular choice of item weights and values, this is an irrelevant distinction.
 
=={{header|Java}}==
General dynamic solution after [[wp:Knapsack_problem#0-1_knapsack_problem|wikipedia]]. The solution extends the method of [[Knapsack problem/0-1#Java ]].
<langsyntaxhighlight lang="java">package hu.pj.alg.test;
 
import hu.pj.alg.BoundedKnapsack;
Line 1,233 ⟶ 1,621:
new BoundedKnapsackForTourists();
}
} // class</langsyntaxhighlight>
<langsyntaxhighlight lang="java">package hu.pj.alg;
 
import hu.pj.obj.Item;
Line 1,296 ⟶ 1,684:
setInitialStateForCalculation();
}
} // class</langsyntaxhighlight>
<langsyntaxhighlight lang="java">package hu.pj.alg;
 
import hu.pj.obj.Item;
Line 1,448 ⟶ 1,836:
solutionWeight = 0;
}
} // class</langsyntaxhighlight>
<langsyntaxhighlight lang="java">package hu.pj.obj;
 
public class Item {
Line 1,517 ⟶ 1,905:
public int getInKnapsack() {return inKnapsack;}
public int getBounding() {return bounding;}
} // class</langsyntaxhighlight>
{{out}}
<pre>
Line 1,540 ⟶ 1,928:
=={{header|JavaScript}}==
Based on the (dynamic) J implementation. Expressed as an htm page:
<langsyntaxhighlight lang="javascript"><html><head><title></title></head><body></body></html>
 
<script type="text/javascript">
Line 1,618 ⟶ 2,006:
}
findBestPack();
</script></langsyntaxhighlight>
This will generate (translating html to mediawiki markup):
{|
Line 1,683 ⟶ 2,071:
Total weight: 396<br>
Total value: 1010
 
=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
 
<syntaxhighlight lang="jq"># Item {name, weight, value, count}
 
def Item($name; $weight; $value; $count): {$name, $weight, $value, $count};
 
def items: [
Item("map"; 9; 150; 1),
Item("compass"; 13; 35; 1),
Item("water"; 153; 200; 2),
Item("sandwich"; 50; 60; 2),
Item("glucose"; 15; 60; 2),
Item("tin"; 68; 45; 3),
Item("banana"; 27; 60; 3),
Item("apple"; 39; 40; 3),
Item("cheese"; 23; 30; 1),
Item("beer"; 52; 10; 3),
Item("suntan cream"; 11; 70; 1),
Item("camera"; 32; 30; 1),
Item("T-shirt"; 24; 15; 2),
Item("trousers"; 48; 10; 2),
Item("umbrella"; 73; 40; 1),
Item("waterproof trousers"; 42; 70; 1),
Item("waterproof overclothes"; 43; 75; 1),
Item("note-case"; 22; 80; 1),
Item("sunglasses"; 7; 20; 1),
Item("towel"; 18; 12; 2),
Item("socks"; 4; 50; 1),
Item("book"; 30; 10; 2)
];
def knapsack($w):
def list($init): [range(0; .) | $init];
(items|length) as $n
| {m: ($n+1 | list( $w + 1 | list(0) )) }
| reduce range(1; $n+1) as $i (.;
reduce range (0; $w + 1) as $j (.;
.m[$i][$j] = .m[$i-1][$j]
| label $out
| foreach (range(1; 1 + ((items[$i - 1].count))), null) as $k (.stop = false;
if $k == null then .
elif ($k * items[$i - 1].weight > $j) then .stop = true
else (.m[$i - 1][$j - ($k * items[$i - 1].weight)] + $k * items[$i - 1].value) as $v
| if $v > .m[$i][$j] then .m[$i][$j] = $v else . end
end;
if .stop or ($k == null) then ., break $out else empty end)
) )
| .s = ($n|list(0))
| .j = $w
| reduce range($n; 0; -1) as $i (.;
.m[$i][.j] as $v
| .k = 0
| until ($v == .m[$i - 1][.j] + .k * items[$i - 1].value;
.s[$i - 1] += 1
| .j = .j - items[$i - 1].weight
| .k += 1 ) )
| .s;
 
def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;
 
def task(maxWeight):
def f(a;b;c;d): "\(a|lpad(22)) \(b|lpad(6)) \(c|lpad(6)) \(d|lpad(6))";
def f: . as [$a,$b,$c,$d] | f($a;$b;$c;$d);
 
(items|length) as $n
| knapsack(maxWeight) as $s
| f("Item Chosen"; "Weight";"Value";"Number"),
"---------------------- ------ ----- ------",
({ itemCount:0,
sumWeight:0,
sumValue :0,
sumNumber:0 }
| reduce range(0; $n) as $i (.;
if ($s[$i] != 0)
then .itemCount += 1
| .name = items[$i].name
| .number = $s[$i]
| .weight = items[$i].weight * .number
| .value = items[$i].value * .number
| .sumNumber += .number
| .sumWeight += .weight
| .sumValue += .value
| .emit += [[.name, .weight, .value, .number]]
else .
end )
| (.emit[] | f),
"---------------------- ------ ----- ------",
f("Items chosen \(.itemCount|lpad(4))"; .sumWeight; .sumValue; .sumNumber) );
 
task(400)
</syntaxhighlight>
{{out}}
<pre>
Item Chosen Weight Value Number
---------------------- ------ ----- ------
map 9 150 1
compass 13 35 1
water 153 200 1
glucose 30 120 2
banana 81 180 3
cheese 23 30 1
suntan cream 11 70 1
waterproof overclothes 43 75 1
note-case 22 80 1
sunglasses 7 20 1
socks 4 50 1
---------------------- ------ ----- ------
Items chosen 11 396 1010 14
</pre>
 
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
The solution uses Julia's [https://github.com/JuliaOpt/MathProgBase.jl MathProgBase]. Most of the work is done with this package's <code>mixintprog</code> function.
 
'''Type and Function''':
<syntaxhighlight lang="julia">using MathProgBase, Cbc
<lang Julia>
using MathProgBase
 
immutablestruct KPDSupply{S<:String, T<:Integer}
item::SString
weight::T
value::T
quant::T
end
Base.show(io::IO, kdps::KPDSupply) = print(io, kdps.quant, " ", kdps.item, " ($(kdps.weight) kg, $(kdps.value) €)")
 
function solve{S<:String, T<:Integer}(gear::ArrayVector{KPDSupply{S,T},1}, capacity::Integer) where T<:Integer
w = getfield.(gear, :weight)
capacity::T)
wv = map(x->xgetfield.weight(gear, gear:value)
vq = map(x->xgetfield.value(gear, gear:quant)
sol = mixintprog(-v, w', '<', capacity, :Int, 0, q, CbcSolver())
q = map(x->x.quant, gear)
sol.status == mixintprog(-v,:Optimal w',|| '<',error("this capacity,problem :Int,could not 0,be qsolved")
 
sol.status == :Optimal || error("This Problem could not be solved")
if all(q .== 1) # simpler case
return gear[sol.sol .== 1.0]
else
pack = KPDSupply[]similar(gear, 0)
s = intround.(Int, sol.sol)
for (i, g) in enumerate(gear)
iszero(s[i]) != 0 ||&& continue
push!(pack, KPDSupply(g.item, g.weight, g.value, s[i]))
end
return pack
end
end</syntaxhighlight>
end
</lang>
 
'''Main''':
<syntaxhighlight lang="julia">gear = [KPDSupply("map", 9, 150, 1),
<lang Julia>
gear = [KPDSupply("map", 9, 150, 1),
KPDSupply("compass", 13, 35, 1),
KPDSupply("water", 153, 200, 2),
Line 1,745 ⟶ 2,246:
 
pack = solve(gear, 400)
println("The hiker should pack: \n - ", join(pack, "\n - "))
println("\nPacked weight: ", sum(getfield.(pack, :weight)), " kg")
println("Packed value: ", sum(getfield.(pack, :value)), " €")</syntaxhighlight>
 
{{out}}
println("The hiker should pack:")
for<pre>The shiker inshould pack:
- 1 map (9 kg, 150 €)
println(" ", s.quant, " ", s.item)
- 1 compass (13 kg, 35 €)
end
- 1 water (153 kg, 200 €)
println()
- 2 glucose (15 kg, 60 €)
println("Packed Weight: ", mapreduce(x->x.weight*x.quant, +, pack))
- 3 banana (27 kg, 60 €)
println("Packed Value: ", mapreduce(x->x.value*x.quant, +, pack))
- 1 cheese (23 kg, 30 €)
</lang>
- 1 suntan cream (11 kg, 70 €)
- 1 waterproof overclothes (43 kg, 75 €)
- 1 note-case (22 kg, 80 €)
- 1 sunglasses (7 kg, 20 €)
- 1 socks (4 kg, 50 €)
 
Packed weight: 327 kg
Packed value: 830 €</pre>
 
=={{header|Kotlin}}==
{{trans|C}}
<syntaxhighlight lang="scala">// version 1.1.2
 
data class Item(val name: String, val weight: Int, val value: Int, val count: Int)
 
val items = listOf(
Item("map", 9, 150, 1),
Item("compass", 13, 35, 1),
Item("water", 153, 200, 2),
Item("sandwich", 50, 60, 2),
Item("glucose", 15, 60, 2),
Item("tin", 68, 45, 3),
Item("banana", 27, 60, 3),
Item("apple", 39, 40, 3),
Item("cheese", 23, 30, 1),
Item("beer", 52, 10, 3),
Item("suntan cream", 11, 70, 1),
Item("camera", 32, 30, 1),
Item("T-shirt", 24, 15, 2),
Item("trousers", 48, 10, 2),
Item("umbrella", 73, 40, 1),
Item("waterproof trousers", 42, 70, 1),
Item("waterproof overclothes", 43, 75, 1),
Item("note-case", 22, 80, 1),
Item("sunglasses", 7, 20, 1),
Item("towel", 18, 12, 2),
Item("socks", 4, 50, 1),
Item("book", 30, 10, 2)
)
 
val n = items.size
 
const val MAX_WEIGHT = 400
 
fun knapsack(w: Int): IntArray {
val m = Array(n + 1) { IntArray(w + 1) }
for (i in 1..n) {
for (j in 0..w) {
m[i][j] = m[i - 1][j]
for (k in 1..items[i - 1].count) {
if (k * items[i - 1].weight > j) break
val v = m[i - 1][j - k * items[i - 1].weight] + k * items[i - 1].value
if (v > m[i][j]) m[i][j] = v
}
}
}
val s = IntArray(n)
var j = w
for (i in n downTo 1) {
val v = m[i][j]
var k = 0
while (v != m[i - 1][j] + k * items[i - 1].value) {
s[i - 1]++
j -= items[i - 1].weight
k++
}
}
return s
}
 
fun main(args: Array<String>) {
val s = knapsack(MAX_WEIGHT)
println("Item Chosen Weight Value Number")
println("--------------------- ------ ----- ------")
var itemCount = 0
var sumWeight = 0
var sumValue = 0
var sumNumber = 0
for (i in 0 until n) {
if (s[i] == 0) continue
itemCount++
val name = items[i].name
val number = s[i]
val weight = items[i].weight * number
val value = items[i].value * number
sumNumber += number
sumWeight += weight
sumValue += value
println("${name.padEnd(22)} ${"%3d".format(weight)} ${"%4d".format(value)} ${"%2d".format(number)}")
}
println("--------------------- ------ ----- ------")
println("Items chosen $itemCount ${"%3d".format(sumWeight)} ${"%4d".format(sumValue)} ${"%2d".format(sumNumber)}")
}</syntaxhighlight>
 
{{out}}
<pre>
Item Chosen Weight Value Number
The hiker should pack:
--------------------- ------ ----- ------
1 map
map 9 150 1
1 compass
compass 13 35 1
1 water
water 153 200 1
2 glucose
glucose 30 120 2
3 banana
banana 81 180 3
1 cheese
cheese 23 30 1
1 suntan cream
suntan cream 11 70 1
1 waterproof overclothes
waterproof overclothes 43 75 1
1 note-case
note-case 22 80 1
1 sunglasses
sunglasses 7 20 1
1 socks
socks 4 50 1
 
--------------------- ------ ----- ------
Packed Weight: 396
Items chosen 11 396 1010 14
Packed Value: 1010
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight lang="mathematica">Transpose@{#[[;; , 1]],
LinearProgramming[-#[[;; , 3]], -{#[[;; , 2]]}, -{400},
{0, #[[4]]} & /@ #, Integers]} &@{{"map", 9, 150, 1},
Line 1,798 ⟶ 2,395:
{"towel", 18, 12, 2},
{"socks", 4, 50, 1},
{"book", 30, 10, 2}}</langsyntaxhighlight>
{{Out}}
<pre>{{"map", 1}, {"compass", 1}, {"water", 1}, {"sandwich",
Line 1,809 ⟶ 2,406:
 
=={{header|Mathprog}}==
<langsyntaxhighlight lang="mathprog">/*Knapsack
This model finds the integer optimal packing of a knapsack
Line 1,854 ⟶ 2,451:
;
 
end;</langsyntaxhighlight>
 
The solution produced using glpk is here: [[Knapsack problem/Bounded/Mathprog]]
Line 1,861 ⟶ 2,458:
 
The constraints may be found here: [[:File:Knap_constraint.png]]
 
=={{header|MiniZinc}}==
<syntaxhighlight lang="minizinc">
%Solve Knapsack Problem Bounded. Nigel Galloway, Octoer 12th., 2020.
enum Items={map,compass,water,sandwich,glucose,tin,banana,apple,cheese,beer,suntan_cream,camera,t_shirt,trousers,umbrella,waterproof_trousers,waterproof_overclothes,note_case,sunglasses,towel,socks,book};
array[Items] of int: weight =[9,13,153,50,15,68,27,39,23,52,11,32,24,48,73,42,43,22,7,18,4,30];
array[Items] of int: value =[150,35,200,60,60,45,60,40,30,10,70,30,15,10,40,70,75,80,20,12,50,10];
array[Items] of int: quantity=[1,1,2,2,2,3,3,3,1,3,1,1,2,2,1,1,1,1,1,2,1,2];
array[Items] of var 0..max(quantity): take; constraint forall(n in Items)(take[n]<=quantity[n]);
int: maxWeight=400;
var int: wTaken=sum(n in Items)(weight[n]*take[n]);
var int: wValue=sum(n in Items)(value[n]*take[n]);
constraint wTaken <= maxWeight;
solve maximize wValue;
output[concat([let {string: g=show(take[n])} in "Take "++(if g==show(quantity[n]) then "all" else g endif)++" of \(n)\n" | n in Items where show(take[n])!="0"])++"\nTotal Weight=\(wTaken) Total Value="++show_float(4,2,wValue)]
</syntaxhighlight>
{{out}}
<pre>
Take all of map
Take all of compass
Take 1 of water
Take all of glucose
Take all of banana
Take all of cheese
Take all of suntan_cream
Take all of waterproof_overclothes
Take all of note_case
Take all of sunglasses
Take all of socks
 
Total Weight=396 Total Value=1010.00
</pre>
=={{header|Nim}}==
We expand the list of items and apply the 0-1 algorithm.
<syntaxhighlight lang="python"># Knapsack. Recursive solution.
 
import strformat
import tables
 
# Description of an item.
type Item = tuple[name: string; weight, value, pieces: int]
 
# List of available items.
const Items: seq[Item] = @[("map", 9, 150, 1),
("compass", 13, 35, 1),
("water", 153, 200, 2),
("sandwich", 50, 60, 2),
("glucose", 15, 60, 2),
("tin", 68, 45, 3),
("banana", 27, 60, 3),
("apple", 39, 40, 3),
("cheese", 23, 30, 1),
("beer", 52, 10, 3),
("suntan cream", 11, 70, 1),
("camera", 32, 30, 1),
("T-shirt", 24, 15, 2),
("trousers", 48, 10, 2),
("umbrella", 73, 40, 1),
("waterproof trousers", 42, 70, 1),
("waterproof overclothes", 43, 75, 1),
("note-case", 22, 80, 1),
("sunglasses", 7, 20, 1),
("towel", 18, 12, 2),
("socks", 4, 50, 1),
("book", 30, 10, 2)
]
 
type
 
# Item numbers (used rather than items themselves).
Number = range[0..Items.high]
 
# Description of an expanded item.
ExpandedItem = tuple[num: Number; weight, value: int]
 
 
# Expanded items management.
 
proc expandedItems(items: seq[Item]): seq[ExpandedItem] =
## Expand the list of items.
for idx, item in Items:
for _ in 1..item.pieces:
result.add((idx.Number, item.weight, item.value))
 
const ItemList = expandedItems(Items)
 
type
 
# Index in the expanded list.
ExpandedIndex = 0..ItemList.high
 
# Chosen items and their total value.
Choice = tuple[indexes: set[ExpandedIndex]; weight, value: int]
 
# Cache used to speed up the search.
var cache: Table[tuple[index, weight: int], Choice]
 
 
#---------------------------------------------------------------------------------------------------
 
proc select(idx, weightLimit: int): Choice =
## Find the best choice starting from item at index "idx".
 
if idx < 0 or weightLimit == 0:
return
 
if (idx, weightLimit) in cache:
return cache[(idx, weightLimit)]
 
let weight = ItemList[idx].weight
if weight > weightLimit:
return select(idx - 1, weightLimit)
 
# Try by leaving this item and selecting among remaining items.
result = select(idx - 1, weightLimit)
 
# Try by taking this item and completing with some remaining items.
var result1 = select(idx - 1, weightLimit - weight)
inc result1.value, ItemList[idx].value
 
# Select the best choice (giving the greater value).
if result1.value > result.value:
result = (result1.indexes + {idx.ExpandedIndex}, result1.weight + weight, result1.value)
 
cache[(idx, weightLimit)] = result
 
#---------------------------------------------------------------------------------------------------
 
let (indexes, weight, value) = select(ItemList.high, 400)
 
# Count the number of pieces for each item.
var pieces = newSeq[int](Items.len)
for idx in indexes:
inc pieces[ItemList[idx].num]
 
echo "List of items:"
for num in 0..Items.high:
if pieces[num] > 0:
echo fmt"– {pieces[num]} of {Items[num].pieces} {Items[num].name}"
echo ""
echo "Total weight: ", weight
echo "Total value: ", value
</syntaxhighlight>
 
{{out}}
<pre>
List of items:
– 1 of 1 map
– 1 of 1 compass
– 1 of 2 water
– 2 of 2 glucose
– 3 of 3 banana
– 1 of 1 cheese
– 1 of 1 suntan cream
– 1 of 1 waterproof overclothes
– 1 of 1 note-case
– 1 of 1 sunglasses
– 1 of 1 socks
 
Total weight: 396
Total value: 1010
</pre>
 
=={{header|OOCalc}}==
Line 1,895 ⟶ 2,654:
 
=={{header|OxygenBasic}}==
<langsyntaxhighlight lang="oxygenbasic">
type KnapSackItem string name,sys dag,value,tag
 
Line 2,006 ⟶ 2,765:
'
'Weight: 396
</syntaxhighlight>
</lang>
 
=={{header|Oz}}==
Using constraint programming.
<langsyntaxhighlight lang="oz">declare
%% maps items to tuples of
%% Weight(hectogram), Value and available Pieces
Line 2,078 ⟶ 2,837:
{System.printInfo "\n"}
{System.showInfo "total value: "#{Value Best}}
{System.showInfo "total weight: "#{Weight Best}}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,098 ⟶ 2,857:
</pre>
Takes about 3 seconds on a slow netbook.
 
=={{header|Pascal}}==
{{works with|FPC}}
Dynamic programming solution (tested with FPC 3.2.2).
<syntaxhighlight lang="pascal">
program KnapsackBounded;
{$mode objfpc}{$j-}
uses
SysUtils, Math;
 
type
TItem = record
Name: string;
Weight, Value, Count: Integer;
end;
 
const
NUM_ITEMS = 22;
ITEMS: array[0..NUM_ITEMS-1] of TItem = (
(Name: 'map'; Weight: 9; Value: 150; Count: 1),
(Name: 'compass'; Weight: 13; Value: 35; Count: 1),
(Name: 'water'; Weight: 153; Value: 200; Count: 2),
(Name: 'sandwich'; Weight: 50; Value: 60; Count: 2),
(Name: 'glucose'; Weight: 15; Value: 60; Count: 2),
(Name: 'tin'; Weight: 68; Value: 45; Count: 3),
(Name: 'banana'; Weight: 27; Value: 60; Count: 3),
(Name: 'apple'; Weight: 39; Value: 40; Count: 3),
(Name: 'cheese'; Weight: 23; Value: 30; Count: 1),
(Name: 'beer'; Weight: 52; Value: 10; Count: 3),
(Name: 'suntan cream'; Weight: 11; Value: 70; Count: 1),
(Name: 'camera'; Weight: 32; Value: 30; Count: 1),
(Name: 'T-shirt'; Weight: 24; Value: 15; Count: 2),
(Name: 'trousers'; Weight: 48; Value: 10; Count: 2),
(Name: 'umbrella'; Weight: 73; Value: 40; Count: 1),
(Name: 'waterproof trousers'; Weight: 42; Value: 70; Count: 1),
(Name: 'waterproof overclothes'; Weight: 43; Value: 75; Count: 1),
(Name: 'note-case'; Weight: 22; Value: 80; Count: 1),
(Name: 'sunglasses'; Weight: 7; Value: 20; Count: 1),
(Name: 'towel'; Weight: 18; Value: 12; Count: 2),
(Name: 'socks'; Weight: 4; Value: 50; Count: 1),
(Name: 'book'; Weight: 30; Value: 10; Count: 2)
);
MAX_WEIGHT = 400;
 
var
D: array of array of Integer; //DP matrix
I, W, V, C, MaxWeight: Integer;
begin
SetLength(D, NUM_ITEMS + 1, MAX_WEIGHT + 1);
for I := 0 to High(ITEMS) do
for W := 0 to MAX_WEIGHT do begin
D[I+1, W] := D[I, W];
for C := 1 to ITEMS[I].Count do begin
if ITEMS[I].Weight * C > W then break;
V := D[I, W - ITEMS[I].Weight * C] + ITEMS[I].Value * C;
if V > D[I+1, W] then
D[I+1, W] := V;
end;
end;
 
W := MAX_WEIGHT;
MaxWeight := 0;
WriteLn('bagged:');
for I := High(ITEMS) downto 0 do begin
V := D[I+1, W];
C := 0;
while V <> D[I, W] + ITEMS[I].Value * C do begin
Dec(W, ITEMS[I].Weight);
Inc(C);
end;
Inc(MaxWeight, C * ITEMS[I].Weight);
if C <> 0 then
WriteLn(' ', C, ' ', ITEMS[I].Name);
end;
WriteLn('value = ', D[NUM_ITEMS, MAX_WEIGHT]);
WriteLn('weight = ', MaxWeight);
end.
</syntaxhighlight>
{{out}}
<pre>
bagged:
1 socks
1 sunglasses
1 note-case
1 waterproof overclothes
1 suntan cream
1 cheese
3 banana
2 glucose
1 water
1 compass
1 map
value = 1010
weight = 396
</pre>
 
=={{header|Perl}}==
Recursive solution with caching.
<langsyntaxhighlight Perllang="perl">#!/usr/bin/perl
 
use strict;
Line 2,173 ⟶ 3,027:
}
}
print "Value: $v; Weight: $w\n";</langsyntaxhighlight>
{{out}}
<pre>1 of map
Line 2,187 ⟶ 3,041:
1 of socks
Value: 1010; Weight: 396</pre>
 
=={{header|Perl 6}}==
{{works with|Rakudo|2017.01}}
<lang perl6>my class KnapsackItem { has $.name; has $.weight; has $.unit; }
 
multi sub pokem ([], $, $v = 0) { $v }
multi sub pokem ([$, *@], 0, $v = 0) { $v }
multi sub pokem ([$i, *@rest], $w, $v = 0) {
my $key = "{+@rest} $w $v";
(state %cache){$key} or do {
my @skip = pokem @rest, $w, $v;
if $w >= $i.weight { # next one fits
my @put = pokem @rest, $w - $i.weight, $v + $i.unit;
return (%cache{$key} = |@put, $i.name).list if @put[0] > @skip[0];
}
return (%cache{$key} = |@skip).list;
}
}
 
my $MAX_WEIGHT = 400;
my @table = flat map -> $name, $weight, $unit, $count {
KnapsackItem.new( :$name, :$weight, :$unit ) xx $count;
},
'map', 9, 150, 1,
'compass', 13, 35, 1,
'water', 153, 200, 2,
'sandwich', 50, 60, 2,
'glucose', 15, 60, 2,
'tin', 68, 45, 3,
'banana', 27, 60, 3,
'apple', 39, 40, 3,
'cheese', 23, 30, 1,
'beer', 52, 10, 3,
'suntan cream', 11, 70, 1,
'camera', 32, 30, 1,
'T-shirt', 24, 15, 2,
'trousers', 48, 10, 2,
'umbrella', 73, 40, 1,
'waterproof trousers', 42, 70, 1,
'waterproof overclothes', 43, 75, 1,
'note-case', 22, 80, 1,
'sunglasses', 7, 20, 1,
'towel', 18, 12, 2,
'socks', 4, 50, 1,
'book', 30, 10, 2
;
 
my ($value, @result) = pokem @table, $MAX_WEIGHT;
 
(my %hash){$_}++ for @result;
 
say "Value = $value";
say "Tourist put in the bag:";
say " # ITEM";
for %hash.sort -> $item {
say " {$item.value} {$item.key}";
}</lang>
{{out}}
<pre>Value = 1010
Tourist put in the bag:
# ITEM
3 banana
1 cheese
1 compass
2 glucose
1 map
1 note-case
1 socks
1 sunglasses
1 suntan cream
1 water
1 waterproof overclothes</pre>
 
=={{header|Phix}}==
===Very dumb and very slow brute force version===
Of no practical use, except for comparison against improvements.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>atom t0 = time()
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
 
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
constant goodies = {
-- item weight value pieces
<span style="color: #008080;">constant</span> <span style="color: #000000;">goodies</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span>
{"map", 9, 150, 1},
{ <span style="compasscolor: #000080;font-style:italic;", >-- item 13, 35, weight value 1},pieces</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"map"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">150</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"sandwich", 50, 60, 2},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"compass"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">35</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"glucose", 15, 60, 2},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"sandwich"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">50</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">60</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
{"tin", 68, 45, 3},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"glucose"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">60</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
{"banana", 27, 60, 3},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"tin"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">68</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">45</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
{"apple", 39, 40, 3},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"banana"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">27</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">60</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
{"cheese", 23, 30, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"apple"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">39</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">40</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
{"beer", 52, 10, 3},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"cheese"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">23</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">30</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"suntan cream", 11, 70, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"beer"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">52</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
{"water", 153, 200, 2},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"suntan cream"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">70</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"camera", 32, 30, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"water"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">153</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">200</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
{"T-shirt", 24, 15, 2},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"camera"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">30</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"trousers", 48, 10, 2},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"T-shirt"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">24</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
{"umbrella", 73, 40, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"trousers"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">48</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
{"waterproof trousers", 42, 70, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"umbrella"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">73</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">40</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"waterproof overclothes", 43, 75, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"waterproof trousers"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">42</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">70</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"note-case", 22, 80, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"waterproof overclothes"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">43</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">75</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"sunglasses", 7, 20, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"note-case"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">22</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">80</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"towel", 18, 12, 2},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"sunglasses"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">20</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"socks", 4, 50, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"towel"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">18</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
{"book", 30, 10, 2}}
<span style="color: #0000FF;">{</span><span style="color: #008000;">"socks"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">50</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
 
<span style="color: #0000FF;">{</span><span style="color: #008000;">"book"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">30</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">}}</span>
function knapsack(integer max_weight, integer at)
integer best_points = 0, points
<span style="color: #008080;">function</span> <span style="color: #000000;">knapsack</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">max_weight</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">at</span><span style="color: #0000FF;">)</span>
sequence best_choices = {}, choices
<span style="color: #004080;">integer</span> <span style="color: #000000;">best_points</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">points</span>
atom act_weight = 0, sub_weight
<span style="color: #004080;">sequence</span> <span style="color: #000000;">best_choices</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000000;">choices</span>
if at>=1 then
<span style="color: #004080;">atom</span> <span style="color: #000000;">act_weight</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">sub_weight</span>
integer {?,witem,pitem,imax} = goodies[at]
<span style="color: #008080;">if</span> <span style="color: #000000;">at</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
for i=0 to imax do
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{?,</span><span style="color: #000000;">witem</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pitem</span><span style="color: #0000FF;">,</span><span style="color: #000000;">imax</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">goodies</span><span style="color: #0000FF;">[</span><span style="color: #000000;">at</span><span style="color: #0000FF;">]</span>
integer wlim = max_weight-i*witem
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">imax</span> <span style="color: #008080;">do</span>
if wlim<0 then exit end if
<span style="color: #004080;">integer</span> <span style="color: #000000;">wlim</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">max_weight</span><span style="color: #0000FF;">-</span><span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">witem</span>
{points,sub_weight,choices} = knapsack(wlim, at-1)
<span style="color: #008080;">if</span> <span style="color: #000000;">wlim</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
points += i*pitem
<span style="color: #0000FF;">{</span><span style="color: #000000;">points</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sub_weight</span><span style="color: #0000FF;">,</span><span style="color: #000000;">choices</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">knapsack</span><span style="color: #0000FF;">(</span><span style="color: #000000;">wlim</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">at</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
if points>best_points then
<span style="color: #000000;">points</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">pitem</span>
best_points = points
<span style="color: #008080;">if</span> <span style="color: #000000;">points</span><span style="color: #0000FF;">></span><span style="color: #000000;">best_points</span> <span style="color: #008080;">then</span>
best_choices = choices&i
<span style="color: #000000;">best_points</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">points</span>
act_weight = sub_weight+i*witem
<span style="color: #000000;">best_choices</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">choices</span><span style="color: #0000FF;">)&</span><span style="color: #000000;">i</span>
end if
<span style="color: #000000;">act_weight</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sub_weight</span><span style="color: #0000FF;">+</span><span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">witem</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return {best_points, act_weight, best_choices}
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">best_points</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">act_weight</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">best_choices</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
sequence res = knapsack(400, length(goodies)) -- {points,act_weight,choices}
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">knapsack</span><span style="color: #0000FF;">(</span><span style="color: #000000;">400</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">goodies</span><span style="color: #0000FF;">))</span> <span style="color: #000080;font-style:italic;">-- {points,act_weight,choices}</span>
atom weight = 0, witem
atom points = 0, pitem
<span style="color: #004080;">atom</span> <span style="color: #000000;">weight</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">witem</span>
string idesc
<span style="color: #004080;">atom</span> <span style="color: #000000;">points</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pitem</span>
for i=1 to length(goodies) do
<span style="color: #004080;">string</span> <span style="color: #000000;">idesc</span>
integer c = res[3][i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">goodies</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if c then
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
{idesc,witem,pitem} = goodies[i]
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span> <span style="color: #008080;">then</span>
printf(1,"%d %s\n",{c,idesc})
<span style="color: #0000FF;">{</span><span style="color: #000000;">idesc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">witem</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pitem</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">goodies</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
weight += c*witem
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">idesc</span><span style="color: #0000FF;">})</span>
points += c*pitem
<span style="color: #000000;">weight</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">*</span><span style="color: #000000;">witem</span>
end if
<span style="color: #000000;">points</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">*</span><span style="color: #000000;">pitem</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if points!=res[1] then ?9/0 end if -- sanity check
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
printf(1,"Value %d, weight %g [%3.2fs]\n",{points,weight,time()-t0})</lang>
<span style="color: #008080;">if</span> <span style="color: #000000;">points</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- sanity check</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Value %d, weight %g [%3.2fs]\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">points</span><span style="color: #0000FF;">,</span><span style="color: #000000;">weight</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 2,345 ⟶ 3,130:
Much faster but limited to integer weights
{{trans|C}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>sequence items = {
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
{"map", 9, 150, 1},
<span style="color: #004080;">sequence</span> <span style="color: #000000;">items</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span>
{"compass", 13, 35, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"map"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">150</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"water", 153, 200, 2},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"compass"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">35</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"sandwich", 50, 60, 2},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"water"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">153</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">200</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
{"glucose", 15, 60, 2},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"sandwich"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">50</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">60</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
{"tin", 68, 45, 3},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"glucose"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">60</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
{"banana", 27, 60, 3},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"tin"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">68</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">45</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
{"apple", 39, 40, 3},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"banana"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">27</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">60</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
{"cheese", 23, 30, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"apple"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">39</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">40</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
{"beer", 52, 10, 3},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"cheese"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">23</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">30</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"suntan cream", 11, 70, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"beer"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">52</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
{"camera", 32, 30, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"suntan cream"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">70</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"T-shirt", 24, 15, 2},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"camera"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">30</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"trousers", 48, 10, 2},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"T-shirt"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">24</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
{"umbrella", 73, 40, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"trousers"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">48</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
{"waterproof trousers", 42, 70, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"umbrella"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">73</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">40</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"waterproof overclothes",43, 75, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"waterproof trousers"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">42</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">70</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"note-case", 22, 80, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"waterproof overclothes"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">43</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">75</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"sunglasses", 7, 20, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"note-case"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">22</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">80</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"towel", 18, 12, 2},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"sunglasses"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">20</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
{"socks", 4, 50, 1},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"towel"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">18</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
{"book", 30, 10, 2},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"socks"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">50</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
};
<span style="color: #0000FF;">{</span><span style="color: #008000;">"book"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">30</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
 
<span style="color: #0000FF;">};</span>
sequence {names,weights,points,counts} = columnize(items)
 
<span style="color: #004080;">sequence</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">names</span><span style="color: #0000FF;">,</span><span style="color: #000000;">weights</span><span style="color: #0000FF;">,</span><span style="color: #000000;">points</span><span style="color: #0000FF;">,</span><span style="color: #000000;">counts</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize</span><span style="color: #0000FF;">(</span><span style="color: #000000;">items</span><span style="color: #0000FF;">)</span>
constant n = length(items)
 
<span style="color: #008080;">constant</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">items</span><span style="color: #0000FF;">)</span>
function knapsack(int w)
int v
<span style="color: #008080;">function</span> <span style="color: #000000;">knapsack</span><span style="color: #0000FF;">(</span><span style="color: #004080;">int</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">)</span>
-- m is the achievable points matrix:
<span style="color: #004080;">integer</span> <span style="color: #000000;">v</span>
-- Note that Phix uses 1-based indexes, so m[1][1]
<span style="color: #000080;font-style:italic;">-- m is the achievable points matrix:
-- actually holds points for 0 items of weight 0,
-- Note that Phix uses 1-based indexes, so m[1][1]
-- and m[n+1][w+1] is for n items at weight w.
-- actually holds points for 0 items of weight 0,
seq m = repeat(repeat(0,w+1),n+1)
-- and m[n+1][w+1] is for n items at weight w.</span>
for i=1 to n do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">w</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span><span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
for j=1 to w+1 do -- (0 to w really)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
m[i+1][j] = m[i][j]
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- (0 to w really)</span>
for k=1 to counts[i] do
<span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
if k*weights[i]>j-1 then
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">do</span>
exit
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">*</span><span style="color: #000000;">weights</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]></span><span style="color: #000000;">j</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
end if
v <span style="color: m[i][j-k*weights[i]]+k*points[i]#008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if v>m[i+1][j] then
<span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">-</span><span style="color: #000000;">k</span><span style="color: #0000FF;">*</span><span style="color: #000000;">weights</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]]+</span><span style="color: #000000;">k</span><span style="color: #0000FF;">*</span><span style="color: #000000;">points</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
m[i+1][j] = v
<span style="color: #008080;">if</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">></span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">v</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
seq s = repeat(0,n)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
int j = w+1 -- (w -> 0 really)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
for i=n+1 to 2 by -1 do -- (n to 1 really)
<span style="color: #004080;">integer</span> <span style="color: #000000;">j</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- (w -&gt; 0 really)</span>
v = m[i][j]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">n</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
int k = 0
<span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
while v!=m[i-1][j]+k*points[i-1] do
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
s[i-1] += 1
<span style="color: #008080;">while</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">k</span><span style="color: #0000FF;">*</span><span style="color: #000000;">points</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">do</span>
j -= weights[i-1]
<span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
k += 1
<span style="color: #000000;">j</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">weights</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
end while
<span style="color: #000000;">k</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
return s
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">s</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
int tc = 0, tw = 0, tv = 0
seq s = knapsack(400)
<span style="color: #004080;">integer</span> <span style="color: #000000;">tc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tw</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tv</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
for i=1 to n do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">knapsack</span><span style="color: #0000FF;">(</span><span style="color: #000000;">400</span><span style="color: #0000FF;">)</span>
int si = s[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
if si then
<span style="color: #004080;">integer</span> <span style="color: #000000;">si</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
printf(1,"%-22s %5d %5d %5d\n", {names[i], si, si*weights[i], si*points[i]})
<span style="color: #008080;">if</span> <span style="color: #000000;">si</span> <span style="color: #008080;">then</span>
tc += si
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%-22s %5d %5d %5d\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">names</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">*</span><span style="color: #000000;">weights</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">*</span><span style="color: #000000;">points</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]})</span>
tw += si*weights[i]
<span style="color: #000000;">tc</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">si</span>
tv += si*points[i]
<span style="color: #000000;">tw</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">*</span><span style="color: #000000;">weights</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
end if
<span style="color: #000000;">tv</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">*</span><span style="color: #000000;">points</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
printf(1,"%-22s %5d %5d %5d\n", {"count, weight, points:", tc, tw, tv})</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%-22s %5d %5d %5d\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"count, weight, points:"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tw</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tv</span><span style="color: #0000FF;">})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 2,441 ⟶ 3,229:
would obviously increase dramatically. A naive cache could also suffer similarly, if it retained
duplicate solutions for w=15.783, 15.784, 15.785, and everything in between.
Using a (bespoke) range cache solves this problem, although the simplistic version given could probably be improved with a binary search or similar. It also significantly reduces the workload; for instance if you find a solution for 170 that actually weighs 150 then any subsequent query in 150..170 requires zero work, unlike the naive cache and dp solutions.
Using a (bespoke) range cache solves this problem.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>--
<span style="color: #000080;font-style:italic;">-- demo\rosetta\knapsackB.exw</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
-- ==========================
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
--
atom t0 = time()
 
enum HI,PTS,ACTW,SOLN
sequence range_cache = {}
 
integer cache_entries = 0
 
procedure add_range(integer at, atom weight, atom actual_weight, atom points, sequence soln)
if actual_weight>weight then ?9/0 end if
for i=length(range_cache)+1 to at do -- (while too small do)
if i=at then
range_cache = append(range_cache,{{weight,points,actual_weight,soln}})
cache_entries += 1
return
end if
range_cache = append(range_cache,{})
end for
for i=1 to length(range_cache[at]) do
sequence rcati = range_cache[at][i]
if weight=rcati[ACTW] then
if rcati[PTS..SOLN]!={points,actual_weight,soln} then ?9/0 end if
elsif weight<rcati[ACTW] then
-- (we cannot extend an existing range down...)
if soln=rcati[SOLN] then ?9/0 end if
-- insert a new range
range_cache[at][i..i-1] = {{weight,points,actual_weight,soln}}
cache_entries += 1
return
elsif soln=rcati[SOLN] then
if rcati[PTS..SOLN]!={points,actual_weight,soln} then ?9/0 end if
if weight>rcati[HI] then -- extend existing range up
rcati = {}
range_cache[at][i][HI] = weight
end if
return
elsif weight<=rcati[HI] then
?9/0 -- duplicate solution?? (or discard as below)
-- return -- (discard)
end if
end for
range_cache[at] = append(range_cache[at],{weight,points,actual_weight,soln})
cache_entries += 1
end procedure
 
function in_range(integer at, atom weight)
if at<=length(range_cache) then
for i=1 to length(range_cache[at]) do
sequence rcati = range_cache[at][i]
if weight<=rcati[HI] then
if weight>=rcati[ACTW] then
return rcati[PTS..SOLN] -- {pts,act_weight,soln}
end if
exit
end if
end for
end if
return {} -- (no suitable cache entry found)
end function
 
constant goodies = {
-- item weight value pieces
{"map", 9, 150, 1},
{"compass", 13, 35, 1},
{"sandwich", 50, 60, 2},
{"glucose", 15, 60, 2},
{"tin", 68, 45, 3},
{"banana", 27, 60, 3},
{"apple", 39, 40, 3},
{"cheese", 23, 30, 1},
{"beer", 52, 10, 3},
{"suntan cream", 11, 70, 1},
{"water", 153, 200, 2},
{"camera", 32, 30, 1},
{"T-shirt", 24, 15, 2},
{"trousers", 48, 10, 2},
{"umbrella", 73, 40, 1},
{"waterproof trousers", 42, 70, 1},
{"waterproof overclothes", 43, 75, 1},
{"note-case", 22, 80, 1},
{"sunglasses", 7, 20, 1},
{"towel", 18, 12, 2},
{"socks", 4, 50, 1},
{"book", 30, 10, 2}}
 
integer cache_hits = 0
integer cache_misses = 0
 
function knapsack(integer max_weight, integer at)
integer best_points = 0, points
sequence best_choices = {}, choices
atom act_weight = 0, sub_weight
if at>=1 then
sequence soln = in_range(at,max_weight)
if length(soln) then
cache_hits += 1
return soln
end if
cache_misses += 1
integer {?,witem,pitem,imax} = goodies[at]
for i=0 to imax do
integer wlim = max_weight-i*witem
if wlim<0 then exit end if
{points,sub_weight,choices} = knapsack(wlim, at-1)
points += i*pitem
if points>best_points then
best_points = points
best_choices = choices&i
act_weight = sub_weight+i*witem
end if
end for
add_range(at,max_weight,act_weight,best_points,best_choices)
end if
return {best_points, act_weight, best_choices}
end function
<span style="color: #008080;">enum</span> <span style="color: #000000;">HI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PTS</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ACTW</span><span style="color: #0000FF;">,</span><span style="color: #000000;">SOLN</span>
sequence res = knapsack(400, length(goodies)) -- {points,act_weight,choices}
<span style="color: #004080;">sequence</span> <span style="color: #000000;">range_cache</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">cache_entries</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
atom weight = 0, witem
atom points = 0, pitem
<span style="color: #008080;">procedure</span> <span style="color: #000000;">add_range</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">at</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">weight</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">actual_weight</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">points</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">soln</span><span style="color: #0000FF;">)</span>
string idesc
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">actual_weight</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">weight</span><span style="color: #0000FF;">)</span>
for i=1 to length(goodies) do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">range_cache</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">at</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- (while too small do)</span>
integer c = res[3][i]
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">at</span> <span style="color: #008080;">then</span>
if c then
<span style="color: #000000;">range_cache</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">range_cache</span><span style="color: #0000FF;">,{{</span><span style="color: #000000;">weight</span><span style="color: #0000FF;">,</span><span style="color: #000000;">points</span><span style="color: #0000FF;">,</span><span style="color: #000000;">actual_weight</span><span style="color: #0000FF;">,</span><span style="color: #000000;">soln</span><span style="color: #0000FF;">}})</span>
{idesc,witem,pitem} = goodies[i]
<span style="color: #000000;">cache_entries</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
printf(1,"%d %s\n",{c,idesc})
<span style="color: #008080;">return</span>
weight += c*witem
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
points += c*pitem
<span style="color: #000000;">range_cache</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">range_cache</span><span style="color: #0000FF;">,{})</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #004080;">integer</span> <span style="color: #000000;">lastHI</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
if points!=res[1] then ?9/0 end if -- sanity check
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">range_cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">at</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
printf(1,"Value %d, weight %g [%3.2fs]\n",{points,weight,time()-t0})
<span style="color: #004080;">sequence</span> <span style="color: #000000;">rcati</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">range_cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">at</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
 
<span style="color: #008080;">if</span> <span style="color: #000000;">weight</span><span style="color: #0000FF;">=</span><span style="color: #000000;">rcati</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ACTW</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
printf(1,"cache_entries:%d, hits:%d, misses:%d\n",{cache_entries,cache_hits,cache_misses})</lang>
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rcati</span><span style="color: #0000FF;">[</span><span style="color: #000000;">PTS</span><span style="color: #0000FF;">..</span><span style="color: #000000;">SOLN</span><span style="color: #0000FF;">]=={</span><span style="color: #000000;">points</span><span style="color: #0000FF;">,</span><span style="color: #000000;">actual_weight</span><span style="color: #0000FF;">,</span><span style="color: #000000;">soln</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">return</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">weight</span><span style="color: #0000FF;"><</span><span style="color: #000000;">rcati</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ACTW</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- (we cannot extend an existing range down...)</span>
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">soln</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">rcati</span><span style="color: #0000FF;">[</span><span style="color: #000000;">SOLN</span><span style="color: #0000FF;">])</span>
<span style="color: #000080;font-style:italic;">-- insert a new range</span>
<span style="color: #000000;">range_cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">at</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">..</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">weight</span><span style="color: #0000FF;">,</span><span style="color: #000000;">points</span><span style="color: #0000FF;">,</span><span style="color: #000000;">actual_weight</span><span style="color: #0000FF;">,</span><span style="color: #000000;">soln</span><span style="color: #0000FF;">}}</span>
<span style="color: #000000;">cache_entries</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">return</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">soln</span><span style="color: #0000FF;">=</span><span style="color: #000000;">rcati</span><span style="color: #0000FF;">[</span><span style="color: #000000;">SOLN</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rcati</span><span style="color: #0000FF;">[</span><span style="color: #000000;">PTS</span><span style="color: #0000FF;">..</span><span style="color: #000000;">SOLN</span><span style="color: #0000FF;">]=={</span><span style="color: #000000;">points</span><span style="color: #0000FF;">,</span><span style="color: #000000;">actual_weight</span><span style="color: #0000FF;">,</span><span style="color: #000000;">soln</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">weight</span><span style="color: #0000FF;">></span><span style="color: #000000;">rcati</span><span style="color: #0000FF;">[</span><span style="color: #000000;">HI</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- extend existing range up</span>
<span style="color: #000000;">rcati</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #000000;">range_cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">at</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">HI</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">weight</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">weight</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">rcati</span><span style="color: #0000FF;">[</span><span style="color: #000000;">HI</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"duplicate solution??"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (or discard as below)
-- return -- (discard)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rcati</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ACTW</span><span style="color: #0000FF;">]></span><span style="color: #000000;">lastHI</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">lastHI</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rcati</span><span style="color: #0000FF;">[</span><span style="color: #000000;">HI</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">range_cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">at</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">range_cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">at</span><span style="color: #0000FF;">],{</span><span style="color: #000000;">weight</span><span style="color: #0000FF;">,</span><span style="color: #000000;">points</span><span style="color: #0000FF;">,</span><span style="color: #000000;">actual_weight</span><span style="color: #0000FF;">,</span><span style="color: #000000;">soln</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">cache_entries</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">in_range</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">at</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">weight</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">at</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">range_cache</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">range_cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">at</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">rcati</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">range_cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">at</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">weight</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">rcati</span><span style="color: #0000FF;">[</span><span style="color: #000000;">HI</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">weight</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">rcati</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ACTW</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">rcati</span><span style="color: #0000FF;">[</span><span style="color: #000000;">PTS</span><span style="color: #0000FF;">..</span><span style="color: #000000;">SOLN</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">-- {pts,act_weight,soln}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">-- (no suitable cache entry found)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">goodies</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">({</span>
<span style="color: #000080;font-style:italic;">-- item weight value pieces</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"map"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">150</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"compass"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">35</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"sandwich"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">50</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">60</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"glucose"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">60</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"tin"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">68</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">45</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"banana"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">27</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">60</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"apple"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">39</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">40</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"cheese"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">23</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">30</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"beer"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">52</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"suntan cream"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">70</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"water"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">153</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">200</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"camera"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">30</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"T-shirt"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">24</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"trousers"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">48</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"umbrella"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">73</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">40</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"waterproof trousers"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">42</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">70</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"waterproof overclothes"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">43</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">75</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"note-case"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">22</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">80</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"sunglasses"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">20</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"towel"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">18</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"socks"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">50</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"book"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">30</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">}})</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">cache_hits</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">cache_misses</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">knapsack</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">max_weight</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">at</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">best_points</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">points</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">best_choices</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000000;">choices</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">act_weight</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">sub_weight</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">at</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">soln</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">in_range</span><span style="color: #0000FF;">(</span><span style="color: #000000;">at</span><span style="color: #0000FF;">,</span><span style="color: #000000;">max_weight</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">soln</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">cache_hits</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">soln</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">cache_misses</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{?,</span><span style="color: #000000;">witem</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pitem</span><span style="color: #0000FF;">,</span><span style="color: #000000;">imax</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">goodies</span><span style="color: #0000FF;">[</span><span style="color: #000000;">at</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">best_choices</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">at</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">imax</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">wlim</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">max_weight</span><span style="color: #0000FF;">-</span><span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">witem</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">wlim</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">points</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sub_weight</span><span style="color: #0000FF;">,</span><span style="color: #000000;">choices</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">knapsack</span><span style="color: #0000FF;">(</span><span style="color: #000000;">wlim</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">at</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">points</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">pitem</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">points</span><span style="color: #0000FF;">></span><span style="color: #000000;">best_points</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">best_points</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">points</span>
<span style="color: #000000;">best_choices</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">choices</span><span style="color: #0000FF;">)&</span><span style="color: #000000;">i</span>
<span style="color: #000000;">act_weight</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sub_weight</span><span style="color: #0000FF;">+</span><span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">witem</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">add_range</span><span style="color: #0000FF;">(</span><span style="color: #000000;">at</span><span style="color: #0000FF;">,</span><span style="color: #000000;">max_weight</span><span style="color: #0000FF;">,</span><span style="color: #000000;">act_weight</span><span style="color: #0000FF;">,</span><span style="color: #000000;">best_points</span><span style="color: #0000FF;">,</span><span style="color: #000000;">best_choices</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">best_points</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">act_weight</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">best_choices</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">knapsack</span><span style="color: #0000FF;">(</span><span style="color: #000000;">400</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">goodies</span><span style="color: #0000FF;">))</span> <span style="color: #000080;font-style:italic;">-- {points,act_weight,choices}</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">weight</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">witem</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">points</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pitem</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">idesc</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">choices</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">goodies</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">choices</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">idesc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">witem</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pitem</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">goodies</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">idesc</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">weight</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">*</span><span style="color: #000000;">witem</span>
<span style="color: #000000;">points</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">*</span><span style="color: #000000;">pitem</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">({</span><span style="color: #000000;">points</span><span style="color: #0000FF;">,</span><span style="color: #000000;">weight</span><span style="color: #0000FF;">}==</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span> <span style="color: #000080;font-style:italic;">-- sanity check</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Value %d, weight %g [%3.2fs]:\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">points</span><span style="color: #0000FF;">,</span><span style="color: #000000;">weight</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"cache_entries:%d, hits:%d, misses:%d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">cache_entries</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cache_hits</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cache_misses</span><span style="color: #0000FF;">})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 2,602 ⟶ 3,396:
</pre>
Even on this simple integer-only case, range cache reduces cache size better than 10-fold and effort 6-fold.<br>
We also know the dp solution matrix has 9223 entries, admittedly each being much smaller than a cache entry.<br>
Anf finally CACHE_NONE (the dumb version): (as above but ending)
And finally CACHE_NONE (the dumb version): (as above but ending)
<pre>
Value 1010, weight 396 [18.14s]
cache_entries:0, hits:0, misses:33615741
</pre>
 
=={{header|Picat}}==
<syntaxhighlight lang="picat">import mip,util.
 
go =>
data(AllItems,MaxWeight),
[Items,Weights,Values,Pieces] = transpose(AllItems),
knapsack_bounded(Weights,Values,Pieces,MaxWeight, X,TotalWeight,TotalValue),
print_solution(Items,Weights,Values, X,TotalWeight,TotalValue),
nl.
 
% Print the solution
print_solution(Items,Weights,Values, X,TotalWeight,TotalValue) ?=>
println("\nThese are the items to pick:"),
println(" Item Weight Value"),
 
foreach(I in 1..Items.len)
if X[I] > 0 then
printf("* %d %-29w %3d %3d\n", X[I],Items[I],Weights[I],Values[I])
end
end,
nl,
printf("Total weight: %d\n", TotalWeight),
printf("Total value: %d\n", TotalValue),
nl.
 
% Solve knapsack problem
knapsack_bounded(Weights,Values,Pieces,MaxWeight, X,TotalWeight,TotalValue) =>
NumItems = length(Weights),
 
% Variables
MaxPieces = max(Pieces),
X = new_list(NumItems),
X :: 0..MaxPieces,
 
% Constraints
SumValues = sum(Values),
TotalValue :: 0..SumValues,
TotalWeight :: 0..MaxWeight,
 
scalar_product(Weights,X,TotalWeight),
scalar_product(Values,X,TotalValue),
 
TotalWeight #<= MaxWeight,
 
% Check number of pieces
foreach({XVal,Piece} in zip(X,Pieces))
XVal #=< Piece
end,
 
% Search
Vars = X ++ [TotalWeight, TotalValue],
solve($[max(TotalValue),down],Vars).
 
% data
data(Items,MaxWeight) =>
Items =
% Item Weight Value Pieces
[["map", 9, 150, 1],
["compass", 13, 35, 1],
["water", 153, 200, 2],
["sandwich", 50, 60, 2],
["glucose", 15, 60, 2],
["tin", 68, 45, 3],
["banana", 27, 60, 3],
["apple", 39, 40, 3],
["cheese", 23, 30, 1],
["beer", 52, 10, 3],
["suntancream", 11, 70, 1],
["camera", 32, 30, 1],
["T-shirt", 24, 15, 2],
["trousers", 48, 10, 2],
["umbrella", 73, 40, 1],
["waterproof trousers", 42, 70, 1],
["waterproof overclothes", 43, 75, 1],
["note-case", 22, 80, 1],
["sunglasses", 7, 20, 1],
["towel", 18, 12, 2],
["socks", 4, 50, 1],
["book", 30, 10, 2]],
MaxWeight = 400.</syntaxhighlight>
 
{{out}}
<pre>These are the items to pick:
Item Weight Value
* 1 map 9 150
* 1 compass 13 35
* 1 water 153 200
* 2 glucose 15 60
* 3 banana 27 60
* 1 cheese 23 30
* 1 suntancream 11 70
* 1 waterproof overclothes 43 75
* 1 note-case 22 80
* 1 sunglasses 7 20
* 1 socks 4 50
 
Total weight: 396
Total value: 1010</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de *Items
("map" 9 150 1) ("compass" 13 35 1)
("water" 153 200 3) ("sandwich" 50 60 2)
Line 2,640 ⟶ 3,536:
(for I K
(apply tab I (3 -24 6 6) NIL) )
(tab (27 6 6) NIL (sum cadr K) (sum caddr K)) )</langsyntaxhighlight>
{{out}}
<pre> map 9 150
Line 2,663 ⟶ 3,559:
{{libheader|clpfd}}
Library clpfd is written by <b>Markus Triska</b>. Takes about 3 seconds to compute the best solution.
<langsyntaxhighlight Prologlang="prolog">:- use_module(library(clpfd)).
 
% tuples (name, weights, value, nb pieces).
Line 2,738 ⟶ 3,634:
sformat(W3, A3, [V]),
format('~w~w~w~w~n', [W0,W1,W2,W3]),
print_results(A1, A2, A3, T, TR, WM, VM).</langsyntaxhighlight>
{{out}}
<pre> ?- knapsack.
Line 2,758 ⟶ 3,654:
===Library simplex===
Library simplex is written by <b>Markus Triska</b>. Takes about 10 seconds to compute the best solution.
<langsyntaxhighlight Prologlang="prolog">:- use_module(library(simplex)).
% tuples (name, weights, value, pieces).
knapsack :-
Line 2,837 ⟶ 3,733:
W2 is W1 + X * W,
V2 is V1 + X * V),
print_results(S, A1, A2, A3, T, TN, W2, V2).</langsyntaxhighlight>
 
=={{header|Python}}==
Not as [[Knapsack problem/0-1#Python|dumb a search]] over all possible combinations under the maximum allowed weight:
<langsyntaxhighlight lang="python">from itertools import groupby
from collections import namedtuple
from pprint import pprint as pp
 
def anyvalidcomb(items, maxwt, val=0, wt=0):
' All combinations below the maxwt '
if not items:
Line 2,851 ⟶ 3,746:
else:
this, *items = items # car, cdr
for n in range(this.number + 1):
vw = valwt + n * this.valueweight
w = wt + n*this.weight
if w > maxwt:
break
forv c= inval anyvalidcomb(items,+ v,n * w):this.value
this_comb yield= [this] * n + c[COMB], c[VAL], c[WT]
for comb, value, weight in anyvalidcomb(items, maxwt, v, w):
yield this_comb + comb, value, weight
 
maxwt = 400
Line 2,888 ⟶ 3,784:
) ]
 
bagged = max( anyvalidcomb(items, maxwt), key=lambda c: (c[VAL], -c[WT])) # max val or min wt if values equal
print("Bagged the following %i items\n " % len(bagged[COMB]) +)
print('\n \t'.join('%i off: %s' % (len(list(grp)), item.name) for item, grp in groupby(sorted(bagged[COMB]))))
print("for a total value of %i and a total weight of %i" % bagged[1:])</syntaxhighlight>
for item,grp in groupby(sorted(bagged[COMB]))))
print("for a total value of %i and a total weight of %i" % bagged[1:])</lang>
{{out}}
<pre>Bagged the following 14 items
Line 2,909 ⟶ 3,804:
===Dynamic programming solution===
This is much faster. It expands the multiple possible instances of an item into individual instances then applies the zero-one dynamic knapsack solution:
<langsyntaxhighlight lang="python">from itertools import groupby
 
try:
Line 2,974 ⟶ 3,869:
for item,grp in groupby(sorted(bagged))))
print("for a total value of %i and a total weight of %i" % (
sum(item[2] for item in bagged), sum(item[1] for item in bagged)))</langsyntaxhighlight>
===Non-zero-one solution===
<langsyntaxhighlight Pythonlang="python">items = ({
("mapsandwich",: 9(50, 15060, 12),
("compassmap",: 13 (9, 35150, 1),
("watercompass",: 153(13, 20035, 31),
("sandwichwater",: 50(153, 60200, 23),
("glucose",: (15, 60, 2),
("tin",: (68, 45, 3),
("banana",: (27, 60, 3),
("apple",: (39, 40, 3),
("cheese",: (23, 30, 1),
("beer",: (52, 10, 3),
("suntan cream",: (11, 70, 1),
("camera",: (32, 30, 1),
("t-shirt",: (24, 15, 2),
("trousers",: (48, 10, 2),
("umbrella",: (73, 40, 1),
("w-trousers",: (42, 70, 1),
("w-overcoat",: (43, 75, 1),
("note-case",: (22, 80, 1),
("sunglasses",: (7, 20, 1),
("towel",: (18, 12, 2),
("socks",: (4, 50, 1),
("book",: (30, 10, 2),
}
)
 
item_keys = list(items.keys())
 
#cache: could just use memoize module, but explicit caching is clearer
def choose_item(weight, idx, cache):
if idx < 0: return 0, []
 
k = (weight, idx)
if k in cache: return cache[k]
 
name, w, v, qty = item_keys[idx], *items[item_keys[idx]]
best_v, best_list = 0, []
 
for i in range(0, qty + 1):
wlim = weight - i * w
if wlim < 0: break
 
val, taken = choose_item(wlim, idx - 1, cache)
if val + i * v > best_v:
best_v = val + i * v
best_list = taken[:]
best_list.append((i, name))
 
cache[k] = [best_v, best_list]
return best_v, best_list
 
 
v, lst = choose_item(400, len(items) - 1, {})
w = 0
for icnt, cntname in enumerate(lst):
if cnt > 0:
print (cnt, items[i][0]name)
w = w + items[iname][10] * cnt
print("Total weight:", w, "Value:", v)</syntaxhighlight>
 
=={{header|R}}==
print "Total weight:", w, "Value:", v</lang>
Reading in task via web scraping.
 
<syntaxhighlight lang="r">library(tidyverse)
library(rvest)
 
task_html= read_html("http://rosettacode.org/wiki/Knapsack_problem/Bounded")
task_table= html_nodes(html, "table")[[1]] %>%
html_table(table, header= T, trim= T) %>%
set_names(c("items", "weight", "value", "pieces")) %>%
filter(items != "knapsack") %>%
mutate(weight= as.numeric(weight),
value= as.numeric(value),
pieces= as.numeric(pieces))</syntaxhighlight>
 
Solution of the task using genetic algorithm.
 
<syntaxhighlight lang="r">library(rgenoud)
 
fitness= function(x= rep(1, nrow(task_table))){
total_value= sum(task_table$value * x)
total_weight= sum(task_table$weight * x)
ifelse(total_weight <= 400, total_value, 400-total_weight)
}
 
allowed= matrix(c(rep(0, nrow(task_table)), task_table$pieces), ncol = 2)
set.seed(42)
evolution= genoud(fn= fitness,
nvars= nrow(allowed),
max= TRUE,
pop.size= 10000,
data.type.int= TRUE,
Domains= allowed)
 
cat("Value: ", evolution$value, "\n")
cat("Weight:", sum(task_table$weight * evolution$par), "dag", "\n")
data.frame(item= task_table$items, pieces= as.integer(solution)) %>%
filter(solution> 0)</syntaxhighlight>
 
{{out}}
<pre>
Value: 1010
Weight: 396 dag
item pieces
1 map 1
2 compass 1
3 sandwich 1
4 glucose 2
5 banana 3
6 apple 2
7 cheese 1
8 suntan cream 1
9 waterproof overclothes 1
10 note-case 1
11 sunglasses 1
12 towel 1
13 socks 1
</pre>
 
=={{header|Racket}}==
The algorithm is nearly a direct translation of Haskell's array-based implementation. However, the data is taken from the webpage itself.
 
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
(require net/url html xml xml/path)
Line 3,126 ⟶ 4,083:
(match-let ([(solution value choices) (best (vector->list (solution-vector capacity)))])
(solution value (filter (compose positive? choice-count) choices))))
</syntaxhighlight>
</lang>
 
{{out}}
Line 3,145 ⟶ 4,102:
(choice "map" 1)))
</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
==== Original ====
Recursive algorithm, with cache. Idiomatic code style, using multi-subs and a class.
{{works with|Rakudo|2017.01}}
<syntaxhighlight lang="raku" line>my class KnapsackItem { has $.name; has $.weight; has $.unit; }
 
multi sub pokem ([], $, $v = 0) { $v }
multi sub pokem ([$, *@], 0, $v = 0) { $v }
multi sub pokem ([$i, *@rest], $w, $v = 0) {
my $key = "{+@rest} $w $v";
(state %cache){$key} or do {
my @skip = pokem @rest, $w, $v;
if $w >= $i.weight { # next one fits
my @put = pokem @rest, $w - $i.weight, $v + $i.unit;
return (%cache{$key} = |@put, $i.name).list if @put[0] > @skip[0];
}
return (%cache{$key} = |@skip).list;
}
}
 
my $MAX_WEIGHT = 400;
my @table = flat map -> $name, $weight, $unit, $count {
KnapsackItem.new( :$name, :$weight, :$unit ) xx $count;
},
'map', 9, 150, 1,
'compass', 13, 35, 1,
'water', 153, 200, 2,
'sandwich', 50, 60, 2,
'glucose', 15, 60, 2,
'tin', 68, 45, 3,
'banana', 27, 60, 3,
'apple', 39, 40, 3,
'cheese', 23, 30, 1,
'beer', 52, 10, 3,
'suntan cream', 11, 70, 1,
'camera', 32, 30, 1,
'T-shirt', 24, 15, 2,
'trousers', 48, 10, 2,
'umbrella', 73, 40, 1,
'waterproof trousers', 42, 70, 1,
'waterproof overclothes', 43, 75, 1,
'note-case', 22, 80, 1,
'sunglasses', 7, 20, 1,
'towel', 18, 12, 2,
'socks', 4, 50, 1,
'book', 30, 10, 2
;
 
my ($value, @result) = pokem @table, $MAX_WEIGHT;
 
(my %hash){$_}++ for @result;
 
say "Value = $value";
say "Tourist put in the bag:";
say " # ITEM";
for %hash.sort -> $item {
say " {$item.value} {$item.key}";
}</syntaxhighlight>
{{out}}
<pre>Value = 1010
Tourist put in the bag:
# ITEM
3 banana
1 cheese
1 compass
2 glucose
1 map
1 note-case
1 socks
1 sunglasses
1 suntan cream
1 water
1 waterproof overclothes</pre>
 
==== Faster alternative ====
Also recursive, with cache, but substantially faster. Code more generic (ported from Perl solution).
<syntaxhighlight lang="raku" line>my $raw = qq:to/TABLE/;
map 9 150 1
compass 13 35 1
water 153 200 2
sandwich 50 60 2
glucose 15 60 2
tin 68 45 3
banana 27 60 3
apple 39 40 3
cheese 23 30 1
beer 52 10 1
suntancream 11 70 1
camera 32 30 1
T-shirt 24 15 2
trousers 48 10 2
umbrella 73 40 1
w_trousers 42 70 1
w_overcoat 43 75 1
note-case 22 80 1
sunglasses 7 20 1
towel 18 12 2
socks 4 50 1
book 30 10 2
TABLE
 
my @items;
for split(["\n", /\s+/], $raw, :skip-empty) -> $n,$w,$v,$q {
@items.push: %{ name => $n, weight => $w, value => $v, quant => $q}
}
 
my $max_weight = 400;
 
sub pick ($weight, $pos) {
state %cache;
return 0, 0 if $pos < 0 or $weight <= 0;
 
my $key = $weight ~ $pos;
%cache{$key} or do {
my %item = @items[$pos];
my ($bv, $bi, $bw, @bp) = (0, 0, 0);
 
for 0 .. %item{'quant'} -> $i {
last if $i * %item{'weight'} > $weight;
my ($v, $w, @p) = pick($weight - $i * %item{'weight'}, $pos - 1);
next if ($v += $i * %item{'value'}) <= $bv;
 
($bv, $bi, $bw, @bp) = ($v, $i, $w, |@p);
}
%cache{$key} = $bv, $bw + $bi * %item{'weight'}, |@bp, $bi;
}
}
 
my ($v, $w, @p) = pick($max_weight, @items.end);
{ say "{@p[$_]} of @items[$_]{'name'}" if @p[$_] } for 0 .. @p.end;
say "Value: $v Weight: $w";</syntaxhighlight>
{{out}}
<pre>1 of map
1 of compass
1 of water
2 of glucose
3 of banana
1 of cheese
1 of suntancream
1 of w_overcoat
1 of note-case
1 of sunglasses
1 of socks
Value: 1010 Weight: 396</pre>
 
=={{header|REXX}}==
Line 3,152 ⟶ 4,255:
<br>"unrolled" and converted into discrete combination checks (based on the number of items). &nbsp; The unused combinatorial
<br>checks were discarded and only the pertinent code was retained.
<langsyntaxhighlight lang="rexx">/*REXX program solves a knapsack problem (22 items + repeats, with weight restriction.*/
call @gen /*generate items and initializations. */
call @sort /*sort items by decreasing their weight*/
Line 3,307 ⟶ 4,410:
do j37=j36+(j36>0) to h;if w.j37+w36>m then iterate j36;w37=w36+w.j37;z37=z36+v.j37;if z37>$ then call j? 37
end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end
end;end;end;end;end;end;end;end;end;end; return /* [↑] there is one END for each DO loop.*/</langsyntaxhighlight>
'''output'''
<pre>
Line 3,366 ⟶ 4,469:
{{trans|Python}}
 
<langsyntaxhighlight lang="ruby">
# Item struct to represent each item in the problem
Struct.new('Item', :name, :weight, :value, :count)
Line 3,426 ⟶ 4,529:
 
p "Total weight: #{w}, Value: #{val}"
</syntaxhighlight>
</lang>
 
=={{header|SAS}}==
 
Use MILP solver in SAS/OR:
<langsyntaxhighlight lang="sas">/* create SAS data set */
data mydata;
input item $1-23 weight value pieces;
Line 3,480 ⟶ 4,583:
print TotalValue;
print {i in ITEMS: NumSelected[i].sol > 0.5} NumSelected;
quit;</langsyntaxhighlight>
 
Output:
Line 3,503 ⟶ 4,606:
=={{header|Sidef}}==
{{trans|Perl}}
<langsyntaxhighlight lang="ruby">var raw = <<'TABLE'
map 9 150 1
compass 13 35 1
Line 3,569 ⟶ 4,672:
say "#{p[i]} of #{items[i].name}" if p[i].is_pos
}
say "Value: #{v}; Weight: #{w}"</langsyntaxhighlight>
{{out}}
<pre>
Line 3,584 ⟶ 4,687:
1 of socks
Value: 1010; Weight: 396
</pre>
 
=={{header|Swift}}==
 
{{trans|Python}}
 
<syntaxhighlight lang="swift">public struct KnapsackItem: Hashable {
public var name: String
public var weight: Int
public var value: Int
 
public init(name: String, weight: Int, value: Int) {
self.name = name
self.weight = weight
self.value = value
}
}
 
public func knapsack(items: [KnapsackItem], limit: Int) -> [KnapsackItem] {
var table = Array(repeating: Array(repeating: 0, count: limit + 1), count: items.count + 1)
 
for j in 1...items.count {
let item = items[j-1]
 
for w in 1...limit {
if item.weight > w {
table[j][w] = table[j-1][w]
} else {
table[j][w] = max(table[j-1][w], table[j-1][w-item.weight] + item.value)
}
}
}
 
var result = [KnapsackItem]()
var w = limit
 
for j in stride(from: items.count, to: 0, by: -1) where table[j][w] != table[j-1][w] {
let item = items[j-1]
 
result.append(item)
 
w -= item.weight
}
 
return result
}
 
typealias GroupedItem = (name: String, weight: Int, val: Int, n: Int)
 
let groupedItems: [GroupedItem] = [
("map", 9, 150, 1),
("compass", 13, 35, 1),
("water", 153, 200, 3),
("sandwich", 50, 60, 2),
("glucose", 15, 60, 2),
("tin", 68, 45, 3),
("banana", 27, 60, 3),
("apple", 39, 40, 3),
("cheese", 23, 30, 1),
("beer", 52, 10, 3),
("suntan cream", 11, 70, 1),
("camera", 32, 30, 1),
("t-shirt", 24, 15, 2),
("trousers", 48, 10, 2),
("umbrella", 73, 40, 1),
("waterproof trousers", 42, 70, 1),
("waterproof overclothes", 43, 75, 1),
("note-case", 22, 80, 1),
("sunglasses", 7, 20, 1),
("towel", 18, 12, 2),
("socks", 4, 50, 1),
("book", 30, 10, 2)
]
 
let items = groupedItems.flatMap({item in
(0..<item.n).map({_ in KnapsackItem(name: item.name, weight: item.weight, value: item.val) })
})
 
let bagged = knapsack(items: items, limit: 400)
let (totalVal, totalWeight) = bagged.reduce((0, 0), {cur, item in (cur.0 + item.value, cur.1 + item.weight) })
 
print("Bagged the following \(bagged.count) items:")
 
for item in bagged {
print("\t\(item.name)")
}
 
print("For a total value of \(totalVal) and weight of \(totalWeight)")</syntaxhighlight>
 
{{out}}
 
<pre>Bagged the following 14 items:
socks
sunglasses
note-case
waterproof overclothes
suntan cream
cheese
banana
banana
banana
glucose
glucose
water
compass
map
For a total value of 1010 and weight of 396
</pre>
 
=={{header|Tcl}}==
Classic dumb search algorithm:
<langsyntaxhighlight lang="tcl"># The list of items to consider, as list of lists
set items {
{map 9 150 1}
Line 3,674 ⟶ 4,884:
foreach {count item} [countednames $best] {
puts "\t$count * $item"
}</langsyntaxhighlight>
{{out}}
<pre>
Line 3,695 ⟶ 4,905:
Instead of an ''ad-hoc'' solution, we can convert this task to a
[[wp:Mixed_integer_programming#Integer_unknowns|mixed integer programming]] problem instance and solve it with the [http://lpsolve.sourceforge.net lpsolve] library, which is callable in Ursala.
<langsyntaxhighlight Ursalalang="ursala">#import std
#import flo
#import lin
Line 3,738 ⟶ 4,948:
#show+
 
main = format solution system items</langsyntaxhighlight>
The <code>linear_system$[</code>...<code>]</code> function takes the item list as an argument and returns a data structure with the following fields, which is passed to the <code>solution</code> function, which calls the <code>lpsolve</code> routines.
* <code>integers</code> declares that all variables in the list take integer values
Line 3,758 ⟶ 4,968:
1 water
1 waterproof overclothes</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./fmt" for Fmt
 
class Item {
construct new(name, weight, value, count) {
_name = name
_weight = weight
_value = value
_count = count
}
 
name { _name }
weight { _weight }
value { _value }
count { _count }
}
 
var items = [
Item.new("map", 9, 150, 1),
Item.new("compass", 13, 35, 1),
Item.new("water", 153, 200, 2),
Item.new("sandwich", 50, 60, 2),
Item.new("glucose", 15, 60, 2),
Item.new("tin", 68, 45, 3),
Item.new("banana", 27, 60, 3),
Item.new("apple", 39, 40, 3),
Item.new("cheese", 23, 30, 1),
Item.new("beer", 52, 10, 3),
Item.new("suntan cream", 11, 70, 1),
Item.new("camera", 32, 30, 1),
Item.new("T-shirt", 24, 15, 2),
Item.new("trousers", 48, 10, 2),
Item.new("umbrella", 73, 40, 1),
Item.new("waterproof trousers", 42, 70, 1),
Item.new("waterproof overclothes", 43, 75, 1),
Item.new("note-case", 22, 80, 1),
Item.new("sunglasses", 7, 20, 1),
Item.new("towel", 18, 12, 2),
Item.new("socks", 4, 50, 1),
Item.new("book", 30, 10, 2)
]
 
var n = items.count
var maxWeight = 400
 
var knapsack = Fn.new { |w|
var m = List.filled(n + 1, null)
for (i in 0..n) m[i] = List.filled(w + 1, 0)
for (i in 1..n) {
for (j in 0..w) {
m[i][j] = m[i-1][j]
for (k in 1..items[i - 1].count) {
if (k * items[i - 1].weight > j) break
var v = m[i - 1][j - k * items[i - 1].weight] + k * items[i - 1].value
if (v > m[i][j]) m[i][j] = v
}
}
}
var s = List.filled(n, 0)
var j = w
for (i in n..1) {
var v = m[i][j]
var k = 0
while (v != m[i - 1][j] + k * items[i - 1].value) {
s[i - 1] = s[i - 1] + 1
j = j - items[i - 1].weight
k = k + 1
}
}
return s
}
 
var s = knapsack.call(maxWeight)
System.print("Item Chosen Weight Value Number")
System.print("--------------------- ------ ----- ------")
var itemCount = 0
var sumWeight = 0
var sumValue = 0
var sumNumber = 0
for (i in 0... n) {
if (s[i] != 0) {
itemCount = itemCount + 1
var name = items[i].name
var number = s[i]
var weight = items[i].weight * number
var value = items[i].value * number
sumNumber = sumNumber + number
sumWeight = sumWeight + weight
sumValue = sumValue + value
Fmt.print("$-22s $3d $4d $2d", name, weight, value, number)
}
}
System.print("--------------------- ------ ----- ------")
Fmt.print("Items chosen $d $3d $4d $2d", itemCount, sumWeight, sumValue, sumNumber)</syntaxhighlight>
 
{{out}}
<pre>
Item Chosen Weight Value Number
--------------------- ------ ----- ------
map 9 150 1
compass 13 35 1
water 153 200 1
glucose 30 120 2
banana 81 180 3
cheese 23 30 1
suntan cream 11 70 1
waterproof overclothes 43 75 1
note-case 22 80 1
sunglasses 7 20 1
socks 4 50 1
--------------------- ------ ----- ------
Items chosen 11 396 1010 14
</pre>
 
=={{header|zkl}}==
{{trans|Haskell}}
<langsyntaxhighlight lang="zkl">fcn addItem(old,[(nm,w,v,c)]){ // old:list:(cost of:,(name,#,...))
[1..c].reduce(fcn(list,i,nm,w,v,old){
wi,left,right:=w*i,list[0,wi],list[wi,*];
Line 3,768 ⟶ 5,094:
fcn([(v1,_)]a,[(v2,_)]b){ v1>v2 and a or b },new));
},old,nm,w,v,old);
}//--> new list</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">items:=T( // item: (name,weight,value,#)
T("apple", 39, 40,3),T("banana", 27,60,3),
T("beer", 52, 10,3),T("book", 30,10,2),T("camera", 32, 30,1),
Line 3,782 ⟶ 5,108:
'wrap(nm,n){ items[items.filter1n(fcn(it,nm){ it[0]==nm },nm)][1]*n })
.sum(0)
};</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">const MAX_WEIGHT=400;
knapsack:=items.reduce(addItem,(MAX_WEIGHT).pump(List,T(0,T).copy))[-1];
knapsack.toString(*).println(weight(knapsack));</langsyntaxhighlight>
{{out}}
<pre>
9,476

edits