Rebol3 Code Examplex
Knapsack problem/0-1
Choose a maximum-value set without reuse.
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]