Data update

This commit is contained in:
Ingy döt Net 2026-04-30 12:34:36 -04:00
parent 4bb20c9b71
commit cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions

View file

@ -0,0 +1,125 @@
BEGIN # Knapsack problem: 0-1 #
PR read "bits.incl.a68" PR # include bit manipulation utilities #
# returns the next highest integer with the same number of set bits #
PROC gospers hack = ( INT x )INT: # using Gosper's Hack #
BEGIN
INT c = x AND - x;
INT r = x + c;
ENTIER ( ENTIER ( ( r XOR x ) / 4 ) / c ) OR r
END # gospers hack # ;
# knapsack items #
MODE ITEM = STRUCT( STRING name, INT weight, value );
[]ITEM possible 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 )
);
[ 1 : UPB possible items ]ITEM sack items := possible items;
PRIO SWAP = 1;
OP SWAP = ( REF ITEM a, b )VOID: BEGIN ITEM t = a; a := b; b := t END;
# sort the items into descending value order #
FOR p TO UPB sack items - 1 DO
FOR q FROM p + 1 TO UPB sack items DO
IF value OF sack items[ q ] > value OF sack items[ p ] THEN sack items[ p ] SWAP sack items[ q ] FI
OD
OD;
# calculate the maximum value of each number of items, #
# if they could all be carried #
[ 1 : UPB possible items ]INT possible value;
INT curr value := 0;
FOR p TO UPB sack items - 1 DO
curr value +:= value OF sack items[ p ];
possible value[ p ] := curr value
OD;
# sort the items into descending weight order #
FOR p TO UPB sack items - 1 DO
FOR q FROM p + 1 TO UPB sack items DO
IF weight OF sack items[ q ] > weight OF sack items[ p ] THEN sack items[ p ] SWAP sack items[ q ] FI
OD
OD;
# find the minimum and maximum number of items we can carry #
# NB - assumes that each item weighs less than the maximum that can #
# be carried #
INT max weight = 400;
INT min carry := 0;
INT curr weight := weight OF sack items[ 1 ];
FOR s pos FROM 2 TO UPB sack items WHILE curr weight <= max weight DO
min carry +:= 1;
curr weight +:= weight OF sack items[ s pos ]
OD;
INT max carry := 0;
curr weight := weight OF sack items[ UPB sack items ];
FOR s pos FROM UPB sack items - 1 BY -1 TO 1 WHILE curr weight <= max weight DO
max carry +:= 1;
curr weight +:= weight OF sack items[ s pos ]
OD;
INT best items := 0;
INT best value := 0;
INT best weight := 0;
# for each possible number of items, find the best value for weight #
# with that many items #
# we use a bit mask to select the permutations, the maximum #
# permutation is 2^length - 1 #
INT max perm = 2 ^ UPB sack items - 1;
FOR item count FROM max carry BY -1 TO min carry WHILE best value < possible value[ item count ] DO
# the lowest permutation is 2^number of items - 1 #
INT perm := 2 ^ item count - 1;
WHILE perm <= max perm DO
INT v := perm;
INT weight := 0;
INT value := 0;
INT used := 0;
FOR sack pos TO UPB sack items WHILE v > 0 AND weight <= max weight DO
IF ODD v THEN
weight +:= weight OF sack items[ sack pos ];
value +:= value OF sack items[ sack pos ];
used +:= 1
FI;
v OVERAB 2
OD;
IF weight <= max weight AND used = item count THEN
IF value > best value THEN
best items := perm;
best value := value;
best weight := weight
FI
FI;
perm := gospers hack( perm )
OD
OD;
print( ( "At least ", whole( min carry, 0 ), " and at most ", whole( max carry, 0 ) ) );
print( ( " items could be carried", newline ) );
print( ( "Bast value: ", whole( best value, 0 ), " with weight: ", whole( best weight, 0 ), " is:", newline ) );
INT items := best items;
INT count := 0;
FOR sack pos TO UPB sack items WHILE items > 0 DO
IF ODD items THEN
count +:= 1;
print( ( " ", name OF sack items[ sack pos ], newline ) )
FI;
items OVERAB 2
OD;
print( ( "total: ", whole( count, 0 ), " items.", newline ) )
END

View file

@ -0,0 +1,109 @@
with Ada.Text_IO;
with Ada.Strings.Unbounded;
procedure Knapsack_01 is
package US renames Ada.Strings.Unbounded;
type Item is record
Name : US.Unbounded_String;
Weight : Positive;
Value : Positive;
Taken : Boolean;
end record;
type Item_Array is array (Positive range <>) of Item;
function Total_Weight (Items : Item_Array; Untaken : Boolean := False) return Natural is
Sum : Natural := 0;
begin
for I in Items'Range loop
if Untaken or else Items (I).Taken then
Sum := Sum + Items (I).Weight;
end if;
end loop;
return Sum;
end Total_Weight;
function Total_Value (Items : Item_Array; Untaken : Boolean := False) return Natural is
Sum : Natural := 0;
begin
for I in Items'Range loop
if Untaken or else Items (I).Taken then
Sum := Sum + Items (I).Value;
end if;
end loop;
return Sum;
end Total_Value;
function Max (Left, Right : Natural) return Natural is
begin
if Right > Left then
return Right;
else
return Left;
end if;
end Max;
procedure Solve_Knapsack_01 (Items : in out Item_Array;
Weight_Limit : Positive := 400) is
type W_Array is array (0..Items'Length, 0..Weight_Limit) of Natural;
W : W_Array := (others => (others => 0));
begin
-- fill W
for I in Items'Range loop
for J in 1 .. Weight_Limit loop
if Items (I).Weight > J then
W (I, J) := W (I - 1, J);
else
W (I, J) := Max (W (I - 1, J),
W (I - 1, J - Items (I).Weight) + Items (I).Value);
end if;
end loop;
end loop;
declare
Rest : Natural := Weight_Limit;
begin
for I in reverse Items'Range loop
if W (I, Rest) /= W (I - 1, Rest) then
Items (I).Taken := True;
Rest := Rest - Items (I).Weight;
end if;
end loop;
end;
end Solve_Knapsack_01;
All_Items : Item_Array :=
( (US.To_Unbounded_String ("map"), 9, 150, False),
(US.To_Unbounded_String ("compass"), 13, 35, False),
(US.To_Unbounded_String ("water"), 153, 200, False),
(US.To_Unbounded_String ("sandwich"), 50, 160, False),
(US.To_Unbounded_String ("glucose"), 15, 60, False),
(US.To_Unbounded_String ("tin"), 68, 45, False),
(US.To_Unbounded_String ("banana"), 27, 60, False),
(US.To_Unbounded_String ("apple"), 39, 40, False),
(US.To_Unbounded_String ("cheese"), 23, 30, False),
(US.To_Unbounded_String ("beer"), 52, 10, False),
(US.To_Unbounded_String ("suntan cream"), 11, 70, False),
(US.To_Unbounded_String ("camera"), 32, 30, False),
(US.To_Unbounded_String ("t-shirt"), 24, 15, False),
(US.To_Unbounded_String ("trousers"), 48, 10, False),
(US.To_Unbounded_String ("umbrella"), 73, 40, False),
(US.To_Unbounded_String ("waterproof trousers"), 42, 70, False),
(US.To_Unbounded_String ("waterproof overclothes"), 43, 75, False),
(US.To_Unbounded_String ("note-case"), 22, 80, False),
(US.To_Unbounded_String ("sunglasses"), 7, 20, False),
(US.To_Unbounded_String ("towel"), 18, 12, False),
(US.To_Unbounded_String ("socks"), 4, 50, False),
(US.To_Unbounded_String ("book"), 30, 10, False) );
begin
Solve_Knapsack_01 (All_Items, 400);
Ada.Text_IO.Put_Line ("Total Weight: " & Natural'Image (Total_Weight (All_Items)));
Ada.Text_IO.Put_Line ("Total Value: " & Natural'Image (Total_Value (All_Items)));
Ada.Text_IO.Put_Line ("Items:");
for I in All_Items'Range loop
if All_Items (I).Taken then
Ada.Text_IO.Put_Line (" " & US.To_String (All_Items (I).Name));
end if;
end loop;
end Knapsack_01;

View file

@ -41,7 +41,7 @@ int main( ) {
int totalweight = 0 ;
std::cout << "The following items should be packed in the knapsack:\n" ;
for ( std::set<int>::const_iterator si = bestItems.begin( ) ;
si != bestItems.end( ) ; si++ ) {
si != bestItems.end( ) ; si++ ) {
std::cout << (items.begin( ) + *si)->get<0>( ) << "\n" ;
totalweight += (items.begin( ) + *si)->get<1>( ) ;
}
@ -61,35 +61,35 @@ int findBestPack( const std::vector<boost::tuple<std::string , int , int> > & it
std::set<int> emptyset ;
for ( int i = 0 ; i < n ; i++ ) {
for ( int j = 0 ; j < weightlimit ; j++ ) {
bestValues[ i ][ j ] = 0 ;
solutionSets[ i ][ j ] = emptyset ;
bestValues[ i ][ j ] = 0 ;
solutionSets[ i ][ j ] = emptyset ;
}
}
for ( int i = 0 ; i < n ; i++ ) {
for ( int weight = 0 ; weight < weightlimit ; weight++ ) {
if ( i == 0 )
bestValues[ i ][ weight ] = 0 ;
else {
int itemweight = (items.begin( ) + i)->get<1>( ) ;
if ( weight < itemweight ) {
bestValues[ i ][ weight ] = bestValues[ i - 1 ][ weight ] ;
solutionSets[ i ][ weight ] = solutionSets[ i - 1 ][ weight ] ;
} else { // weight >= itemweight
if ( bestValues[ i - 1 ][ weight - itemweight ] +
(items.begin( ) + i)->get<2>( ) >
bestValues[ i - 1 ][ weight ] ) {
bestValues[ i ][ weight ] =
bestValues[ i - 1 ][ weight - itemweight ] +
(items.begin( ) + i)->get<2>( ) ;
solutionSets[ i ][ weight ] =
solutionSets[ i - 1 ][ weight - itemweight ] ;
solutionSets[ i ][ weight ].insert( i ) ;
}
else {
bestValues[ i ][ weight ] = bestValues[ i - 1 ][ weight ] ;
solutionSets[ i ][ weight ] = solutionSets[ i - 1 ][ weight ] ;
}
}
if ( i == 0 )
bestValues[ i ][ weight ] = 0 ;
else {
int itemweight = (items.begin( ) + i)->get<1>( ) ;
if ( weight < itemweight ) {
bestValues[ i ][ weight ] = bestValues[ i - 1 ][ weight ] ;
solutionSets[ i ][ weight ] = solutionSets[ i - 1 ][ weight ] ;
} else { // weight >= itemweight
if ( bestValues[ i - 1 ][ weight - itemweight ] +
(items.begin( ) + i)->get<2>( ) >
bestValues[ i - 1 ][ weight ] ) {
bestValues[ i ][ weight ] =
bestValues[ i - 1 ][ weight - itemweight ] +
(items.begin( ) + i)->get<2>( ) ;
solutionSets[ i ][ weight ] =
solutionSets[ i - 1 ][ weight - itemweight ] ;
solutionSets[ i ][ weight ].insert( i ) ;
}
else {
bestValues[ i ][ weight ] = bestValues[ i - 1 ][ weight ] ;
solutionSets[ i ][ weight ] = solutionSets[ i - 1 ][ weight ] ;
}
}
}
}
}

View file

@ -3,28 +3,28 @@
(defun knapsack (max-weight items)
(let ((cache (make-array (list (1+ max-weight) (1+ (length items)))
:initial-element nil)))
:initial-element nil)))
(labels ((knapsack1 (spc items)
(if (not items) (return-from knapsack1 (list 0 0 '())))
(mm-set (aref cache spc (length items))
(let* ((i (first items))
(w (second i))
(v (third i))
(x (knapsack1 spc (cdr items))))
(if (> w spc) x
(let* ((y (knapsack1 (- spc w) (cdr items)))
(v (+ v (first y))))
(if (< v (first x)) x
(list v (+ w (second y)) (cons i (third y))))))))))
(if (not items) (return-from knapsack1 (list 0 0 '())))
(mm-set (aref cache spc (length items))
(let* ((i (first items))
(w (second i))
(v (third i))
(x (knapsack1 spc (cdr items))))
(if (> w spc) x
(let* ((y (knapsack1 (- spc w) (cdr items)))
(v (+ v (first y))))
(if (< v (first x)) x
(list v (+ w (second y)) (cons i (third y))))))))))
(knapsack1 max-weight items))))
(print
(knapsack 400
'((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) (cream 11 70) (camera 32 30)
(T-shirt 24 15) (trousers 48 10) (umbrella 73 40)
(trousers 42 70) (overclothes 43 75) (notecase 22 80)
(glasses 7 20) (towel 18 12) (socks 4 50) (book 30 10))))
'((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) (cream 11 70) (camera 32 30)
(T-shirt 24 15) (trousers 48 10) (umbrella 73 40)
(trousers 42 70) (overclothes 43 75) (notecase 22 80)
(glasses 7 20) (towel 18 12) (socks 4 50) (book 30 10))))

View file

@ -55,13 +55,13 @@ function TBitIterator.Next(var Index: integer): boolean;
begin
Result:=False;
while FNumber>0 do
begin
Result:=(FNumber and 1)=1;
if Result then Index:=FIndex;
FNumber:=FNumber shr 1;
Inc(FIndex);
if Result then break;
end;
begin
Result:=(FNumber and 1)=1;
if Result then Index:=FIndex;
FNumber:=FNumber shr 1;
Inc(FIndex);
if Result then break;
end;
end;
{=============================================================================}
@ -78,10 +78,10 @@ try
BI.Start(N);
Weight:=0; Value:=0;
while BI.Next(Inx) do
begin
Weight:=Weight+ItemsList[Inx].Weight;
Value:=Value+ItemsList[Inx].Value;
end;
begin
Weight:=Weight+ItemsList[Inx].Weight;
Value:=Value+ItemsList[Inx].Value;
end;
finally BI.Free; end;
end;
@ -104,30 +104,30 @@ Max:=1 shl Length(ItemsList)-1;
BestValue:=0;
{Iterate through all combinations of bits}
for I:=1 to Max do
begin
{Get the sum of the weights and values}
GetSums(I,WeightSum,ValueSum);
{Ignore any weight greater than 400}
if WeightSum>400 then continue;
{Test if this is the best value so far}
if ValueSum>BestValue then
begin
BestValue:=ValueSum;
BestWeight:=WeightSum;
BestIndex:=I;
end;
end;
begin
{Get the sum of the weights and values}
GetSums(I,WeightSum,ValueSum);
{Ignore any weight greater than 400}
if WeightSum>400 then continue;
{Test if this is the best value so far}
if ValueSum>BestValue then
begin
BestValue:=ValueSum;
BestWeight:=WeightSum;
BestIndex:=I;
end;
end;
{Display the best result}
Memo.Lines.Add(' Item Weight Value');
Memo.Lines.Add('---------------------------------------');
BI.Start(BestIndex);
while BI.Next(Inx) do
begin
S:=' '+Format('%-25s',[ItemsList[Inx].Name]);
S:=S+Format('%5d',[ItemsList[Inx].Weight]);
S:=S+Format('%7d',[ItemsList[Inx].Value]);
Memo.Lines.Add(S);
end;
begin
S:=' '+Format('%-25s',[ItemsList[Inx].Name]);
S:=S+Format('%5d',[ItemsList[Inx].Weight]);
S:=S+Format('%7d',[ItemsList[Inx].Value]);
Memo.Lines.Add(S);
end;
Memo.Lines.Add('---------------------------------------');
Memo.Lines.Add(Format('Total %6d %6d',[BestWeight,BestValue]));
Memo.Lines.Add('Best Inx: '+IntToStr(BestIndex));

View file

@ -15,20 +15,20 @@
;; compute best score (i), assuming best (i-1 rest) is known
(define (score i restant)
(if (< i 0) 0
(hash-ref! H (t-idx i restant)
(if ( >= restant (poids i))
(max
(score (1- i) restant)
(+ (score (1- i) (- restant (poids i))) (valeur i)))
(score (1- i) restant)))))
(if (< i 0) 0
(hash-ref! H (t-idx i restant)
(if ( >= restant (poids i))
(max
(score (1- i) restant)
(+ (score (1- i) (- restant (poids i))) (valeur i)))
(score (1- i) restant)))))
;; compute best scores, starting from last item
(define (task W)
(define restant W)
(define N (1- (table-count T)))
(writeln 'total-value (score N W))
(for/list ((i (in-range N -1 -1)))
#:continue (= (t-get i restant) (t-get (1- i) restant))
(set! restant (- restant (poids i)))
(name i)))
(writeln 'total-value (score N W))
(for/list ((i (in-range N -1 -1)))
#:continue (= (t-get i restant) (t-get (1- i) restant))
(set! restant (- restant (poids i)))
(name i)))

View file

@ -1,40 +1,40 @@
class
APPLICATION
APPLICATION
create
make
make
feature {NONE} -- Initialization
make
local
knapsack: KNAPSACKZEROONE
do
create knapsack.make (400)
knapsack.add_item (create {ITEM}.make ("", 0, 0))
knapsack.add_item (create {ITEM}.make ("map", 9, 150))
knapsack.add_item (create {ITEM}.make ("compass", 13, 35))
knapsack.add_item (create {ITEM}.make ("water", 153, 200))
knapsack.add_item (create {ITEM}.make ("sandwich", 50, 160))
knapsack.add_item (create {ITEM}.make ("glucose", 15, 60))
knapsack.add_item (create {ITEM}.make ("tin", 68, 45))
knapsack.add_item (create {ITEM}.make ("banana", 27, 60))
knapsack.add_item (create {ITEM}.make ("apple", 39, 40))
knapsack.add_item (create {ITEM}.make ("cheese", 23, 30))
knapsack.add_item (create {ITEM}.make ("beer", 52, 10))
knapsack.add_item (create {ITEM}.make ("suntan cream", 11, 70))
knapsack.add_item (create {ITEM}.make ("camera", 32, 30))
knapsack.add_item (create {ITEM}.make ("T-shirt", 24, 15))
knapsack.add_item (create {ITEM}.make ("trousers", 48, 10))
knapsack.add_item (create {ITEM}.make ("umbrella, ella ella", 73, 40))
knapsack.add_item (create {ITEM}.make ("waterproof trousers", 42, 70))
knapsack.add_item (create {ITEM}.make ("waterproof overclothes", 43, 75))
knapsack.add_item (create {ITEM}.make ("note-case", 22, 80))
knapsack.add_item (create {ITEM}.make ("sunglasses", 7, 20))
knapsack.add_item (create {ITEM}.make ("towel", 18, 12))
knapsack.add_item (create {ITEM}.make ("socks", 4, 50))
knapsack.add_item (create {ITEM}.make ("book", 30, 10))
knapsack.compute_solution
end
make
local
knapsack: KNAPSACKZEROONE
do
create knapsack.make (400)
knapsack.add_item (create {ITEM}.make ("", 0, 0))
knapsack.add_item (create {ITEM}.make ("map", 9, 150))
knapsack.add_item (create {ITEM}.make ("compass", 13, 35))
knapsack.add_item (create {ITEM}.make ("water", 153, 200))
knapsack.add_item (create {ITEM}.make ("sandwich", 50, 160))
knapsack.add_item (create {ITEM}.make ("glucose", 15, 60))
knapsack.add_item (create {ITEM}.make ("tin", 68, 45))
knapsack.add_item (create {ITEM}.make ("banana", 27, 60))
knapsack.add_item (create {ITEM}.make ("apple", 39, 40))
knapsack.add_item (create {ITEM}.make ("cheese", 23, 30))
knapsack.add_item (create {ITEM}.make ("beer", 52, 10))
knapsack.add_item (create {ITEM}.make ("suntan cream", 11, 70))
knapsack.add_item (create {ITEM}.make ("camera", 32, 30))
knapsack.add_item (create {ITEM}.make ("T-shirt", 24, 15))
knapsack.add_item (create {ITEM}.make ("trousers", 48, 10))
knapsack.add_item (create {ITEM}.make ("umbrella, ella ella", 73, 40))
knapsack.add_item (create {ITEM}.make ("waterproof trousers", 42, 70))
knapsack.add_item (create {ITEM}.make ("waterproof overclothes", 43, 75))
knapsack.add_item (create {ITEM}.make ("note-case", 22, 80))
knapsack.add_item (create {ITEM}.make ("sunglasses", 7, 20))
knapsack.add_item (create {ITEM}.make ("towel", 18, 12))
knapsack.add_item (create {ITEM}.make ("socks", 4, 50))
knapsack.add_item (create {ITEM}.make ("book", 30, 10))
knapsack.compute_solution
end
end

View file

@ -1,35 +1,35 @@
class
ITEM
ITEM
create
make, make_from_other
make, make_from_other
feature
name: STRING
name: STRING
weight: INTEGER
weight: INTEGER
value: INTEGER
value: INTEGER
make_from_other (other: ITEM)
-- Item with name, weight and value set to 'other's name, weight and value.
do
name := other.name
weight := other.weight
value := other.value
end
make_from_other (other: ITEM)
-- Item with name, weight and value set to 'other's name, weight and value.
do
name := other.name
weight := other.weight
value := other.value
end
make (a_name: String; a_weight, a_value: INTEGER)
-- Item with name, weight and value set to 'a_name', 'a_weight' and 'a_value'.
require
a_name /= Void
a_weight >= 0
a_value >= 0
do
name := a_name
weight := a_weight
value := a_value
end
make (a_name: String; a_weight, a_value: INTEGER)
-- Item with name, weight and value set to 'a_name', 'a_weight' and 'a_value'.
require
a_name /= Void
a_weight >= 0
a_value >= 0
do
name := a_name
weight := a_weight
value := a_value
end
end

View file

@ -1,106 +1,106 @@
class
KNAPSACKZEROONE
KNAPSACKZEROONE
create
make
make
feature
items: ARRAY [ITEM]
items: ARRAY [ITEM]
max_weight: INTEGER
max_weight: INTEGER
feature
make (a_max_weight: INTEGER)
-- Make an empty knapsack.
require
a_max_weight >= 0
do
create items.make_empty
max_weight := a_max_weight
end
make (a_max_weight: INTEGER)
-- Make an empty knapsack.
require
a_max_weight >= 0
do
create items.make_empty
max_weight := a_max_weight
end
add_item (item: ITEM)
-- Add 'item' to knapsack.
local
temp: ITEM
do
create temp.make_from_other (item)
items.force (item, items.count + 1)
end
add_item (item: ITEM)
-- Add 'item' to knapsack.
local
temp: ITEM
do
create temp.make_from_other (item)
items.force (item, items.count + 1)
end
compute_solution
local
M: ARRAY [INTEGER]
n: INTEGER
i, j: INTEGER
w_i, v_i: INTEGER
item_i: ITEM
final_items: LINKED_LIST [ITEM]
do
n := items.count
create M.make_filled (0, 1, n * max_weight)
from
i := 2
until
(i > n)
loop
from
j := 1
until
j > max_weight
loop
item_i := items [i]
w_i := item_i.weight
if w_i <= j then
v_i := item_i.value
M [(i - 1) * max_weight + j] := max (M [(i - 2) * max_weight + j], M [(i - 2) * max_weight + j - w_i + 1] + v_i)
else
M [(i - 1) * max_weight + j] := M [(i - 2) * max_weight + j]
end
j := j + 1
end
i := i + 1
end
io.put_string ("The final value of the knapsack will be: ")
io.put_integer (M [(n - 1) * max_weight + max_weight]);
io.new_line
--compute the items that fit into the knapsack
create final_items.make
io.put_string ("We'll take the following items: %N");
from
i := n
j := max_weight
until
i <= 1 or j <= 1
loop
item_i := items [i]
w_i := item_i.weight
if w_i <= j then
v_i := item_i.value
if M [(i - 1) * max_weight + j] = M [(i - 2) * max_weight + j] then
else
final_items.extend (item_i)
io.put_string (item_i.name)
io.new_line
j := j - w_i
end
else
end
i := i - 1
end
end
compute_solution
local
M: ARRAY [INTEGER]
n: INTEGER
i, j: INTEGER
w_i, v_i: INTEGER
item_i: ITEM
final_items: LINKED_LIST [ITEM]
do
n := items.count
create M.make_filled (0, 1, n * max_weight)
from
i := 2
until
(i > n)
loop
from
j := 1
until
j > max_weight
loop
item_i := items [i]
w_i := item_i.weight
if w_i <= j then
v_i := item_i.value
M [(i - 1) * max_weight + j] := max (M [(i - 2) * max_weight + j], M [(i - 2) * max_weight + j - w_i + 1] + v_i)
else
M [(i - 1) * max_weight + j] := M [(i - 2) * max_weight + j]
end
j := j + 1
end
i := i + 1
end
io.put_string ("The final value of the knapsack will be: ")
io.put_integer (M [(n - 1) * max_weight + max_weight]);
io.new_line
--compute the items that fit into the knapsack
create final_items.make
io.put_string ("We'll take the following items: %N");
from
i := n
j := max_weight
until
i <= 1 or j <= 1
loop
item_i := items [i]
w_i := item_i.weight
if w_i <= j then
v_i := item_i.value
if M [(i - 1) * max_weight + j] = M [(i - 2) * max_weight + j] then
else
final_items.extend (item_i)
io.put_string (item_i.name)
io.new_line
j := j - w_i
end
else
end
i := i - 1
end
end
feature {NONE}
max (a, b: INTEGER): INTEGER
-- Max of 'a' and 'b'.
do
Result := a
if a < b then
Result := b
end
end
max (a, b: INTEGER): INTEGER
-- Max of 'a' and 'b'.
do
Result := a
if a < b then
Result := b
end
end
end

View file

@ -0,0 +1,34 @@
(defun ks (max-w items)
(let ((cache (make-vector (1+ (length items)) nil)))
(dotimes (n (1+ (length items)))
(setf (aref cache n) (make-hash-table :test 'eql)))
(defun ks-emb (spc items)
(let ((slot (gethash spc (aref cache (length items)))))
(cond
((null items) (list 0 0 '()))
(slot slot)
(t (puthash spc
(let*
((i (car items))
(w (nth 1 i))
(v (nth 2 i))
(x (ks-emb spc (cdr items))))
(cond
((> w spc) x)
(t
(let* ((y (ks-emb (- spc w) (cdr items)))
(v (+ v (car y))))
(cond
((< v (car x)) x)
(t
(list v (+ w (nth 1 y)) (cons i (nth 2 y)))))))))
(aref cache (length items)))))))
(ks-emb max-w items)))
(ks 400
'((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) (cream 11 70) (camera 32 30)
(T-shirt 24 15) (trousers 48 10) (umbrella 73 40)
(waterproof-trousers 42 70) (overclothes 43 75) (notecase 22 80)
(glasses 7 20) (towel 18 12) (socks 4 50) (book 30 10)))

View file

@ -0,0 +1,47 @@
(defun best-rate (l1 l2)
"predicate for sorting a list of elements regarding the value/weight rate"
(let*
((r1 (/ (* 1.0 (nth 2 l1)) (nth 1 l1)))
(r2 (/ (* 1.0 (nth 2 l2)) (nth 1 l2))))
(cond
((> r1 r2) t)
(t nil))))
(defun ks1 (l max)
"return a complete list - complete means 'less than max-weight
but add the next element is impossible'"
(let ((l (sort l 'best-rate)))
(cond
((null l) l)
((<= (nth 1 (car l)) max)
(cons (car l) (ks1 (cdr l) (- max (nth 1 (car l))))))
(t (ks1 (cdr l) max)))))
(defun totval (lol)
"totalize values of a list - lol is not for laughing
but for list of list"
(cond
((null lol) 0)
(t
(+
(nth 2 (car lol))
(totval (cdr lol))))))
(defun ks (l max)
"browse the list to find the best subset to put in the f***ing knapsack"
(cond
((null (cdr l)) (list (car l)))
(t
(let*
((x (ks1 l max))
(y (ks (cdr l) max)))
(cond
((> (totval x) (totval y)) x)
(t y))))))
(ks '((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) (cream 11 70) (camera 32 30)
(T-shirt 24 15) (trousers 48 10) (umbrella 73 40)
(waterproof-trousers 42 70) (overclothes 43 75) (notecase 22 80)
(glasses 7 20) (towel 18 12) (socks 4 50) (book 30 10)) 400)

View file

@ -0,0 +1,73 @@
knapsack[values, weights, capacity] :=
{
n = length[values]
if length[weights] != n
{
println["knapsack: length of values does not equal length of weights."]
return undef
}
V = new array[[n+1, capacity+1], 0]
keep = new array[[n+1, capacity+1], false]
for i = 1 to n
{
for w = 0 to capacity
{
if weights@(i-1) <= w and (values@(i-1) + V@(i-1)@(w - weights@(i-1)) > V@(i-1)@w)
{
V@i@w = values@(i-1) + V@(i-1)@(w-weights@(i-1))
keep@i@w = true
} else
{
V@i@w = V@(i-1)@w
keep@i@w = false
}
}
}
included = new array
K = capacity
for i = n to 1 step -1
if keep@i@K == true
{
included.push[ [i-1, values@(i-1), weights@(i-1)] ]
K = K - weights@(i-1)
}
return concat[V@n@capacity, included.transpose[]]
}
i= [["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]]
[maxval, indices, values, weights] = knapsack[i.getColumn[2], i.getColumn[1], 400]
println["Items:"]
for ind = sort[indices]
println[" " +i@ind@0]
println[]
println["Total weight: " + sum[weights]]
println["Total value: $maxval"]

View file

@ -1,17 +1,17 @@
inv = [("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), ("cream",11,70), ("camera",32,30),
("tshirt",24,15), ("trousers",48,10), ("umbrella",73,40), ("trousers",42,70),
("overclothes",43,75), ("notecase",22,80), ("sunglasses",7,20), ("towel",18,12),
("socks",4,50), ("book",30,10)]
("glucose",15,60), ("tin",68,45), ("banana",27,60), ("apple",39,40),
("cheese",23,30), ("beer",52,10), ("cream",11,70), ("camera",32,30),
("tshirt",24,15), ("trousers",48,10), ("umbrella",73,40), ("trousers",42,70),
("overclothes",43,75), ("notecase",22,80), ("sunglasses",7,20), ("towel",18,12),
("socks",4,50), ("book",30,10)]
-- get all combos of items under total weight sum; returns value sum and list
combs [] _ = [ (0, []) ]
combs ((name,w,v):rest) cap = combs rest cap ++
if w > cap then [] else map (prepend (name,w,v)) (combs rest (cap - w))
where prepend (name,w,v) (v2, lst) = (v2 + v, (name,w,v):lst)
if w > cap then [] else map (prepend (name,w,v)) (combs rest (cap - w))
where prepend (name,w,v) (v2, lst) = (v2 + v, (name,w,v):lst)
main = do
putStr "Total value: "; print value
mapM_ print items
where (value, items) = maximum $ combs inv 400
putStr "Total value: "; print value
mapM_ print items
where (value, items) = maximum $ combs inv 400

View file

@ -1,15 +1,15 @@
inv = [("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), ("cream",11,70), ("camera",32,30),
("tshirt",24,15), ("trousers",48,10), ("umbrella",73,40), ("trousers",42,70),
("overclothes",43,75), ("notecase",22,80), ("sunglasses",7,20), ("towel",18,12),
("socks",4,50), ("book",30,10)]
("glucose",15,60), ("tin",68,45), ("banana",27,60), ("apple",39,40),
("cheese",23,30), ("beer",52,10), ("cream",11,70), ("camera",32,30),
("tshirt",24,15), ("trousers",48,10), ("umbrella",73,40), ("trousers",42,70),
("overclothes",43,75), ("notecase",22,80), ("sunglasses",7,20), ("towel",18,12),
("socks",4,50), ("book",30,10)]
combs [] _ = (0, [])
combs ((name,w,v):rest) cap
| w <= cap = max skipthis $ prepend (name,w,v) (combs rest (cap - w))
| otherwise = skipthis
where prepend (name,w,v) (v2, lst) = (v2 + v, (name,w,v):lst)
skipthis = combs rest cap
| w <= cap = max skipthis $ prepend (name,w,v) (combs rest (cap - w))
| otherwise = skipthis
where prepend (name,w,v) (v2, lst) = (v2 + v, (name,w,v):lst)
skipthis = combs rest cap
main = do print $ combs inv 400

View file

@ -6,8 +6,8 @@ inv = [("map",9,150), ("compass",13,35), ("water",153,200), ("sandwich",50,160),
("sunglasses",7,20), ("towel",18,12), ("socks",4,50), ("book",30,10)]
knapsack = foldr addItem (repeat (0,[])) where
addItem (name,w,v) list = left ++ zipWith max right newlist where
newlist = map (\(val, names)->(val + v, name:names)) list
(left,right) = splitAt w list
addItem (name,w,v) list = left ++ zipWith max right newlist where
newlist = map (\(val, names)->(val + v, name:names)) list
(left,right) = splitAt w list
main = print $ (knapsack inv) !! 400

View file

@ -0,0 +1,202 @@
/*global portviz:false, _:false */
/*
* 0-1 knapsack solution, recursive, memoized, approximate.
*
* credits:
*
* the Go implementation here:
* http://rosettacode.org/mw/index.php?title=Knapsack_problem/0-1
*
* approximation details here:
* http://math.mit.edu/~goemans/18434S06/knapsack-katherine.pdf
*/
portviz.knapsack = {};
(function() {
this.combiner = function(items, weightfn, valuefn) {
// approximation guarantees result >= (1-e) * optimal
var _epsilon = 0.01;
var _p = _.max(_.map(items,valuefn));
var _k = _epsilon * _p / items.length;
var _memo = (function(){
var _mem = {};
var _key = function(i, w) {
return i + '::' + w;
};
return {
get: function(i, w) {
return _mem[_key(i,w)];
},
put: function(i, w, r) {
_mem[_key(i,w)]=r;
return r;
}
};
})();
var _m = function(i, w) {
i = Math.round(i);
w = Math.round(w);
if (i < 0 || w === 0) {
// empty base case
return {items: [], totalWeight: 0, totalValue: 0};
}
var mm = _memo.get(i,w);
if (!_.isUndefined(mm)) {
return mm;
}
var item = items[i];
if (weightfn(item) > w) {
//item does not fit, try the next item
return _memo.put(i, w, _m(i-1, w));
}
// this item could fit.
// are we better off excluding it?
var excluded = _m(i-1, w);
// or including it?
var included = _m(i-1, w - weightfn(item));
if (included.totalValue + Math.floor(valuefn(item)/_k) > excluded.totalValue) {
// better off including it
// make a copy of the list
var i1 = included.items.slice();
i1.push(item);
return _memo.put(i, w,
{items: i1,
totalWeight: included.totalWeight + weightfn(item),
totalValue: included.totalValue + Math.floor(valuefn(item)/_k)});
}
//better off excluding it
return _memo.put(i,w, excluded);
};
return {
/* one point */
one: function(maxweight) {
var scaled = _m(items.length - 1, maxweight);
return {
items: scaled.items,
totalWeight: scaled.totalWeight,
totalValue: scaled.totalValue * _k
};
},
/* the entire EF */
ef: function(maxweight, step) {
return _.map(_.range(0, maxweight+1, step), function(weight) {
var scaled = _m(items.length - 1, weight);
return {
items: scaled.items,
totalWeight: scaled.totalWeight,
totalValue: scaled.totalValue * _k
};
});
}
};
};
}).apply(portviz.knapsack);
/*global portviz:false, _:false */
/*
* after rosettacode.org/mw/index.php?title=Knapsack_problem/0-1
*/
var allwants = [
{name:"map", weight:9, value: 150},
{name:"compass", weight:13, value: 35},
{name:"water", weight:153, value: 200},
{name:"sandwich", weight: 50, value: 160},
{name:"glucose", weight:15, value: 60},
{name:"tin", weight:68, value: 45},
{name:"banana", weight:27, value: 60},
{name:"apple", weight:39, value: 40},
{name:"cheese", weight:23, value: 30},
{name:"beer", weight:52, value: 10},
{name:"suntan cream", weight:11, value: 70},
{name:"camera", weight:32, value: 30},
{name:"T-shirt", weight:24, value: 15},
{name:"trousers", weight:48, value: 10},
{name:"umbrella", weight:73, value: 40},
{name:"waterproof trousers", weight:42, value: 70},
{name:"waterproof overclothes", weight:43, value: 75},
{name:"note-case", weight:22, value: 80},
{name:"sunglasses", weight:7, value: 20},
{name:"towel", weight:18, value: 12},
{name:"socks", weight:4, value: 50},
{name:"book", weight:30, value: 10}
];
var near = function(actual, expected, tolerance) {
if (expected === 0 && actual === 0) return true;
if (expected === 0) {
return Math.abs(expected - actual) / actual < tolerance;
}
return Math.abs(expected - actual) / expected < tolerance;
};
test("one knapsack", function() {
var combiner =
portviz.knapsack.combiner(allwants,
function(x){return x.weight;},
function(x){return x.value;});
var oneport = combiner.one(400);
ok(near(oneport.totalValue, 1030, 0.01), "correct total value");
ok(near(oneport.totalValue, 1030, 0.01), "correct total value");
equal(oneport.totalWeight, 396, "correct total weight");
});
test("frontier", function() {
var combiner =
portviz.knapsack.combiner(allwants,
function(x){return x.weight;},
function(x){return x.value;});
var ef = combiner.ef(400, 1);
equal(ef.length, 401, "401 because it includes the endpoints");
ef = combiner.ef(400, 40);
equal(ef.length, 11, "11 because it includes the endpoints");
var expectedTotalValue = [
0,
330,
445,
590,
685,
755,
810,
860,
902,
960,
1030
] ;
_.each(ef, function(element, index) {
// 15% error! bleah!
ok(near(element.totalValue, expectedTotalValue[index], 0.15),
'actual ' + element.totalValue + ' expected ' + expectedTotalValue[index]);
});
deepEqual(_.pluck(ef, 'totalWeight'), [
0,
39,
74,
118,
158,
200,
236,
266,
316,
354,
396
]);
deepEqual(_.map(ef, function(x){return x.items.length;}), [
0,
4,
6,
7,
9,
10,
10,
12,
14,
11,
12
]);
});

View file

@ -0,0 +1,68 @@
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>KNAPSACK 22 JavaScript</title> </head> <body> <noscript>Vkluch JS</noscript>
https://jdoodle.com/h/2Ut
rextester.com/BQYV50962
<script>
var n=22; G=400; a = Math.pow(2,n+1); // KNAPSACKj.js
var dec, i, h, k, max, m, s;
var L=[n], C=[n], j=[n], q=[a], d=[a]; e=[a];
document.write("<br><br># Kol Cena<br>")
document.write("# Amo Price<br><br>")
L=[ 9,13,153,50,15,68,27,39,23,52,11,32,24,48,73,42,43,22,7,18,4,30 ]
C=[ 150,35,200,160,60,45,60,40,30,10,70,30,15,10,40,70,75,80,20,12,50,10 ]
for (i=0; i<n; i++)
{ // L[i]=1+Math.floor(Math.random()*3)
// C[i]=10+Math.floor(Math.random()*9);
j[i]=0;
document.write( (i+1) +" "+ L[i] +" "+ C[i] +"<br>")
}
for (i=0; i<a; i++) { q[i]=0; d[i]=0;}
document.write("<br>")
document.write("Mx Kol St-st Schifr<br>")
document.write("Mx Amo Price Cipher<br>")
for (h = a-1; h>(a-1)/2; h--)
{ dec=h; e[h]=""
while (dec > 0)
{ s = Math.floor(dec % 2);
e[h] = s + e[h]; dec = Math.floor(dec/2);
}
if (e[h] == "") {e[h] = "0";}
e[h]= e[h].substr(1, e[h].length-1);
for (k=0; k<n; k++)
{ j[k] = Number(e[h].substr(k,1));
q[h]=q[h]+j[k]*C[k];
d[h]=d[h]+L[k]*j[k];
}
// if (d[h] <= G)
// document.write("<br>"+ G +" "+ d[h] +" "+ q[h] +" "+ e[h])
} document.write("<br>")
max=0; m=1;
for (i=0; i<a; i++)
{ if (d[i]<=G && q[i]>max){ max=q[i]; m=i;}
}
document.write("<br>"+ d[m] +" "+ q[m] +" "+ e[m] +"<br><br>")
document.write("Mx St-st Schifr<br>")
document.write("Mx Price Cipher<br><br>")
</script>
</body> </html>

View file

@ -3,48 +3,48 @@ integer iMAX_WEIGHT = 400;
integer iSTRIDE = 4;
list lList = [];
default {
integer iNotecardLine = 0;
state_entry() {
llOwnerSay("Reading '"+sNOTECARD+"'");
llGetNotecardLine(sNOTECARD, iNotecardLine);
}
dataserver(key kRequestId, string sData) {
if(sData==EOF) {
//llOwnerSay("EOF");
lList = llListSort(lList, iSTRIDE, FALSE);
integer iTotalWeight = 0;
integer iTotalValue = 0;
list lKnapsack = [];
integer x = 0;
while(x*iSTRIDE<llGetListLength(lList)) {
float fValueWeight = (float)llList2String(lList, x*iSTRIDE);
string sItem = (string)llList2String(lList, x*iSTRIDE+1);
integer iWeight = (integer)llList2String(lList, x*iSTRIDE+2);
integer iValue = (integer)llList2String(lList, x*iSTRIDE+3);
if(iTotalWeight+iWeight<iMAX_WEIGHT) {
iTotalWeight += iWeight;
iTotalValue += iValue;
lKnapsack += [sItem, iWeight, iValue, fValueWeight];
}
x++;
}
for(x=0 ; x*iSTRIDE<llGetListLength(lKnapsack) ; x++) {
llOwnerSay((string)x+": "+llList2String(lList, x*iSTRIDE+1)+", "+llList2String(lList, x*iSTRIDE+2)+", "+llList2String(lList, x*iSTRIDE+3));
integer iNotecardLine = 0;
state_entry() {
llOwnerSay("Reading '"+sNOTECARD+"'");
llGetNotecardLine(sNOTECARD, iNotecardLine);
}
dataserver(key kRequestId, string sData) {
if(sData==EOF) {
//llOwnerSay("EOF");
lList = llListSort(lList, iSTRIDE, FALSE);
integer iTotalWeight = 0;
integer iTotalValue = 0;
list lKnapsack = [];
integer x = 0;
while(x*iSTRIDE<llGetListLength(lList)) {
float fValueWeight = (float)llList2String(lList, x*iSTRIDE);
string sItem = (string)llList2String(lList, x*iSTRIDE+1);
integer iWeight = (integer)llList2String(lList, x*iSTRIDE+2);
integer iValue = (integer)llList2String(lList, x*iSTRIDE+3);
if(iTotalWeight+iWeight<iMAX_WEIGHT) {
iTotalWeight += iWeight;
iTotalValue += iValue;
lKnapsack += [sItem, iWeight, iValue, fValueWeight];
}
x++;
}
for(x=0 ; x*iSTRIDE<llGetListLength(lKnapsack) ; x++) {
llOwnerSay((string)x+": "+llList2String(lList, x*iSTRIDE+1)+", "+llList2String(lList, x*iSTRIDE+2)+", "+llList2String(lList, x*iSTRIDE+3));
}
llOwnerSay("iTotalWeight="+(string)iTotalWeight);
llOwnerSay("iTotalValue="+(string)iTotalValue);
} else {
//llOwnerSay((string)iNotecardLine+": "+sData);
if(llStringTrim(sData, STRING_TRIM)!="") {
list lParsed = llParseString2List(sData, [","], []);
string sItem = llStringTrim(llList2String(lParsed, 0), STRING_TRIM);
integer iWeight = (integer)llStringTrim(llList2String(lParsed, 1), STRING_TRIM);
integer iValue = (integer)llStringTrim(llList2String(lParsed, 2), STRING_TRIM);
float fValueWeight = (1.0*iValue)/iWeight;
lList += [fValueWeight, sItem, iWeight, iValue];
}
llGetNotecardLine(sNOTECARD, ++iNotecardLine);
}
}
}
llOwnerSay("iTotalWeight="+(string)iTotalWeight);
llOwnerSay("iTotalValue="+(string)iTotalValue);
} else {
//llOwnerSay((string)iNotecardLine+": "+sData);
if(llStringTrim(sData, STRING_TRIM)!="") {
list lParsed = llParseString2List(sData, [","], []);
string sItem = llStringTrim(llList2String(lParsed, 0), STRING_TRIM);
integer iWeight = (integer)llStringTrim(llList2String(lParsed, 1), STRING_TRIM);
integer iValue = (integer)llStringTrim(llList2String(lParsed, 2), STRING_TRIM);
float fValueWeight = (1.0*iValue)/iWeight;
lList += [fValueWeight, sItem, iWeight, iValue];
}
llGetNotecardLine(sNOTECARD, ++iNotecardLine);
}
}
}

View file

@ -4,60 +4,60 @@ global neededItems = #()
global totalValue = 0
struct kn_item
(
item, weight, value
item, weight, value
)
itemStrings = #("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")
"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")
fn sortByValue a b =
(
if a[1].value > b[1].value then return -1
else
(
if a[1].value == b[1].value then return 0
else return 1
)
if a[1].value > b[1].value then return -1
else
(
if a[1].value == b[1].value then return 0
else return 1
)
)
fn chooseBestItem maximumWeight: items: =
(
local itemsCopy = deepcopy items
local possibleItems = #()
for i = 1 to itemsCopy.count do
(
if itemsCopy[i].weight <= maximumWeight do append possibleItems (#(itemsCopy[i],i))
)
qsort possibleItems sortByValue
if possibleItems.count > 0 then return possibleItems[1] else return 0
local itemsCopy = deepcopy items
local possibleItems = #()
for i = 1 to itemsCopy.count do
(
if itemsCopy[i].weight <= maximumWeight do append possibleItems (#(itemsCopy[i],i))
)
qsort possibleItems sortByValue
if possibleItems.count > 0 then return possibleItems[1] else return 0
)
for i = 1 to itemStrings.count do
(
local split = filterstring itemStrings[i] "#"
local itemStruct = kn_item item:split[1] weight:(split[2] as integer) \
value:(split[3] as integer)
appendifunique globalItems itemstruct
local split = filterstring itemStrings[i] "#"
local itemStruct = kn_item item:split[1] weight:(split[2] as integer) \
value:(split[3] as integer)
appendifunique globalItems itemstruct
)
while usedMass < 400 do
(
local item = chooseBestItem maximumweight:(400-usedMass) items:(globalItems)
if item != 0 then
(
deleteitem globalItems (item[2])
appendifunique neededItems item[1]
usedMass += item[1].weight
) else exit
local item = chooseBestItem maximumweight:(400-usedMass) items:(globalItems)
if item != 0 then
(
deleteitem globalItems (item[2])
appendifunique neededItems item[1]
usedMass += item[1].weight
) else exit
)
for i in neededitems do
(
format "Item name: %, weight: %, value:%\n" i.item i.weight i.value
totalValue += i.value
format "Item name: %, weight: %, value:%\n" i.item i.weight i.value
totalValue += i.value
)
format "Total mass: %, Total Value: %\n" usedMass totalValue

View file

@ -4,26 +4,26 @@ items := ["map","compass","water","sandwich","glucose","tin","banana","apple","c
acc := Array(1..numelems(vals)+1,1..400+1,1,fill=0):
len := numelems(weights):
for i from 2 to len+1 do #number of items picked + 1
for j from 2 to 401 do #weight capacity left + 1
if weights[i-1] > j-1 then
acc[i,j] := acc[i-1, j]:
else
acc[i,j] := max(acc[i-1,j], acc[i-1, j-weights[i-1]]+vals[i-1]):
end if:
end do:
for j from 2 to 401 do #weight capacity left + 1
if weights[i-1] > j-1 then
acc[i,j] := acc[i-1, j]:
else
acc[i,j] := max(acc[i-1,j], acc[i-1, j-weights[i-1]]+vals[i-1]):
end if:
end do:
end do:
printf("Total Value is %d\n", acc[len+1, 401]):
count := 0:
i := len+1:
j := 401:
while (i>1 and j>1) do
if acc[i,j] <> acc[i-1,j] then
printf("Item: %s\n", items[i-1]):
count := count+weights[i-1]:
j := j-weights[i-1]:
i := i-1:
else
i := i-1:
end if:
if acc[i,j] <> acc[i-1,j] then
printf("Item: %s\n", items[i-1]):
count := count+weights[i-1]:
j := j-weights[i-1]:
i := i-1:
else
i := i-1:
end if:
end do:
printf("Total Weight is %d\n", count):

View file

@ -19,28 +19,28 @@ maximize knap_value: sum{t in Items} take[t] * value[t];
data;
param : Items : 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
suntancream 11 70
camera 32 30
T-shirt 24 15
trousers 48 10
umbrella 73 40
w-trousers 42 70
w-overclothes 43 75
note-case 22 80
sunglasses 7 20
towel 18 12
socks 4 50
book 30 10
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
suntancream 11 70
camera 32 30
T-shirt 24 15
trousers 48 10
umbrella 73 40
w-trousers 42 70
w-overclothes 43 75
note-case 22 80
sunglasses 7 20
towel 18 12
socks 4 50
book 30 10
;
end;

View file

@ -12,61 +12,61 @@
function knapSolveFast2($w, $v, $i, $aW, &$m) {
global $numcalls;
$numcalls ++;
// echo "Called with i=$i, aW=$aW<br>";
global $numcalls;
$numcalls ++;
// echo "Called with i=$i, aW=$aW<br>";
// Return memo if we have one
if (isset($m[$i][$aW])) {
return array( $m[$i][$aW], $m['picked'][$i][$aW] );
} else {
// Return memo if we have one
if (isset($m[$i][$aW])) {
return array( $m[$i][$aW], $m['picked'][$i][$aW] );
} else {
// At end of decision branch
if ($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 item
return array($v[$i],array($i)); // Return the value of this item and add it to the picked list
// At end of decision branch
if ($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 item
return array($v[$i],array($i)); // Return the value of this item and add it to the picked list
} else {
// Won't fit
$m[$i][$aW] = 0; // Memo zero
$m['picked'][$i][$aW] = array(); // and a blank array entry...
return array(0,array()); // Return nothing
}
}
// 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);
} else {
// Won't fit
$m[$i][$aW] = 0; // Memo zero
$m['picked'][$i][$aW] = array(); // and a blank array entry...
return array(0,array()); // Return nothing
}
}
if ($w[$i] > $aW) { // Does it return too many?
$m[$i][$aW] = $without_i; // Memo without including this one
$m['picked'][$i][$aW] = $without_PI; // and a blank array entry...
return array($without_i, $without_PI); // and return it
// 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);
} 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);
$with_i += $v[$i]; // ..and add the value of this one..
// Get the greater of WITH or WITHOUT
if ($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 item
return array ($res,$picked); // and then return it
}
}
if ($w[$i] > $aW) { // Does it return too many?
$m[$i][$aW] = $without_i; // Memo without including this one
$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);
$with_i += $v[$i]; // ..and add the value of this one..
// Get the greater of WITH or WITHOUT
if ($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 item
return array ($res,$picked); // and then return it
}
}
}
@ -92,9 +92,9 @@ echo "<table border cellspacing=0>";
echo "<tr><td>Item</td><td>Value</td><td>Weight</td></tr>";
$totalVal = $totalWt = 0;
foreach($pickedItems as $key) {
$totalVal += $v4[$key];
$totalWt += $w4[$key];
echo "<tr><td>".$items4[$key]."</td><td>".$v4[$key]."</td><td>".$w4[$key]."</td></tr>";
$totalVal += $v4[$key];
$totalWt += $w4[$key];
echo "<tr><td>".$items4[$key]."</td><td>".$v4[$key]."</td><td>".$w4[$key]."</td></tr>";
}
echo "<tr><td align=right><b>Totals</b></td><td>$totalVal</td><td>$totalWt</td></tr>";
echo "</table><hr>";

View file

@ -9,25 +9,25 @@
function knapSolve($w,$v,$i,$aW) {
global $numcalls;
$numcalls ++;
// echo "Called with i=$i, aW=$aW<br>";
global $numcalls;
$numcalls ++;
// echo "Called with i=$i, aW=$aW<br>";
if ($i == 0) {
if ($w[$i] <= $aW) {
return $v[$i];
} else {
return 0;
}
}
$without_i = knapSolve($w, $v, $i-1, $aW);
if ($w[$i] > $aW) {
return $without_i;
} else {
$with_i = $v[$i] + knapSolve($w, $v, ($i-1), ($aW - $w[$i]));
return max($with_i, $without_i);
}
if ($i == 0) {
if ($w[$i] <= $aW) {
return $v[$i];
} else {
return 0;
}
}
$without_i = knapSolve($w, $v, $i-1, $aW);
if ($w[$i] > $aW) {
return $without_i;
} else {
$with_i = $v[$i] + knapSolve($w, $v, ($i-1), ($aW - $w[$i]));
return max($with_i, $without_i);
}
}
@ -44,36 +44,36 @@ function knapSolve($w,$v,$i,$aW) {
function knapSolveFast($w,$v,$i,$aW,&$m) { // Note: We use &$m because the function writes to the $m array
global $numcalls;
$numcalls ++;
// echo "Called with i=$i, aW=$aW<br>";
global $numcalls;
$numcalls ++;
// echo "Called with i=$i, aW=$aW<br>";
// Return memo if we have one
if (isset($m[$i][$aW])) {
return $m[$i][$aW];
} else {
// Return memo if we have one
if (isset($m[$i][$aW])) {
return $m[$i][$aW];
} else {
if ($i == 0) {
if ($w[$i] <= $aW) {
$m[$i][$aW] = $v[$i]; // save memo
return $v[$i];
} else {
$m[$i][$aW] = 0; // save memo
return 0;
}
}
$without_i = knapSolveFast($w, $v, $i-1, $aW,$m);
if ($w[$i] > $aW) {
$m[$i][$aW] = $without_i; // save memo
return $without_i;
} else {
$with_i = $v[$i] + knapSolveFast($w, $v, ($i-1), ($aW - $w[$i]),$m);
$res = max($with_i, $without_i);
$m[$i][$aW] = $res; // save memo
return $res;
}
}
if ($i == 0) {
if ($w[$i] <= $aW) {
$m[$i][$aW] = $v[$i]; // save memo
return $v[$i];
} else {
$m[$i][$aW] = 0; // save memo
return 0;
}
}
$without_i = knapSolveFast($w, $v, $i-1, $aW,$m);
if ($w[$i] > $aW) {
$m[$i][$aW] = $without_i; // save memo
return $without_i;
} else {
$with_i = $v[$i] + knapSolveFast($w, $v, ($i-1), ($aW - $w[$i]),$m);
$res = max($with_i, $without_i);
$m[$i][$aW] = $res; // save memo
return $res;
}
}
}

View file

@ -1,26 +1,26 @@
my $raw = <<'TABLE';
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
suntancream 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
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
suntancream 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
TABLE
my (@name, @weight, @value);

View file

@ -0,0 +1,51 @@
local fmt = require "fmt"
local wants = {
{"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}
}
local function m(i, w)
if i < 1 or w == 0 then return {}, 0, 0 end
if wants[i][2] > w then return m(i - 1, w) end
local i0, w0, v0 = m(i - 1, w)
local i1, w1, v1 = m(i - 1, w - wants[i][2])
v1 += wants[i][3]
if v1 > v0 then
i1:insert(wants[i])
return i1, w1 + wants[i][2], v1
end
return i0, w0, v0
end
local max_wt = 400
local items, tw, tv = m(#wants, max_wt)
print($"Max weight: {max_wt}\n")
print("Item Weight Value")
print("------------------------------------")
for i = 1, #items do
local [item, w, v] = items[i]
fmt.print("%-22s %3d %4s", item, w, v)
end
print(" --- ----")
fmt.print("totals %3d %4d", tw, tv)

View file

@ -1,51 +1,51 @@
:- use_module(library(simplex)).
knapsack :-
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),
('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 )],
gen_state(S0),
length(L, N),
numlist(1, N, LN),
time(( create_constraint_N(LN, S0, S1),
maplist(create_constraint_WV, LN, L, LW, LV),
constraint(LW =< 400, S1, S2),
maximize(LV, S2, S3)
)),
compute_lenword(L, 0, Len),
sformat(A1, '~~w~~t~~~w|', [Len]),
sformat(A2, '~~t~~w~~~w|', [4]),
sformat(A3, '~~t~~w~~~w|', [5]),
print_results(S3, A1,A2,A3, L, LN, 0, 0).
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),
('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 )],
gen_state(S0),
length(L, N),
numlist(1, N, LN),
time(( create_constraint_N(LN, S0, S1),
maplist(create_constraint_WV, LN, L, LW, LV),
constraint(LW =< 400, S1, S2),
maximize(LV, S2, S3)
)),
compute_lenword(L, 0, Len),
sformat(A1, '~~w~~t~~~w|', [Len]),
sformat(A2, '~~t~~w~~~w|', [4]),
sformat(A3, '~~t~~w~~~w|', [5]),
print_results(S3, A1,A2,A3, L, LN, 0, 0).
create_constraint_N([], S, S).
create_constraint_N([HN|TN], S1, SF) :-
constraint(integral(x(HN)), S1, S2),
constraint([x(HN)] =< 1, S2, S3),
constraint([x(HN)] >= 0, S3, S4),
create_constraint_N(TN, S4, SF).
constraint(integral(x(HN)), S1, S2),
constraint([x(HN)] =< 1, S2, S3),
constraint([x(HN)] >= 0, S3, S4),
create_constraint_N(TN, S4, SF).
create_constraint_WV(N, (_, W, V), W * x(N), V * x(N)).
@ -53,26 +53,26 @@ create_constraint_WV(N, (_, W, V), W * x(N), V * x(N)).
%
compute_lenword([], N, N).
compute_lenword([(Name, _, _)|T], N, NF):-
atom_length(Name, L),
( L > N -> N1 = L; N1 = N),
compute_lenword(T, N1, NF).
atom_length(Name, L),
( L > N -> N1 = L; N1 = N),
compute_lenword(T, N1, NF).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
print_results(_S, A1, A2, A3, [], [], WM, VM) :-
sformat(W1, A1, [' ']),
sformat(W2, A2, [WM]),
sformat(W3, A3, [VM]),
format('~w~w~w~n', [W1,W2,W3]).
sformat(W1, A1, [' ']),
sformat(W2, A2, [WM]),
sformat(W3, A3, [VM]),
format('~w~w~w~n', [W1,W2,W3]).
print_results(S, A1, A2, A3, [(Name, W, V)|T], [N|TN], W1, V1) :-
variable_value(S, x(N), X),
( X = 0 -> W1 = W2, V1 = V2
; sformat(S1, A1, [Name]),
sformat(S2, A2, [W]),
sformat(S3, A3, [V]),
format('~w~w~w~n', [S1,S2,S3]),
W2 is W1 + W,
V2 is V1 + V),
print_results(S, A1, A2, A3, T, TN, W2, V2).
variable_value(S, x(N), X),
( X = 0 -> W1 = W2, V1 = V2
; sformat(S1, A1, [Name]),
sformat(S2, A2, [W]),
sformat(S3, A3, [V]),
format('~w~w~w~n', [S1,S2,S3]),
W2 is W1 + W,
V2 is V1 + V),
print_results(S, A1, A2, A3, T, TN, W2, V2).

View file

@ -1,4 +1,4 @@
n, G = 5, 5 # KNAPSACK 0-1 DANILIN
n, G = 5, 5 # KNAPSACK 0-1 DANILIN
N = n + 1 # rextester.com/BCKP19591
a = 2 ** N
L, C, j, q, s, d, e = [1]*n, [1]*n, [1]*n, [0]*a, [0]*a, [0]*a, [""]*a
@ -26,5 +26,5 @@ print()
max, m = 0, 1
for i in range(a):
if d[i] <= G and q[i] > max:
max, m = q[i], i
max, m = q[i], i
print(d[m], q[m], e[m])

View file

@ -11,68 +11,68 @@ Full_Data<-structure(list(item = c("map", "compass", "water", "sandwich",
Bounded_knapsack<-function(Data,W)
{
K<-matrix(NA,nrow=W+1,ncol=dim(Data)[1]+1)
0->K[1,]->K[,1]
matrix_item<-matrix('',nrow=W+1,ncol=dim(Data)[1]+1)
for(j in 1:dim(Data)[1])
{
for(w in 1:W)
{
wj<-Data$weigth[j]
item<-Data$item[j]
value<-Data$value[j]
if( wj > w )
{
K[w+1,j+1]<-K[w+1,j]
matrix_item[w+1,j+1]<-matrix_item[w+1,j]
}
else
{
if( K[w+1,j] >= K[w+1-wj,j]+value )
{
K[w+1,j+1]<-K[w+1,j]
matrix_item[w+1,j+1]<-matrix_item[w+1,j]
}
else
{
K[w+1,j+1]<-K[w+1-wj,j]+value
matrix_item[w+1,j+1]<-item
}
}
}
}
K<-matrix(NA,nrow=W+1,ncol=dim(Data)[1]+1)
0->K[1,]->K[,1]
matrix_item<-matrix('',nrow=W+1,ncol=dim(Data)[1]+1)
for(j in 1:dim(Data)[1])
{
for(w in 1:W)
{
wj<-Data$weigth[j]
item<-Data$item[j]
value<-Data$value[j]
if( wj > w )
{
K[w+1,j+1]<-K[w+1,j]
matrix_item[w+1,j+1]<-matrix_item[w+1,j]
}
else
{
if( K[w+1,j] >= K[w+1-wj,j]+value )
{
K[w+1,j+1]<-K[w+1,j]
matrix_item[w+1,j+1]<-matrix_item[w+1,j]
}
else
{
K[w+1,j+1]<-K[w+1-wj,j]+value
matrix_item[w+1,j+1]<-item
}
}
}
}
return(list(K=K,Item=matrix_item))
}
backtracking<-function(knapsack, Data)
{
W<-dim(knapsack$K)[1]
itens<-c()
col<-dim(knapsack$K)[2]
selected_item<-knapsack$Item[W,col]
while(selected_item!='')
{
selected_item<-knapsack$Item[W,col]
if(selected_item!='')
{
selected_item_value<-Data[Data$item == selected_item,]
if(-knapsack$K[W - selected_item_value$weigth,col-1]+knapsack$K[W,col]==selected_item_value$value)
{
W <- W - selected_item_value$weigth
itens<-c(itens,selected_item)
}
col <- col - 1
}
}
W<-dim(knapsack$K)[1]
itens<-c()
col<-dim(knapsack$K)[2]
selected_item<-knapsack$Item[W,col]
while(selected_item!='')
{
selected_item<-knapsack$Item[W,col]
if(selected_item!='')
{
selected_item_value<-Data[Data$item == selected_item,]
if(-knapsack$K[W - selected_item_value$weigth,col-1]+knapsack$K[W,col]==selected_item_value$value)
{
W <- W - selected_item_value$weigth
itens<-c(itens,selected_item)
}
col <- col - 1
}
}
return(itens)
}
print_output<-function(Data,W)
{
Bounded_knapsack(Data,W)->Knap
backtracking(Knap, Data)->Items
output<-paste('You must carry:', paste(Items, sep = ', '), sep=' ' )
return(output)
Bounded_knapsack(Data,W)->Knap
backtracking(Knap, Data)->Items
output<-paste('You must carry:', paste(Items, sep = ', '), sep=' ' )
return(output)
}
print_output(Full_Data, 400)

View file

@ -0,0 +1,85 @@
Rebol [
title: "Rosetta code: Knapsack problem/0-1"
file: %Knapsack_problem-0-1.r3
url: https://rosettacode.org/wiki/Knapsack_problem/0-1
]
knapsack: function/with [
"Solves the 0/1 knapsack problem via top-down dynamic programming."
capacity [integer!] "remaining weight capacity"
remaining [block!] "items not yet considered"
][
;;Each item may be taken at most once (unlike the bounded variant).
;;Returns a 3-element block [value weight items] representing the
;;optimal selection. Results are memoised in `cache` keyed by
;;"capacity,item-count" so each sub-problem is solved at most once.
if empty? remaining [ return reduce [0 0 copy []] ] ;; base case: no items left
key: rejoin [capacity "," length? remaining]
if cached: cache/:key [ return cached ] ;; memoisation hit
item: first remaining
rest: next remaining
name: item/1
weight: item/2
value: item/3
skip-it: knapsack capacity rest ;; best result without this item
result: either weight > capacity [
skip-it ;; item too heavy: must skip
][
take-it: knapsack (capacity - weight) rest ;; best result with this item
take-value: take-it/1 + value
either take-value > skip-it/1 [
reduce [
take-value
take-it/2 + weight
append copy take-it/3 item
]
][
skip-it ;; skipping is better
]
]
cache/:key: result
result
][
cache: make map! 2000 ;; memoisation table
]
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]
[cream 11 70]
[camera 32 30]
[t-shirt 24 15]
[trousers 48 10]
[umbrella 73 40]
[trousers 42 70]
[overclothes 43 75]
[notecase 22 80]
[glasses 7 20]
[towel 18 12]
[socks 4 50]
[book 30 10]
]
result: knapsack 400 items
print "Bagged the following items:"
foreach [item weight value] result/3 [
printf [" * " 12 -4 -4] reduce [item value weight]
]
print [
"Total value :" as-green result/1 LF
"Total weight :" as-green result/2]

View file

@ -55,9 +55,9 @@ fn test_dp_results() {
}
else {
m(n)(w) = m(n-1)(w-wn)+vn
plm(n)(w) = plm(n-1)(w-wn)+in
}
}
plm(n)(w) = plm(n-1)(w-wn)+in
}
}
}
}

View file

@ -1,27 +1,27 @@
# The list of items to consider, as list of lists
set 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}
{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}
}
# Simple extraction functions
@ -45,18 +45,18 @@ proc value {chosen} {
proc knapsackSearch {items {chosen {}}} {
# If we've gone over the weight limit, stop now
if {[weight $chosen] > 400} {
return
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 max
set v [value $chosen]
if {$v > $max} {
set max $v
set best $chosen
}
return
global best max
set v [value $chosen]
if {$v > $max} {
set max $v
set best $chosen
}
return
}
# Branch, so recurse for chosing the current item or not
set this [lindex $items 0]

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

@ -1,11 +1,11 @@
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) );
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