September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -39,8 +39,11 @@ This is the item list in the butcher's shop:
Show which items the thief carries in his knapsack so that their total weight does not exceed 15 kg, and their total value is maximized.
;Related task:
*   [[Knapsack problem]]
;Related tasks:
*   [[Knapsack problem/Bounded]]
*   [[Knapsack problem/Unbounded]]
*   [[Knapsack problem/0-1]]
<br><br>
;See also:

View file

@ -0,0 +1,42 @@
# syntax: GAWK -f KNAPSACK_PROBLEM_CONTINUOUS.AWK
BEGIN {
# arr["item,weight,price"]
arr["beef,3.8,36"]
arr["pork,5.4,43"]
arr["ham,3.6,90"]
arr["greaves,2.4,45"]
arr["flitch,4.0,30"]
arr["brawn,2.5,56"]
arr["welt,3.7,67"]
arr["salami,3.0,95"]
arr["sausage,5.9,98"]
for (i in arr) {
split(i,tmp,",")
arr[i] = tmp[3] / tmp[2] # $/unit
}
sack_size = 15 # kg
PROCINFO["sorted_in"] = "@val_num_desc"
print("item weight price $/unit")
for (i in arr) {
if (total_weight >= sack_size) {
break
}
split(i,tmp,",")
weight = tmp[2]
if (total_weight + weight <= sack_size) {
price = tmp[3]
msg = "all"
}
else {
weight = sack_size - total_weight
price = weight * arr[i]
msg = weight " of " tmp[2]
}
printf("%-7s %6.2f %6.2f %6.2f take %s\n",tmp[1],weight,tmp[3],arr[i],msg)
total_items++
total_price += price
total_weight += weight
}
printf("%7d %6.2f %6.2f total\n",total_items,total_weight,total_price)
exit(0)
}

View file

@ -0,0 +1,28 @@
(defstruct item
(name nil :type string)
(weight nil :type real)
(price nil :type real))
(defun price-per-weight (item)
(/ (item-price item) (item-weight item)))
(defun knapsack (items total-weight)
(loop with sorted = (sort items #'> :key #'price-per-weight)
while (plusp total-weight)
for item in sorted
for amount = (min (item-weight item) total-weight)
collect (list (item-name item) amount)
do (decf total-weight amount)))
(defun main ()
(let ((items (list (make-item :name "beef" :weight 3.8 :price 36)
(make-item :name "pork" :weight 5.4 :price 43)
(make-item :name "ham" :weight 3.6 :price 90)
(make-item :name "greaves" :weight 2.4 :price 45)
(make-item :name "flitch" :weight 4.0 :price 30)
(make-item :name "brawn" :weight 2.5 :price 56)
(make-item :name "welt" :weight 3.7 :price 67)
(make-item :name "salami" :weight 3.0 :price 95)
(make-item :name "sausage" :weight 5.9 :price 98))))
(loop for (name amount) in (knapsack items 15)
do (format t "~8A: ~,2F kg~%" name amount))))

View file

@ -1,40 +1,49 @@
import Control.Monad
import Data.List (sortBy)
import Data.Ord (comparing)
import Text.Printf (printf)
import Control.Monad (forM_)
import Data.Ratio (numerator, denominator)
import Text.Printf
maxWgt :: Rational
maxWgt = 15
data Bounty = Bounty
{itemName :: String,
itemVal, itemWgt :: Rational}
{ itemName :: String
, itemVal, itemWgt :: Rational
}
items :: [Bounty]
items =
[Bounty "beef" 36 3.8,
Bounty "pork" 43 5.4,
Bounty "ham" 90 3.6,
Bounty "greaves" 45 2.4,
Bounty "flitch" 30 4.0,
Bounty "brawn" 56 2.5,
Bounty "welt" 67 3.7,
Bounty "salami" 95 3.0,
Bounty "sausage" 98 5.9]
[ Bounty "beef" 36 3.8
, Bounty "pork" 43 5.4
, Bounty "ham" 90 3.6
, Bounty "greaves" 45 2.4
, Bounty "flitch" 30 4.0
, Bounty "brawn" 56 2.5
, Bounty "welt" 67 3.7
, Bounty "salami" 95 3.0
, Bounty "sausage" 98 5.9
]
solution :: [(Rational, Bounty)]
solution = g maxWgt $ sortBy (flip $ comparing f) items
where g room (b@(Bounty _ _ w) : bs) = if w < room
then (w, b) : g (room - w) bs
else [(room, b)]
f (Bounty _ v w) = v / w
where
g room (b@(Bounty _ _ w):bs) =
if w < room
then (w, b) : g (room - w) bs
else [(room, b)]
f (Bounty _ v w) = v / w
main :: IO ()
main = do
forM_ solution $ \(w, b) ->
printf "%s kg of %s\n" (mixedNum w) (itemName b)
printf "Total value: %s\n" $ mixedNum $ sum $ map f solution
where f (w, Bounty _ v wtot) = v * (w / wtot)
mixedNum q = if b == 0
then show a
else printf "%d %d/%d" a (numerator b) (denominator b)
where a = floor q
b = q - toEnum a
forM_ solution $ \(w, b) -> printf "%s kg of %s\n" (mixedNum w) (itemName b)
(printf "Total value: %s\n" . mixedNum . sum) $ f <$> solution
where
f (w, Bounty _ v wtot) = v * (w / wtot)
mixedNum q =
if b == 0
then show a
else printf "%d %d/%d" a (numerator b) (denominator b)
where
a = floor q
b = q - toEnum a

View file

@ -3,21 +3,24 @@ import Data.Ord (comparing)
import Text.Printf (printf)
-- (name, (value, weight))
items = [("beef", (36, 3.8)),
("pork", (43, 5.4)),
("ham", (90, 3.6)),
("greaves", (45, 2.4)),
("flitch", (30, 4.0)),
("brawn", (56, 2.5)),
("welt", (67, 3.7)),
("salami", (95, 3.0)),
("sausage", (98, 5.9))]
items =
[ ("beef", (36, 3.8))
, ("pork", (43, 5.4))
, ("ham", (90, 3.6))
, ("greaves", (45, 2.4))
, ("flitch", (30, 4.0))
, ("brawn", (56, 2.5))
, ("welt", (67, 3.7))
, ("salami", (95, 3.0))
, ("sausage", (98, 5.9))
]
unitWeight (_, (val, weight)) = (fromIntegral val) / weight
unitWeight (_, (val, weight)) = fromIntegral val / weight
solution k = loop k . sortBy (flip $ comparing unitWeight)
where loop k ((name, (_, weight)):xs)
| weight < k = putStrLn ("Take all the " ++ name) >> loop (k-weight) xs
| otherwise = printf "Take %.2f kg of the %s\n" (k :: Float) name
where
loop k ((name, (_, weight)):xs)
| weight < k = putStrLn ("Take all the " ++ name) >> loop (k - weight) xs
| otherwise = printf "Take %.2f kg of the %s\n" (k :: Float) name
main = solution 15 items

View file

@ -0,0 +1,47 @@
// version 1.1.2
data class Item(val name: String, val weight: Double, val value: Double)
val items = mutableListOf(
Item("beef", 3.8, 36.0),
Item("pork", 5.4, 43.0),
Item("ham", 3.6, 90.0),
Item("greaves", 2.4, 45.0),
Item("flitch", 4.0, 30.0),
Item("brawn", 2.5, 56.0),
Item("welt", 3.7, 67.0),
Item("salami", 3.0, 95.0),
Item("sausage", 5.9, 98.0)
)
const val MAX_WEIGHT = 15.0
fun main(args: Array<String>) {
// sort items by value per unit weight in descending order
items.sortByDescending { it.value / it.weight }
println("Item Chosen Weight Value Percentage")
println("----------- ------ ------ ----------")
var w = MAX_WEIGHT
var itemCount = 0
var sumValue = 0.0
for (item in items) {
itemCount++
if (item.weight <= w) {
sumValue += item.value
print("${item.name.padEnd(11)} ${"%3.1f".format(item.weight)} ${"%5.2f".format(item.value)}")
println(" 100.00")
}
else {
val value = Math.round((w / item.weight * item.value * 100.0)) / 100.0
val percentage = Math.round((w / item.weight * 10000.0)) / 100.0
sumValue += value
print("${item.name.padEnd(11)} ${"%3.1f".format(w)} ${"%5.2f".format(value)}")
println(" $percentage")
break
}
w -= item.weight
if (w == 0.0) break
}
println("----------- ------ ------")
println("${itemCount} items 15.0 ${"%6.2f".format(sumValue)}")
}

View file

@ -0,0 +1,75 @@
/*--------------------------------------------------------------------
* 20.09.2014 Walter Pachl translated from REXX version 2
* utilizing ooRexx features like objects, array(s) and sort
*-------------------------------------------------------------------*/
maxweight = 15.0
items=.array~new
items~append(.item~new('beef', 3.8, 36.0))
items~append(.item~new('pork', 5.4, 43.0))
items~append(.item~new('ham', 3.6, 90.0))
items~append(.item~new('greaves', 2.4, 45.0))
items~append(.item~new('flitch', 4.0, 30.0))
items~append(.item~new('brawn', 2.5, 56.0))
items~append(.item~new('welt', 3.7, 67.0))
items~append(.item~new('salami', 3.0, 95.0))
items~append(.item~new('sausage', 5.9, 98.0))
/* show the input */
Say '# vpu name weight value'
i=0
Do x over items
i+=1
Say i format(x~vpu,2,3) left(x~name,7) format(x~weight,2,3) format(x~value,3,3)
End
/* sort the items by descending value per unit of weight */
items~sortWith(.DescendingComparator~new)
total_weight=0
total_value =0
Say ' '
Say 'Item Weight Value'
i=0
Do x over items
i+=1
Parse Var item.i name '*' weight '*' value
if total_weight+x~weight<maxweight then Do
total_weight = total_weight + x~weight
total_value = total_value + x~value
Say left(x~name,7) format(x~weight,3,3) format(x~value,3,3)
End
Else Do
weight=maxweight-total_weight
value=weight*x~vpu
total_value = total_value + value
total_weight = maxweight
Say left(x~name,7) format(weight,3,3) format(value,3,3)
Leave
End
End
Say copies('-',23)
Say 'total ' format(total_weight,4,3) format(total_value,3,3)
Exit
::class item
::attribute vpu
::attribute name
::attribute weight
::attribute value
::method init
Expose vpu
Use Arg name, weight, value
self~name=name
self~weight=weight
self~value=value
self~vpu=value/weight
::CLASS 'DescendingComparator' MIXINCLASS Comparator
::METHOD compare
use strict arg a, b
Select
When (a~vpu)<(b~vpu) Then res='1'
Otherwise res='-1'
End
Return res

View file

@ -0,0 +1,73 @@
/*--------------------------------------------------------------------
* 20.09.2014 Walter Pachl translated from REXX version 2
* utilizing ooRexx features like objects, array(s) and sort
* 21.09.2014 simplified (courtesy Rony Flatscher)
* (sort uses now the method "compareTo" defined for item)
*-------------------------------------------------------------------*/
maxweight = 15.0
items=.array~new
items~append(.item~new('beef', 3.8, 36.0))
items~append(.item~new('pork', 5.4, 43.0))
items~append(.item~new('ham', 3.6, 90.0))
items~append(.item~new('greaves', 2.4, 45.0))
items~append(.item~new('flitch', 4.0, 30.0))
items~append(.item~new('brawn', 2.5, 56.0))
items~append(.item~new('welt', 3.7, 67.0))
items~append(.item~new('salami', 3.0, 95.0))
items~append(.item~new('sausage', 5.9, 98.0))
/* show the input */
Say '# vpu name weight value'
i=0
Do x over items
i+=1
Say i format(x~vpu,2,3) left(x~name,7) format(x~weight,2,3) format(x~value,3,3)
End
/* sort the items by descending value per unit of weight */
items~sort /* using the method compareTo used for item */
total_weight=0
total_value =0
Say ' '
Say 'Item Weight Value'
i=0
Do x over items
i+=1
Parse Var item.i name '*' weight '*' value
if total_weight+x~weight<maxweight then Do
total_weight = total_weight + x~weight
total_value = total_value + x~value
Say left(x~name,7) format(x~weight,3,3) format(x~value,3,3)
End
Else Do
weight=maxweight-total_weight
value=weight*x~vpu
total_value = total_value + value
total_weight = maxweight
Say left(x~name,7) format(weight,3,3) format(value,3,3)
Leave
End
End
Say copies('-',23)
Say 'total ' format(total_weight,4,3) format(total_value,3,3)
Exit
::class item
::attribute vpu
::attribute name
::attribute weight
::attribute value
::method init
Expose vpu
Use Arg name, weight, value
self~name=name
self~weight=weight
self~value=value
self~vpu=value/weight
::method compareTo -- default sort order
Expose vpu
use Arg other
return -sign(vpu - other~vpu)

View file

@ -0,0 +1,30 @@
constant meats = {
--Item Weight (kg) Price (Value)
{"beef", 3.8, 36},
{"pork", 5.4, 43},
{"ham", 3.6, 90},
{"greaves", 2.4, 45},
{"flitch", 4.0, 30},
{"brawn", 2.5, 56},
{"welt", 3.7, 67},
{"salami", 3.0, 95},
{"sausage", 5.9, 98}}
function by_weighted_value(integer i, j)
atom {?,weighti,pricei} = meats[i],
{?,weightj,pricej} = meats[j]
return compare(pricej/weightj,pricei/weighti)
end function
sequence tags = custom_sort(routine_id("by_weighted_value"),tagset(length(meats)))
atom w = 15, worth = 0
for i=1 to length(tags) do
object {desc,wi,price} = meats[tags[i]]
atom c = min(wi,w)
printf(1,"%3.1fkg%s of %s\n",{c,iff(c=wi?" (all)":""),desc})
worth += (c/wi)*price
w -= c
if w=0 then exit end if
end for
printf(1,"Total value: %f\n",{worth})

View file

@ -1,40 +1,37 @@
/*REXX pgm solves the continuous burglar's knapsack problem; items with weight and value*/
@.= /*═══════ name weight value ══════*/
@.1 = 'flitch 4 30 '
@.2 = 'beef 3.8 36 '
@.3 = 'pork 5.4 43 '
@.4 = 'greaves 2.4 45 '
@.5 = 'brawn 2.5 56 '
@.6 = 'welt 3.7 67 '
@.7 = 'ham 3.6 90 '
@.8 = 'salami 3 95 '
@.9 = 'sausage 5.9 98 '
@.= /*═══════ name weight value ══════*/
@.1 = 'flitch 4 30 '
@.2 = 'beef 3.8 36 '
@.3 = 'pork 5.4 43 '
@.4 = 'greaves 2.4 45 '
@.5 = 'brawn 2.5 56 '
@.6 = 'welt 3.7 67 '
@.7 = 'ham 3.6 90 '
@.8 = 'salami 3 95 '
@.9 = 'sausage 5.9 98 '
parse arg maxW d . /*get possible arguments from the C.L. */
if maxW=='' | maxW=="," then maxW=15 /*the burglar's knapsack maximum weight*/
if d=='' | d=="," then d= 3 /*number of decimal digits in FORMAT. */
wL=d+length('weight'); nL=d+length("total weight"); vL=d+length('value')
totW=0; totV=0
do #=1 while @.#\==''; parse var @.# n.# w.# v.# .
end /*#*/ /* [↑] assign item to separate lists. */
#=#-1 /*#: is the number of items in @ list.*/
if d=='' | d=="," then d= 3 /*# decimal digits shown with FORMAT. */
wL=d+length('weight'); nL=d+length("total weight"); vL=d+length('value') /*lengths*/
totW=0; totV=0 /* [↓] assign item to separate lists. */
do #=1 while @.#\==''; parse var @.# n.# w.# v.# .; end; #=#-1
call show 'unsorted item list' /*display the header and the @ list.*/
call sortD /*invoke sort (which sorts descending).*/
call sortD /*invoke descemdomg sort for: n. w. v.*/
call hdr "burglar's knapsack contents"
do j=1 for # while totW<maxW; f=1 /*process the items. */
if totW+w.j>=maxW then f=(maxW-totW)/w.j /*calculate fraction. */
totW=totW+w.j*f; totV=totV+v.j*f /*add it ───► totals. */
call syf left(word('{all}',1+(f\==1)),5) n.j, w.j*f, v.j*f
end /*j*/ /* [↑] display item. */
call sep; say ' /* [] $ suppresses trailing zeroes.*/
end /*j*/ /* [↑] display item, maybe with {all} */
call sep; say /* [↓] $ suppresses trailing zeroes.*/
call sy left('total weight', nL, ""), $(format(totW,,d))
call sy left('total value', nL, ""), , $(format(totV,,d))
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
sortD: do s=2 to #; a=n.s; !=w.s; u=v.s /* [↓] this is a descending sort. */
do k=s-1 by -1 to 1 while v.k/w.k<u/!; ?=k+1; n.?=n.k; w.?=w.k;v.?=v.k;end
?=k+1; n.?=a; w.?=!; v.?=u
end /*s*/
return /* ↑↑↑ sort algorithm is OK for small arrays*/
sortD: do s=2 to #; a=n.s; !=w.s; u=v.s /* [↓] this is a descending sort. */
do k=s-1 by -1 to 1 while v.k/w.k<u/!; ?=k+1; n.?=n.k; w.?=w.k; v.?=v.k; end
?=k+1; n.?=a; w.?=!; v.?=u
end /*s*/; return /* ↑↑↑ algorithm is OK for small arrays*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
hdr: say; say; say center(arg(1),50,''); say; call title; call sep; return
sep: call sy copies('', nL), copies("", wL), copies('', vL); return

View file

@ -0,0 +1,14 @@
items:=List( T(3.8, 36.0, "beef"), T(5.4, 43.0, "pork"), // weight, value, name
T(3.6, 90.0, "ham"), T(2.4, 45.0, "greaves"),
T(4.0, 30.0, "flitch"),T(2.5, 56.0, "brawn"),
T(3.7, 67.0, "welt"), T(3.0, 95.0, "salami"),
T(5.9, 98.0, "sausage"),
);
fcn item_cmp(a,b){ a[1]/a[0] > b[1]/b[0] }
items.sort(item_cmp);
space := 15.0;
foreach it in (items){ w,_,nm:=it;
if (space >= w){ println("take all ",nm); space-=w }
else{ println("take %gkg of %gkg of %s".fmt(space,w,nm)); break }
}