September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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))))
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)}")
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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})
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue