September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -79,6 +79,7 @@ exceed 400 dag [4 kg],   and their total value is maximized.
;Related tasks:
*   [[Knapsack problem/Unbounded]]
*   [[Knapsack problem/Bounded]]
*   [[Knapsack problem/Unbounded]]
*   [[Knapsack problem/Continuous]]
<br><br>

View file

@ -0,0 +1,124 @@
* Knapsack problem/0-1 16/02/2017
KNAPSA01 CSECT
USING KNAPSA01,R13
B 72(R15)
DC 17F'0'
STM R14,R12,12(R13)
ST R13,4(R15)
ST R15,8(R13)
LR R13,R15 end of prolog
L R0,N n
LA R1,1
POWER MH R1,=H'2' *2
BCT R0,POWER
BCTR R1,0 -1
ST R1,IMAX imax=2**n-1
SR R6,R6 i=0
DO WHILE=(C,R6,LE,IMAX) do i=0 to imax
SR R10,R10 im=0
SR R8,R8 iw=0
SR R9,R9 iv=0
LA R7,1 j=1
DO WHILE=(C,R7,LE,N) do j=1 to n
LR R1,R6 i
LR R2,R7 j
BAL R14,TSTBIT call tstbit(i,j)
IF C,R0,EQ,=F'1' THEN if tstbit(i,j)=1 then
LA R10,1(R10) im=im+1
LR R3,R7 j
BCTR R3,0
SLA R3,5
LA R1,24(R3)
A R8,DATA(R1) iw=iw+data(j).w
LA R1,28(R3)
A R9,DATA(R1) iv=iv+data(j).v
ENDIF , endif
LA R7,1(R7) j=j+1
ENDDO , enddo j
IF C,R8,LE,MAXW,AND,C,R9,GT,XV THEN if w<=maxw and iv>xv then
ST R6,XB xb=i
ST R10,XM xm=im
ST R8,XW xw=iw
ST R9,XV xv=iv
ENDIF , endif
LA R6,1(R6) i=i+1
ENDDO , enddo i
MVC PG(2),=C'n='
L R1,N n
XDECO R1,XDEC edit n
MVC PG+2(2),XDEC+10
XPRNT PG,L'PG print buffer
LA R6,1
DO WHILE=(C,R6,LE,N) do i=1 to n
L R1,XB xb
LR R2,R6 i
BAL R14,TSTBIT call tstbit(xb,i)
IF C,R0,EQ,=F'1' THEN if tstbit(xb,i)=1 then
LR R1,R6 i
BCTR R1,0
SLA R1,5
LA R2,DATA(R1) @data(i).n
MVC PG(24),0(R2)
XPRNT PG,24 print item
ENDIF , endif
LA R6,1(R6) i=i+1
ENDDO , enddo i
L R1,XM xm
XDECO R1,XDEC edit xm
MVC PGT+6(2),XDEC+10
L R1,XW xw
XDECO R1,XDEC edit xw
MVC PGT+16(3),XDEC+9
L R1,XV xv
XDECO R1,XDEC edit xv
MVC PGT+26(4),XDEC+8
XPRNT PGT,L'PGT print buffer
L R13,4(0,R13) epilog
LM R14,R12,12(R13)
XR R15,R15
BR R14 exit
TSTBIT EQU * R1 value to test the R2 bit
LA R3,32 32
SR R3,R2 (32-i)
STC R3,XSLL+3
LR R0,R1 n
EX 0,XSLL SLL R0,(32-i)
SRL R0,31
BR R14 return R0
XSLL SLL R0,0 shift left logical
*
MAXW DC F'400' maximum weight
N DC A((DATAE-DATA)/32)
IMAX DS F number of combinations
XB DS F max vector
XM DS F max items
XW DS F max weight
XV DS F max value
PG DC CL80' '
PGT DC CL32'items=.. weight=... value=....'
XDEC DS CL12
DATA DC CL24'map',F'9',F'150'
DC CL24'compass',F'13',F'35'
DC CL24'water',F'153',F'200'
DC CL24'sandwich',F'50',F'160'
DC CL24'glucose',F'15',F'60'
DC CL24'tin',F'68',F'45'
DC CL24'banana',F'27',F'60'
DC CL24'apple',F'39',F'40'
DC CL24'cheese',F'23',F'30'
DC CL24'beer',F'52',F'10'
DC CL24'suntan cream',F'11',F'70'
DC CL24'camera',F'32',F'30'
DC CL24'T-shirt',F'24',F'15'
DC CL24'trousers',F'48',F'10'
DC CL24'umbrella',F'73',F'40'
DC CL24'book',F'30',F'10'
DC CL24'waterproof trousers',F'42',F'70'
DC CL24'waterproof overclothes',F'43',F'75'
DC CL24'note-case',F'22',F'80'
DC CL24'sunglasses',F'7',F'20'
DC CL24'towel',F'18',F'12'
DC CL24'socks',F'4',F'50'
DATAE DC 0C
YREGS
END KNAPSA01

View file

@ -0,0 +1,43 @@
# syntax: GAWK -f KNAPSACK_PROBLEM_0-1.AWK
BEGIN {
# arr["item,weight"] = value
arr["map,9"] = 150
arr["compass,13"] = 35
arr["water,153"] = 200
arr["sandwich,50"] = 160
arr["glucose,15"] = 60
arr["tin,68"] = 45
arr["banana,27"] = 60
arr["apple,39"] = 40
arr["cheese,23"] = 30
arr["beer,52"] = 10
arr["suntan cream,11"] = 70
arr["camera,32"] = 30
arr["T-shirt,24"] = 15
arr["trousers,48"] = 10
arr["umbrella,73"] = 40
arr["waterproof trousers,42"] = 70
arr["waterproof overclothes,43"] = 75
arr["note-case,22"] = 80
arr["sunglasses,7"] = 20
arr["towel,18"] = 12
arr["socks,4"] = 50
arr["book,30"] = 10
sack_size = 400 # dag
PROCINFO["sorted_in"] = "@val_num_desc"
for (i in arr) {
if (total_weight >= sack_size) {
break
}
split(i,tmp,",")
weight = tmp[2]
if (total_weight + weight <= sack_size) {
printf("%s\n",tmp[1])
total_items++
total_value += arr[i]
total_weight += weight
}
}
printf("items=%d (out of %d) weight=%d value=%d\n",total_items,length(arr),total_weight,total_value)
exit(0)
}

View file

@ -0,0 +1,66 @@
:: Initiate command line environment
@echo off
setlocal enabledelayedexpansion
:: Establish arrays we'll be using
set items=map compass water sandwich glucose tin banana apple cheese beer suntancream camera tshirt trousers umbrella waterprooftrousers waterproofoverclothes notecase sunglasses towel socks book
set weight=9 13 153 50 15 68 27 39 23 52 11 32 24 48 73 42 43 22 7 18 4 30
set importance=150 35 200 160 60 45 60 40 30 10 70 30 15 10 40 70 75 80 20 12 50 10
:: Put the above 3 arrays into their own variables with the form of "item[]", "w[]" and "i[]"
set tempnum=0
for %%i in (%items%) do (
set /a tempnum+=1
set item!tempnum!=%%i
)
set tempnum=0
for %%i in (%weight%) do (
set /a tempnum+=1
set w!tempnum!=%%i
)
set tempnum=0
for %%i in (%importance%) do (
set /a tempnum+=1
set i!tempnum!=%%i
)
:: Define the array "r[]" as the ratio between the importance ("i[]") and the weight ("w[]").
for /l %%i in (1,1,22) do set /a r%%i=!i%%i!*100/!w%%i! & rem batch doesn't support decimals, so the numerator is multiplied by 100 to get past this
set totalimportance=0
set totalweight=0
set amount=0
:: Find the largest number in "r[]" and define some temp variables based off it
:load
set tempr=0
set tempitem=0
for /l %%i in (1,1,22) do (
if !r%%i! gtr !tempr! (
set tempr=!r%%i!
set tempitem=%%i
set /a testweight=%totalweight%+!w%%i!
if !tempr!==0 goto end
if !testweight! geq 400 goto end
)
)
:: Do basic error checking using the temp variables from above and either output and end the program or send back to load
set /a totaltempweight=%totalweight%+!w%tempitem%!
if %totaltempweight% gtr 400 (
set !r%tempitem%!=0
goto load
)
set totalweight=%totaltempweight%
set /a totalimportance+=!i%tempitem%!
set taken=%taken% !item%tempitem%!
set /a amount+=1
set r%tempitem%=0 & rem set the ratio variable of the item we just added to the knapsack as 0 to stop it repeat
goto load
:end
echo List of things taken [%amount%]: %taken%
echo Total Value: %totalimportance% Total Weight: %totalweight%
pause>nul

View file

@ -0,0 +1,61 @@
defmodule Knapsack do
def solve([], _total_weight, item_acc, value_acc, weight_acc), do:
{item_acc, value_acc, weight_acc}
def solve([{_item, item_weight, _item_value} | t],
total_weight,
item_acc,
value_acc,
weight_acc) when item_weight > total_weight, do:
solve(t, total_weight, item_acc, value_acc, weight_acc)
def solve([{item_name, item_weight, item_value} | t],
total_weight,
item_acc,
value_acc,
weight_acc) do
{_tail_item_acc, tail_value_acc, _tail_weight_acc} = tail_res =
solve(t, total_weight, item_acc, value_acc, weight_acc)
{_head_item_acc, head_value_acc, _head_weight_acc} = head_res =
solve(t,
total_weight - item_weight,
[item_name | item_acc],
value_acc + item_value,
weight_acc + item_weight)
if tail_value_acc > head_value_acc, do: tail_res, else: head_res
end
end
stuff = [{"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}]
max_weight = 400
go = fn (stuff, max_weight) ->
{time, {item_list, total_value, total_weight}} = :timer.tc(fn ->
Knapsack.solve(stuff, max_weight, [], 0, 0)
end)
IO.puts "Items:"
Enum.each(item_list, fn item -> IO.inspect item end)
IO.puts "Total value: #{total_value}"
IO.puts "Total weight: #{total_weight}"
IO.puts "Time elapsed in milliseconds: #{time/1000}"
end
go.(stuff, max_weight)

View file

@ -0,0 +1,54 @@
// version 1.1.2
data class Item(val name: String, val weight: Int, val value: Int)
val wants = listOf(
Item("map", 9, 150),
Item("compass", 13, 35),
Item("water", 153, 200),
Item("sandwich", 50, 160),
Item("glucose", 15, 60),
Item("tin", 68, 45),
Item("banana", 27, 60),
Item("apple", 39, 40),
Item("cheese", 23, 30),
Item("beer", 52, 10),
Item("suntan cream", 11, 70),
Item("camera", 32, 30),
Item("T-shirt", 24, 15),
Item("trousers", 48, 10),
Item("umbrella", 73, 40),
Item("waterproof trousers", 42, 70),
Item("waterproof overclothes", 43, 75),
Item("note-case", 22, 80),
Item("sunglasses", 7, 20),
Item("towel", 18, 12),
Item("socks", 4, 50),
Item("book", 30, 10)
)
const val MAX_WEIGHT = 400
fun m(i: Int, w: Int): Triple<MutableList<Item>, Int, Int> {
val chosen = mutableListOf<Item>()
if (i < 0 || w == 0) return Triple(chosen, 0, 0)
else if (wants[i].weight > w) return m(i - 1, w)
val (l0, w0, v0) = m(i - 1, w)
var (l1, w1, v1) = m(i - 1, w - wants[i].weight)
v1 += wants[i].value
if (v1 > v0) {
l1.add(wants[i])
return Triple(l1, w1 + wants[i].weight, v1)
}
return Triple(l0, w0, v0)
}
fun main(args: Array<String>) {
val (chosenItems, totalWeight, totalValue) = m(wants.size - 1, MAX_WEIGHT)
println("Knapsack Item Chosen Weight Value")
println("---------------------- ------ -----")
for (item in chosenItems.sortedByDescending { it.value} )
println("${item.name.padEnd(24)} ${"%3d".format(item.weight)} ${"%3d".format(item.value)}")
println("---------------------- ------ -----")
println("Total ${chosenItems.size} Items Chosen $totalWeight $totalValue")
}

View file

@ -8,11 +8,9 @@
# PHP Translation from Python, Memoization,
# and index return functionality added by Brian Berneker
#
#It works uncorrectly! For examle if $aw=4. Max value is true, but no "Array Indices" and its parameters are displayed
#
#########################################################
function knapSolveFast2($w, $v, $i, $aW, &$m, &$pickedItems) {
function knapSolveFast2($w, $v, $i, $aW, &$m) {
global $numcalls;
$numcalls ++;
@ -40,18 +38,18 @@ function knapSolveFast2($w, $v, $i, $aW, &$m, &$pickedItems) {
// 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);
list ($without_i, $without_PI) = knapSolveFast2($w, $v, $i-1, $aW, $m);
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...
return array($without_i,array()); // and return it
$m['picked'][$i][$aW] = $without_PI; // and a blank array entry...
return array($without_i, $without_PI); // 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);
list ($with_i,$with_PI) = knapSolveFast2($w, $v, ($i-1), ($aW - $w[$i]), $m);
$with_i += $v[$i]; // ..and add the value of this one..
// Get the greater of WITH or WITHOUT
@ -81,7 +79,7 @@ $v4 = array(150,35,200,160,60,45,60,40,30,10,70,30,15,10,40,70,75,80,20,12,50,10
$numcalls = 0; $m = array(); $pickedItems = array();
## Solve
list ($m4,$pickedItems) = knapSolveFast2($w4, $v4, sizeof($v4) -1, 400,$m,$pickedItems);
list ($m4,$pickedItems) = knapSolveFast2($w4, $v4, sizeof($v4) -1, 400, $m);
# Display Result
echo "<b>Items:</b><br>".join(", ",$items4)."<br>";

View file

@ -0,0 +1,83 @@
program project1;
uses
sysutils, classes, math;
const
MaxWeight = 400;
N = 21;
type
TMaxArray = array[0..N, 0..MaxWeight] of integer;
TEquipment = record
Description : string;
Weight : integer;
Value : integer;
end;
TEquipmentList = array[1..N] of TEquipment;
var
M:TMaxArray;
MaxValue, WeightLeft, i, j, Sum : integer;
S,KnapSack:TStringList;
L:string;
List:TEquipmentList;
begin
//Put all the items into an array called List
L:='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 ,suntancreme ,11 ,70 ,camera ,32 ,30 ,T-shirt ,24 ,15 ,trousers ,48 ,40 ,waterprooftrousers ,42 ,70 ,waterproofoverclothes ,43 ,75 ,notecase ,22 ,80 ,sunglasses ,7 ,20 ,towel ,18 ,12 ,socks ,4 ,50 ,book ,30 ,10';
S:=TStringList.create;
S.Commatext:=L;
For i:= 1 to N do
begin
List[i].Description:=S[3*i - 3];
List[i].Weight:=strtoint(S[3*i - 2]);
List[i].Value:=strtoint(S[3*i - 1]);
end;
//create M, a table linking the possible items for each weight
//and recording the value at that point
for j := 0 to MaxWeight do
M[0, j] := 0
for i := 1 to N do
for j := 0 to MaxWeight do
if List[i].weight > j then
M[i, j] := M[i-1, j]
else
M[i, j] := max(M[i-1, j], M[i-1, j-List[i].weight] + List[i].value);
//get the highest total value by testing every value in table M
for i:=1 to N do
for j:= 0 to MaxWeight do
If M[i,j] > MaxValue then
MaxValue := m[i,j];
writeln('Highest total value : ',MaxValue);
//Work backwards through the items to find those items that go in the Knapsack (a stringlist)
KnapSack := TStringList.create;
WeightLeft := MaxWeight;
For i:= N downto 1 do
if M[i,WeightLeft] = MaxValue then
if M[i-1, WeightLeft - List[i].Weight] = MaxValue - List[i].Value then
begin
Knapsack.add(List[i].Description + ' ' + IntToStr(List[i].Weight)+ ' ' + inttostr(List[i].Value));
MaxValue := MaxValue - List[i].Value;
WeightLeft := WeightLeft - List[i].Weight;
end
//Show the items in the knapsack
writeln('Number of items : ',KnapSack.count);
writeln('-------------------------');
For i:= KnapSack.count-1 downto 0 do
writeln(KnapSack[i]);
KnapSack.free;
S.free;
writeln('-------------------------');
writeln('done');
readln;
end.

View file

@ -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 {
KnapsackItem.new: :$name, :$weight, :$unit;
my @table = flat map -> $name, $weight, $unit {
KnapsackItem.new: :$name, :$weight, :$unit;
},
'map', 9, 150,
'compass', 13, 35,

View file

@ -0,0 +1,68 @@
integer terminate=0
integer attempts = 0
function knapsack(sequence res, goodies, atom points, weight, at=1, sequence chosen={})
atom {witem,pitem} = goodies[at][2]
integer n = (witem<=weight)
chosen &= n
points += n*pitem -- increase value
weight -= n*witem -- decrease weight left
if at=length(goodies) then
attempts += 1
if length(res)=0
or res<{points,weight} then
res = {points,weight,chosen}
end if
terminate = (n=1)
else
while n>=0 and not terminate do
res = knapsack(res,goodies,points,weight,at+1,chosen)
n -= 1
chosen[$] = n
points -= pitem
weight += witem
end while
end if
return res
end function
function byweightedvalue(object a, b)
-- sort by weight/value
return compare(a[2][1]/a[2][2],b[2][1]/b[2][2])
-- nb other sort orders break the optimisation
end function
constant goodies = custom_sort(routine_id("byweightedvalue"),{
-- item weight value
{"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 }}})
atom t0 = time()
object {points,weight,counts} = knapsack({},goodies,0,400)
printf(1,"Value %d, weight %g [%d attempts, %3.2fs]:\n",{points,400-weight,attempts,time()-t0})
for i=1 to length(counts) do
integer c = counts[i]
if c then
printf(1,"%s\n",{goodies[i][1]})
end if
end for

View file

@ -1,112 +1,102 @@
/*REXX program solves a knapsack problem (23 items with a weight restriction).*/
@.=; @.1 = 'map 9 150'
@.2 = 'compass 13 35'
@.3 = 'water 153 200'
@.4 = 'sandwich 50 160'
@.5 = 'glucose 15 60'
@.6 = 'tin 68 45'
@.7 = 'banana 27 60'
@.8 = 'apple 39 40'
@.9 = 'cheese 23 30'
@.10 = 'beer 52 10'
@.11 = 'suntan_cream 11 70'
@.12 = 'camera 32 30'
@.13 = 'T-shirt 24 15'
@.14 = 'trousers 48 10'
@.15 = 'umbrella 73 40'
@.16 = 'waterproof_trousers 42 70'
@.17 = 'waterproof_overclothes 43 75'
@.18 = 'note-case 22 80'
@.19 = 'sunglasses 7 20'
@.20 = 'towel 18 12'
@.21 = 'socks 4 50'
@.22 = 'book 30 10'
@.23 = 'anvil 1000 1250'
maxWeight=400 /*the maximum weight for the knapsack. */
say 'maximum weight allowed for a knapsack:' commas(maxWeight); say
pot_item= 'potential knapsack items' /*the full name for the header title. */
maxL=length(pot_item) /*maximum width for the table names. */
maxW=length('weight') /* " " " " " weights. */
maxV=length('value') /* " " " " " values. */
#=0; i.=; w.=0; v.=0; q.=0; Tw=0; Tv=0 /*initialize some stuff.*/
/*══════════════════════════════════════sort the choices by decreasing weight.*/
do j=1 while @.j\=='' /*process each of the knapsack choices.*/
_=space(@.j); _wt=word(_, 2) /*choose the first item (arbitrary). */
do k=j+1 while @.k\=='' /*find a possible heavier knapsack item*/
?wt=word(@.k, 2)
if ?wt>_wt then do; _=@.k; @.k=@.j; @.j=_; _wt=?wt; end
end /*k*/
end /*j*/
obj=j-1 /*decrement J for the DO loop index*/
/*══════════════════════════════════════build list of choices.════════════════*/
do j=1 for obj /*construct a list of knapsack choices.*/
parse var @.j item w v . /*parse the original choice for table. */
if w>maxWeight then iterate /*Is weight greater than max? Ignore.*/
Tw=Tw+w; Tv=Tv+v /*add the totals (for output alignment)*/
maxL=max(maxL, length(item)) /*determine the maximum width for item.*/
#=#+1; i.#=item; w.#=w; v.#=v /*bump the number of items (choices). */
end /*j*/
maxW=max(maxW,length(commas(Tw))) /*find the maximum width for weight. */
maxV=max(maxV,length(commas(Tv))) /* " " " " " value. */
maxL=maxL + maxL%4 + 4 /*extend the width of name for table. */
/*══════════════════════════════════════show the list of choices.═════════════*/
call hdr pot_item; do j=1 for obj /*show all choices in a nice format. */
parse var @.j item weight value .
call show item, weight, value
end /*j*/
say
say 'number of allowable items: ' # /* [↓] examine all possible choices. */
$=0; m=maxWeight
do j1 =0 for #+1; w1 = w.j1; v1 = v.j1
do j2 =j1 +(j1 \==0) to #; if w.j2 +w1 >m then iterate j1 ; w2 =w1 +w.j2; v2 =v1 +v.j2
do j3 =j2 +(j2 \==0) to #; if w.j3 +w2 >m then iterate j2 ; w3 =w2 +w.j3; v3 =v2 +v.j3
do j4 =j3 +(j3 \==0) to #; if w.j4 +w3 >m then iterate j3 ; w4 =w3 +w.j4; v4 =v3 +v.j4
do j5 =j4 +(j4 \==0) to #; if w.j5 +w4 >m then iterate j4 ; w5 =w4 +w.j5; v5 =v4 +v.j5
do j6 =j5 +(j5 \==0) to #; if w.j6 +w5 >m then iterate j5 ; w6 =w5 +w.j6; v6 =v5 +v.j6
do j7 =j6 +(j6 \==0) to #; if w.j7 +w6 >m then iterate j6 ; w7 =w6 +w.j7; v7 =v6 +v.j7
do j8 =j7 +(j7 \==0) to #; if w.j8 +w7 >m then iterate j7 ; w8 =w7 +w.j8; v8 =v7 +v.j8
do j9 =j8 +(j8 \==0) to #; if w.j9 +w8 >m then iterate j8 ; w9 =w8 +w.j9; v9 =v8 +v.j9
do j10=j9 +(j9 \==0) to #; if w.j10+w9 >m then iterate j9 ; w10=w9 +w.j10;v10=v9 +v.j10
do j11=j10+(j10\==0) to #; if w.j11+w10>m then iterate j10; w11=w10+w.j11;v11=v10+v.j11
do j12=j11+(j11\==0) to #; if w.j12+w11>m then iterate j11; w12=w11+w.j12;v12=v11+v.j12
do j13=j12+(j12\==0) to #; if w.j13+w12>m then iterate j12; w13=w12+w.j13;v13=v12+v.j13
do j14=j13+(j13\==0) to #; if w.j14+w13>m then iterate j13; w14=w13+w.j14;v14=v13+v.j14
do j15=j14+(j14\==0) to #; if w.j15+w14>m then iterate j14; w15=w14+w.j15;v15=v14+v.j15
do j16=j15+(j15\==0) to #; if w.j16+w15>m then iterate j15; w16=w15+w.j16;v16=v15+v.j16
do j17=j16+(j16\==0) to #; if w.j17+w16>m then iterate j16; w17=w16+w.j17;v17=v16+v.j17
do j18=j17+(j17\==0) to #; if w.j18+w17>m then iterate j17; w18=w17+w.j18;v18=v17+v.j18
do j19=j18+(j18\==0) to #; if w.j19+w18>m then iterate j18; w19=w18+w.j19;v19=v18+v.j19
do j20=j19+(j19\==0) to #; if w.j20+w19>m then iterate j19; w20=w19+w.j20;v20=v19+v.j20
do j21=j20+(j20\==0) to #; if w.j21+w20>m then iterate j20; w21=w20+w.j21;v21=v20+v.j21
do j22=j21+(j21\==0) to #; if w.j22+w21>m then iterate j21; w22=w21+w.j22;v22=v21+v.j22
if v22>$ then do; _=22; ?=; $=v22; do j=1 for _; ?=? value("J"j); end /*j*/; end
end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end
bestC=?; bestW=0; bestV=$; totP=words(bestC); say
call hdr 'best choice'
do j=1 for totP; _=word(bestC, j); _w=w._; _v=v._
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
end /*k*/
call show i._,w._,v._; bestW=bestw+w._
end /*j*/
call hdr2; say; @btk= 'best total knapsack'
call show @btk 'weight' , bestW /*display a nicely formatted winnerW. */
call show @btk 'value' ,, bestV /* " " " " winnerV. */
call show @btk 'items' ,,, totP /* " " " " pieces. */
exit /*stick a fork in it, we're all done. */
/*────────────────────────────────────────────────────────────────────────────*/
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: call show center(arg(1),maxL),center('weight',maxW),center("value",maxV)
call hdr2; return
/*────────────────────────────────────────────────────────────────────────────*/
hdr2: call show copies('',maxL),copies('',maxW),copies('',maxV); return
/*────────────────────────────────────────────────────────────────────────────*/
show: parse arg _it,_wt,_val,_p; say translate( left(_it, maxL, ''),,"_"),
right(commas(_wt),maxW) right(commas(_val),maxV) ' ' _p; return
/*REXX program solves a knapsack problem (22 {+1} items with a weight restriction). */
maxWeight=400 /*the maximum weight for the knapsack. */
say 'maximum weight allowed for a knapsack:' commas(maxWeight); say
call gen@ /*generate the @ array of choices. */
call sortD /* sort " " " " " */
call build /*build some associative arrays from @.*/
call findBest /*go ye forth and find the best choises*/
call results /*display the best choices for knapsack*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
build: do j=1 for obj; parse var @.j x w v . /*construct a list of knapsack choices.*/
if w>maxWeight then iterate /*Is weight greater than max? Ignore.*/
totW=totW + w; totV=totV + v /*add the totals (for output alignment)*/
maxL=max(maxL, length(x) ) /*determine maximum width for an item. */
#=#+1; i.#=x; w.#=w; v.#=v /*bump the number of items (choices). */
end /*j*/ /* [↑] build indexable arrays of items*/
maxL= maxL + maxL%4 + 4 /*extend width of name for shown table.*/
maxW= max(maxW, length( commas(totW) ) ) /*find the maximum width for weight. */
maxV= max(maxV, length( commas(totV) ) ) /* " " " " " value. */
call hdr 'potential knapsack items' /*display a header for list of choices.*/
do j=1 for obj; parse var @.j i w v . /*show all the choices in a nice format*/
if w<=maxWeight then call show i,w,v /*Is weight within limits? Then show. */
end /*j*/ /* [↑] display the list of choices. */
$=0
say; say 'number of allowable items: ' #
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: procedure; parse arg _; n=_'.9'; #=123456789; b=verify(n, #, "M")
e=verify(n, #'0', , verify(n, #"0.", 'M')) - 4; comma=','
do j=e to b by -3; _=insert(comma, _, j); end /*j*/; return _
/*──────────────────────────────────────────────────────────────────────────────────────*/
findBest: m=maxWeight /*items are in decreasing weight.*/
do j1 =0 for #+1; w1 = w.j1 ; z1 = v.j1
do j2 =j1 +(j1 >0) to #; if w.j2 +w1 >m then iterate j1 ; w2 =w1 +w.j2 ; z2 =z1 +v.j2
do j3 =j2 +(j2 >0) to #; if w.j3 +w2 >m then iterate j2 ; w3 =w2 +w.j3 ; z3 =z2 +v.j3
do j4 =j3 +(j3 >0) to #; if w.j4 +w3 >m then iterate j3 ; w4 =w3 +w.j4 ; z4 =z3 +v.j4
do j5 =j4 +(j4 >0) to #; if w.j5 +w4 >m then iterate j4 ; w5 =w4 +w.j5 ; z5 =z4 +v.j5
do j6 =j5 +(j5 >0) to #; if w.j6 +w5 >m then iterate j5 ; w6 =w5 +w.j6 ; z6 =z5 +v.j6
do j7 =j6 +(j6 >0) to #; if w.j7 +w6 >m then iterate j6 ; w7 =w6 +w.j7 ; z7 =z6 +v.j7
do j8 =j7 +(j7 >0) to #; if w.j8 +w7 >m then iterate j7 ; w8 =w7 +w.j8 ; z8 =z7 +v.j8
do j9 =j8 +(j8 >0) to #; if w.j9 +w8 >m then iterate j8 ; w9 =w8 +w.j9 ; z9 =z8 +v.j9
do j10=j9 +(j9 >0) to #; if w.j10+w9 >m then iterate j9 ; w10=w9 +w.j10; z10=z9 +v.j10
do j11=j10+(j10>0) to #; if w.j11+w10>m then iterate j10; w11=w10+w.j11; z11=z10+v.j11
do j12=j11+(j11>0) to #; if w.j12+w11>m then iterate j11; w12=w11+w.j12; z12=z11+v.j12
do j13=j12+(j12>0) to #; if w.j13+w12>m then iterate j12; w13=w12+w.j13; z13=z12+v.j13
do j14=j13+(j13>0) to #; if w.j14+w13>m then iterate j13; w14=w13+w.j14; z14=z13+v.j14
do j15=j14+(j14>0) to #; if w.j15+w14>m then iterate j14; w15=w14+w.j15; z15=z14+v.j15
do j16=j15+(j15>0) to #; if w.j16+w15>m then iterate j15; w16=w15+w.j16; z16=z15+v.j16
do j17=j16+(j16>0) to #; if w.j17+w16>m then iterate j16; w17=w16+w.j17; z17=z16+v.j17
do j18=j17+(j17>0) to #; if w.j18+w17>m then iterate j17; w18=w17+w.j18; z18=z17+v.j18
do j19=j18+(j18>0) to #; if w.j19+w18>m then iterate j18; w19=w18+w.j19; z19=z18+v.j19
do j20=j19+(j19>0) to #; if w.j20+w19>m then iterate j19; w20=w19+w.j20; z20=z19+v.j20
do j21=j20+(j20>0) to #; if w.j21+w20>m then iterate j20; w21=w20+w.j21; z21=z20+v.j21
do j22=j21+(j21>0) to #; if w.j22+w21>m then iterate j21; w22=w21+w.j22; z22=z21+v.j22
if z22>$ then do; ?=; $=z22; do j=1 for 22; ?=? value("J"j); end /*j*/; end
end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
gen@: @. = ; @.12= 'camera 32 30'
@.1 = 'map 9 150' ; @.13= 'T-shirt 24 15'
@.2 = 'compass 13 35' ; @.14= 'trousers 48 10'
@.3 = 'water 153 200' ; @.15= 'umbrella 73 40'
@.4 = 'sandwich 50 160' ; @.16= 'waterproof_trousers 42 70'
@.5 = 'glucose 15 60' ; @.17= 'waterproof_overclothes 43 75'
@.6 = 'tin 68 45' ; @.18= 'note-case 22 80'
@.7 = 'banana 27 60' ; @.19= 'sunglasses 7 20'
@.8 = 'apple 39 40' ; @.20= 'towel 18 12'
@.9 = 'cheese 23 30' ; @.21= 'socks 4 50'
@.10= 'beer 52 10' ; @.22= 'book 30 10'
@.11= 'suntan_cream 11 70' ; @.23= 'anvil 100000 1'
maxL = length('potential knapsack items') /*maximum width for the table items. */
maxW = length('weight') /* " " " " " weights. */
maxV = length('value') /* " " " " " values. */
#=0; i.=; w.=0; v.=0; totW=0; totV=0 /*initialize some REX variables stuff. */
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
hdr: say; call show center(arg(1),maxL),center('weight',maxW),center("value",maxV)
hdr2: call show copies('',maxL),copies('',maxW),copies('',maxV); return
/*──────────────────────────────────────────────────────────────────────────────────────*/
results: do #; ?=strip( space(?), "L", 0); end /*h*/ /*elide leading zeroes*/
bestC=?; bestW=0; totP=words(bestC); say; call hdr 'best choice'
do j=1 for totP; _=word(bestC, j); _w=w._; _v=v._
do k=j+1 to totP; __=word(bestC, k); if i._\==i.__ then leave
j=j+1; w._=w._ + _w; v._=v._ + _v
end /*k*/
call show i._, w._, v._; bestW=bestW + w._
end /*j*/
call hdr2 ; say; @bestTK= 'best total knapsack'
call show @bestTK 'weight' , bestW /*display a nicely formatted winner wt.*/
call show @bestTK 'value' ,, $ /* " " " " winner val*/
call show @bestTK 'items' ,,, totP /* " " " " pieces. */
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
show: parse arg _i,_w,_v,_p; say translate( left(_i,maxL,''), , "_") ,
right(commas(_w),maxW) right(commas(_v),maxV) _p; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
sortD: do j=1 while @.j\==''; y=word(@.j,2) /*process each of the knapsack choices.*/
do k=j+1 while @.k\=='' /*find a possible heavier knapsack item*/
?=word(@.k,2); if ?>y then do; _=@.k; @.k=@.j; @.j=_; y=?; end /*swap*/
end /*k*/
end /*j*/ /* [↑] sort choices by decreasing wt. */
obj=j-1; return /*decrement J for the DO loop index*/

View file

@ -1,86 +1,30 @@
#![feature(iter_arith)]
use std::cmp::max;
use std::vec::Vec;
use std::cmp;
// This struct is used to store our items that we want in our knap-sack.
#[derive(Clone, Debug)]
struct Item<'a> {
name: &'a str,
struct Item {
name: &'static str,
weight: usize,
value: usize
}
// This is a bottom-up dynamic programming solution to the 0-1 knap-sack problem.
// maximize value
// subject to weights <= max_weight
fn knapsack01_dyn<'a>(items: &[Item<'a>], max_weight: usize) -> Vec<Item<'a>> {
// Imagine we wrote a recursive function(item, max_weight) that returns a
// usize corresponding to the maximum cumulative value by considering a
// subset of items such that the combined weight <= max_weight.
//
// fn best_value(item: usize, max_weight: usize) -> usize {
// if item == 0 {
// return 0;
// }
// if items[item - 1].weight > max_weight {
// return best_value(item - 1, max_weight);
// }
// return max(best_value(item - 1, max_weight),
// best_value(item - 1, max_weight - items[item - 1].weight)
// + items[item - 1].value);
// }
// }
//
// best_value(n_items, max_weight) is equal to the maximum value that
// we can add to the bag.
//
// The problem with using this function is that it performs redundant
// calculations.
//
// The dynamic programming solution is to precompute all of the values
// we need and put them into a 2D array.
//
// In a similar vein, the top-down solution would be to memoize the
// function then compute the results on demand.
let mut best_value = vec![vec![0usize; max_weight + 1]; items.len() + 1];
// Loop over the items.
fn knapsack01_dyn(items: &[Item], max_weight: usize) -> Vec<&Item> {
let mut best_value = vec![vec![0; max_weight + 1]; items.len() + 1];
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()
best_value[i][w]
} 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)
cmp::max(best_value[i][w], best_value[i][w - it.weight] + it.value)
}
}
}
// A possibly over-allocated dynamically sized vector to push results to.
let mut result = Vec::with_capacity(items.len());
let mut left_weight = max_weight;
// Variable representing the weight left in the bag
let mut left_weight = max_weight.clone();
// 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.
result.push(it);
left_weight -= it.weight;
}
}
@ -92,9 +36,7 @@ fn knapsack01_dyn<'a>(items: &[Item<'a>], max_weight: usize) -> Vec<Item<'a>> {
fn main () {
const MAX_WEIGHT: usize = 400;
// Static immutable allocation of our items.
static ITEMS: &'static [Item<'static>] = &[
// Too much repetition of field names here!
const ITEMS: &[Item] = &[
Item { name: "map", weight: 9, value: 150 },
Item { name: "compass", weight: 13, value: 35 },
Item { name: "water", weight: 153, value: 200 },
@ -123,12 +65,9 @@ fn main () {
// We reverse the order because we solved the problem backward.
for it in items.iter().rev() {
println!("{:?}", it);
println!("{}", it.name);
}
let tot_weight: usize = items.iter().map(|w| w.weight).sum();
println!("Total weight: {}", tot_weight);
let tot_value: usize = items.iter().map(|w| w.value).sum();
println!("Total value: {}", tot_value);
println!("Total weight: {}", items.iter().map(|w| w.weight).sum::<usize>());
println!("Total value: {}", items.iter().map(|w| w.value).sum::<usize>());
}

View file

@ -0,0 +1,58 @@
'Knapsack problem/0-1 - 12/02/2017
Option Explicit
Const maxWeight = 400
Dim DataList As Variant
Dim xList(64, 3) As Variant
Dim nItems As Integer
Dim s As String, xss As String
Dim xwei As Integer, xval As Integer, nn As Integer
Sub Main()
Dim i As Integer, j As Integer
DataList = Array("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, "book", 30, 10, _
"waterproof trousers", 42, 70, "waterproof overclothes", 43, 75, _
"note-case", 22, 80, "sunglasses", 7, 20, "towel", 18, 12, "socks", 4, 50)
nItems = (UBound(DataList) + 1) / 3
j = 0
For i = 1 To nItems
xList(i, 1) = DataList(j)
xList(i, 2) = DataList(j + 1)
xList(i, 3) = DataList(j + 2)
j = j + 3
Next i
s = ""
For i = 1 To nItems
s = s & Chr(i)
Next
nn = 0
Call ChoiceBin(1, "")
For i = 1 To Len(xss)
j = Asc(Mid(xss, i, 1))
Debug.Print xList(j, 1)
Next i
Debug.Print "count=" & Len(xss), "weight=" & xwei, "value=" & xval
End Sub 'Main
Private Sub ChoiceBin(n As String, ss As String)
Dim r As String
Dim i As Integer, j As Integer, iwei As Integer, ival As Integer
Dim ipct As Integer
If n = Len(s) + 1 Then
iwei = 0: ival = 0
For i = 1 To Len(ss)
j = Asc(Mid(ss, i, 1))
iwei = iwei + xList(j, 2)
ival = ival + xList(j, 3)
Next
If iwei <= maxWeight And ival > xval Then
xss = ss: xwei = iwei: xval = ival
End If
Else
r = Mid(s, n, 1)
Call ChoiceBin(n + 1, ss & r)
Call ChoiceBin(n + 1, ss)
End If
End Sub 'ChoiceBin

View file

@ -0,0 +1,214 @@
' Knapsack problem/0-1 - 13/02/2017
dim w(22),v(22),m(22)
data=array( "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, "book", 30, 10 , _
"waterproof trousers", 42, 70, "waterproof overclothes", 43, 75 , _
"note-case", 22, 80, "sunglasses", 7, 20, "towel", 18, 12, "socks", 4, 50)
ww=400
xw=0:iw=0:iv=0
w(1)=iw:v(1)=iv
for i1=0 to 1:m(1)=i1:j=0
if i1=1 then
iw=w(1)+data(j*3+1):iv=v(1)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i1
if iw<=ww then
w(2)=iw: v(2)=iv
for i2=0 to 1:m(2)=i2:j=1
if i2=1 then
iw=w(2)+data(j*3+1):iv=v(2)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i2
if iw<=ww then
w(3)=iw: v(3)=iv
for i3=0 to 1:m(3)=i3:j=2
if i3=1 then
iw=w(3)+data(j*3+1):iv=v(3)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i3
if iw<=ww then
w(4)=iw: v(4)=iv
for i4=0 to 1:m(4)=i4:j=3
if i4=1 then
iw=w(4)+data(j*3+1):iv=v(4)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i4
if iw<=ww then
w(5)=iw: v(5)=iv
for i5=0 to 1:m(5)=i5:j=4
if i5=1 then
iw=w(5)+data(j*3+1):iv=v(5)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i5
if iw<=ww then
w(6)=iw: v(6)=iv
for i6=0 to 1:m(6)=i6:j=5
if i6=1 then
iw=w(6)+data(j*3+1):iv=v(6)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i6
if iw<=ww then
w(7)=iw: v(7)=iv
for i7=0 to 1:m(7)=i7:j=6
if i7=1 then
iw=w(7)+data(j*3+1):iv=v(7)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i7
if iw<=ww then
w(8)=iw: v(8)=iv
for i8=0 to 1:m(8)=i8:j=7
if i8=1 then
iw=w(8)+data(j*3+1):iv=v(8)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i8
if iw<=ww then
w(9)=iw: v(9)=iv
for i9=0 to 1:m(9)=i9:j=8
if i9=1 then
iw=w(9)+data(j*3+1):iv=v(9)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i9
if iw<=ww then
w(10)=iw: v(10)=iv
for i10=0 to 1:m(10)=i10:j=9
if i10=1 then
iw=w(10)+data(j*3+1):iv=v(10)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i10
if iw<=ww then
w(11)=iw: v(11)=iv
for i11=0 to 1:m(11)=i11:j=10
if i11=1 then
iw=w(11)+data(j*3+1):iv=v(11)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i11
if iw<=ww then
w(12)=iw: v(12)=iv
for i12=0 to 1:m(12)=i12:j=11
if i12=1 then
iw=w(12)+data(j*3+1):iv=v(12)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i12
if iw<=ww then
w(13)=iw: v(13)=iv
for i13=0 to 1:m(13)=i13:j=12
if i13=1 then
iw=w(13)+data(j*3+1):iv=v(13)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i13
if iw<=ww then
w(14)=iw: v(14)=iv
for i14=0 to 1:m(14)=i14:j=13
if i14=1 then
iw=w(14)+data(j*3+1):iv=v(14)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i14
if iw<=ww then
w(15)=iw: v(15)=iv
for i15=0 to 1:m(15)=i15:j=14
if i15=1 then
iw=w(15)+data(j*3+1):iv=v(15)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i15
if iw<=ww then
w(16)=iw: v(16)=iv
for i16=0 to 1:m(16)=i16:j=15
if i16=1 then
iw=w(16)+data(j*3+1):iv=v(16)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i16
if iw<=ww then
w(17)=iw: v(17)=iv
for i17=0 to 1:m(17)=i17:j=16
if i17=1 then
iw=w(17)+data(j*3+1):iv=v(17)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i17
if iw<=ww then
w(18)=iw: v(18)=iv
for i18=0 to 1:m(18)=i18:j=17
if i18=1 then
iw=w(18)+data(j*3+1):iv=v(18)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i18
if iw<=ww then
w(19)=iw: v(19)=iv
for i19=0 to 1:m(19)=i19:j=18
if i19=1 then
iw=w(19)+data(j*3+1):iv=v(19)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i19
if iw<=ww then
w(20)=iw: v(20)=iv
for i20=0 to 1:m(20)=i20:j=19
if i20=1 then
iw=w(20)+data(j*3+1):iv=v(20)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i20
if iw<=ww then
w(21)=iw: v(21)=iv
for i21=0 to 1:m(21)=i21:j=20
if i21=1 then
iw=w(21)+data(j*3+1):iv=v(21)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i21
if iw<=ww then
w(22)=iw: v(22)=iv
for i22=0 to 1:m(22)=i22:j=21
nn=nn+1
if i22=1 then
iw=w(22)+data(j*3+1):iv=v(22)+data(j*3+2)
if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
end if 'i22
if iw<=ww then
end if 'i22
next:m(22)=0
end if 'i21
next:m(21)=0
end if 'i20
next:m(20)=0
end if 'i19
next:m(19)=0
end if 'i18
next:m(18)=0
end if 'i17
next:m(17)=0
end if 'i16
next:m(16)=0
end if 'i15
next:m(15)=0
end if 'i14
next:m(14)=0
end if 'i13
next:m(13)=0
end if 'i12
next:m(12)=0
end if 'i11
next:m(11)=0
end if 'i10
next:m(10)=0
end if 'i9
next:m(9)=0
end if 'i8
next:m(8)=0
end if 'i7
next:m(7)=0
end if 'i6
next:m(6)=0
end if 'i5
next:m(5)=0
end if 'i4
next:m(4)=0
end if 'i3
next:m(3)=0
end if 'i2
next:m(2)=0
end if 'i1
next:m(1)=0
for i=1 to 22
if l(i)=1 then wlist=wlist&vbCrlf&data((i-1)*3)
next
Msgbox mid(wlist,3)&vbCrlf&vbCrlf&"weight="&xw&vbCrlf&"value="&xv,,"Knapsack - nn="&nn

View file

@ -0,0 +1,83 @@
'Knapsack problem/0-1 - 12/02/2017
Public Class KnapsackBin
Const knam = 0, kwei = 1, kval = 2
Const maxWeight = 400
Dim xList(,) As Object = { _
{"map", 9, 150}, _
{"compass", 13, 35}, _
{"water", 153, 200}, _
{"sandwich", 50, 160}, _
{"glucose", 15, 60}, _
{"tin", 68, 45}, _
{"banana", 27, 60}, _
{"ChoiceBinle", 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}}
Dim s, xss As String, xwei, xval, nn As Integer
Private Sub KnapsackBin_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim i As Integer
xListView.View = View.Details
xListView.Columns.Add("item", 120, HorizontalAlignment.Left)
xListView.Columns.Add("weight", 50, HorizontalAlignment.Right)
xListView.Columns.Add("value", 50, HorizontalAlignment.Right)
For i = 0 To UBound(xList, 1)
xListView.Items.Add(New ListViewItem(New String() {xList(i, 0), _
xList(i, 1).ToString, xList(i, 2).ToString}))
Next i
End Sub 'KnapsackBin_Load
Private Sub cmdOK_Click(sender As Object, e As EventArgs) Handles cmdOK.Click
Dim i, j, nItems As Integer
For i = xListView.Items.Count - 1 To 0 Step -1
xListView.Items.RemoveAt(i)
Next i
Me.Refresh()
nItems = UBound(xList, 1) + 1
s = ""
For i = 1 To nItems
s = s & Chr(i - 1)
Next
nn = 0
Call ChoiceBin(1, "")
For i = 1 To Len(xss)
j = Asc(Mid(xss, i, 1))
xListView.Items.Add(New ListViewItem(New String() {xList(j, 0), _
xList(j, 1).ToString, xList(j, 2).ToString}))
Next i
xListView.Items.Add(New ListViewItem(New String() {"*Total*", xwei, xval}))
End Sub 'cmdOK_Click
Private Sub ChoiceBin(n As String, ss As String)
Dim r As String, i, j, iwei, ival As Integer
Dim ipct As Integer
If n = Len(s) + 1 Then
iwei = 0 : ival = 0
For i = 1 To Len(ss)
j = Asc(Mid(ss, i, 1))
iwei = iwei + xList(j, 1)
ival = ival + xList(j, 2)
Next
If iwei <= maxWeight And ival > xval Then
xss = ss : xwei = iwei : xval = ival
End If
Else
r = Mid(s, n, 1)
Call ChoiceBin(n + 1, ss & r)
Call ChoiceBin(n + 1, ss)
End If
End Sub 'ChoiceBin
End Class 'KnapsackBin

View file

@ -0,0 +1,68 @@
'Knapsack problem/0-1 - 12/02/2017
Option Explicit
Const maxWeight = 400
Dim DataList As Variant
Dim xList(64, 3) As Variant
Dim nItems As Integer
Dim s As String, xss As String
Dim xwei As Integer, xval As Integer, nn As Integer
Private Sub Form_Load()
Dim i As Integer, j As Integer
DataList = Array("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, "book", 30, 10, _
"waterproof trousers", 42, 70, "waterproof overclothes", 43, 75, _
"note-case", 22, 80, "sunglasses", 7, 20, "towel", 18, 12, "socks", 4, 50)
nItems = (UBound(DataList) + 1) / 3
j = 0
For i = 1 To nItems
xList(i, 1) = DataList(j)
xList(i, 2) = DataList(j + 1)
xList(i, 3) = DataList(j + 2)
j = j + 3
Next i
For i = 1 To nItems
xListBox.AddItem xList(i, 1)
Next i
End Sub
Private Sub cmdOK_Click()
Dim i As Integer, j As Integer
For i = 1 To xListBox.ListCount
xListBox.RemoveItem 0
Next i
s = ""
For i = 1 To nItems
s = s & Chr(i)
Next
nn = 0
Call ChoiceBin(1, "")
For i = 1 To Len(xss)
j = Asc(Mid(xss, i, 1))
xListBox.AddItem xList(j, 1)
Next i
xListBox.AddItem "*Total* " & xwei & " " & xval
End Sub
Private Sub ChoiceBin(n As String, ss As String)
Dim r As String
Dim i As Integer, j As Integer, iwei As Integer, ival As Integer
Dim ipct As Integer
If n = Len(s) + 1 Then
iwei = 0: ival = 0
For i = 1 To Len(ss)
j = Asc(Mid(ss, i, 1))
iwei = iwei + xList(j, 2)
ival = ival + xList(j, 3)
Next
If iwei <= maxWeight And ival > xval Then
xss = ss: xwei = iwei: xval = ival
End If
Else
r = Mid(s, n, 1)
Call ChoiceBin(n + 1, ss & r)
Call ChoiceBin(n + 1, ss)
End If
End Sub 'ChoiceBin

View file

@ -0,0 +1,6 @@
fcn addItem(pairs,it){ // pairs is list of (cost of:,names), it is (name,w,v)
w,left,right:=it[1],pairs[0,w],pairs[w,*];
left.extend(right.zipWith(
fcn([(t1,_)]a,[(t2,_)]b){ t1>t2 and a or b },
pairs.apply('wrap([(tot,names)]){ T(tot + it[2], names + it[0]) })))
}//--> new list of pairs

View file

@ -0,0 +1,13 @@
items:=T(T("apple", 39, 40),T("banana", 27,60), // item: (name,weight,value)
T("beer", 52, 10),T("book", 30,10),T("camera", 32, 30),
T("cheese", 23, 30),T("compass", 13,35),T("glucose", 15, 60),
T("map", 9,150),T("note-case",22,80),T("sandwich", 50,160),
T("socks", 4, 50),T("sunglasses",7,20),T("suntan cream",11, 70),
T("t-shirt", 24, 15),T("tin", 68,45),T("towel", 18, 12),
T("trousers", 48, 10),T("umbrella", 73,40),T("water", 153,200),
T("overclothes",43, 75),T("waterproof trousers",42,70) );
const MAX_WEIGHT=400;
knapsack:=items.reduce(addItem,
(MAX_WEIGHT).pump(List,T(0,T).copy))[-1]; // nearest to max weight
weight:=items.apply('wrap(it){ knapsack[1].holds(it[0]) and it[1] }).sum(0);
knapsack.println(weight);