1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- #!/usr/bin/ruby
- #
- ## https://rosettacode.org/wiki/Knapsack_problem/Bounded
- #
- var raw = <<'TABLE'
- map 9 150 1
- compass 13 35 1
- water 153 200 2
- sandwich 50 60 2
- glucose 15 60 2
- tin 68 45 3
- banana 27 60 3
- apple 39 40 3
- cheese 23 30 1
- beer 52 10 1
- suntancream 11 70 1
- camera 32 30 1
- T-shirt 24 15 2
- trousers 48 10 2
- umbrella 73 40 1
- w_trousers 42 70 1
- w_overcoat 43 75 1
- note-case 22 80 1
- sunglasses 7 20 1
- towel 18 12 2
- socks 4 50 1
- book 30 10 2
- TABLE
- struct KnapsackItem {
- String name,
- Number weight,
- Number value,
- Number quant,
- }
- var items = []
- raw.each_line{ |row|
- var fields = row.words;
- items << KnapsackItem(
- name: fields[0],
- weight: fields[1].to_n,
- value: fields[2].to_n,
- quant: fields[3].to_n,
- )
- }
- func pick(weight, pos) is cached {
- if (pos.is_neg || weight.is_neg || weight.is_zero) {
- return (0, 0, [])
- }
- var (bv=0, bi=0, bw=0, bp=[])
- var item = items[pos];
- for i in range(0, item.quant) {
- break if (i*item.weight > weight)
- var (v, w, p) = pick(weight - i*item.weight, pos.dec)
- next if ((v += i*item.value) <= bv)
- (bv, bi, bw, bp) = (v, i, w, p)
- }
- (bv, bw + bi*item.weight, [bp..., bi])
- }
- var (v, w, p) = pick(400, items.end)
- p.range.each { |i|
- say "#{p[i]} of #{items[i].name}" if p[i].is_pos
- }
- say "Value: #{v}; Weight: #{w}"
|