Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
|
|
@ -1,4 +1,9 @@
|
|||
A tourist wants to make a good trip at the weekend with his friends. They will go to the mountains to see the wonders of nature, so he needs to pack well for the trip. He has a good knapsack for carrying things, but knows that he can carry a maximum of only 4kg in it and it will have to last the whole day. He creates a list of what he wants to bring for the trip but the total weight of all items is too much. He then decides to add columns to his initial list detailing their weights and a numerical value representing how important the item is for the trip.
|
||||
{{omit from|GUISS}}
|
||||
A tourist wants to make a good trip at the weekend with his friends.
|
||||
They will go to the mountains to see the wonders of nature, so he needs to pack well for the trip.
|
||||
He has a good knapsack for carrying things, but knows that he can carry a maximum of only 4kg in it and it will have to last the whole day.
|
||||
He creates a list of what he wants to bring for the trip but the total weight of all items is too much.
|
||||
He then decides to add columns to his initial list detailing their weights and a numerical value representing how important the item is for the trip.
|
||||
|
||||
Here is the list:
|
||||
|
||||
|
|
@ -54,9 +59,13 @@ Here is the list:
|
|||
| knapsack || ≤400 dag || ?
|
||||
|}
|
||||
|
||||
The tourist can choose to take any combination of items from the list, but only one of each item is available. He may not cut or diminish the items, so he can only take whole units of any item.
|
||||
The tourist can choose to take any combination of items from the list,
|
||||
but only one of each item is available.
|
||||
He may not cut or diminish the items, so he can only take whole units of any item.
|
||||
|
||||
'''Which items does the tourist carry in his knapsack so that their total weight does not exceed 400 dag [4 kg], and their total value is maximised?'''
|
||||
'''Which items does the tourist carry in his knapsack
|
||||
so that their total weight does not exceed 400 dag [4 kg],
|
||||
and their total value is maximised?'''
|
||||
|
||||
[dag = decagram = 10 grams]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
---
|
||||
category:
|
||||
- Memoization
|
||||
- Puzzles
|
||||
note: Classic CS problems and programs
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import std.stdio, std.algorithm, std.typecons, std.array, std.range;
|
|||
|
||||
struct Item { string name; int weight, value; }
|
||||
|
||||
Item[] knapsack01DinamicProgramming(in Item[] items, in int limit)
|
||||
pure nothrow {
|
||||
Item[] knapsack01DinamicProgramming(immutable Item[] items, in int limit)
|
||||
pure nothrow @safe {
|
||||
auto tab = new int[][](items.length + 1, limit + 1);
|
||||
|
||||
foreach (immutable i, immutable it; items)
|
||||
|
|
@ -22,7 +22,7 @@ pure nothrow {
|
|||
return result;
|
||||
}
|
||||
|
||||
void main() {
|
||||
void main() @safe {
|
||||
enum int limit = 400;
|
||||
immutable Item[] items = [
|
||||
{"apple", 39, 40}, {"banana", 27, 60},
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ immutable Item[] items = [
|
|||
struct Solution { uint bits; int value; }
|
||||
static assert(items.length <= Solution.bits.sizeof * 8);
|
||||
|
||||
void solve(in int weight, in int idx, ref Solution s) pure nothrow {
|
||||
void solve(in int weight, in int idx, ref Solution s)
|
||||
pure nothrow @nogc @safe {
|
||||
if (idx < 0) {
|
||||
s.bits = s.value = 0;
|
||||
return;
|
||||
|
|
@ -38,8 +39,9 @@ void solve(in int weight, in int idx, ref Solution s) pure nothrow {
|
|||
s = (v1.value >= v2.value) ? v1 : v2;
|
||||
}
|
||||
|
||||
void main() {
|
||||
void main() @safe {
|
||||
import std.stdio;
|
||||
|
||||
auto s = Solution(0, 0);
|
||||
solve(400, items.length - 1, s);
|
||||
|
||||
|
|
@ -50,5 +52,5 @@ void main() {
|
|||
writeln(" ", it.name);
|
||||
w += it.weight;
|
||||
}
|
||||
writeln("\nTotal value: %d; weight: %d", s.value, w);
|
||||
writefln("\nTotal value: %d; weight: %d", s.value, w);
|
||||
}
|
||||
|
|
|
|||
202
Task/Knapsack-problem-0-1/JavaScript/knapsack-problem-0-1.js
Normal file
202
Task/Knapsack-problem-0-1/JavaScript/knapsack-problem-0-1.js
Normal 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
|
||||
]);
|
||||
});
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
global globalItems = #()
|
||||
global usedMass = 0
|
||||
global neededItems = #()
|
||||
global totalValue = 0
|
||||
struct kn_item
|
||||
(
|
||||
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")
|
||||
|
||||
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
|
||||
)
|
||||
)
|
||||
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
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
for i in neededitems do
|
||||
(
|
||||
format "Item name: %, weight: %, value:%\n" i.item i.weight i.value
|
||||
totalValue += i.value
|
||||
)
|
||||
format "Total mass: %, Total Value: %\n" usedMass totalValue
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
Item name: water, weight: 153, value:200
|
||||
Item name: sandwich, weight: 50, value:160
|
||||
Item name: map, weight: 9, value:150
|
||||
Item name: note-case, weight: 22, value:80
|
||||
Item name: waterproof overclothes, weight: 43, value:75
|
||||
Item name: suntan cream, weight: 11, value:70
|
||||
Item name: waterproof trousers, weight: 42, value:70
|
||||
Item name: glucose, weight: 15, value:60
|
||||
Item name: banana, weight: 27, value:60
|
||||
Item name: socks, weight: 4, value:50
|
||||
Item name: compass, weight: 13, value:35
|
||||
Item name: sunglasses, weight: 7, value:20
|
||||
OK
|
||||
Total mass: 396, Total Value: 1030
|
||||
OK
|
||||
|
|
@ -1,27 +1,26 @@
|
|||
/*REXX pgm solves a knapsack problem (22 items with weight restriction).*/
|
||||
@.=
|
||||
@.1 = 'map 9 150'
|
||||
@.2 = 'compass 13 35'
|
||||
@.3 = 'water 153 200'
|
||||
@.4 = 'sandwich 50 160'
|
||||
@.5 = 'glucose 15 60'
|
||||
@.6 = 'tin 68 45'
|
||||
@.7 = 'banana 27 60'
|
||||
@.8 = 'apple 39 40'
|
||||
@.9 = 'cheese 23 30'
|
||||
@.10 = 'beer 52 10'
|
||||
@.11 = 'suntan_cream 11 70'
|
||||
@.12 = 'camera 32 30'
|
||||
@.13 = 'T-shirt 24 15'
|
||||
@.14 = 'trousers 48 10'
|
||||
@.15 = 'umbrella 73 40'
|
||||
@.16 = 'waterproof_trousers 42 70'
|
||||
@.17 = 'waterproof_overclothes 43 75'
|
||||
@.18 = 'note-case 22 80'
|
||||
@.19 = 'sunglasses 7 20'
|
||||
@.20 = 'towel 18 12'
|
||||
@.21 = 'socks 4 50'
|
||||
@.22 = 'book 30 10'
|
||||
@.=; @.1 = 'map 9 150'
|
||||
@.2 = 'compass 13 35'
|
||||
@.3 = 'water 153 200'
|
||||
@.4 = 'sandwich 50 160'
|
||||
@.5 = 'glucose 15 60'
|
||||
@.6 = 'tin 68 45'
|
||||
@.7 = 'banana 27 60'
|
||||
@.8 = 'apple 39 40'
|
||||
@.9 = 'cheese 23 30'
|
||||
@.10 = 'beer 52 10'
|
||||
@.11 = 'suntan_cream 11 70'
|
||||
@.12 = 'camera 32 30'
|
||||
@.13 = 'T-shirt 24 15'
|
||||
@.14 = 'trousers 48 10'
|
||||
@.15 = 'umbrella 73 40'
|
||||
@.16 = 'waterproof_trousers 42 70'
|
||||
@.17 = 'waterproof_overclothes 43 75'
|
||||
@.18 = 'note-case 22 80'
|
||||
@.19 = 'sunglasses 7 20'
|
||||
@.20 = 'towel 18 12'
|
||||
@.21 = 'socks 4 50'
|
||||
@.22 = 'book 30 10'
|
||||
maxWeight=400 /*the maximum weight for knapsack*/
|
||||
say; say 'maximum weight allowed for a knapsack:' comma(maxWeight); say
|
||||
maxL=length('item') /*maximum width for table names. */
|
||||
|
|
@ -53,7 +52,7 @@ obj=j-1 /*adjust for the DO loop index. */
|
|||
highQ=max(highQ,q)
|
||||
items=items+1 /*bump the item counter. */
|
||||
i.items=item; w.items=w; v.items=v; q.items=q
|
||||
do k=2 to q; items=items+1 /*bump the item counter. */
|
||||
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
|
||||
end /*k*/
|
||||
|
|
@ -72,100 +71,72 @@ call hdr 'item'; do j=1 for obj /*show all choices, nice format. */
|
|||
end /*j*/
|
||||
|
||||
say; say 'number of items:' items; say
|
||||
/*─────────────────────────────────────examine 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
|
||||
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
|
||||
do k=j+1 to totP
|
||||
__=word(bestC,k); if i._\==i.__ then leave
|
||||
j=j+1; w._=w._+_w; v._=v._+_v; q=q+1
|
||||
end /*k*/
|
||||
call show i._,w._,v._,q; bestW=bestw+w._
|
||||
end /*j*/
|
||||
do j=1 to totP /*J is modified within DO loop. */
|
||||
_=word(bestC,j); _w=w._; _v=v._; q=1
|
||||
if _==0 then iterate
|
||||
do k=j+1 to totP
|
||||
__=word(bestC,k); if i._\==i.__ then leave
|
||||
j=j+1; w._=w._+_w; v._=v._+_v; q=q+1
|
||||
end /*k*/
|
||||
call show i._,w._,v._,q; bestW=bestw+w._
|
||||
end /*j*/
|
||||
call hdr2; say
|
||||
call show 'best weight' ,bestW /*show a nicely formatted winnerW*/
|
||||
call show 'best value' ,,bestV /*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);p=abs(o);t=word(t 999999999,1)
|
||||
if \datatype(p,'W')|\datatype(t,'W')|p==0|arg()>4 then return _;n=_'.9'
|
||||
#=123456789;k=0;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 _
|
||||
/*────────────────────────────────HDR subroutine────────────────────────*/
|
||||
/*────────────────────────────────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
|
||||
call show center(_item_ ,maxL), center('weight',maxW), center('value',maxV), center(_,maxQ)
|
||||
call hdr2; return
|
||||
/*────────────────────────────────HDR2 subroutine────────────────────────────────────────────────*/
|
||||
hdr2: _=maxQ; if highq==1 then _=0
|
||||
call show copies('=',maxL),copies('=',maxW),copies('=',maxV),copies('=',_)
|
||||
return
|
||||
/*────────────────────────────────HDR2 subroutine───────────────────────*/
|
||||
hdr2: _=maxQ; if highq==1 then _=0; call show copies('=' ,maxL),,
|
||||
copies('=' ,maxW),,
|
||||
copies('=' ,maxV),,
|
||||
copies('=' ,_ )
|
||||
return
|
||||
/*────────────────────────────────J? subroutine─────────────────────────*/
|
||||
j?: parse arg _,?; $=value('V'_); do j=1 for _; ?=? value('J'j); end; return
|
||||
/*────────────────────────────────J? subroutine────────────────────────────────────────*/
|
||||
j?: parse arg _,?; $=value('V'_); do j=1 for _; ?=? value('J'j); end; return
|
||||
/*────────────────────────────────SHOW subroutine───────────────────────*/
|
||||
show: parse arg _item,_weight,_value,_quant
|
||||
say translate(left(_item,maxL,'─'),,'_'),
|
||||
right(comma(_weight),maxW),
|
||||
right(comma(_value ),maxV),
|
||||
right(comma(_quant ),maxQ)
|
||||
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
|
||||
do j2=j1+(j1\==0) to h
|
||||
if w.j2+w1>m then iterate j1;w2=w1+w.j2;v2=v1+v.j2;if v2>$ then call j? 2
|
||||
do j3=j2+(j2\==0) to h
|
||||
if w.j3+w2>m then iterate j2;w3=w2+w.j3;v3=v2+v.j3;if v3>$ then call j? 3
|
||||
do j4=j3+(j3\==0) to h
|
||||
if w.j4+w3>m then iterate j3;w4=w3+w.j4;v4=v3+v.j4;if v4>$ then call j? 4
|
||||
do j5=j4+(j4\==0) to h
|
||||
if w.j5+w4>m then iterate j4;w5=w4+w.j5;v5=v4+v.j5;if v5>$ then call j? 5
|
||||
do j6=j5+(j5\==0) to h
|
||||
if w.j6+w5>m then iterate j5;w6=w5+w.j6;v6=v5+v.j6;if v6>$ then call j? 6
|
||||
do j7=j6+(j6\==0) to h
|
||||
if w.j7+w6>m then iterate j6;w7=w6+w.j7;v7=v6+v.j7;if v7>$ then call j? 7
|
||||
do j8=j7+(j7\==0) to h
|
||||
if w.j8+w7>m then iterate j7;w8=w7+w.j8;v8=v7+v.j8;if v8>$ then call j? 8
|
||||
do j9=j8+(j8\==0) to h
|
||||
if w.j9+w8>m then iterate j8;w9=w8+w.j9;v9=v8+v.j9;if v9>$ then call j? 9
|
||||
do j10=j9+(j9\==0) to h
|
||||
if w.j10+w9>m then iterate j9;w10=w9+w.j10;v10=v9+v.j10;if v10>$ then call j? 10
|
||||
do j11=j10+(j10\==0) to h
|
||||
if w.j11+w10>m then iterate j10;w11=w10+w.j11;v11=v10+v.j11;if v11>$ then call j? 11
|
||||
do j12=j11+(j11\==0) to h
|
||||
if w.j12+w11>m then iterate j11;w12=w11+w.j12;v12=v11+v.j12;if v12>$ then call j? 12
|
||||
do j13=j12+(j12\==0) to h
|
||||
if w.j13+w12>m then iterate j12;w13=w12+w.j13;v13=v12+v.j13;if v13>$ then call j? 13
|
||||
do j14=j13+(j13\==0) to h
|
||||
if w.j14+w13>m then iterate j13;w14=w13+w.j14;v14=v13+v.j14;if v14>$ then call j? 14
|
||||
do j15=j14+(j14\==0) to h
|
||||
if w.j15+w14>m then iterate j14;w15=w14+w.j15;v15=v14+v.j15;if v15>$ then call j? 15
|
||||
do j16=j15+(j15\==0) to h
|
||||
if w.j16+w15>m then iterate j15;w16=w15+w.j16;v16=v15+v.j16;if v16>$ then call j? 16
|
||||
do j17=j16+(j16\==0) to h
|
||||
if w.j17+w16>m then iterate j16;w17=w16+w.j17;v17=v16+v.j17;if v17>$ then call j? 17
|
||||
do j18=j17+(j17\==0) to h
|
||||
if w.j18+w17>m then iterate j17;w18=w17+w.j18;v18=v17+v.j18;if v18>$ then call j? 18
|
||||
do j19=j18+(j18\==0) to h
|
||||
if w.j19+w18>m then iterate j18;w19=w18+w.j19;v19=v18+v.j19;if v19>$ then call j? 19
|
||||
do j20=j19+(j19\==0) to h
|
||||
if w.j20+w19>m then iterate j19;w20=w19+w.j20;v20=v19+v.j20;if v20>$ then call j? 20
|
||||
do j21=j20+(j20\==0) to h
|
||||
if w.j21+w20>m then iterate j20;w21=w20+w.j21;v21=v20+v.j21;if v21>$ then call j? 21
|
||||
do j22=j21+(j21\==0) to h
|
||||
if w.j22+w21>m then iterate j21;w22=w21+w.j22;v22=v21+v.j22;if v22>$ then call j? 22
|
||||
end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end
|
||||
/*────────────────────────────────SIM22 subroutine───────────────────────────────────────────────────────────*/
|
||||
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
|
||||
do j5 =j4 +(j4 \==0) to h;if w.j5 +w4>m then iterate j4; w5 =w4 +w.j5; v5 =v4 +v.j5; if v5>$ then call j? 5
|
||||
do j6 =j5 +(j5 \==0) to h;if w.j6 +w5>m then iterate j5; w6 =w5 +w.j6; v6 =v5 +v.j6; if v6>$ then call j? 6
|
||||
do j7 =j6 +(j6 \==0) to h;if w.j7 +w6>m then iterate j6; w7 =w6 +w.j7; v7 =v6 +v.j7; if v7>$ then call j? 7
|
||||
do j8 =j7 +(j7 \==0) to h;if w.j8 +w7>m then iterate j7; w8 =w7 +w.j8; v8 =v7 +v.j8; if v8>$ then call j? 8
|
||||
do j9 =j8 +(j8 \==0) to h;if w.j9 +w8>m then iterate j8; w9 =w8 +w.j9; v9 =v8 +v.j9; if v9>$ then call j? 9
|
||||
do j10=j9 +(j9 \==0) to h;if w.j10+w9>m then iterate j9; w10=w9 +w.j10;v10=v9 +v.j10;if v10>$ then call j? 10
|
||||
do j11=j10+(j10\==0) to h;if w.j11+w10>m then iterate j10;w11=w10+w.j11;v11=v10+v.j11;if v11>$ then call j? 11
|
||||
do j12=j11+(j11\==0) to h;if w.j12+w11>m then iterate j11;w12=w11+w.j12;v12=v11+v.j12;if v12>$ then call j? 12
|
||||
do j13=j12+(j12\==0) to h;if w.j13+w12>m then iterate j12;w13=w12+w.j13;v13=v12+v.j13;if v13>$ then call j? 13
|
||||
do j14=j13+(j13\==0) to h;if w.j14+w13>m then iterate j13;w14=w13+w.j14;v14=v13+v.j14;if v14>$ then call j? 14
|
||||
do j15=j14+(j14\==0) to h;if w.j15+w14>m then iterate j14;w15=w14+w.j15;v15=v14+v.j15;if v15>$ then call j? 15
|
||||
do j16=j15+(j15\==0) to h;if w.j16+w15>m then iterate j15;w16=w15+w.j16;v16=v15+v.j16;if v16>$ then call j? 16
|
||||
do j17=j16+(j16\==0) to h;if w.j17+w16>m then iterate j16;w17=w16+w.j17;v17=v16+v.j17;if v17>$ then call j? 17
|
||||
do j18=j17+(j17\==0) to h;if w.j18+w17>m then iterate j17;w18=w17+w.j18;v18=v17+v.j18;if v18>$ then call j? 18
|
||||
do j19=j18+(j18\==0) to h;if w.j19+w18>m then iterate j18;w19=w18+w.j19;v19=v18+v.j19;if v19>$ then call j? 19
|
||||
do j20=j19+(j19\==0) to h;if w.j20+w19>m then iterate j19;w20=w19+w.j20;v20=v19+v.j20;if v20>$ then call j? 20
|
||||
do j21=j20+(j20\==0) to h;if w.j21+w20>m then iterate j20;w21=w20+w.j21;v21=v20+v.j21;if v21>$ then call j? 21
|
||||
do j22=j21+(j21\==0) to h;if w.j22+w21>m then iterate j21;w22=w21+w.j22;v22=v21+v.j22;if v22>$ then call j? 22
|
||||
end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end; end
|
||||
return
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
KnapsackItem = Struct.new(:name, :weight, :value)
|
||||
potential_items = [
|
||||
KnapsackItem.new('map', 9, 150), KnapsackItem.new('compass', 13, 35),
|
||||
KnapsackItem.new('water', 153, 200), KnapsackItem.new('sandwich', 50, 160),
|
||||
KnapsackItem.new('glucose', 15, 60), KnapsackItem.new('tin', 68, 45),
|
||||
KnapsackItem.new('banana', 27, 60), KnapsackItem.new('apple', 39, 40),
|
||||
KnapsackItem.new('cheese', 23, 30), KnapsackItem.new('beer', 52, 10),
|
||||
KnapsackItem.new('suntan cream', 11, 70), KnapsackItem.new('camera', 32, 30),
|
||||
KnapsackItem.new('t-shirt', 24, 15), KnapsackItem.new('trousers', 48, 10),
|
||||
KnapsackItem.new('umbrella', 73, 40), KnapsackItem.new('waterproof trousers', 42, 70),
|
||||
KnapsackItem.new('waterproof overclothes', 43, 75), KnapsackItem.new('note-case', 22, 80),
|
||||
KnapsackItem.new('sunglasses', 7, 20), KnapsackItem.new('towel', 18, 12),
|
||||
KnapsackItem.new('socks', 4, 50), KnapsackItem.new('book', 30, 10),
|
||||
KnapsackItem['map', 9, 150], KnapsackItem['compass', 13, 35],
|
||||
KnapsackItem['water', 153, 200], KnapsackItem['sandwich', 50, 160],
|
||||
KnapsackItem['glucose', 15, 60], KnapsackItem['tin', 68, 45],
|
||||
KnapsackItem['banana', 27, 60], KnapsackItem['apple', 39, 40],
|
||||
KnapsackItem['cheese', 23, 30], KnapsackItem['beer', 52, 10],
|
||||
KnapsackItem['suntan cream', 11, 70], KnapsackItem['camera', 32, 30],
|
||||
KnapsackItem['t-shirt', 24, 15], KnapsackItem['trousers', 48, 10],
|
||||
KnapsackItem['umbrella', 73, 40], KnapsackItem['waterproof trousers', 42, 70],
|
||||
KnapsackItem['waterproof overclothes', 43, 75], KnapsackItem['note-case', 22, 80],
|
||||
KnapsackItem['sunglasses', 7, 20], KnapsackItem['towel', 18, 12],
|
||||
KnapsackItem['socks', 4, 50], KnapsackItem['book', 30, 10],
|
||||
]
|
||||
knapsack_capacity = 400
|
||||
|
||||
|
|
@ -19,39 +19,25 @@ class Array
|
|||
def power_set
|
||||
yield [] if block_given?
|
||||
self.inject([[]]) do |ps, elem|
|
||||
r = []
|
||||
ps.each do |i|
|
||||
ps.each_with_object([]) do |i,r|
|
||||
r << i
|
||||
new_subset = i + [elem]
|
||||
yield new_subset if block_given?
|
||||
r << new_subset
|
||||
end
|
||||
r
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
maxval = 0
|
||||
solutions = []
|
||||
|
||||
potential_items.power_set do |subset|
|
||||
weight = subset.inject(0) {|w, elem| w += elem.weight}
|
||||
next if weight > knapsack_capacity
|
||||
|
||||
value = subset.inject(0) {|v, elem| v += elem.value}
|
||||
if value == maxval
|
||||
solutions << subset
|
||||
elsif value > maxval
|
||||
maxval = value
|
||||
solutions = [subset]
|
||||
end
|
||||
end
|
||||
maxval, solutions = potential_items.power_set.group_by {|subset|
|
||||
weight = subset.inject(0) {|w, elem| w + elem.weight}
|
||||
weight>knapsack_capacity ? 0 : subset.inject(0){|v, elem| v + elem.value}
|
||||
}.max
|
||||
|
||||
puts "value: #{maxval}"
|
||||
solutions.each do |set|
|
||||
items = []
|
||||
wt = 0
|
||||
wt, items = 0, []
|
||||
set.each {|elem| wt += elem.weight; items << elem.name}
|
||||
puts "weight: #{wt}"
|
||||
puts "items: #{items.sort.join(',')}"
|
||||
puts "items: #{items.join(',')}"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,84 +1,63 @@
|
|||
KnapsackItem = Struct.new(:name, :cost, :value)
|
||||
KnapsackProblem = Struct.new(:items, :max_cost)
|
||||
KnapsackItem = Struct.new(:name, :weight, :value)
|
||||
|
||||
def dynamic_programming_knapsack(problem)
|
||||
num_items = problem.items.size
|
||||
items = problem.items
|
||||
max_cost = problem.max_cost
|
||||
|
||||
cost_matrix = zeros(num_items, max_cost+1)
|
||||
def dynamic_programming_knapsack(items, max_weight)
|
||||
num_items = items.size
|
||||
cost_matrix = Array.new(num_items){Array.new(max_weight+1, 0)}
|
||||
|
||||
num_items.times do |i|
|
||||
(max_cost + 1).times do |j|
|
||||
if(items[i].cost > j)
|
||||
(max_weight + 1).times do |j|
|
||||
if(items[i].weight > j)
|
||||
cost_matrix[i][j] = cost_matrix[i-1][j]
|
||||
else
|
||||
cost_matrix[i][j] = [cost_matrix[i-1][j], items[i].value + cost_matrix[i-1][j-items[i].cost]].max
|
||||
cost_matrix[i][j] = [cost_matrix[i-1][j], items[i].value + cost_matrix[i-1][j-items[i].weight]].max
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cost_matrix
|
||||
used_items = get_used_items(items, cost_matrix)
|
||||
[get_list_of_used_items_names(items, used_items), # used items names
|
||||
items.zip(used_items).map{|item,used| item.weight*used}.inject(:+), # total weight
|
||||
cost_matrix.last.last] # total value
|
||||
end
|
||||
|
||||
def get_used_items(problem, cost_matrix)
|
||||
def get_used_items(items, cost_matrix)
|
||||
i = cost_matrix.size - 1
|
||||
currentCost = cost_matrix[0].size - 1
|
||||
marked = Array.new(cost_matrix.size, 0)
|
||||
marked = cost_matrix.map{0}
|
||||
|
||||
while(i >= 0 && currentCost >= 0)
|
||||
if(i == 0 && cost_matrix[i][currentCost] > 0 ) || (cost_matrix[i][currentCost] != cost_matrix[i-1][currentCost])
|
||||
marked[i] = 1
|
||||
currentCost -= problem.items[i].cost
|
||||
currentCost -= items[i].weight
|
||||
end
|
||||
i -= 1
|
||||
end
|
||||
marked
|
||||
end
|
||||
|
||||
def get_list_of_used_items_names(problem, cost_matrix)
|
||||
items = problem.items
|
||||
used_items = get_used_items(problem, cost_matrix)
|
||||
|
||||
result = []
|
||||
|
||||
used_items.each_with_index do |item,i|
|
||||
if item > 0
|
||||
result << items[i].name
|
||||
end
|
||||
end
|
||||
|
||||
result.sort.join(', ')
|
||||
end
|
||||
|
||||
def zeros(rows, cols)
|
||||
Array.new(rows) do |row|
|
||||
Array.new(cols, 0)
|
||||
end
|
||||
def get_list_of_used_items_names(items, used_items)
|
||||
items.zip(used_items).map{|item,used| item.name if used>0}.compact.join(', ')
|
||||
end
|
||||
|
||||
if $0 == __FILE__
|
||||
items = [
|
||||
KnapsackItem['map' , 9, 150], KnapsackItem['compass' , 13, 35],
|
||||
KnapsackItem['water' , 153, 200], KnapsackItem['sandwich' , 50, 160],
|
||||
KnapsackItem['glucose' , 15, 60], KnapsackItem['tin' , 68, 45],
|
||||
KnapsackItem['banana' , 27, 60], KnapsackItem['apple' , 39, 40],
|
||||
KnapsackItem['cheese' , 23, 30], KnapsackItem['beer' , 52, 10],
|
||||
KnapsackItem['suntan cream' , 11, 70], KnapsackItem['camera' , 32, 30],
|
||||
KnapsackItem['t-shirt' , 24, 15], KnapsackItem['trousers' , 48, 10],
|
||||
KnapsackItem['umbrella' , 73, 40], KnapsackItem['waterproof trousers', 42, 70],
|
||||
KnapsackItem['waterproof overclothes', 43, 75], KnapsackItem['note-case' , 22, 80],
|
||||
KnapsackItem['sunglasses' , 7, 20], KnapsackItem['towel' , 18, 12],
|
||||
KnapsackItem['socks' , 4, 50], KnapsackItem['book' , 30, 10]
|
||||
]
|
||||
|
||||
items = [
|
||||
KnapsackItem.new('map' , 9 , 150) , KnapsackItem.new('compass' , 13 , 35) ,
|
||||
KnapsackItem.new('water' , 153 , 200) , KnapsackItem.new('sandwich' , 50 , 160) ,
|
||||
KnapsackItem.new('glucose' , 15 , 60) , KnapsackItem.new('tin' , 68 , 45) ,
|
||||
KnapsackItem.new('banana' , 27 , 60) , KnapsackItem.new('apple' , 39 , 40) ,
|
||||
KnapsackItem.new('cheese' , 23 , 30) , KnapsackItem.new('beer' , 52 , 10) ,
|
||||
KnapsackItem.new('suntan cream' , 11 , 70) , KnapsackItem.new('camera' , 32 , 30) ,
|
||||
KnapsackItem.new('t-shirt' , 24 , 15) , KnapsackItem.new('trousers' , 48 , 10) ,
|
||||
KnapsackItem.new('umbrella' , 73 , 40) , KnapsackItem.new('waterproof trousers' , 42 , 70) ,
|
||||
KnapsackItem.new('waterproof overclothes' , 43 , 75) , KnapsackItem.new('note-case' , 22 , 80) ,
|
||||
KnapsackItem.new('sunglasses' , 7 , 20) , KnapsackItem.new('towel' , 18 , 12) ,
|
||||
KnapsackItem.new('socks' , 4 , 50) , KnapsackItem.new('book' , 30 , 10)
|
||||
]
|
||||
|
||||
problem = KnapsackProblem.new(items, 400)
|
||||
|
||||
cost_matrix = dynamic_programming_knapsack problem
|
||||
names, weight, value = dynamic_programming_knapsack(items, 400)
|
||||
puts
|
||||
puts 'Dynamic Programming:'
|
||||
puts
|
||||
puts 'Found solution: ' + get_list_of_used_items_names(problem, cost_matrix)
|
||||
puts 'With value: ' + cost_matrix.last.last.to_s
|
||||
puts "Found solution: #{names}"
|
||||
puts "total weight: #{weight}"
|
||||
puts "total value: #{value}"
|
||||
end
|
||||
|
|
|
|||
140
Task/Knapsack-problem-0-1/Rust/knapsack-problem-0-1.rust
Normal file
140
Task/Knapsack-problem-0-1/Rust/knapsack-problem-0-1.rust
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
extern crate std;
|
||||
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> {
|
||||
name: &'a str,
|
||||
weight: uint,
|
||||
value: uint
|
||||
}
|
||||
|
||||
|
||||
// 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();
|
||||
|
||||
// Imagine we wrote a recursive function(item, max_weight) that returns a
|
||||
// uint 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{
|
||||
// if item == 0 {
|
||||
// return 0;
|
||||
// }
|
||||
// if xs[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(xs_len, max_weight) is equal to the maximum value that we
|
||||
// can add to the bag.
|
||||
//
|
||||
// The problem with using this function is that it performs redundant
|
||||
// calculations.
|
||||
//
|
||||
// The dynamic programming solution is to precompute all of the values we
|
||||
// need and put them into a 2D array.
|
||||
//
|
||||
// In a similar vein, the top-down solution would be to memoize the
|
||||
// function then compute the results on demand.
|
||||
|
||||
let zero_vec = Vec::from_elem(max_weight + 1, 0 as uint);
|
||||
let mut best_value = Vec::from_elem(xs_len + 1, zero_vec);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// a 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;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
fn main () {
|
||||
let xs = knap_01_dp(items, 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
}
|
||||
|
|
@ -10,7 +10,14 @@ object Knapsack extends App {
|
|||
val tv:Set[Item]=>Int=ps=>(ps:\0)((a,b)=>a.value+b) //total value
|
||||
val pis = (loi.toSet.subsets).toList.filterNot(_==Set())
|
||||
|
||||
val res = pis.map(ss=>Pair(ss,tw(ss)))
|
||||
#[test]
|
||||
fn test_dp_results() {
|
||||
let dp_results = knap_01_dp(items, 400);
|
||||
let dp_weights= dp_results.iter().fold(0, |a, &b| a + b.weight);
|
||||
let dp_values = dp_results.iter().fold(0, |a, &b| a + b.value);
|
||||
assert_eq!(dp_weights, 396);
|
||||
assert_eq!(dp_values, 1030);
|
||||
} val res = pis.map(ss=>Pair(ss,tw(ss)))
|
||||
.filter(p=>p._2>350 && p._2<401).map(p=>Pair(p,tv(p._1)))
|
||||
.sortWith((s,t)=>s._2.compareTo(t._2) < 0)
|
||||
.last
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue