September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -72,5 +72,6 @@ Show which items does the tourist carry in his knapsack so that their total weig
|
|||
|
||||
;Related tasks:
|
||||
* [[Knapsack problem/Unbounded]]
|
||||
* [[Knapsack problem/Continuous]]
|
||||
* [[Knapsack problem/0-1]]
|
||||
<br><br>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
// 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)}")
|
||||
}
|
||||
|
|
@ -8,15 +8,15 @@ multi sub pokem ([$i, *@rest], $w, $v = 0) {
|
|||
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} = |@put, $i.name).list if @put[0] > @skip[0];
|
||||
}
|
||||
return (%cache{$key} = @skip).list;
|
||||
return (%cache{$key} = |@skip).list;
|
||||
}
|
||||
}
|
||||
|
||||
my $MAX_WEIGHT = 400;
|
||||
my @table = map -> $name, $weight, $unit, $count {
|
||||
KnapsackItem.new( :$name, :$weight, :$unit ) xx $count;
|
||||
my @table = flat map -> $name, $weight, $unit, $count {
|
||||
KnapsackItem.new( :$name, :$weight, :$unit ) xx $count;
|
||||
},
|
||||
'map', 9, 150, 1,
|
||||
'compass', 13, 35, 1,
|
||||
|
|
@ -39,7 +39,7 @@ my @table = map -> $name, $weight, $unit, $count {
|
|||
'sunglasses', 7, 20, 1,
|
||||
'towel', 18, 12, 2,
|
||||
'socks', 4, 50, 1,
|
||||
'book', 30, 10, 2,
|
||||
'book', 30, 10, 2
|
||||
;
|
||||
|
||||
my ($value, @result) = pokem @table, $MAX_WEIGHT;
|
||||
|
|
@ -49,6 +49,6 @@ my ($value, @result) = pokem @table, $MAX_WEIGHT;
|
|||
say "Value = $value";
|
||||
say "Tourist put in the bag:";
|
||||
say " # ITEM";
|
||||
for %hash.kv -> $item, $number {
|
||||
say " $number $item";
|
||||
for %hash.sort -> $item {
|
||||
say " {$item.value} {$item.key}";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
atom t0 = time()
|
||||
|
||||
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}}
|
||||
|
||||
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
|
||||
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
|
||||
end if
|
||||
return {best_points, act_weight, best_choices}
|
||||
end function
|
||||
|
||||
sequence res = knapsack(400, length(goodies)) -- {points,act_weight,choices}
|
||||
|
||||
atom weight = 0, witem
|
||||
atom points = 0, pitem
|
||||
string idesc
|
||||
for i=1 to length(goodies) do
|
||||
integer c = res[3][i]
|
||||
if c then
|
||||
{idesc,witem,pitem} = goodies[i]
|
||||
printf(1,"%d %s\n",{c,idesc})
|
||||
weight += c*witem
|
||||
points += c*pitem
|
||||
end if
|
||||
end for
|
||||
if points!=res[1] then ?9/0 end if -- sanity check
|
||||
printf(1,"Value %d, weight %g [%3.2fs]\n",{points,weight,time()-t0})
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
sequence items = {
|
||||
{"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},
|
||||
};
|
||||
|
||||
sequence {names,weights,points,counts} = columnize(items)
|
||||
|
||||
constant n = length(items)
|
||||
|
||||
function knapsack(int w)
|
||||
int v
|
||||
-- m is the achievable points matrix:
|
||||
-- Note that Phix uses 1-based indexes, so m[1][1]
|
||||
-- actually holds points for 0 items of weight 0,
|
||||
-- and m[n+1][w+1] is for n items at weight w.
|
||||
seq m = repeat(repeat(0,w+1),n+1)
|
||||
for i=1 to n do
|
||||
for j=1 to w+1 do -- (0 to w really)
|
||||
m[i+1][j] = m[i][j]
|
||||
for k=1 to counts[i] do
|
||||
if k*weights[i]>j-1 then
|
||||
exit
|
||||
end if
|
||||
v = m[i][j-k*weights[i]]+k*points[i]
|
||||
if v>m[i+1][j] then
|
||||
m[i+1][j] = v
|
||||
end if
|
||||
end for
|
||||
end for
|
||||
end for
|
||||
seq s = repeat(0,n)
|
||||
int j = w+1 -- (w -> 0 really)
|
||||
for i=n+1 to 2 by -1 do -- (n to 1 really)
|
||||
v = m[i][j]
|
||||
int k = 0
|
||||
while v!=m[i-1][j]+k*points[i-1] do
|
||||
s[i-1] += 1
|
||||
j -= weights[i-1]
|
||||
k += 1
|
||||
end while
|
||||
end for
|
||||
return s
|
||||
end function
|
||||
|
||||
int tc = 0, tw = 0, tv = 0
|
||||
seq s = knapsack(400)
|
||||
for i=1 to n do
|
||||
int si = s[i]
|
||||
if si then
|
||||
printf(1,"%-22s %5d %5d %5d\n", {names[i], si, si*weights[i], si*points[i]})
|
||||
tc += si
|
||||
tw += si*weights[i]
|
||||
tv += si*points[i]
|
||||
end if
|
||||
end for
|
||||
printf(1,"%-22s %5d %5d %5d\n", {"count, weight, points:", tc, tw, tv})
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
--
|
||||
-- demo\rosetta\knapsackB.exw
|
||||
-- ==========================
|
||||
--
|
||||
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
|
||||
return
|
||||
elsif weight<rcati[ACTW] then
|
||||
-- (we cannot extend an existing range down, since it starts at
|
||||
-- the actual weight, that must also be the minimum weight...)
|
||||
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]
|
||||
best_choices = repeat(0,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
|
||||
|
||||
sequence res = knapsack(400, length(goodies)) -- {points,act_weight,choices}
|
||||
|
||||
atom weight = 0, witem
|
||||
atom points = 0, pitem
|
||||
string idesc
|
||||
for i=1 to length(goodies) do
|
||||
integer c = res[3][i]
|
||||
if c then
|
||||
{idesc,witem,pitem} = goodies[i]
|
||||
printf(1,"%d %s\n",{c,idesc})
|
||||
weight += c*witem
|
||||
points += c*pitem
|
||||
end if
|
||||
end for
|
||||
if points!=res[1] then ?9/0 end if -- sanity check
|
||||
if weight!=res[2] then ?9/0 end if -- sanity check
|
||||
printf(1,"Value %d, weight %g [%3.2fs]\n",{points,weight,time()-t0})
|
||||
|
||||
printf(1,"cache_entries:%d, hits:%d, misses:%d\n",{cache_entries,cache_hits,cache_misses})
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
/*REXX pgm solves a knapsack problem (22 items + repeats, weight restriction. */
|
||||
call @gen /*generate items and initializations. */
|
||||
call @sort /*sort items by decreasing their weight*/
|
||||
call bOBJ /*build a list of choices (objects). */
|
||||
call showOBJ /*display the list of choices (objects)*/
|
||||
call sim37 /*examine and find the possible choices*/
|
||||
call showBest /*display best choice (weight, value).*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*────────────────────────────────@GEN subroutine─────────────────────────────*/
|
||||
/*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*/
|
||||
call build /*build a list of choices (objects). */
|
||||
call showOBJ /*display the list of choices (objects)*/
|
||||
call findBest /*examine and find the possible choices*/
|
||||
call showBest /*display best choice (weight, value).*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
@gen: @.=; @.1 = 'map 9 150'
|
||||
@.2 = 'compass 13 35'
|
||||
@.3 = 'water 153 200 2'
|
||||
|
|
@ -29,139 +29,128 @@ exit /*stick a fork in it, we're all done. */
|
|||
@.20 = 'towel 18 12 2'
|
||||
@.21 = 'socks 4 50'
|
||||
@.22 = 'book 30 10 2'
|
||||
highQ=0 /*maximum quantity specified (if any). */
|
||||
maxWeight=400 /*the maximum weight for the knapsack. */
|
||||
maxL=length('knapsack items') /* " " width for the table names*/
|
||||
maxW=length('weight') /* " " " " " weights. */
|
||||
maxV=length('value') /* " " " " " values. */
|
||||
maxQ=length('pieces') /* " " " " " quantity.*/
|
||||
items=0; i.=; w.=0; v.=0; q.=0 /*initialize some stuff and things. */
|
||||
Tw=0; Tv=0; Tq=0; m=maxWeight /* " more " " " */
|
||||
say; say 'maximum weight allowed for a knapsack: ' commas(maxWeight); say
|
||||
return
|
||||
/*────────────────────────────────@SORT subroutine────────────────────────────*/
|
||||
@sort: do j=1 while @.j\=='' /*process each choice and sort the item*/
|
||||
_=space(@.j); @.j=_ /*remove any superfluous blanks. */
|
||||
_wt=word(_, 2) /*choose first item (arbitrary). */
|
||||
do k=j+1 while @.k\=='' /*find a possible heavier item. */
|
||||
?wt=word(@.k, 2)
|
||||
if ?wt>_wt then do; _=@.k; @.k=@.j; @.j=_; _wt=?wt; end
|
||||
end /*k*/
|
||||
end /*j*/ /* [↑] minimizes the # of combinations*/
|
||||
obj=j-1 /*adjust for the DO loop index. */
|
||||
return
|
||||
/*────────────────────────────────BOBJ subroutine─────────────────────────────*/
|
||||
bOBJ: do j=1 for obj /*build a list of choices (objects). */
|
||||
parse var @.j item w v q . /*parse the original choice for table. */
|
||||
if w>maxWeight then iterate /*Is the weight > maximum? Then ignore*/
|
||||
Tw=Tw+w; Tv=Tv+v; Tq=Tq+1 /*add the totals up (for alignment). */
|
||||
maxL=max(maxL, length(item)) /*find the maximum width for an item. */
|
||||
if q=='' then q=1
|
||||
highQ=max(highQ, q)
|
||||
items=items+1 /*bump the item counter. */
|
||||
i.items=item; w.items=w; v.items=v; q.items=q
|
||||
do k=2 to q; items=items+1 /*bump the item counter (each piece). */
|
||||
i.items=item; w.items=w; v.items=v; q.items=q
|
||||
Tw=Tw+w; Tv=Tv+v; Tq=Tq+1
|
||||
end /*k*/
|
||||
end /*j*/
|
||||
|
||||
maxW=max(maxW, length(commas(Tw))) /*find the maximum width for weight. */
|
||||
maxV=max(maxV, length(commas(Tv))) /* " " " " " value. */
|
||||
maxQ=max(maxQ, length(commas(Tq))) /* " " " " " quantity. */
|
||||
maxL=maxL + maxL %4 + 4 /*extend the width of name for table. */
|
||||
return /* [↑] % is REXX integer division. */
|
||||
/*────────────────────────────────comma subroutine────────────────────────────*/
|
||||
commas: procedure; parse arg _; n=_'.9'; #=123456789; b=verify(n,#,"M")
|
||||
e=verify(n,#'0',,verify(n,#"0.",'M'))-4
|
||||
do j=e to b by -3; _=insert(',',_,j); end /*j*/; return _
|
||||
/*────────────────────────────────HDR subroutine──────────────────────────────*/
|
||||
hdr: parse arg _item_, _; if highq\==1 then _=center('pieces', maxq)
|
||||
call show center( _item_ , maxL),,
|
||||
center('weight', maxW),,
|
||||
center('value' , maxV),,
|
||||
center(_ , maxQ)
|
||||
call hdr2; return
|
||||
/*────────────────────────────────HDR2 subroutine─────────────────────────────*/
|
||||
hdr2: _=maxQ; if highq==1 then _=0; call show copies('═' ,maxL),,
|
||||
copies('═' ,maxW),,
|
||||
copies('═' ,maxV),,
|
||||
copies('═' ,_ )
|
||||
return
|
||||
/*────────────────────────────────J? subroutine──────────-────────────────────*/
|
||||
j?: parse arg _,?; $=value('V'_); do j=1 for _; ?=? value('J'j); end; return
|
||||
/*────────────────────────────────SHOW subroutine─────────────────────────────*/
|
||||
show: parse arg _item, _weight, _value, _quant
|
||||
say translate(left(_item, maxL,'─'), ,'_'),
|
||||
right(commas(_weight), maxW),
|
||||
right(commas(_value ), maxV),
|
||||
right(commas(_quant ), maxQ)
|
||||
return
|
||||
/*──────────────────────────────────SHOWOBJ subroutine────────────────────────*/
|
||||
showOBJ: call hdr 'item'; do j=1 for obj /*show the formatted choices. */
|
||||
highQ = 0 /*maximum quantity specified (if any). */
|
||||
maxL = length('knapsack items') /* " " width for the table names*/
|
||||
maxW = length('weight') /* " " " " " weights. */
|
||||
maxV = length('value') /* " " " " " values. */
|
||||
maxQ = length('pieces') /* " " " " " quantity.*/
|
||||
maxWeight=400 /*the maximum weight for the knapsack. */
|
||||
items= 0; i.=; w.=0; v.=0; q.=0 /*initialize some stuff and things. */
|
||||
Tw= 0; Tv=0; Tq=0; m=maxWeight /* " more " " " */
|
||||
say; say 'maximum weight allowed for a knapsack: ' commas(maxWeight); say
|
||||
return
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
@sort: do j=1 while @.j\=='' /*process each choice and sort the item*/
|
||||
@.j=space(@.j); _wt=word(@.j, 2) /*choose first item (arbitrary). */
|
||||
do k=j+1 while @.k\=='' /*find a possible heavier item. */
|
||||
?wt=word(@.k, 2)
|
||||
if ?wt>_wt then do; _=@.k; @.k=@.j; @.j=_; _wt=?wt; end /*swap*/
|
||||
end /*k*/
|
||||
end /*j*/ /* [↑] minimizes the # of combinations*/
|
||||
obj=j-1 /*adjust for the DO loop index. */
|
||||
return
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
build: do j=1 for obj /*build a list of choices (objects). */
|
||||
parse var @.j item w v q . /*parse the original choice for table. */
|
||||
if w>maxWeight then iterate /*Is the weight > maximum? Then ignore*/
|
||||
Tw=Tw+w; Tv=Tv+v; Tq=Tq+1 /*add the totals up (for alignment). */
|
||||
maxL=max(maxL, length(item)) /*find the maximum width for an item. */
|
||||
if q=='' then q=1
|
||||
highQ=max(highQ, q)
|
||||
items=items+1 /*bump the item counter. */
|
||||
i.items=item; w.items=w; v.items=v; q.items=q
|
||||
do k=2 to q ; items=items+1 /*bump the item counter (each piece). */
|
||||
i.items=item; w.items=w; v.items=v; q.items=q
|
||||
Tw=Tw+w; Tv=Tv+v; Tq=Tq+1
|
||||
end /*k*/
|
||||
end /*j*/
|
||||
maxW = max(maxW, length( commas(Tw) ) ) /*find the maximum width for weight. */
|
||||
maxV = max(maxV, length( commas(Tv) ) ) /* " " " " " value. */
|
||||
maxQ = max(maxQ, length( commas(Tq) ) ) /* " " " " " quantity. */
|
||||
maxL = maxL + maxL %4 + 4 /*extend the width of name for table. */
|
||||
return /* [↑] % is REXX integer division. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
commas: procedure; parse arg _; n=_'.9'; #=123456789; b=verify(n, #, "M"); x=','
|
||||
e=verify(n, #'0', , verify(n, #"0.", 'M') ) - 4 /* [↓] add commas to number*/
|
||||
do j=e to b by -3; _=insert(x, _, j); end /*j*/; return _
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
hdr: parse arg _item_, _; if highq\==1 then _=center('pieces', maxq)
|
||||
call show center(_item_, maxL), center('weight', maxW), center('value', maxV), ,
|
||||
center(_ , maxQ); call hdr2; return
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
hdr2: _=maxQ; x='═'; if highq==1 then _=0
|
||||
call show copies(x, maxL), copies(x, maxW), copies(x, maxV), copies(x, _); return
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
j?: parse arg _,?; $=value('Z'_); do k=1 for _; ?=? value('J'k); end; return
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
show: parse arg _item, _weight, _value, _quant
|
||||
say translate(left(_item, maxL,'─'), ,'_') right(commas(_weight), maxW),
|
||||
right(commas(_value ), maxV) right(commas(_quant ), maxQ); return
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
showOBJ: call hdr 'item'; do j=1 for obj /*show the formatted choices. */
|
||||
parse var @.j item weight value q .
|
||||
if highq==1 then q=
|
||||
else if q=='' then q=1
|
||||
call show item, weight, value, q
|
||||
end /*j*/
|
||||
say; say 'number of items (with repetitions): ' items; say
|
||||
return
|
||||
/*──────────────────────────────────SHOWBEST subroutine───────────────────────*/
|
||||
showBest: do h-1; ?=strip(strip(?), "L", 0); end /*h-1*/
|
||||
bestC=?; bestW=0; bestV=$; highQ=0; totP=words(bestC); say; say
|
||||
call hdr 'best choice'
|
||||
do j=1 to totP /*J is modified within DO loop. */
|
||||
_=word(bestC, j); _w=w._; _v=v._; q=1
|
||||
if _==0 then iterate
|
||||
do k=j+1 to totP
|
||||
__=word(bestC, k); if i._\==i.__ then leave
|
||||
j=j+1; w._=w._+_w; v._=v._+_v; q=q+1
|
||||
end /*k*/
|
||||
call show i._, w._, v._, q; bestW=bestw+w._
|
||||
end /*j*/
|
||||
call hdr2; say
|
||||
call show 'best weight' , bestW /*show a nicely formatted winnerW*/
|
||||
call show 'best value' , , bestV /* " " " " winnerV*/
|
||||
call show 'knapsack items', , , totP /* " " " " pieces.*/
|
||||
return
|
||||
/*─────────────────────────────────────SIM37 subroutine──────────────────────────────────────────────────────────────────────────────────────────*/
|
||||
sim37: h=items; $=0
|
||||
do j1 =0 for h+1; w1= w.j1 ; v1= v.j1 ; if v1>$ then call j? 1
|
||||
do j2 =j1 +(j1 \==0) to h; if w.j2 +w1 >m then iterate j1; w2=w1 +w.j2 ; v2=v1 +v.j2 ; if v2>$ then call j? 2
|
||||
do j3 =j2 +(j2 \==0) to h; if w.j3 +w2 >m then iterate j2; w3=w2 +w.j3 ; v3=v2 +v.j3 ; if v3>$ then call j? 3
|
||||
do j4 =j3 +(j3 \==0) to h; if w.j4 +w3 >m then iterate j3; w4=w3 +w.j4 ; v4=v3 +v.j4 ; if v4>$ then call j? 4
|
||||
do j5 =j4 +(j4 \==0) to h; if w.j5 +w4 >m then iterate j4; w5=w4 +w.j5 ; v5=v4 +v.j5 ; if v5>$ then call j? 5
|
||||
do j6 =j5 +(j5 \==0) to h; if w.j6 +w5 >m then iterate j5; w6=w5 +w.j6 ; v6=v5 +v.j6 ; if v6>$ then call j? 6
|
||||
do j7 =j6 +(j6 \==0) to h; if w.j7 +w6 >m then iterate j6; w7=w6 +w.j7 ; v7=v6 +v.j7 ; if v7>$ then call j? 7
|
||||
do j8 =j7 +(j7 \==0) to h; if w.j8 +w7 >m then iterate j7; w8=w7 +w.j8 ; v8=v7 +v.j8 ; if v8>$ then call j? 8
|
||||
do j9 =j8 +(j8 \==0) to h; if w.j9 +w8 >m then iterate j8; w9=w8 +w.j9 ; v9=v8 +v.j9 ; if v9>$ then call j? 9
|
||||
do j10=j9 +(j9 \==0) to h; if w.j10+w9 >m then iterate j9; w10=w9 +w.j10; v10=v9 +v.j10; if v10>$ then call j? 10
|
||||
do j11=j10+(j10\==0) to h; if w.j11+w10>m then iterate j10; w11=w10+w.j11; v11=v10+v.j11; if v11>$ then call j? 11
|
||||
do j12=j11+(j11\==0) to h; if w.j12+w11>m then iterate j11; w12=w11+w.j12; v12=v11+v.j12; if v12>$ then call j? 12
|
||||
do j13=j12+(j12\==0) to h; if w.j13+w12>m then iterate j12; w13=w12+w.j13; v13=v12+v.j13; if v13>$ then call j? 13
|
||||
do j14=j13+(j13\==0) to h; if w.j14+w13>m then iterate j13; w14=w13+w.j14; v14=v13+v.j14; if v14>$ then call j? 14
|
||||
do j15=j14+(j14\==0) to h; if w.j15+w14>m then iterate j14; w15=w14+w.j15; v15=v14+v.j15; if v15>$ then call j? 15
|
||||
do j16=j15+(j15\==0) to h; if w.j16+w15>m then iterate j15; w16=w15+w.j16; v16=v15+v.j16; if v16>$ then call j? 16
|
||||
do j17=j16+(j16\==0) to h; if w.j17+w16>m then iterate j16; w17=w16+w.j17; v17=v16+v.j17; if v17>$ then call j? 17
|
||||
do j18=j17+(j17\==0) to h; if w.j18+w17>m then iterate j17; w18=w17+w.j18; v18=v17+v.j18; if v18>$ then call j? 18
|
||||
do j19=j18+(j18\==0) to h; if w.j19+w18>m then iterate j18; w19=w18+w.j19; v19=v18+v.j19; if v19>$ then call j? 19
|
||||
do j20=j19+(j19\==0) to h; if w.j20+w19>m then iterate j19; w20=w19+w.j20; v20=v19+v.j20; if v20>$ then call j? 20
|
||||
do j21=j20+(j20\==0) to h; if w.j21+w20>m then iterate j20; w21=w20+w.j21; v21=v20+v.j21; if v21>$ then call j? 21
|
||||
do j22=j21+(j21\==0) to h; if w.j22+w21>m then iterate j21; w22=w21+w.j22; v22=v21+v.j22; if v22>$ then call j? 22
|
||||
do j23=j22+(j22\==0) to h; if w.j23+w22>m then iterate j22; w23=w22+w.j23; v23=v22+v.j23; if v23>$ then call j? 23
|
||||
do j24=j23+(j23\==0) to h; if w.j24+w23>m then iterate j23; w24=w23+w.j24; v24=v23+v.j24; if v24>$ then call j? 24
|
||||
do j25=j24+(j24\==0) to h; if w.j25+w24>m then iterate j24; w25=w24+w.j25; v25=v24+v.j25; if v25>$ then call j? 25
|
||||
do j26=j25+(j25\==0) to h; if w.j26+w25>m then iterate j25; w26=w25+w.j26; v26=v25+v.j26; if v26>$ then call j? 26
|
||||
do j27=j26+(j26\==0) to h; if w.j27+w26>m then iterate j26; w27=w26+w.j27; v27=v26+v.j27; if v27>$ then call j? 27
|
||||
do j28=j27+(j27\==0) to h; if w.j28+w27>m then iterate j27; w28=w27+w.j28; v28=v27+v.j28; if v28>$ then call j? 28
|
||||
do j29=j28+(j28\==0) to h; if w.j29+w28>m then iterate j28; w29=w28+w.j29; v29=v28+v.j29; if v29>$ then call j? 29
|
||||
do j30=j29+(j29\==0) to h; if w.j30+w29>m then iterate j29; w30=w29+w.j30; v30=v29+v.j30; if v30>$ then call j? 30
|
||||
do j31=j30+(j30\==0) to h; if w.j31+w30>m then iterate j30; w31=w30+w.j31; v31=v30+v.j31; if v31>$ then call j? 31
|
||||
do j32=j31+(j31\==0) to h; if w.j32+w31>m then iterate j31; w32=w31+w.j32; v32=v31+v.j32; if v32>$ then call j? 32
|
||||
do j33=j32+(j32\==0) to h; if w.j33+w32>m then iterate j32; w33=w32+w.j33; v33=v32+v.j33; if v33>$ then call j? 33
|
||||
do j34=j33+(j33\==0) to h; if w.j34+w33>m then iterate j33; w34=w33+w.j34; v34=v33+v.j34; if v34>$ then call j? 34
|
||||
do j35=j34+(j34\==0) to h; if w.j35+w34>m then iterate j34; w35=w34+w.j35; v35=v34+v.j35; if v35>$ then call j? 35
|
||||
do j36=j35+(j35\==0) to h; if w.j36+w35>m then iterate j35; w36=w35+w.j36; v36=v35+v.j36; if v36>$ then call j? 36
|
||||
do j37=j36+(j36\==0) to h; if w.j37+w36>m then iterate j36; w37=w36+w.j37; v37=v36+v.j37; if v37>$ 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 of the DO loops. */
|
||||
say; say 'number of unique named items: ' obj
|
||||
say 'number of items (including reps): ' items; say; return
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
showBest: do words(?); ?=strip(space(?), "L", 0); end /*words(?)*/
|
||||
bestC=?; bestW=0; bestV=$; highQ=0; totP=words(bestC); say
|
||||
call hdr 'best choice'
|
||||
do j=1 to totP /*J is modified within DO loop.*/
|
||||
_=word(bestC, j); _w=w._; _v=v._; q=1
|
||||
if _==0 then iterate
|
||||
do k=j+1 to totP; __=word(bestC, k) /*get a choice.*/
|
||||
if i._\==i.__ then leave /*not equal ? */
|
||||
j=j+1; w._=w._+_w; v._=v._+_v; q=q+1
|
||||
end /*k*/
|
||||
call show i._, w._, v._, q; bestW=bestw+w._
|
||||
end /*j*/
|
||||
call hdr2; say
|
||||
call show 'best weight' , bestW /*show a nicely formatted winnerW.*/
|
||||
call show 'best value' , , bestV /* " " " " winnerV.*/
|
||||
call show 'knapsack items', , , totP /* " " " " pieces. */
|
||||
return
|
||||
/*─────────────────────────────────────────────────────────────────────────────────────────────────────────*/
|
||||
findBest: h=items; $=0
|
||||
do j1 =0 for h+1; w1= w.j1 ; z1= v.j1 ;if z1>$ then call j? 1
|
||||
do j2 =j1 +(j1 >0) to h;if w.j2 +w1 >m then iterate j1; w2=w1 +w.j2 ; z2=z1 +v.j2 ;if z2>$ then call j? 2
|
||||
do j3 =j2 +(j2 >0) to h;if w.j3 +w2 >m then iterate j2; w3=w2 +w.j3 ; z3=z2 +v.j3 ;if z3>$ then call j? 3
|
||||
do j4 =j3 +(j3 >0) to h;if w.j4 +w3 >m then iterate j3; w4=w3 +w.j4 ; z4=z3 +v.j4 ;if z4>$ then call j? 4
|
||||
do j5 =j4 +(j4 >0) to h;if w.j5 +w4 >m then iterate j4; w5=w4 +w.j5 ; z5=z4 +v.j5 ;if z5>$ then call j? 5
|
||||
do j6 =j5 +(j5 >0) to h;if w.j6 +w5 >m then iterate j5; w6=w5 +w.j6 ; z6=z5 +v.j6 ;if z6>$ then call j? 6
|
||||
do j7 =j6 +(j6 >0) to h;if w.j7 +w6 >m then iterate j6; w7=w6 +w.j7 ; z7=z6 +v.j7 ;if z7>$ then call j? 7
|
||||
do j8 =j7 +(j7 >0) to h;if w.j8 +w7 >m then iterate j7; w8=w7 +w.j8 ; z8=z7 +v.j8 ;if z8>$ then call j? 8
|
||||
do j9 =j8 +(j8 >0) to h;if w.j9 +w8 >m then iterate j8; w9=w8 +w.j9 ; z9=z8 +v.j9 ;if z9>$ then call j? 9
|
||||
do j10=j9 +(j9 >0) to h;if w.j10+w9 >m then iterate j9;w10=w9 +w.j10;z10=z9 +v.j10;if z10>$ then call j? 10
|
||||
do j11=j10+(j10>0) to h;if w.j11+w10>m then iterate j10;w11=w10+w.j11;z11=z10+v.j11;if z11>$ then call j? 11
|
||||
do j12=j11+(j11>0) to h;if w.j12+w11>m then iterate j11;w12=w11+w.j12;z12=z11+v.j12;if z12>$ then call j? 12
|
||||
do j13=j12+(j12>0) to h;if w.j13+w12>m then iterate j12;w13=w12+w.j13;z13=z12+v.j13;if z13>$ then call j? 13
|
||||
do j14=j13+(j13>0) to h;if w.j14+w13>m then iterate j13;w14=w13+w.j14;z14=z13+v.j14;if z14>$ then call j? 14
|
||||
do j15=j14+(j14>0) to h;if w.j15+w14>m then iterate j14;w15=w14+w.j15;z15=z14+v.j15;if z15>$ then call j? 15
|
||||
do j16=j15+(j15>0) to h;if w.j16+w15>m then iterate j15;w16=w15+w.j16;z16=z15+v.j16;if z16>$ then call j? 16
|
||||
do j17=j16+(j16>0) to h;if w.j17+w16>m then iterate j16;w17=w16+w.j17;z17=z16+v.j17;if z17>$ then call j? 17
|
||||
do j18=j17+(j17>0) to h;if w.j18+w17>m then iterate j17;w18=w17+w.j18;z18=z17+v.j18;if z18>$ then call j? 18
|
||||
do j19=j18+(j18>0) to h;if w.j19+w18>m then iterate j18;w19=w18+w.j19;z19=z18+v.j19;if z19>$ then call j? 19
|
||||
do j20=j19+(j19>0) to h;if w.j20+w19>m then iterate j19;w20=w19+w.j20;z20=z19+v.j20;if z20>$ then call j? 20
|
||||
do j21=j20+(j20>0) to h;if w.j21+w20>m then iterate j20;w21=w20+w.j21;z21=z20+v.j21;if z21>$ then call j? 21
|
||||
do j22=j21+(j21>0) to h;if w.j22+w21>m then iterate j21;w22=w21+w.j22;z22=z21+v.j22;if z22>$ then call j? 22
|
||||
do j23=j22+(j22>0) to h;if w.j23+w22>m then iterate j22;w23=w22+w.j23;z23=z22+v.j23;if z23>$ then call j? 23
|
||||
do j24=j23+(j23>0) to h;if w.j24+w23>m then iterate j23;w24=w23+w.j24;z24=z23+v.j24;if z24>$ then call j? 24
|
||||
do j25=j24+(j24>0) to h;if w.j25+w24>m then iterate j24;w25=w24+w.j25;z25=z24+v.j25;if z25>$ then call j? 25
|
||||
do j26=j25+(j25>0) to h;if w.j26+w25>m then iterate j25;w26=w25+w.j26;z26=z25+v.j26;if z26>$ then call j? 26
|
||||
do j27=j26+(j26>0) to h;if w.j27+w26>m then iterate j26;w27=w26+w.j27;z27=z26+v.j27;if z27>$ then call j? 27
|
||||
do j28=j27+(j27>0) to h;if w.j28+w27>m then iterate j27;w28=w27+w.j28;z28=z27+v.j28;if z28>$ then call j? 28
|
||||
do j29=j28+(j28>0) to h;if w.j29+w28>m then iterate j28;w29=w28+w.j29;z29=z28+v.j29;if z29>$ then call j? 29
|
||||
do j30=j29+(j29>0) to h;if w.j30+w29>m then iterate j29;w30=w29+w.j30;z30=z29+v.j30;if z30>$ then call j? 30
|
||||
do j31=j30+(j30>0) to h;if w.j31+w30>m then iterate j30;w31=w30+w.j31;z31=z30+v.j31;if z31>$ then call j? 31
|
||||
do j32=j31+(j31>0) to h;if w.j32+w31>m then iterate j31;w32=w31+w.j32;z32=z31+v.j32;if z32>$ then call j? 32
|
||||
do j33=j32+(j32>0) to h;if w.j33+w32>m then iterate j32;w33=w32+w.j33;z33=z32+v.j33;if z33>$ then call j? 33
|
||||
do j34=j33+(j33>0) to h;if w.j34+w33>m then iterate j33;w34=w33+w.j34;z34=z33+v.j34;if z34>$ then call j? 34
|
||||
do j35=j34+(j34>0) to h;if w.j35+w34>m then iterate j34;w35=w34+w.j35;z35=z34+v.j35;if z35>$ then call j? 35
|
||||
do j36=j35+(j35>0) to h;if w.j36+w35>m then iterate j35;w36=w35+w.j36;z36=z35+v.j36;if z36>$ then call j? 36
|
||||
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.*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
# Item struct to represent each item in the problem
|
||||
Struct.new('Item', :name, :weight, :value, :count)
|
||||
|
||||
$items = [
|
||||
Struct::Item.new('map', 9, 150, 1),
|
||||
Struct::Item.new('compass', 13, 35, 1),
|
||||
Struct::Item.new('water', 153, 200, 3),
|
||||
Struct::Item.new('sandwich', 50, 60, 2),
|
||||
Struct::Item.new('glucose', 15, 60, 2),
|
||||
Struct::Item.new('tin', 68, 45, 3),
|
||||
Struct::Item.new('banana', 27, 60, 3),
|
||||
Struct::Item.new('apple', 39, 40, 3),
|
||||
Struct::Item.new('cheese', 23, 30, 1),
|
||||
Struct::Item.new('beer', 52, 10, 3),
|
||||
Struct::Item.new('suntan cream', 11, 70, 1),
|
||||
Struct::Item.new('camera', 32, 30, 1),
|
||||
Struct::Item.new('t-shirt', 24, 15, 2),
|
||||
Struct::Item.new('trousers', 48, 10, 2),
|
||||
Struct::Item.new('umbrella', 73, 40, 1),
|
||||
Struct::Item.new('w-trousers', 42, 70, 1),
|
||||
Struct::Item.new('w-overcoat', 43, 75, 1),
|
||||
Struct::Item.new('note-case', 22, 80, 1),
|
||||
Struct::Item.new('sunglasses', 7, 20, 1),
|
||||
Struct::Item.new('towel', 18, 12, 2),
|
||||
Struct::Item.new('socks', 4, 50, 1),
|
||||
Struct::Item.new('book', 30, 10, 2)
|
||||
]
|
||||
|
||||
def choose_item(weight, id, cache)
|
||||
return 0, [] if id < 0
|
||||
|
||||
k = [weight, id]
|
||||
return cache[k] unless cache[k].nil?
|
||||
value = $items[id].value
|
||||
best_v = 0
|
||||
best_list = []
|
||||
($items[id].count+1).times do |i|
|
||||
wlim = weight - i * $items[id].weight
|
||||
break if wlim < 0
|
||||
val, taken = choose_item(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
|
||||
|
||||
val, list = choose_item(400, $items.length - 1, {})
|
||||
w = 0
|
||||
list.each_with_index do |cnt, i|
|
||||
if cnt > 0
|
||||
print "#{cnt} #{$items[i].name}\n"
|
||||
w += $items[i][1] * cnt
|
||||
end
|
||||
end
|
||||
|
||||
p "Total weight: #{w}, Value: #{val}"
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
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,*];
|
||||
new:=old.apply('wrap([(val,itms)]){ T(val + v*i,itms.append(nm,i)) });
|
||||
left.extend(right.zipWith( // inc
|
||||
fcn([(v1,_)]a,[(v2,_)]b){ v1>v2 and a or b },new));
|
||||
},old,nm,w,v,old);
|
||||
}//--> new list
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
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),
|
||||
T("cheese", 23, 30,1),T("compass", 13,35,1),T("glucose", 15, 60,2),
|
||||
T("map", 9,150,1),T("note-case",22,80,1),T("sandwich", 50, 60,2),
|
||||
T("socks", 4, 50,1),T("sunglasses",7,20,1),T("suntan cream",11, 70,1),
|
||||
T("t-shirt", 24, 15,2),T("tin", 68,45,3),T("towel", 18, 12,2),
|
||||
T("trousers", 48, 10,2),T("umbrella", 73,40,1),T("water", 153,200,2),
|
||||
T("overclothes",43, 75,1),T("waterproof trousers",42,70,1) );
|
||||
weight:='wrap(knapsack){ // knapsack is (cost, (nm,#,nm,#...))
|
||||
knapsack[1].pump(List,Void.Read, // read nm,#, first read is implicit
|
||||
'wrap(nm,n){ items[items.filter1n(fcn(it,nm){ it[0]==nm },nm)][1]*n })
|
||||
.sum(0)
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
const MAX_WEIGHT=400;
|
||||
knapsack:=items.reduce(addItem,(MAX_WEIGHT).pump(List,T(0,T).copy))[-1];
|
||||
knapsack.toString(*).println(weight(knapsack));
|
||||
Loading…
Add table
Add a link
Reference in a new issue