The best value that can be packed in the given knapsack is 1030 !
The following items should be packed in the knapsack:
map
compass
water
sandwich
glucose
banana
suntan creme
waterproof trousers
waterproof overclothes
note-case
sunglasses
socks
The total weight of all items is 396 !

m is as per the Wikipedia formula, except that it returns a pair [value indexes] where indexes is a vector of index values in items. value is the maximum value attainable using items 0..i whose total weight doesn't exceed w; indexes are the item indexes that produces the value.

\ Rosetta Code Knapp-sack 0-1 problem. Tested under GForth 0.7.3.\ 22 items. On current processors a set fits nicely in one CELL (32 or 64 bits).\ Brute force approach: for every possible set of 22 items,\ check for admissible solution then for optimal set.

dim as short n : n = _numberOfObjects /* The number of objects available to pack */dim as Str31 s(_numberOfObjects) /* The names of available objects */dim as short c(_numberOfObjects) /* The *COST* of the ith object i.e. how much weight you must carry to pack the object */dim as short v(_numberOfObjects) /* The *VALUE* of the ith object i.e. on a scale of 1 to 200, how important is it that the object included */dim as short W : W = _weightOfKnapsack /* The maximum weight your knapsack will carry in ounces*/

procedure showwanted(wants)#: show the list of wanted itemsevery(tw :=0)+:=(!wants).weight printf("Packing list has total weight=%d and includes %d items [",tw,*wants)every printf(" %s",!(!wants).items|"]\n")end

"dynamic_knapsack(W)" implements a dynamic programming algorithm based
on computing m[i,W] as the maximum value that can be attained with
weight no greater than W using the first i items (with i = 0
corresponding to no items). Here, m[i,W] is set to [V, ary]
where ary is an array of the names of the accepted items.

# Input should be the array of objects giving name, weight and value.# Because of the way addition is defined on null and because of the# way setpath works, there is no need to initialize the matrix m in# detail.def dynamic_knapsack(W): . as $objects | length as $n | reduce range(1; $n+1) as $i # i is the number of items # state: m[i][j] is an array of [value, array_of_object_names] (null; # see above remark about initialization of m $objects[$i-1] as $o | reduce range(0; W+1) as $j ( .; if $o.weight <= $j then .[$i-1][$j][0] as $v1 # option 1: do not add this object | (.[$i-1][$j - $o.weight][0] + $o.value) as $v2 # option 2: add it | (if $v1 > $v2 then [$v1, .[$i-1][$j][1]] # do not add this object else [$v2, .[$i-1][$j - $o.weight][1]+[$o.name]] # add it end) as $mx | .[$i][$j] = $mx else .[$i][$j] = .[$i-1][$j] end)) | .[$n][W];

// Return memo if we have oneif(isset($m[$i][$aW])){returnarray($m[$i][$aW],$m['picked'][$i][$aW]);}else{

// At end of decision branchif($i==0){if($w[$i]<=$aW){// Will this item fit?$m[$i][$aW]=$v[$i];// Memo this item$m['picked'][$i][$aW]=array($i);// and the picked itemreturnarray($v[$i],array($i));// Return the value of this item and add it to the picked list

// Not at end of decision branch..// Get the result of the next branch (without this one)list($without_i,$without_PI)= knapSolveFast2($w,$v,$i-1,$aW,$m,$pickedItems);

if($w[$i]>$aW){// Does it return too many?

$m[$i][$aW]=$without_i;// Memo without including this one$m['picked'][$i][$aW]=array();// and a blank array entry...returnarray($without_i,array());// and return it

}else{

// Get the result of the next branch (WITH this one picked, so available weight is reduced)list($with_i,$with_PI)= knapSolveFast2($w,$v,($i-1),($aW-$w[$i]),$m,$pickedItems);$with_i+=$v[$i];// ..and add the value of this one..

// Get the greater of WITH or WITHOUTif($with_i>$without_i){$res=$with_i;$picked=$with_PI;array_push($picked,$i);}else{$res=$without_i;$picked=$without_PI;}

$m[$i][$aW]=$res;// Store it in the memo$m['picked'][$i][$aW]=$picked;// and store the picked itemreturnarray($res,$picked);// and then return it}}}

items =(("map",9,150),("compass",13,35),("water",153,200),("sandwich",50,160),("glucose",15,60),("tin",68,45),("banana",27,60),("apple",39,40),("cheese",23,30),("beer",52,10),("suntan cream",11,70),("camera",32,30),("t-shirt",24,15),("trousers",48,10),("umbrella",73,40),("waterproof trousers",42,70),("waterproof overclothes",43,75),("note-case",22,80),("sunglasses",7,20),("towel",18,12),("socks",4,50),("book",30,10),)bagged =max( anycomb(items), key=totalvalue)# max val or min wt if values equalprint("Bagged the following items\n " +'\n '.join(sorted(item for item,_,_ in bagged)))val, wt = totalvalue(bagged)print("for a total value of %i and a total weight of %i" % (val, -wt))

Output:

Bagged the following items
banana
compass
glucose
map
note-case
sandwich
socks
sunglasses
suntan cream
water
waterproof overclothes
waterproof trousers
for a total value of 1030 and a total weight of 396

bagged = knapsack01_dp(items,400)print("Bagged the following items\n " +'\n '.join(sorted(item for item,_,_ in bagged)))val, wt = totalvalue(bagged)print("for a total value of %i and a total weight of %i" % (val, -wt))

Originally, the combination generator/checker subroutine (sim) was recursive and made the program solution generic (and more concise).

However, a recursive solution also made the solution much more slower, so the combination generator/checker was "unrolled" and converted into discrete combination checks (based on the number of allowable items). The unused combinatorial checks were discarded and only the pertinent code was retained. It made no sense to include all the unused subroutines here as space appears to be a premium for some entries in Rosetta Code.

The term allowable items refers to all items that are of allowable weight (those that weigh within the weight criteria). An half-ton anvil was added to the list to show how overweight items are pruned from the list of items.

classArray# do something for each element of the array's power setdef power_setyield[]if block_given?self.inject([[]])do|ps, elem| ps.each_with_object([])do|i,r| r << i new_subset = i +[elem]yield new_subset if block_given? r << new_subsetendendendend

// Loop over the items. for (i, it) in items.iter().enumerate() { // Loop over the weights. for w in 1 .. max_weight + 1 { best_value[i + 1][w] = // do we have room in our knapsack? if it.weight > w { // if we don't, then we'll say that the value doesn't change // when considering this item best_value[i][w].clone() } else { // If we do, then we have to see if the value we gain by adding // the item, given the weight, is better than not adding the item. max(best_value[i][w].clone(), best_value[i][w - it.weight] + it.value) } } }

// We built up the solution space through a forward pass over the data, // now we have to traverse backwards to get the solution. for (i, it) in items.iter().enumerate().rev() { // We can check if an item should be added to the knap-sack by // comparing best_value with and without this item. If best_value // added this item then so should we. if best_value[i + 1][left_weight] != best_value[i][left_weight] { result.push(it.clone()); // We remove the weight of the object from the remaining weight // we can add to the bag. left_weight -= it.weight; } }

# Recursive function for searching over all possible choices of itemsproc knapsackSearch {items {chosen {}}}{# If we've gone over the weight limit, stop nowif{[weight $chosen]>400}{return}# If we've considered all of the items (i.e., leaf in search tree)# then see if we've got a new best choice.if{[llength$items] == 0}{global best maxset v [value $chosen]if{$v>$max}{set max $vset best $chosen}return}# Branch, so recurse for chosing the current item or notset this [lindex$items0]set rest [lrange$items1 end] knapsackSearch $rest$chosen knapsackSearch $rest[lappend chosen $this]}

This solution follows a very similar approach to the one used in Knapsack problem/Bounded#Ursala, which is to treat it as a mixed integer programming problem and solve it using an off-the-shelf library (lpsolve).

Binary valued variables are a more specific constraint than the general mixed integer programming problem, but can be accommodated as shown using the binaries field in the linear_system specification. The additional slack variable is specified as continuous and non-negative with no cost or benefit so as to make the constraint equation solvable without affecting the solution.