Data update
This commit is contained in:
parent
4bb20c9b71
commit
cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions
|
|
@ -0,0 +1,112 @@
|
|||
Rebol [
|
||||
title: "Rosetta code: Knapsack problem/Bounded"
|
||||
file: %Knapsack_problem-Bounded.r3
|
||||
url: https://rosettacode.org/wiki/Knapsack_problem/Bounded
|
||||
]
|
||||
|
||||
solve-knapsack: function/with [
|
||||
"Solves the bounded knapsack problem via top-down dynamic programming."
|
||||
limit [integer!] "remaining weight capacity"
|
||||
pos [integer!] "current item index (0-based)"
|
||||
][
|
||||
;; Returns a 3-element block [value weight taken] where `taken` is a
|
||||
;; block of per-item counts (parallel to `items`) representing the
|
||||
;; optimal selection, or none if nothing fits.
|
||||
|
||||
;; Results are memoised in `cache` keyed by "limit,pos" so each
|
||||
;; sub-problem is solved at most once.
|
||||
|
||||
if any [pos < 0 limit <= 0] [ ;; base case: no items or no capacity
|
||||
return reduce [0 0 none]
|
||||
]
|
||||
|
||||
key-str: rejoin [limit "," pos]
|
||||
if cached: cache/:key-str [ return cached ] ;; memoisation hit
|
||||
|
||||
item: items/(pos + 1) ;; [name weight value max-qty]
|
||||
best-value: 0
|
||||
best-weight: 0
|
||||
best-count: 0
|
||||
best-taken: none
|
||||
|
||||
taken: 0
|
||||
while [all [taken * item/2 <= limit taken <= item/4]] [ ;; try 0..max-qty copies
|
||||
sub: solve-knapsack (limit - (taken * item/2)) (pos - 1) ;; best for remaining items
|
||||
sub-value: sub/1
|
||||
sub-weight: sub/2
|
||||
sub-taken: sub/3
|
||||
candidate-value: sub-value + (taken * item/3)
|
||||
if candidate-value > best-value [ ;; keep best combination found so far
|
||||
best-value: candidate-value
|
||||
best-weight: sub-weight
|
||||
best-count: taken
|
||||
best-taken: sub-taken
|
||||
]
|
||||
++ taken
|
||||
]
|
||||
|
||||
if best-count > 0 [
|
||||
new-taken: make block! num-items ;; copy before mutating to avoid aliasing cached entries
|
||||
repeat k num-items [append new-taken 0]
|
||||
if block? best-taken [
|
||||
repeat k num-items [new-taken/:k: best-taken/:k]
|
||||
]
|
||||
new-taken/(pos + 1): best-count ;; record how many of this item we take
|
||||
best-weight: best-weight + (best-count * item/2)
|
||||
best-taken: new-taken
|
||||
]
|
||||
|
||||
result: reduce [best-value best-weight best-taken]
|
||||
cache/(key-str): result ;; store [value weight taken-counts] in memo
|
||||
result
|
||||
][
|
||||
cache: make map! 2000 ;; memoisation table, shared across calls
|
||||
]
|
||||
|
||||
items: [
|
||||
["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 3]
|
||||
["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-overclothes" 43 75 1]
|
||||
["note-case" 22 80 1]
|
||||
["sunglasses" 7 20 1]
|
||||
["towel" 18 12 2]
|
||||
["socks" 4 50 1]
|
||||
["book" 30 10 2]
|
||||
]
|
||||
item-name: func [item] [item/1]
|
||||
item-weight: func [item] [item/2]
|
||||
item-value: func [item] [item/3]
|
||||
item-limit: func [item] [item/4]
|
||||
|
||||
num-items: length? items
|
||||
result: solve-knapsack 400 (num-items - 1)
|
||||
|
||||
total-value: result/1
|
||||
total-weight: result/2
|
||||
taken: result/3
|
||||
|
||||
print "Taking:"
|
||||
if block? taken [
|
||||
repeat i num-items [
|
||||
count: pick taken i
|
||||
if count > 0 [
|
||||
item: pick items i
|
||||
print [" " count "of" item-limit item " " item-name item]
|
||||
]
|
||||
]
|
||||
]
|
||||
print ajoin ["Value: " total-value "; weight: " total-weight]
|
||||
Loading…
Add table
Add a link
Reference in a new issue