Another update from ingydotnet^djgoku
This commit is contained in:
parent
91df62d461
commit
948b86eafa
7604 changed files with 108452 additions and 22726 deletions
|
|
@ -42,24 +42,36 @@ typedef struct {
|
|||
|
||||
void optimal(int weight, int idx, solution *s)
|
||||
{
|
||||
solution v1, v2;
|
||||
if (idx < 0) {
|
||||
s->bits = s->value = 0;
|
||||
return;
|
||||
}
|
||||
function solve(itemArray, capacity){
|
||||
matrix = create2DMatrix(itemArray.length, capacity);
|
||||
keep_matrix = create2DMatrix(itemArray.length, capacity);
|
||||
for(var c=0; c <= capacity; c++){
|
||||
matrix[0][c] = 0;
|
||||
keep_matrix[0][c] = 0;
|
||||
}
|
||||
for(var r=1; r<itemArray.length+1; ++r){//rows
|
||||
for(var c=0; c<=capacity; ++c){
|
||||
var toMatrix = 0;
|
||||
//fit in itself?
|
||||
var fit = items[r-1].weight<= c;
|
||||
if(fit){//add remaining mini-knapsack if any, and compare to not putting it
|
||||
var restCap = c-items[r-1].weight;
|
||||
toMatrix = items[r-1].value+ matrix[r-1][restCap];
|
||||
if( toMatrix > matrix[r-1][c])
|
||||
keep_matrix[r][c] = 1;
|
||||
else
|
||||
keep_matrix[r][c] = 0;
|
||||
toMatrix = Math.max(toMatrix, matrix[r-1][c]);
|
||||
}else{//copy the knapsack from row above
|
||||
toMatrix = matrix[r-1][c];
|
||||
keep_matrix[r][c] = 0;
|
||||
}
|
||||
matrix[r][c] = toMatrix;
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
if (weight < item[idx].weight) {
|
||||
optimal(weight, idx - 1, s);
|
||||
return;
|
||||
}
|
||||
|
||||
optimal(weight, idx - 1, &v1);
|
||||
optimal(weight - item[idx].weight, idx - 1, &v2);
|
||||
|
||||
v2.value += item[idx].value;
|
||||
v2.bits |= (1 << idx);
|
||||
|
||||
*s = (v1.value >= v2.value) ? v1 : v2;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
|
|
|||
40
Task/Knapsack-problem-0-1/Eiffel/knapsack-problem-0-1-1.e
Normal file
40
Task/Knapsack-problem-0-1/Eiffel/knapsack-problem-0-1-1.e
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
class
|
||||
APPLICATION
|
||||
|
||||
create
|
||||
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
|
||||
|
||||
end
|
||||
35
Task/Knapsack-problem-0-1/Eiffel/knapsack-problem-0-1-2.e
Normal file
35
Task/Knapsack-problem-0-1/Eiffel/knapsack-problem-0-1-2.e
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
class
|
||||
ITEM
|
||||
|
||||
create
|
||||
make, make_from_other
|
||||
|
||||
feature
|
||||
|
||||
name: STRING
|
||||
|
||||
weight: 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 (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
|
||||
106
Task/Knapsack-problem-0-1/Eiffel/knapsack-problem-0-1-3.e
Normal file
106
Task/Knapsack-problem-0-1/Eiffel/knapsack-problem-0-1-3.e
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
class
|
||||
KNAPSACKZEROONE
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature
|
||||
|
||||
items: ARRAY [ITEM]
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
feature {NONE}
|
||||
|
||||
max (a, b: INTEGER): INTEGER
|
||||
-- Max of 'a' and 'b'.
|
||||
do
|
||||
Result := a
|
||||
if a < b then
|
||||
Result := b
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
70
Task/Knapsack-problem-0-1/Forth/knapsack-problem-0-1.fth
Normal file
70
Task/Knapsack-problem-0-1/Forth/knapsack-problem-0-1.fth
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
\ Rosetta Code Knapp-sack 0-1 problem. Tested under GForth 0.7.3.
|
||||
\ 22 items. On current processors a set fits nicely in one CELL (32 or 64 bits).
|
||||
\ Brute force approach: for every possible set of 22 items,
|
||||
\ check for admissible solution then for optimal set.
|
||||
|
||||
: offs HERE over - ;
|
||||
400 VALUE WLIMIT
|
||||
0 VALUE ITEM
|
||||
0 VALUE VAL
|
||||
0 VALUE /ITEM
|
||||
0 VALUE ITEMS#
|
||||
Create Sack
|
||||
HERE
|
||||
9 , offs TO VAL
|
||||
150 , offs TO ITEM
|
||||
s" map " s, offs TO /ITEM
|
||||
DROP
|
||||
13 , 35 , s" compass " s,
|
||||
153 , 200 , s" water " s,
|
||||
50 , 160 , s" sandwich " s,
|
||||
15 , 60 , s" glucose " s,
|
||||
68 , 45 , s" tin " s,
|
||||
27 , 60 , s" banana " s,
|
||||
39 , 40 , s" apple " s,
|
||||
23 , 30 , s" cheese " s,
|
||||
52 , 10 , s" beer " s,
|
||||
11 , 70 , s" suntan cream " s,
|
||||
32 , 30 , s" camera " s,
|
||||
24 , 15 , s" T-shirt " s,
|
||||
48 , 10 , s" trousers " s,
|
||||
73 , 40 , s" umbrella " s,
|
||||
42 , 70 , s" wp trousers " s,
|
||||
43 , 75 , s" wp overclothes " s,
|
||||
22 , 80 , s" note-case " s,
|
||||
7 , 20 , s" sunglasses " s,
|
||||
18 , 12 , s" towel " s,
|
||||
4 , 50 , s" socks " s,
|
||||
30 , 10 , s" book " s,
|
||||
HERE VALUE END-SACK
|
||||
VARIABLE Sol \ Solution Set
|
||||
VARIABLE Vmax \ Temporary Maximum Value
|
||||
VARIABLE Sum \ Temporary Sum (for speed-up)
|
||||
: ]sum ( Rtime: set -- sum ;Ctime: hilimit.a start.a -- )
|
||||
\ Loop unwinding & precomputing addresses
|
||||
]
|
||||
]] Sum OFF [[
|
||||
DO ]] dup [[ 1 ]] LITERAL AND IF [[ I ]] LITERAL @ Sum +! THEN 2/ [[
|
||||
/ITEM +LOOP ]] drop Sum @ [[
|
||||
; IMMEDIATE
|
||||
: solve ( -- )
|
||||
Vmax OFF
|
||||
[ 1 END-SACK Sack - /ITEM / lshift 1- ]L 0
|
||||
DO
|
||||
I [ END-SACK Sack ]sum ( by weight ) WLIMIT <
|
||||
IF
|
||||
I [ END-SACK VAL + Sack VAL + ]sum ( by value )
|
||||
dup Vmax @ >
|
||||
IF Vmax ! I Sol ! ELSE drop THEN
|
||||
THEN
|
||||
LOOP
|
||||
;
|
||||
: .solution ( -- )
|
||||
Sol @ END-SACK ITEM + Sack ITEM +
|
||||
DO
|
||||
dup 1 AND IF I count type cr THEN
|
||||
2/
|
||||
/ITEM +LOOP
|
||||
drop
|
||||
." Weight: " Sol @ [ END-SACK Sack ]sum . ." Value: " Sol @ [ END-SACK VAL + Sack VAL + ]sum .
|
||||
;
|
||||
20
Task/Knapsack-problem-0-1/Julia/knapsack-problem-0-1-1.julia
Normal file
20
Task/Knapsack-problem-0-1/Julia/knapsack-problem-0-1-1.julia
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using MathProgBase
|
||||
|
||||
immutable KPDSupply{S<:String, T<:Integer}
|
||||
item::S
|
||||
weight::T
|
||||
value::T
|
||||
quant::T
|
||||
end
|
||||
function KPDSupply{S<:String, T<:Integer}(item::S, weight::T, value::T)
|
||||
KPDSupply(item, weight, value, one(T))
|
||||
end
|
||||
|
||||
function solve{S<:String, T<:Integer}(gear::Array{KPDSupply{S,T},1},
|
||||
capacity::T)
|
||||
w = map(x->x.weight, gear)
|
||||
v = map(x->x.value, gear)
|
||||
sol = mixintprog(-v, w', '<', capacity, :Bin, 0, 1)
|
||||
sol.status == :Optimal || error("This Problem could not be solved")
|
||||
gear[sol.sol .== 1.0]
|
||||
end
|
||||
32
Task/Knapsack-problem-0-1/Julia/knapsack-problem-0-1-2.julia
Normal file
32
Task/Knapsack-problem-0-1/Julia/knapsack-problem-0-1-2.julia
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
gear = [KPDSupply("map", 9, 150),
|
||||
KPDSupply("compass", 13, 35),
|
||||
KPDSupply("water", 153, 200),
|
||||
KPDSupply("sandwich", 50, 160),
|
||||
KPDSupply("glucose", 15, 60),
|
||||
KPDSupply("tin", 68, 45),
|
||||
KPDSupply("banana", 27, 60),
|
||||
KPDSupply("apple", 39, 40),
|
||||
KPDSupply("cheese", 23, 30),
|
||||
KPDSupply("beer", 52, 10),
|
||||
KPDSupply("suntan cream", 11, 70),
|
||||
KPDSupply("camera", 32, 30),
|
||||
KPDSupply("T-shirt", 24, 15),
|
||||
KPDSupply("trousers", 48, 10),
|
||||
KPDSupply("umbrella", 73, 40),
|
||||
KPDSupply("waterproof trousers", 42, 70),
|
||||
KPDSupply("waterproof overclothes", 43, 75),
|
||||
KPDSupply("note-case", 22, 80),
|
||||
KPDSupply("sunglasses", 7, 20),
|
||||
KPDSupply("towel", 18, 12),
|
||||
KPDSupply("socks", 4, 50),
|
||||
KPDSupply("book", 30, 10)]
|
||||
|
||||
pack = solve(gear, 400)
|
||||
|
||||
println("The hiker should pack:")
|
||||
for s in pack
|
||||
println(" ", s.item)
|
||||
end
|
||||
println()
|
||||
println("Packed Weight: ", mapreduce(x->x.weight, +, pack))
|
||||
println("Packed Value: ", mapreduce(x->x.value, +, pack))
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
#########################################################
|
||||
|
||||
function knapSolveFast2($w,$v,$i,$aW,&$m) {
|
||||
function knapSolveFast2($w, $v, $i, $aW, &$m, &$pickedItems) {
|
||||
|
||||
global $numcalls;
|
||||
$numcalls ++;
|
||||
|
|
@ -92,6 +92,7 @@ echo "<b>Array Indices:</b><br>".join(",",$pickedItems)."<br>";
|
|||
echo "<b>Chosen Items:</b><br>";
|
||||
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];
|
||||
|
|
|
|||
36
Task/Knapsack-problem-0-1/Python/knapsack-problem-0-1-3.py
Normal file
36
Task/Knapsack-problem-0-1/Python/knapsack-problem-0-1-3.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
def total_value(items, max_weight):
|
||||
return sum([x[2] for x in items]) if sum([x[1] for x in items]) < max_weight else 0
|
||||
|
||||
cache = {}
|
||||
def solve(items, max_weight):
|
||||
if not items:
|
||||
return ()
|
||||
if (items,max_weight) not in cache:
|
||||
head = items[0]
|
||||
tail = items[1:]
|
||||
include = (head,) + solve(tail, max_weight - head[1])
|
||||
dont_include = solve(tail, max_weight)
|
||||
if total_value(include, max_weight) > total_value(dont_include, max_weight):
|
||||
answer = include
|
||||
else:
|
||||
answer = dont_include
|
||||
cache[(items,max_weight)] = answer
|
||||
return cache[(items,max_weight)]
|
||||
|
||||
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),
|
||||
)
|
||||
max_weight = 400
|
||||
|
||||
solution = solve(items, max_weight)
|
||||
print "items:"
|
||||
for x in solution:
|
||||
print x[0]
|
||||
print "value:", total_value(solution, max_weight)
|
||||
print "weight:", sum([x[1] for x in solution])
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/*REXX pgm solves a knapsack problem (22 items with weight restriction).*/
|
||||
/*REXX program solves a knapsack problem (22 items with a weight restriction).*/
|
||||
@.=; @.1 = 'map 9 150'
|
||||
@.2 = 'compass 13 35'
|
||||
@.3 = 'water 153 200'
|
||||
|
|
@ -21,8 +21,8 @@
|
|||
@.20 = 'towel 18 12'
|
||||
@.21 = 'socks 4 50'
|
||||
@.22 = 'book 30 10'
|
||||
maxWeight=400 /*the maximum weight for knapsack*/
|
||||
say; say 'maximum weight allowed for a knapsack:' comma(maxWeight); say
|
||||
maxWeight=400 /*maximum weight for the knapsack*/
|
||||
say; say 'maximum weight allowed for a knapsack:' commas(maxWeight); say
|
||||
maxL=length('item') /*maximum width for table names. */
|
||||
maxL=length('knapsack items') /*maximum width for table names. */
|
||||
maxW=length('weight') /* " " " " weights*/
|
||||
|
|
@ -30,53 +30,58 @@ maxV=length('value') /* " " " " values.*/
|
|||
maxQ=length('pieces') /* " " " " quant. */
|
||||
highQ=0 /*max quantity specified (if any)*/
|
||||
items=0; i.=; w.=0; v.=0; q.=0; Tw=0; Tv=0; Tq=0 /*initialize stuff.*/
|
||||
/*────────────────────────────────sort the choices by decreasing weight.*/
|
||||
/*this minimizes # combinations. */
|
||||
|
||||
/*════════════════════════════════sort the choices by decreasing weight.*/
|
||||
|
||||
do j=1 while @.j\=='' /*process each choice and sort. */
|
||||
_=@.j; _wt=word(_,2) /*choose first item (arbitrary). */
|
||||
_=space(@.j) _wt=word(_,2) /*choose first item (arbitrary). */
|
||||
_wt=word(_,2)
|
||||
|
||||
do k=j+1 while @.k\=='' /*find a possible heavier item. */
|
||||
?wt=word(@.k,2)
|
||||
if ?wt>_wt then do; _=@.k; @.k=@.j; @.j=_; _wt=?wt; end
|
||||
end /*k*/
|
||||
end /*j*/
|
||||
obj=j-1 /*adjust for the DO loop index. */
|
||||
/*────────────────────────────────build list of choices.────────────────*/
|
||||
end /*j*/ /*adjust for the DO loop index.*/
|
||||
obj=j-1
|
||||
/*════════════════════════════════build list of choices.════════════════*/
|
||||
|
||||
do j=1 for obj /*build a list of choices. */
|
||||
_=space(@.j) /*remove superfluous blanks. */
|
||||
parse var _ item w v q . /*parse original choice for table*/
|
||||
parse var @.j item w v q . /*parse original choice for table*/
|
||||
if w>maxWeight then iterate /*if the weight > maximum, ignore*/
|
||||
Tw=Tw+w; Tv=Tv+v; Tq=Tq+1 /*add totals up (for alignment). */
|
||||
maxL=max(maxL,length(item)) /*find maximum width for item. */
|
||||
if q=='' then q=1
|
||||
highQ=max(highQ,q)
|
||||
items=items+1 /*bump the item counter. */
|
||||
items=items+1 /*bump # items.*/
|
||||
i.items=item; w.items=w; v.items=v; q.items=q
|
||||
do k=2 to q; items=items+1 /*bump the item counter. */
|
||||
i.items=item; w.items=w; v.items=v; q.items=q
|
||||
Tw=Tw+w; Tv=Tv+v; Tq=Tq+1
|
||||
|
||||
do k=2 to q; items=items+1 /*bump # items.*/
|
||||
i.items=item; w.items=w; v.items=v; q.items=q
|
||||
Tw=Tw+w; Tv=Tv+v; Tq=Tq+1
|
||||
end /*k*/
|
||||
end /*j*/
|
||||
|
||||
maxW=max(maxW,length(comma(Tw))) /*find maximum width for weight. */
|
||||
maxV=max(maxV,length(comma(Tv))) /* " " " " value. */
|
||||
maxQ=max(maxQ,length(comma(Tq))) /* " " " " quantity*/
|
||||
maxW=max(maxW,length(commas(Tw))) /*find maximum width for weight. */
|
||||
maxV=max(maxV,length(commas(Tv))) /* " " " " value. */
|
||||
maxQ=max(maxQ,length(commas(Tq))) /* " " " " quantity*/
|
||||
maxL=maxL+maxL%4+4 /*extend width of name for table.*/
|
||||
/*────────────────────────────────show the list of choices.─────────────*/
|
||||
/*════════════════════════════════show the list of choices.═════════════*/
|
||||
call hdr 'item'; do j=1 for obj /*show all choices, nice format. */
|
||||
parse var @.j item weight value q .
|
||||
if highq==1 then q=
|
||||
else if q=='' then q=1
|
||||
call show item,weight,value,q
|
||||
call show item, weight, value, q
|
||||
end /*j*/
|
||||
|
||||
say; say 'number of items:' items; say
|
||||
/*─────────────────────────────────────examine all the possible choices.*/
|
||||
/*═════════════════════════════════════examine all the possible choices.*/
|
||||
h=items; ho=h+1; m=maxWeight; $=0; call sim22
|
||||
/*─────────────────────────────────────show the best choice (weight,val)*/
|
||||
do h-1; ?=strip(strip(?),"L",0); end
|
||||
/*═════════════════════════════════════show the best choice (weight,val)*/
|
||||
do h-1; ?=strip(strip(?),"L",0); end
|
||||
|
||||
bestC=?; bestW=0; bestV=$; highQ=0; totP=words(bestC)
|
||||
call hdr 'best choice'
|
||||
|
||||
do j=1 to totP /*J is modified within DO loop. */
|
||||
_=word(bestC,j); _w=w._; _v=v._; q=1
|
||||
if _==0 then iterate
|
||||
|
|
@ -85,38 +90,35 @@ call hdr 'best choice'
|
|||
j=j+1; w._=w._+_w; v._=v._+_v; q=q+1
|
||||
end /*k*/
|
||||
call show i._,w._,v._,q; bestW=bestw+w._
|
||||
end /*j*/
|
||||
end /*j*/
|
||||
call hdr2; say
|
||||
call show 'best weight' ,bestW /*show a nicely formatted winnerW*/
|
||||
call show 'best value' ,,bestV /*show a nicely formatted winnerV*/
|
||||
call show 'knapsack items',,,totP /*show a nicely formatted pieces.*/
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*────────────────────────────────COMMA subroutine───────────────────────────────────────────────*/
|
||||
comma: procedure; parse arg _,c,p,t;arg ,cu;c=word(c ",",1);if cu=='BLANK' then c=' ';o=word(p 3,1)
|
||||
k=0;p=abs(o);t=word(t 999999999,1);if \datatype(p,'W')|\datatype(t,'W')|p==0|arg()>4 then return _
|
||||
n=_'.9'; #=123456789; if o<0 then do; b=verify(_,' '); if b==0 then return _
|
||||
e=length(_)-verify(reverse(_),' ')+1; end; else do; b=verify(n,#,"M")
|
||||
e=verify(n,#'0',,verify(n,#"0.",'M'))-p-1;end;do j=e to b by -p while k<t;_=insert(c,_,j);k=k+1;end
|
||||
return _ /* [↑] adds commas to the 1st number found in the string.*/
|
||||
/*────────────────────────────────HDR subroutine─────────────────────────────────────────────────*/
|
||||
hdr: parse arg _item_,_; if highq\==1 then _=center('pieces',maxq)
|
||||
call show center(_item_ ,maxL), center('weight',maxW), center('value',maxV), center(_,maxQ)
|
||||
call hdr2; return
|
||||
/*────────────────────────────────HDR2 subroutine────────────────────────────────────────────────*/
|
||||
call show 'best weight' ,bestW /*show a nicely formatted winnerW. */
|
||||
call show 'best value' ,,bestV /*show a nicely formatted winnerV. */
|
||||
call show 'knapsack items',,,totP /*show a nicely formatted 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: parse arg _item_,_; if highq\==1 then _=center('pieces',maxq)
|
||||
call show center(_item_,maxL),center('weight',maxW),center('value',maxV),center(_,maxQ)
|
||||
call hdr2; return
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
hdr2: _=maxQ; if highq==1 then _=0
|
||||
call show copies('=',maxL),copies('=',maxW),copies('=',maxV),copies('=',_)
|
||||
return
|
||||
/*────────────────────────────────J? subroutine────────────────────────────────────────*/
|
||||
call show copies('═',maxL),copies('═',maxW),copies('═',maxV),copies('═',_)
|
||||
return
|
||||
/*─────────────────────────────────────────────────────────────────────────────────────*/
|
||||
j?: parse arg _,?; $=value('V'_); do j=1 for _; ?=? value('J'j); end; return
|
||||
/*────────────────────────────────SHOW subroutine───────────────────────*/
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
show: parse arg _item,_weight,_value,_quant
|
||||
say translate(left(_item,maxL,'─'),,'_'),
|
||||
right(comma(_weight),maxW),
|
||||
right(comma(_value ),maxV),
|
||||
right(comma(_quant ),maxQ)
|
||||
return
|
||||
/*────────────────────────────────SIM22 subroutine───────────────────────────────────────────────────────────*/
|
||||
sim22: do j1=0 for h+1; w1=w.j1; v1 = v.j1; if v1>$ then call j? 1
|
||||
say translate(left(_item,maxL,'─'),,'_') right(commas(_weight),maxW),
|
||||
right(commas(_value ),maxV),
|
||||
right(commas(_quant ),maxQ)
|
||||
return
|
||||
/*───────────────────────────────────────────────────────────────────────────────────────────────────────────*/
|
||||
sim22:
|
||||
do j1 =0 for h+1; w1 = w.j1; v1 = v.j1; if v1>$ then call j? 1
|
||||
do j2 =j1 +(j1 \==0) to h;if w.j2 +w1>m then iterate j1; w2 =w1 +w.j2; v2 =v1 +v.j2; if v2>$ then call j? 2
|
||||
do j3 =j2 +(j2 \==0) to h;if w.j3 +w2>m then iterate j2; w3 =w2 +w.j3; v3 =v2 +v.j3; if v3>$ then call j? 3
|
||||
do j4 =j3 +(j3 \==0) to h;if w.j4 +w3>m then iterate j3; w4 =w3 +w.j4; v4 =v3 +v.j4; if v4>$ then call j? 4
|
||||
|
|
@ -138,5 +140,5 @@ sim22: do j1=0 for h+1; w1=w.j1; v1 =
|
|||
do j20=j19+(j19\==0) to h;if w.j20+w19>m then iterate j19;w20=w19+w.j20;v20=v19+v.j20;if v20>$ then call j? 20
|
||||
do j21=j20+(j20\==0) to h;if w.j21+w20>m then iterate j20;w21=w20+w.j21;v21=v20+v.j21;if v21>$ then call j? 21
|
||||
do j22=j21+(j21\==0) to h;if w.j22+w21>m then iterate j21;w22=w21+w.j22;v22=v21+v.j22;if v22>$ then call j? 22
|
||||
end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end
|
||||
end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end
|
||||
return
|
||||
|
|
|
|||
|
|
@ -1,140 +1,134 @@
|
|||
extern crate std;
|
||||
#![feature(iter_arith)]
|
||||
use std::cmp::max;
|
||||
use std::vec::Vec;
|
||||
|
||||
|
||||
// This struct is used to store our items that we want in our knap-sack.
|
||||
struct Want<'a> {
|
||||
#[derive(Clone, Debug)]
|
||||
struct Item<'a> {
|
||||
name: &'a str,
|
||||
weight: uint,
|
||||
value: uint
|
||||
weight: usize,
|
||||
value: usize
|
||||
}
|
||||
|
||||
|
||||
// Global, immutable allocation of our items.
|
||||
static items : &'static [Want<'static>] = &[
|
||||
Want {name: "map", weight: 9, value: 150},
|
||||
Want {name: "compass", weight: 13, value: 35},
|
||||
Want {name: "water", weight: 153, value: 200},
|
||||
Want {name: "sandwich", weight: 50, value: 160},
|
||||
Want {name: "glucose", weight: 15, value: 60},
|
||||
Want {name: "tin", weight: 68, value: 45},
|
||||
Want {name: "banana", weight: 27, value: 60},
|
||||
Want {name: "apple", weight: 39, value: 40},
|
||||
Want {name: "cheese", weight: 23, value: 30},
|
||||
Want {name: "beer", weight: 52, value: 10},
|
||||
Want {name: "suntancream", weight: 11, value: 70},
|
||||
Want {name: "camera", weight: 32, value: 30},
|
||||
Want {name: "T-shirt", weight: 24, value: 15},
|
||||
Want {name: "trousers", weight: 48, value: 10},
|
||||
Want {name: "umbrella", weight: 73, value: 40},
|
||||
Want {name: "waterproof trousers", weight: 42, value: 70},
|
||||
Want {name: "waterproof overclothes", weight: 43, value: 75},
|
||||
Want {name: "note-case", weight: 22, value: 80},
|
||||
Want {name: "sunglasses", weight: 7, value: 20},
|
||||
Want {name: "towel", weight: 18, value: 12},
|
||||
Want {name: "socks", weight: 4, value: 50},
|
||||
Want {name: "book", weight: 30, value: 10}
|
||||
];
|
||||
|
||||
|
||||
// This is a bottom-up dynamic programming solution to the 0-1 knap-sack problem.
|
||||
// maximize value
|
||||
// subject to weights <= max_weight
|
||||
fn knap_01_dp<'a>(xs: &[Want<'a>], max_weight: uint) -> Vec<Want<'a>> {
|
||||
|
||||
// Save this value, so we don't have to make repeated calls.
|
||||
let xs_len = xs.len();
|
||||
|
||||
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
|
||||
// uint corresponding to the maximum cumulative value by considering 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: uint, max_weight: uint) -> uint{
|
||||
// fn best_value(item: usize, max_weight: usize) -> usize {
|
||||
// if item == 0 {
|
||||
// return 0;
|
||||
// }
|
||||
// if xs[item - 1].weight > max_weight {
|
||||
// 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 - xs[item - 1].weight)
|
||||
// + xs[item - 1].value);
|
||||
// best_value(item - 1, max_weight - items[item - 1].weight)
|
||||
// + items[item - 1].value);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// best_value(xs_len, max_weight) is equal to the maximum value that we
|
||||
// can add to the bag.
|
||||
// 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.
|
||||
// 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 zero_vec = Vec::from_elem(max_weight + 1, 0 as uint);
|
||||
let mut best_value = Vec::from_elem(xs_len + 1, zero_vec);
|
||||
let mut best_value = vec![vec![0usize; max_weight + 1]; items.len() + 1];
|
||||
|
||||
// loop over the items
|
||||
for i in range(0, xs_len) {
|
||||
// loop over the weights
|
||||
for w in range(1, max_weight + 1) {
|
||||
// do we have room in our knapsack?
|
||||
if xs[i].weight > w {
|
||||
// if we don't, then we'll say that the value doesn't change
|
||||
// when considering this item
|
||||
*best_value.get_mut(i + 1).get_mut(w) = best_value.get(i).get(w).clone();
|
||||
} else {
|
||||
// if we do, then we have to see if the value we gain by adding
|
||||
// the item, given the weight, is better than not adding the item
|
||||
*best_value.get_mut(i + 1).get_mut(w) =
|
||||
max(best_value.get(i).get(w).clone(),
|
||||
best_value.get(i).get(w - xs[i].weight) + xs[i].value);
|
||||
}
|
||||
// Loop over the items.
|
||||
for (i, it) in items.iter().enumerate() {
|
||||
// Loop over the weights.
|
||||
for w in 1 .. max_weight + 1 {
|
||||
best_value[i + 1][w] =
|
||||
// do we have room in our knapsack?
|
||||
if it.weight > w {
|
||||
// if we don't, then we'll say that the value doesn't change
|
||||
// when considering this item
|
||||
best_value[i][w].clone()
|
||||
} else {
|
||||
// If we do, then we have to see if the value we gain by adding
|
||||
// the item, given the weight, is better than not adding the item.
|
||||
max(best_value[i][w].clone(), best_value[i][w - it.weight] + it.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// a variable representing the weight left in the bag
|
||||
// A possibly over-allocated dynamically sized vector to push results to.
|
||||
let mut result = Vec::with_capacity(items.len());
|
||||
|
||||
// Variable representing the weight left in the bag
|
||||
let mut left_weight = max_weight.clone();
|
||||
|
||||
// a possibly over-allocated dynamically sized vector to push results to
|
||||
let mut result = Vec::with_capacity(xs_len);
|
||||
|
||||
// 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 in range(1, xs_len+1).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.get(i).get(left_weight) != best_value.get(i - 1).get(left_weight) {
|
||||
result.push(xs[i - 1]);
|
||||
// we remove the weight of the object from the remaining weight
|
||||
// we can add to the bag
|
||||
left_weight -= xs[i - 1].weight;
|
||||
// We built up the solution space through a forward pass over the data,
|
||||
// now we have to traverse backwards to get the solution.
|
||||
for (i, it) in items.iter().enumerate().rev() {
|
||||
// We can check if an item should be added to the knap-sack by
|
||||
// comparing best_value with and without this item. If best_value
|
||||
// added this item then so should we.
|
||||
if best_value[i + 1][left_weight] != best_value[i][left_weight] {
|
||||
result.push(it.clone());
|
||||
// We remove the weight of the object from the remaining weight
|
||||
// we can add to the bag.
|
||||
left_weight -= it.weight;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
fn main () {
|
||||
let xs = knap_01_dp(items, 400);
|
||||
const MAX_WEIGHT: usize = 400;
|
||||
|
||||
// Print the items. We have to reverse the order because we solved the
|
||||
// problem backward.
|
||||
for i in xs.iter().rev() {
|
||||
println!("Item: {}, Weight: {}, Value: {}", i.name, i.weight, i.value);
|
||||
// Static immutable allocation of our items.
|
||||
static ITEMS: &'static [Item<'static>] = &[
|
||||
// Too much repetition of field names here!
|
||||
Item { name: "map", weight: 9, value: 150 },
|
||||
Item { name: "compass", weight: 13, value: 35 },
|
||||
Item { name: "water", weight: 153, value: 200 },
|
||||
Item { name: "sandwich", weight: 50, value: 160 },
|
||||
Item { name: "glucose", weight: 15, value: 60 },
|
||||
Item { name: "tin", weight: 68, value: 45 },
|
||||
Item { name: "banana", weight: 27, value: 60 },
|
||||
Item { name: "apple", weight: 39, value: 40 },
|
||||
Item { name: "cheese", weight: 23, value: 30 },
|
||||
Item { name: "beer", weight: 52, value: 10 },
|
||||
Item { name: "suntancream", weight: 11, value: 70 },
|
||||
Item { name: "camera", weight: 32, value: 30 },
|
||||
Item { name: "T-shirt", weight: 24, value: 15 },
|
||||
Item { name: "trousers", weight: 48, value: 10 },
|
||||
Item { name: "umbrella", weight: 73, value: 40 },
|
||||
Item { name: "waterproof trousers", weight: 42, value: 70 },
|
||||
Item { name: "waterproof overclothes", weight: 43, value: 75 },
|
||||
Item { name: "note-case", weight: 22, value: 80 },
|
||||
Item { name: "sunglasses", weight: 7, value: 20 },
|
||||
Item { name: "towel", weight: 18, value: 12 },
|
||||
Item { name: "socks", weight: 4, value: 50 },
|
||||
Item { name: "book", weight: 30, value: 10 }
|
||||
];
|
||||
|
||||
let items = knapsack01_dyn(ITEMS, MAX_WEIGHT);
|
||||
|
||||
// We reverse the order because we solved the problem backward.
|
||||
for it in items.iter().rev() {
|
||||
println!("{:?}", it);
|
||||
}
|
||||
|
||||
// Print the sum of weights.
|
||||
let weights = xs.iter().fold(0, |a, &b| a + b.weight);
|
||||
println!("Total Weight: {}", weights);
|
||||
|
||||
// Print the sum of the values.
|
||||
let values = xs.iter().fold(0, |a, &b| a + b.value);
|
||||
println!("Total Value: {}", values);
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue