sequence cards
cards = repeat(0,52)
integer card,temp

puts(1,"Before:\n")
for i = 1 to 52 do
    cards[i] = i
    printf(1,"%d ",cards[i])
end for

for i = 52 to 1 by -1 do
    card = rand(i)
    if card != i then
        temp = cards[card]
        cards[card] = cards[i]
        cards[i] = temp
    end if
end for

puts(1,"\nAfter:\n")
for i = 1 to 52 do
    printf(1,"%d ",cards[i])
end for


open System

let FisherYatesShuffle (initialList : array<'a>) =                  // '
    let availableFlags = Array.init initialList.Length (fun i -> (i, true))
                                                                    // Which items are available and their indices
    let rnd = new Random()
    let nextItem nLeft =
        let nItem = rnd.Next(0, nLeft)                              // Index out of available items
        let index =                                                 // Index in original deck
            availableFlags                                          // Go through available array
            |> Seq.filter (fun (ndx,f) -> f)                        // and pick out only the available tuples
            |> Seq.nth nItem                                        // Get the one at our chosen index
            |> fst                                                  // and retrieve it's index into the original array
        availableFlags.[index] <- (index, false)                    // Mark that index as unavailable
        initialList.[index]                                         // and return the original item
    seq {(initialList.Length) .. -1 .. 1}                           // Going from the length of the list down to 1
    |> Seq.map (fun i -> nextItem i)                                // yield the next item


: randomize ( seq -- seq )
    dup length [ dup 1 > ]
    [ [ iota random ] [ 1 - ] bi [ pick exchange ] keep ]
    while drop ;


class Main
{
  static Void knuthShuffle (List array)
  {
    ((array.size-1)..1).each |Int i|
    {
      r := Int.random(0..i)
      array.swap (i, r)
    }
  }

  public static Void main ()
  {
    List a := [1,2,3,4,5]
    knuthShuffle (a)
    echo (a)

    List b := ["apples", "oranges", "pears", "bananas"]
    knuthShuffle (b)
    echo (b)
  }
}


include random.fs

: shuffle ( deck size -- )
  2 swap do
    dup i random cells +
    over @ over @  swap
    rot  ! over !
    cell+
  -1 +loop drop ;

: .array   0 do dup @ . cell+ loop drop ;

create deck 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ,

deck 10 2dup shuffle .array


program Knuth_Shuffle
  implicit none

  integer, parameter :: reps = 1000000
  integer :: i, n
  integer, dimension(10) :: a, bins = 0, initial = (/ (n, n=1,10) /)

  do i = 1, reps
    a = initial
 	call Shuffle(a)
    where (a == initial) bins = bins + 1  ! skew tester
  end do
  write(*, "(10(i8))") bins
! prints  100382  100007   99783  100231  100507   99921   99941  100270  100290  100442

contains

subroutine Shuffle(a)
  integer, intent(inout) :: a(:)
  integer :: i, randpos, temp
  real :: r

  do i = size(a), 2, -1
    call random_number(r)
    randpos = int(r * i) + 1
    temp = a(randpos)
    a(randpos) = a(i)
    a(i) = temp
  end do

end subroutine Shuffle

end program Knuth_Shuffle


' version 22-10-2016
' compile with: fbc -s console
' for boundry checks on array's compile with: fbc -s console -exx

' sort from lower bound to the highter bound
' array's can have subscript range from -2147483648 to +2147483647

Sub knuth_down(a() As Long)

    Dim As Long lb = LBound(a)
    Dim As ULong n = UBound(a) - lb +1
    Dim As ULong i, j

    Randomize Timer

    For i = n -1 To 1 Step -1
        j =Fix(Rnd * (i +1))       ' 0 <= j <= i
        Swap a(lb + i), a(lb + j)
    Next

End Sub

Sub knuth_up(a() As Long)

    Dim As Long lb = LBound(a)
    Dim As ULong n = UBound(a) - lb +1
    Dim As ULong i, j

    Randomize Timer

    For i = 0 To n -2
        j = Fix(Rnd * (n - i) + i)   '  0 <= j < n-i, + i ==> i <= j < n
        Swap a(lb + i), a(lb + j)
    Next

End Sub

' ------=< MAIN >=------

Dim As Long i
Dim As Long array(1 To 52), array2(-7 To 7)

For i = 1 To 52 : array(i) = i : Next

Print "Starting array"
For i = 1 To 52
    Print Using " ###";array(i);
Next : Print : Print

knuth_down(array())

Print "After Knuth shuffle downwards"
For i = 1 To 52
    Print Using " ###";array(i);
Next : Print : Print

For i = LBound(array2) To UBound(array2)
    array2(i) = i - LBound(array2) + 1
Next

Print "Starting array, first index <> 0 "
For i = LBound(array2) To UBound(array2)
    Print Using " ##";array2(i);
Next : Print : Print

knuth_up(array2())
Print "After Knuth shuffle upwards"
For i = LBound(array2) To UBound(array2)
    Print Using " ##";array2(i);
Next : Print : Print

' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End


def shuffle( a ) =
  res = array( a )
  n = a.length()

  for i <- 0:n
    r = rnd( i:n )
    res(i), res(r) = res(r), res(i)

  res.toList()


Public Sub Main()
Dim iTotal As Integer = 40
Dim iCount, iRand1, iRand2 As Integer
Dim iArray As New Integer[]

For iCount = 0 To iTotal
  iArray.add(iCount)
Next

Print "Original = ";
For iCount = 0 To iArray.Max
  If iCount = iArray.max Then Print iArray[iCount]; Else Print iArray[iCount] & ",";
Next

For iCount = iTotal DownTo 0
  iRand1 = Rand(iTotal)
  iRand2 = Rand(iTotal)
  Swap iArray[iRand1], iArray[iRand2]
Next

Print gb.NewLine & "Shuffled = ";
For iCount = 0 To iArray.Max
  If iCount = iArray.max Then Print iArray[iCount]; Else Print iArray[iCount] & ",";
Next

End


# Return the list L after applying Knuth shuffle. GAP also has the function Shuffle, which does the same.
ShuffleAlt := function(a)
    local i, j, n, t;
    n := Length(a);
    for i in [n, n - 1 .. 2] do
        j := Random(1, i);
        t := a[i];
        a[i] := a[j];
        a[j] := t;
    od;
    return a;
end;

# Return a "Permutation" object (a permutation of 1 .. n).
# They are printed in GAP, in cycle decomposition form.
PermShuffle := n -> PermList(ShuffleAlt([1 .. n]));

ShuffleAlt([1 .. 10]);
# [ 4, 7, 1, 5, 8, 2, 6, 9, 10, 3 ]

PermShuffle(10);
# (1,9)(2,3,6,4,5,10,8,7)

# One may also call the built-in random generator on the symmetric group :
Random(SymmetricGroup(10));
(1,8,2,5,9,6)(3,4,10,7)


package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    var a [20]int
    for i := range a {
        a[i] = i
    }
    fmt.Println(a)

    rand.Seed(time.Now().UnixNano())
    for i := len(a) - 1; i >= 1; i-- {
        j := rand.Intn(i + 1)
        a[i], a[j] = a[j], a[i]
    }
    fmt.Println(a)
}


def shuffle = { list ->
    if (list == null || list.empty) return list
    def r = new Random()
    def n = list.size()
    (n..1).each { i ->
        def j = r.nextInt(i)
        list[[i-1, j]] = list[[j, i-1]]
    }
    list
}


import System.Random (randomRIO)

mkRands :: Int -> IO [Int]
mkRands = mapM (randomRIO . (,) 0) . enumFromTo 1 . pred

replaceAt :: Int -> a -> [a] -> [a]
replaceAt i c l =
  let (a, b) = splitAt i l
  in a ++ c : drop 1 b

swapElems :: (Int, Int) -> [a] -> [a]
swapElems (i, j) xs
  | i == j = xs
  | otherwise = replaceAt j (xs !! i) $ replaceAt i (xs !! j) xs

knuthShuffle :: [a] -> IO [a]
knuthShuffle xs = (foldr swapElems xs . zip [1 ..]) <$> mkRands (length xs)


procedure main()
    show(shuffle([3,1,4,1,5,9,2,6,3]))
    show(shuffle("this is a string"))
end

procedure shuffle(A)
    every A[i := *A to 1 by -1] :=: A[?i]
    return A
end

procedure show(A)
    every writes(!A," ")
    write()
end


[ shuffle a n i j tmp;
  for(i = n - 1: i > 0: i--)
  {
    j = random(i + 1) - 1;

    tmp = a->j;
    a->j = a->i;
    a->i = tmp;
  }
];


KS=:{~ (2&{[email protected][ {`(|[email protected][)`]} ])/@(,~(,[email protected]>:))@[email protected]#


import java.util.Random;

public static final Random gen = new Random();

// version for array of ints
public static void shuffle (int[] array) {
    int n = array.length;
    while (n > 1) {
        int k = gen.nextInt(n--); //decrements after using the value
        int temp = array[n];
        array[n] = array[k];
        array[k] = temp;
    }
}
// version for array of references
public static void shuffle (Object[] array) {
    int n = array.length;
    while (n > 1) {
        int k = gen.nextInt(n--); //decrements after using the value
        Object temp = array[n];
        array[n] = array[k];
        array[k] = temp;
    }
}


function knuthShuffle(arr) {
    var rand, temp, i;

    for (i = arr.length - 1; i > 0; i -= 1) {
        rand = Math.floor((i + 1) * Math.random());//get random between zero and i (inclusive)
        temp = arr[rand];//swap i and the zero-indexed number
        arr[rand] = arr[i];
        arr[i] = temp;
    }
    return arr;
}

var res = {
    '1,2,3': 0, '1,3,2': 0,
    '2,1,3': 0, '2,3,1': 0,
    '3,1,2': 0, '3,2,1': 0
};

for (var i = 0; i < 100000; i++) {
    res[knuthShuffle([1,2,3]).join(',')] += 1;
}

for (var key in res) {
    print(key + "\t" + res[key]);
}


DEFINE knuth-shuffle ==

(* Take the size of the array (without destroying it) *)
dup dup size

(* Generate a list of as many random numbers *)
[rand] [rem] enconcat map

(* Zip the two lists *)
swap zip

(* Sort according to the new index number *)
[small] [] [uncons unswonsd [first >] split [swons] dip2]
[enconcat] binrec

(* Delete the new index number *)
[second] map.


# 52-card deck:
def deck:
  [range(127137; 127148), range(127149; 127151),  # Spades
   range(127153; 127164), range(127165; 127167),  # Hearts
   range(127169; 127180), range(127181; 127183),  # Diamonds
   range(127185; 127196), range(127197; 127199)]  # Clubs
  ;

# For splitting a deck into hands :-)
def nwise($n):
  def n: if length <= $n then . else .[0:$n] , (.[$n:] | n) end;
  n;

# Output: a prn in range(0;$n) where $n is ., and $n > 0
def prn:
  if . == 1 then 0
  else . as $n
  | (($n-1)|tostring|length) as $w
  | [limit($w; inputs)] | join("") | tonumber
  | if . < $n then . else ($n | prn) end
  end;

def knuthShuffle:
  length as $n
  | if $n <= 1 then .
    else {i: $n, a: .}
    | until(.i ==  0;
        .i += -1
        | (.i + 1 | prn) as $j
        | .a[.i] as $t
        | .a[.i] = .a[$j]
        | .a[$j] = $t)
    | .a
    end;

def task:
  [],
  [10,20],
  [10,20,30]
  | knuthShuffle;

task,
 (deck|knuthShuffle | nwise(13) | implode)


function knuthshuffle!(r::AbstractRNG, v::AbstractVector)
    for i in length(v):-1:2
        j = rand(r, 1:i)
        v[i], v[j] = v[j], v[i]
    end
    return v
end
knuthshuffle!(v::AbstractVector) = knuthshuffle!(Base.Random.GLOBAL_RNG, v)

v = collect(1:20)
println("# v = $v\n   -> ", knuthshuffle!(v))


object Knuth {
    internal val gen = java.util.Random()
}

fun <T> Array<T>.shuffle(): Array<T> {
    val a = clone()
    var n = a.size
    while (n > 1) {
        val k = Knuth.gen.nextInt(n--)
        val t = a[n]
        a[n] = a[k]
        a[k] = t
    }
    return a
}

fun main(args: Array<String>) {
    val str = "abcdefghijklmnopqrstuvwxyz".toCharArray()
    (1..10).forEach {
        val s = str.toTypedArray().shuffle().toCharArray()
        println(s)
        require(s.toSortedSet() == str.toSortedSet())
    }

    val ia = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    (1..10).forEach {
        val s = ia.shuffle()
        println(s.distinct())
        require(s.toSortedSet() == ia.toSet())
    }
}


{def shuffle

 {def shuffle.in
  {lambda {:a}
   {S.map {{lambda {:a :i}
                   {A.swap :i
                           {floor {* {random} {+ :i 1}}}  // j = random integer from 0 to i+1
                           :a}} :a}
          {S.serie {- {A.length :a} 1} 0 -1}}}}           // from length-1 to 0

 {lambda {:a}
  {let { {:b {A.duplicate :a}} }        // optionnaly prevents modifying the original array
   {S.replace \s by in {shuffle.in :b}  // trim extra spaces
    :b}}}}                              // return the new array
-> shuffle

{def A.swap                                    // should probably be promoted as a primitive
 {lambda {:i :j :a}
  {let { {:i :i}
         {:gja {A.get :j :a}}
         {:b {A.set! :j {A.get :i :a} :a}}
       } {let { {_ {A.set! :i :gja :b} }}}}}}  // side effect without any return value
-> A.swap

{def B {A.new a b c d e f g h i j k l m n o p q r s t u v w x y z}}
-> B

{shuffle {B}}
-> [z,t,q,w,c,n,a,u,r,y,i,s,f,d,g,m,h,x,b,e,k,p,l,o,j,v]


define staticarray->swap(p1::integer,p2::integer) => {
    fail_if(
        #p1 < 1 or #p2 < 1 or
        #p1 > .size or #p2 > .size,
        'invalid parameters'
    )
    #p1 == #p2
        ? return

    local(tmp) = .get(#p2)
    .get(#p2)  = .get(#p1)
    .get(#p1)  = #tmp
}
define staticarray->knuthShuffle => {
    loop(-from=.size, -to=2, -by=-1) => {
        .swap(math_random(1, loop_count), loop_count)
    }
}

(1 to 10)->asStaticArray->knuthShuffle&asString


'Declared the UpperBound to prevent confusion with lots of 9's floating around....
UpperBound = 9
Dim array(UpperBound)

For i = 0 To UpperBound
    array(i) = Int(Rnd(1) * 10)
    Print array(i)
Next i

For i = 0 To UpperBound
    'set a random value because we will need to use the same value twice
    randval = Int(Rnd(1) * (UpperBound - i))
    temp1 = array(randval)
    temp2 = array((UpperBound - i))
    array(randval) = temp2
    array((UpperBound - i)) = temp1
Next i

Print
For i = 0 To UpperBound
    Print array(i)
Next i


to swap :i :j :a
  localmake "t item :i :a
  setitem :i :a item :j :a
  setitem :j :a :t
end
to shuffle :a
  for [i [count :a] 2] [swap 1 + random :i :i :a]
end

make "a {1 2 3 4 5 6 7 8 9 10}
shuffle :a
show :a


function table.shuffle(t)
  for n = #t, 1, -1 do
    local k = math.random(n)
    t[n], t[k] = t[k], t[n]
  end

  return t
end

math.randomseed( os.time() )
a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
table.shuffle(a)
for i,v in ipairs(a) do print(i,v) end


Dim Base 0, A(3)
For k=1 to 6 {
      A(0):=10,20, 30
      For i=len(A())-1 to 0 {
            let j=random(0,i)
            Swap a(i), a(j)
      }
 Print A()
}


function list = knuthShuffle(list)

    for i = (numel(list):-1:2)

        j = floor(i*rand(1) + 1); %Generate random int between 1 and i

        %Swap element i with element j.
        list([j i]) = list([i j]);
    end
end


/* Maxima has an implementation of Knuth shuffle */
random_permutation([a, b, c]);


MODULE Shuffle EXPORTS Main;

IMPORT IO, Fmt, Random;

VAR a := ARRAY [0..9] OF INTEGER {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

PROCEDURE Shuffle(VAR a: ARRAY OF INTEGER) =
  VAR temp: INTEGER;
      n: INTEGER := NUMBER(a);
BEGIN
  WITH rand = NEW(Random.Default).init() DO
    WHILE n > 1 DO
      WITH k = rand.integer(0, n - 1) DO
        DEC(n);
        temp := a[n];
        a[n] := a[k];
        a[k] := temp;
      END;
    END;
  END;
END Shuffle;

BEGIN
  Shuffle(a);
  FOR i := FIRST(a) TO LAST(a) DO
    IO.Put(Fmt.Int(a[i]) & " ");
  END;
  IO.Put("\n");
END Shuffle.


Shuffle(items,separator)	New ii,item,list,n
	Set list="",n=0
	Set ii="" For  Set ii=$Order(items(ii)) Quit:ii=""  Do
	. Set n=n+1,list(n)=items(ii),list=list_$Char(n)
	. Quit
	For  Quit:list=""  Do
	. Set n=$Random($Length(list))+1
	. Set item=list($ASCII(list,n))
	. Set $Extract(list,n)=""
	. Write item,separator
	. Quit
	Quit
CardDeck	New card,ii,suite
	Set ii=0
	For suite="Spades","Hearts","Clubs","Diamonds" Do
	. For card=2:1:10,"Jack","Queen","King","Ace" Do
	. . Set ii=ii+1,items(ii)=card_" of "_suite
	. . Quit
	. Quit
	Quit

Kill items
Set items(91)="Red"
Set items(82)="White"
Set items(73)="Blue"
Set items(64)="Yellow"
Set items(55)="Green"
Do Shuffle(.items,"  ") ; Red  Yellow  White  Green  Blue
Do Shuffle(.items,"  ") ; Red  Blue  Yellow  White  Green
Do Shuffle(.items,"  ") ; Green  Blue  Yellow  White  Red

Kill items Do CardDeck,Shuffle(.items,$Char(13,10))
Queen of Hearts
9 of Diamonds
10 of Hearts
King of Hearts
7 of Diamonds
9 of Clubs
6 of Diamonds
8 of Diamonds
Jack of Spades
Ace of Hearts
Queen of Diamonds
9 of Hearts
2 of Hearts
King of Clubs
10 of Spades
7 of Clubs
6 of Clubs
3 of Diamonds
3 of Spades
Queen of Clubs
Ace of Spades
4 of Hearts
Ace of Diamonds
7 of Spades
Ace of Clubs
King of Spades
10 of Diamonds
Jack of Diamonds
8 of Clubs
4 of Spades
Jack of Hearts
10 of Clubs
4 of Diamonds
3 of Hearts
2 of Diamonds
5 of Hearts
Jack of Clubs
2 of Clubs
5 of Diamonds
6 of Hearts
4 of Clubs
9 of Spades
3 of Clubs
5 of Spades
6 of Spades
7 of Hearts
8 of Spades
8 of Hearts
2 of Spades
Queen of Spades
King of Diamonds
5 of Clubs


Shuffle[T] (arr : array[T]) : array[T]
{
    def rnd = Random();

    foreach (i in [0 .. (arr.Length - 2)])
        arr[i] <-> arr[(rnd.Next(i, arr.Length))];
    arr
}


/* NetRexx */
options replace format comments java crossref savelog symbols nobinary

import java.util.List

cards = [String -
    'hA', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9', 'h10', 'hJ', 'hQ', 'hK' -
  , 'cA', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'c10', 'cJ', 'cQ', 'cK' -
  , 'dA', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'd10', 'dJ', 'dQ', 'dK' -
  , 'sA', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10', 'sJ', 'sQ', 'sK' -
]
cardsLen = cards.length
deck = ArrayList(cardsLen)
loop c_ = 0 to cardsLen - 1
  deck.add(String(cards[c_]))
  end c_

showHand(deck)
deck = ArrayList shuffle(deck)
showHand(deck)

return

method shuffle(deck = List) public static binary returns List

  rn = Random()
  dl = deck.size

  loop i_ = dl - 1 to 1 by -1
    j_ = rn.nextInt(i_)
    __ = deck.get(i_)
    deck.set(i_, deck.get(j_))
    deck.set(j_, __)
    end i_

  return deck

method showHand(deck = ArrayList) public static binary

  dl = deck.size
  hl = dl % 4
  loop c_ = 0 to dl - 1 by hl
    d_ = c_ + hl
    if d_ >= dl then d_ = dl
    say ArrayList(deck.subList(c_, d_)).toString
    end c_
    say

  return


import random
randomize()

proc shuffle[T](x: var openArray[T]) =
  for i in countdown(x.high, 1):
    let j = rand(i)
    swap(x[i], x[j])

var x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
shuffle(x)
echo x


#import <Foundation/Foundation.h>

@interface NSMutableArray (KnuthShuffle)
- (void)knuthShuffle;
@end
@implementation NSMutableArray (KnuthShuffle)
- (void)knuthShuffle {
  for (NSUInteger i = self.count-1; i > 0; i--) {
    NSUInteger j = arc4random_uniform(i+1);
    [self exchangeObjectAtIndex:i withObjectAtIndex:j];
  }
}
@end

int main() {
  @autoreleasepool {
    NSMutableArray *x = [NSMutableArray arrayWithObjects:@0, @1, @2, @3, @4, @5, @6, @7, @8, @9, nil];
    [x knuthShuffle];
    NSLog(@"%@", x);
  }
  return 0;
}


let shuffle arr =
  for n = Array.length arr - 1 downto 1 do
    let k = Random.int (n + 1) in
    let temp = arr.(n) in
    arr.(n) <- arr.(k);
    arr.(k) <- temp
  done


Indexable method: shuffle
| s i l |
   self asListBuffer ->l
   self size dup ->s 1- loop: i [ s i - rand i +  i  l swapValues ]
   l dup freeze ;


(define (shuffle tp)
   (let ((items (vm:cast tp (type tp)))) ; make a copy
      (for-each (lambda (i)
            (let ((a (ref items i))
                  (j (+ 1 (rand! i))))
               (set-ref! items i (ref items j))
               (set-ref! items j a)))
         (reverse (iota (size items) 1)))
      items))

(define (list-shuffle tp)
   (map (lambda (i)
         (list-ref tp i))
      (tuple->list
         (shuffle (list->tuple (iota (length tp)))))))


declare
  proc {Shuffle Arr}
     Low = {Array.low Arr}
     High = {Array.high Arr}
  in
     for I in High..Low;~1 do
	J = Low + {OS.rand} mod (I - Low + 1)
        OldI = Arr.I
     in
	Arr.I := Arr.J
        Arr.J := OldI
     end
  end

  X = {Tuple.toArray unit(0 1 2 3 4 5 6 7 8 9)}
in
  {Show {Array.toRecord unit X}}
  {Shuffle X}
  {Show {Array.toRecord unit X}}


program Knuth;

const
  startIdx = -5;
  max = 11;
type
  tmyData = string[9];
  tmylist = array [startIdx..startIdx+max-1] of tmyData;

procedure InitList(var a: tmylist);
var
  i: integer;
Begin
  for i := Low(a) to High(a) do
    str(i:3,a[i])
end;

procedure shuffleList(var a: tmylist);
var
  i,k : integer;
  tmp: tmyData;
begin
  for i := High(a)-low(a) downto 1 do begin
    k := random(i+1) + low(a);
    tmp := a[i+low(a)]; a[i+low(a)] := a[k]; a[k] := tmp
  end
end;

procedure DisplayList(const a: tmylist);
var
  i : integer;
Begin
  for i := Low(a) to High(a) do
    write(a[i]);
  writeln
end;

{ Test and display }
var
 a: tmylist;
 i: integer;
begin
  randomize;
  InitList(a);
  DisplayList(a);
  writeln;
  For i := 0 to 4 do
  Begin
    shuffleList(a);
    DisplayList(a);
  end;
end.


sub shuffle {
  my @a = @_;
  foreach my $n (1 .. $#a) {
    my $k = int rand $n + 1;
    $k == $n or @a[$k, $n] = @a[$n, $k];
  }
  return @a;
}


sequence cards = tagset(52)
puts(1,"Before: ")      ?cards
for i=52 to 1 by -1 do
    integer r = rand(i)
    {cards[r],cards[i]} = {cards[i],cards[r]}
end for
puts(1,"After:  ")      ?cards
puts(1,"Sorted: ")      ?sort(cards)


//The Fisher-Yates original Method
function yates_shuffle($arr){
	$shuffled = Array();
	while($arr){
		$rnd = array_rand($arr);
		$shuffled[] = $arr[$rnd];
		array_splice($arr, $rnd, 1);
	}
	return $shuffled;
}

//The modern Durstenfeld-Knuth algorithm
function knuth_shuffle(&$arr){
	for($i=count($arr)-1;$i>0;$i--){
		$rnd = mt_rand(0,$i);
		list($arr[$i], $arr[$rnd]) = array($arr[$rnd], $arr[$i]);
	}
}


go =>
  _ = random2(),
  L = 1..10,
  println(l_before=L),
  knuth_shuffle(L),
  println('l_after '=L),
  nl.

knuth_shuffle(L) =>
  foreach(I in L.len..-1..1)
    J = random(1,I),
    Tmp = L[I],
    L[I] := L[J],
    L[J] := Tmp
  end.


(seed (in "/dev/urandom" (rd 8)))

(de knuth (Lst)
   (for (N (length Lst) (>= N 2) (dec N))
      (let I (rand 1 N)
         (xchg (nth Lst N) (nth Lst I)) ) ) )

(let L (range 1 15)
   (println 'before L)
   (knuth L)
   (println 'after L) )


declare T(0:10) fixed binary initial (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
declare (i, j, temp) fixed binary;
do i = lbound(T,1) to hbound(T,1);
   j = min(random() * 12, 11);
   temp = T(j);   T(j) = T(i);   T(i) = temp;
end;


$A = 1, 2, 3, 4, 5
Get-Random $A -Count $A.Count


EnableExplicit

Procedure KnuthShuffle(Array a(1))
   Protected i, last = ArraySize(a())

   For i = last To 1 Step -1
      Swap a(i), a(Random(i))
   Next
EndProcedure

Procedure.s ArrayToString(Array a(1))
   Protected ret$, i, last = ArraySize(a())

   ret$ = Str(a(0))
   For i = 1 To last
      ret$ + "," + Str(a(i))
   Next
   ProcedureReturn ret$
EndProcedure

#NumElements = 10

Dim a(#NumElements-1)
Define i

For i = 0 To #NumElements-1
   a(i) = i
Next

KnuthShuffle(a())
Debug "shuffled: " + ArrayToString(a())


from random import randrange

def knuth_shuffle(x):
    for i in range(len(x)-1, 0, -1):
        j = randrange(i + 1)
        x[i], x[j] = x[j], x[i]

x = list(range(10))
knuth_shuffle(x)
print("shuffled:", x)


  [ [] swap dup size times
      [ dup size random pluck
        nested rot join swap ]
    drop ]                      is shuffle (     [ --> [ )

  [ temp put
    2dup swap
    temp share swap peek
    temp share rot peek
    dip
      [ swap
        temp take
        swap poke
        temp put ]
    swap
    temp take
    swap poke ]                 is [exch]  ( n n [ --> [ )

  [ dup size 1 - times
      [ i 1+ dup 1+ random
        rot [exch] ] ]         is knuffle (     [ --> [ )


fisheryatesshuffle <- function(n)
{
  pool <- seq_len(n)
  a <- c()
  while(length(pool) > 0)
  {
     k <- sample.int(length(pool), 1)
     a <- c(a, pool[k])
     pool <- pool[-k]
  }
  a
}


#lang racket

(define (swap! vec i j)
  (let ([tmp (vector-ref vec i)])
    (vector-set! vec i (vector-ref vec j))
    (vector-set! vec j tmp)))

(define (knuth-shuffle x)
  (if (list? x)
    (vector->list (knuth-shuffle (list->vector x)))
    (begin (for ([i (in-range (sub1 (vector-length x)) 0 -1)])
             (define r (random (+ i 1)))
             (swap! x i r))
           x)))

(knuth-shuffle '(1 2 3 4))


sub shuffle (@a is copy) {
    for 1 ..^ @a -> $n {
        my $k = (0 .. $n).pick;
        $k == $n or @a[$k, $n] = @a[$n, $k];
    }
    return @a;
}


rebol [
    Title: "Fisher-Yates"
    Purpose: {Fisher-Yates shuffling algorithm}
]

fisher-yates: func [b [block!] /local n i j k] [
    n: length? b: copy b
    i: n
    while [i > 1] [
        if i <> j: random i [
            error? set/any 'k pick b j
            change/only at b j pick b i
            change/only at b i get/any 'k
        ]
        i: i - 1
    ]
    b
]


/*REXX program shuffles a deck of playing cards (with jokers)  using the  Knuth shuffle.*/
rank= 'A 2 3 4 5 6 7 8 9 10 J Q K'               /*pips  of the various playing cards.  */
suit= '♣♠♦♥'                                     /*suit   "  "     "       "      "     */
parse arg seed .                                 /*obtain optional argument from the CL.*/
if datatype(seed,'W')  then call random ,,seed   /*maybe use for  RANDOM  repeatability.*/
say '══════════════════ getting a new deck out of the box ···'
@.1= 'highJoker'                                 /*good decks have a color joker, and a */
@.2= 'lowJoker'                                  /*            ··· black & white joker. */
cards=2                                          /*now, there're 2 cards are in the deck*/
               do j     =1  for length(suit)
                    do k=1  for  words(rank);      cards=cards + 1
                    @.cards=substr(suit, j, 1)word(rank, k)
                    end  /*k*/
               end       /*j*/
call show
say;      say '══════════════════ shuffling' cards "cards ···"
     do s=cards  by -1  to 2;  ?=random(1,s);  parse value  @.?  @.s   with   @.s  @.?
                                                 /*  [↑]  swap two cards in the deck.   */
     end   /*s*/
call show
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
show: _=;      do m=1  for cards;   _=_ @.m;   end  /*m*/;         say _;           return


# Project : Knuth shuffle

items = list(52)
for n = 1 to len(items)
      items[n] = n
next
knuth(items)
showarray(items)

func knuth(items)
       for i = len(items) to 1 step -1
            j = random(i-1) + 1
            if i != j
               temp = items[i]
               items[i] = items[j]
               items[j] = temp
            ok
       next

func showarray(vect)
       see "["
       svect = ""
       for n = 1 to len(vect)
           svect = svect + vect[n] + " "
       next
       svect = left(svect, len(svect) - 1)
       see svect
       see "]" + nl


class Array
  def knuth_shuffle!
    j = length
    i = 0
    while j > 1
      r = i + rand(j)
      self[i], self[r] = self[r], self[i]
      i += 1
      j -= 1
    end
    self
  end
end

r = Hash.new(0)
100_000.times do |i|
  a = [1,2,3].knuth_shuffle!
  r[a] += 1
end

r.keys.sort.each {|a| puts "#{a.inspect} => #{r[a]}"}


dim cards(52)
for i = 1 to 52                ' make deck
  cards(i) = i
next

for i = 52 to 1 step -1        ' shuffle deck
   r = int((rnd(1)*i) + 1)
   if r <> i then
     hold     = cards(r)
     cards(r) = cards(i)
     cards(i) = hold
   end if
next

print "== Shuffled Cards =="  ' print shuffled cards
for i = 1 to 52
    print cards(i);" ";
    if i mod 18 = 0 then print
next
print


use rand::Rng;

extern crate rand;

fn knuth_shuffle<T>(v: &mut [T]) {
    let mut rng = rand::thread_rng();
    let l = v.len();

    for n in 0..l {
        let i = rng.gen_range(0, l - n);
        v.swap(i, l - n - 1);
    }
}

fn main() {
    let mut v: Vec<_> = (0..10).collect();

    println!("before: {:?}", v);
    knuth_shuffle(&mut v);
    println!("after:  {:?}", v);
}


def shuffle[T](a: Array[T]) = {
  for (i <- 1 until a.size reverse) {
    val j = util.Random nextInt (i + 1)
    val t = a(i)
    a(i) = a(j)
    a(j) = t
  }
  a
}


#!r6rs
(import (rnrs base (6))
        (srfi :27 random-bits))

(define (semireverse li n)
  (define (continue front back n)
    (cond
      ((null? back) front)
      ((zero? n) (cons (car back) (append front (cdr back))))
      (else (continue (cons (car back) front) (cdr back) (- n 1)))))
  (continue '() li n))

(define (shuffle li)
  (if (null? li)
      ()
      (let
          ((li-prime (semireverse li (random-integer (length li)))))
        (cons (car li-prime) (shuffle (cdr li-prime))))))


$ include "seed7_05.s7i";

const type: intArray is array integer;

const proc: shuffle (inout intArray: a) is func
  local
    var integer: i is 0;
    var integer: k is 0;
    var integer: tmp is 0;
  begin
    for i range maxIdx(a) downto 2 do
      k := rand(1, i);
      tmp := a[i];
      a[i] := a[k];
      a[k] := tmp;
    end for;
  end func;

const proc: main is func
  local
    var intArray: a is 10 times 0;
    var integer: i is 0;
  begin
    for key i range a do
      a[i] := i;
    end for;
    shuffle(a);
    for i range a do
      write(i <& " ");
    end for;
    writeln;
  end func;


set list to 1..9 -- a range, will become a list as needed
set last to the number of items in list

repeat with i = last down to 2 -- in SenseTalk, the first index in a list is 1
	set j = random (1,i-1)
	set [item i of list, item j of list] to [item j of list, item i of list] -- swap items
end repeat

put list


func knuth_shuffle(a) {
    for i (a.len ^.. 1) {
        var j = i.irand
        a[i, j] = a[j, i]
    }
    return a
}

say knuth_shuffle(@(1..10))


"The selector swap:with: is documented, but it seems not
 implemented (GNU Smalltalk version 3.0.4); so here it is an implementation"
SequenceableCollection extend [
  swap: i with: j [
    |t|
    t := self at: i.
    self at: i put: (self at: j).
    self at: j put: t.
  ]
].

Object subclass: Shuffler [
  Shuffler class >> Knuth: aSequenceableCollection [
    |n k|
    n := aSequenceableCollection size.
    [ n > 1 ] whileTrue: [
      k := Random between: 1 and: n.
      aSequenceableCollection swap: n with: k.
      n := n - 1
    ]
  ]
].


* Library for random()
-include 'Random.sno'

*       # String -> array
        define('s2a(str,n)i') :(s2a_end)
s2a     s2a = array(n); str = str ' '
sa1     str break(' ') . s2a<i = i + 1> span(' ') = :s(sa1)f(return)
s2a_end

*       # Array -> string
        define('a2s(a)i') :(a2s_end)
a2s     a2s = a2s a<i = i + 1> ' ' :s(a2s)f(return)
a2s_end

*       # Knuth shuffle in-place
        define('shuffle(a)alen,n,k,tmp') :(shuffle_end)
shuffle n = alen = prototype(a);
sh1     k = convert(random() * alen,'integer') + 1
        eq(a<n>,a<k>) :s(sh2)
        tmp = a<n>; a<n> = a<k>; a<k> = tmp
sh2     n = gt(n,1) n - 1 :s(sh1)
        shuffle = a :(return)
shuffle_end

*       # Test and display
        a = s2a('1 2 3 4 5 6 7 8 9 10',10)
        output = a2s(a) '->'
        shuffle(a)
        output = a2s(a)
end


mata
function shuffle(a) {
	n = length(a)
	r = runiformint(1,1,1,1..n)
	for (i=n; i>=2; i--) {
		j = r[i]
		x = a[i]
		a[i] = a[j]
		a[j] = x
	}
	return(a)
}

shuffle(1..10)
end


import func Darwin.arc4random_uniform

extension Array {

    func shuffle() -> Array {

        var result = self; result.shuffleInPlace(); return result
    }

    mutating func shuffleInPlace() {

        for i in 1 ..< count { swap(&self[i], &self[Int(arc4random_uniform(UInt32(i+1)))]) }
    }

}

// Swift 2.0:
print([1, 2, 3, 4, 5, 6, 7, 8, 9, 10].shuffle())
// Swift 1.x:
//println([1, 2, 3, 4, 5, 6, 7, 8, 9, 10].shuffle())


proc knuth_shuffle lst {
   set j [llength $lst]
   for {set i 0} {$j > 1} {incr i;incr j -1} {
       set r [expr {$i+int(rand()*$j)}]
       set t [lindex $lst $i]
       lset lst $i [lindex $lst $r]
       lset lst $r $t
   }
   return $lst
}

% knuth_shuffle {1 2 3 4 5}
2 1 3 5 4
% knuth_shuffle {1 2 3 4 5}
5 2 1 4 3
% knuth_shuffle {tom dick harry peter paul mary}
tom paul mary harry peter dick


:"SHUFFLE"
:L1→L2
:dim(L2)→A
:For(B,1,dim(L2)-1)
:randInt(1,A)→C
:L2(C)→D
:L2(A)→L2(C)
:D→L2(A)
:A-1→A
:End
:DelVar A
:DelVar B
:DelVar C
:DelVar D
:Return


$$ MODE TUSCRIPT
oldnumbers=newnumbers="",range=20
LOOP nr=1,#range
 oldnumbers=APPEND(oldnumbers,nr)
ENDLOOP

PRINT "before ",oldnumbers

LOOP r=#range,1,-1
 RANDNR=RANDOM_NUMBERS (1,#r,1)
 shuffle=SELECT (oldnumbers,#randnr,oldnumbers)
 newnumbers=APPEND(newnumbers,shuffle)
ENDLOOP

PRINT "after  ",newnumbers


PRINT "before:"
FOR L = 0 TO 51
    @(L) = L
    PRINT @(L); " ";
NEXT

FOR L = 51 TO 0 STEP -1
    C = RND(L + 1)
    IF C # L THEN
      PUSH @(C), L, @(L), C
      GOSUB 100
    ENDIF
NEXT

PRINT : PRINT "after:"
FOR L = 0 TO 51
    PRINT @(L); " ";
NEXT
PRINT
END

100 @(POP()) = POP() : @(POP()) = POP() : RETURN


# Shuffle array[@].
function shuffle {
	integer i j t

	((i = ${#array[@]}))
	while ((i > 1)); do
		((j = RANDOM))                 # 0 <= j < 32768
		((j < 32768 % i)) && continue  # no modulo bias
		((j %= i))                     # 0 <= j < i

		((i -= 1))
		((t = array[i]))
		((array[i] = array[j]))
		((array[j] = t))
	done
}

# Test program.
set -A array 11 22 33 44 55 66 77 88 99 110
shuffle
echo "${array[@]}"


Private Sub Knuth(Optional ByRef a As Variant)
    Dim t As Variant, i As Integer
    If Not IsMissing(a) Then
        For i = UBound(a) To LBound(a) + 1 Step -1
            j = Int((UBound(a) - LBound(a) + 1) * Rnd + LBound(a))
            t = a(i)
            a(i) = a(j)
            a(j) = t
        Next i
    End If
End Sub
Public Sub program()
    Dim b As Variant, c As Variant, d As Variant, e As Variant
    Randomize
    'imagine an empty array on this line
    b = [{10}]
    c = [{10, 20}]
    d = [{10, 20, 30}]
    e = [{11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}]
    f = [{"This ", "is ", "a ", "test"}]
    Debug.Print "Before:"
    Knuth 'feeding an empty array ;)
    Debug.Print "After: "
    Debug.Print "Before:";
    For Each i In b: Debug.Print i;: Next i: Debug.Print
    Knuth b
    Debug.Print "After: ";
    For Each i In b: Debug.Print i;: Next i: Debug.Print
    Debug.Print "Before:";
    For Each i In c: Debug.Print i;: Next i: Debug.Print
    Knuth c
    Debug.Print "After: ";
    For Each i In c: Debug.Print i;: Next i: Debug.Print
    Debug.Print "Before:";
    For Each i In d: Debug.Print i;: Next i: Debug.Print
    Knuth d
    Debug.Print "After: ";
    For Each i In d: Debug.Print i;: Next i: Debug.Print
    Debug.Print "Before:";
    For Each i In e: Debug.Print i;: Next i: Debug.Print
    Knuth e
    Debug.Print "After: ";
    For Each i In e: Debug.Print i;: Next i: Debug.Print
    Debug.Print "Before:";
    For Each i In f: Debug.Print i;: Next i: Debug.Print
    Knuth f
    Debug.Print "After: ";
    For Each i In f: Debug.Print i;: Next i: Debug.Print
End Sub


function shuffle( a )
	dim i
	dim r
	randomize timer
	for i = lbound( a ) to ubound( a )
		r = int( rnd * ( ubound( a ) + 1 )  )
		if r <> i then
			swap a(i), a(r)
		end if
	next
	shuffle = a
end function

sub swap( byref a, byref b )
	dim tmp
	tmp = a
	a = b
	b = tmp
end sub


T Bounty
   Int value
   Float weight, volume
   F (value, weight, volume)
      (.value, .weight, .volume) = (value, weight, volume)

V panacea = Bounty(3000,  0.3, 0.025)
V ichor   = Bounty(1800,  0.2, 0.015)
V gold    = Bounty(2500,  2.0, 0.002)
V sack    = Bounty(   0, 25.0, 0.25)
V best    = Bounty(   0,    0, 0)
V current = Bounty(   0,    0, 0)

V best_amounts = (0, 0, 0)

V max_panacea = Int(min(sack.weight I/ panacea.weight, sack.volume I/ panacea.volume))
V max_ichor   = Int(min(sack.weight I/ ichor.weight,   sack.volume I/ ichor.volume))
V max_gold    = Int(min(sack.weight I/ gold.weight,    sack.volume I/ gold.volume))

L(npanacea) 0 .< max_panacea
   L(nichor) 0 .< max_ichor
      L(ngold) 0 .< max_gold
         current.value = npanacea * panacea.value + nichor * ichor.value + ngold * gold.value
         current.weight = npanacea * panacea.weight + nichor * ichor.weight + ngold * gold.weight
         current.volume = npanacea * panacea.volume + nichor * ichor.volume + ngold * gold.volume

         I current.value > best.value & current.weight <= sack.weight & current.volume <= sack.volume
            best = current
            best_amounts = (npanacea, nichor, ngold)

print(‘Maximum value achievable is ’best.value)
print(‘This is achieved by carrying (one solution) #. panacea, #. ichor and #. gold’.format(best_amounts[0], best_amounts[1], best_amounts[2]))
print(‘The weight to carry is #2.1 and the volume used is #.3’.format(best.weight, best.volume))


import rand
import rand.seed

fn shuffle(mut arr []int) {
    for i := arr.len - 1; i >= 0; i-- {
        j := rand.intn(i + 1)
        arr[i], arr[j] = arr[j], arr[i]
    }
    println('After Shuffle: $arr')
}

fn main() {
    seed_array := seed.time_seed_array(2)
    rand.seed(seed_array)
    mut arr := [6, 9, 1, 4]
    println('Input: $arr')
    shuffle(mut arr)
    shuffle(mut arr)
    println('Output: $arr')
}


import "random" for Random

var rand = Random.new()

var knuthShuffle = Fn.new { |a|
    var i = a.count - 1
    while (i >= 1) {
        var j = rand.int(i + 1)
        var t = a[i]
        a[i] = a[j]
        a[j] = t
        i = i - 1
    }
}

var tests = [ [], [10], [10, 20], [10, 20, 30] ]
for (a in tests) {
    var b = a.toList // store original order
    knuthShuffle.call(a)
    System.print("%(b) -> %(a)")
}


*        Knapsack problem/Unbounded   04/02/2017
KNAPSACK CSECT
         USING  KNAPSACK,R13       base register
         B      72(R15)            skip savearea
         DC     17F'0'             savearea
         STM    R14,R12,12(R13)    prolog
         ST     R13,4(R15)         " <-
         ST     R15,8(R13)         " ->
         LR     R13,R15            " addressability
         MVC    S,=F'0'            s(1,kva)=0;
         LA     R11,0              ns=0
         LA     R1,KW              kw
         SLA    R1,2               *4
         L      R2,PANACEA-4(R1)   panacea(kw)
         L      R4,SACKW           sackw
         SRDA   R4,32              ~
         DR     R4,R2              sackw/panacea(kw)
         ST     R5,XP              xp=sackw/panacea(kw)
         LA     R1,KV              kv
         SLA    R1,2               *4
         L      R2,PANACEA-4(R1)   panacea(kv)
         L      R4,SACKV           sackv
         SRDA   R4,32              ~
         DR     R4,R2              r5=sackv/panacea(kv)
         C      R5,XP              if r5<xp
         BNL    EMINXP
         ST     R5,XP     xp=min(sackw/panacea(kw),sackv/panacea(kv))
EMINXP   LA     R1,KW              kw
         SLA    R1,2               *4
         L      R2,ICHOR-4(R1)     ichor(kw)
         L      R4,SACKW           sackw
         SRDA   R4,32              ~
         DR     R4,R2              sackw/ichor(kw)
         ST     R5,XI              xi=sackw/ichor(kw)
         LA     R1,KV              kv
         SLA    R1,2               *4
         L      R2,ICHOR-4(R1)     ichor(kv)
         L      R4,SACKV           sackv
         SRDA   R4,32              ~
         DR     R4,R2              r5=sackv/ichor(kv)
         C      R5,XI              if r5<xi
         BNL    EMINXI
         ST     R5,XI     xi=min(sackw/ichor(kw),sackv/ichor(kv))
EMINXI   LA     R1,KW              kw
         SLA    R1,2               *4
         L      R2,GOLD-4(R1)      gold(kw)
         L      R4,SACKW           sackw
         SRDA   R4,32              ~
         DR     R4,R2              sackw/gold(kw)
         ST     R5,XG              xg=sackw/gold(kw)
         LA     R1,KV              kv
         SLA    R1,2               *4
         L      R2,GOLD-4(R1)      gold(kv)
         L      R4,SACKV           sackv
         SRDA   R4,32              ~
         DR     R4,R2              r5=sackv/gold(kv)
         C      R5,XG              if r5<xg
         BNL    EMINXG
         ST     R5,XG     xg=min(sackw/gold(kw),sackv/gold(kv))
EMINXG   SR     R10,R10            ip=0
LOOPIP   C      R10,XP             do ip=0 to xp
         BH     ELOOPIP
         SR     R9,R9              ii=0
LOOPII   C      R9,XI              do ii=0 to xi
         BH     ELOOPII
         SR     R8,R8              ig=0
LOOPIG   C      R8,XG              do ig=0 to xg
         BH     ELOOPIG
         LA     R7,KVA             m=kva
LOOPM    C      R7,=A(KV)          do m=kva to kv
         BH     ELOOPM
         LR     R1,R7              m
         SLA    R1,2               *4
         LR     R5,R8              ig
         M      R4,GOLD-4(R1)      *gold(m)
         LR     R2,R5              r2=ig*gold(m)
         LR     R5,R9              ii
         M      R4,ICHOR-4(R1)     *ichor(m)
         AR     R2,R5              r2=ig*gold(m)+ii*ichor(m)
         LR     R5,R10             ip
         M      R4,PANACEA-4(R1)   *panacea(m)
         AR     R2,R5              r2=r2+ip*panacea(m)
         ST     R2,CUR-4(R1)       cur(m)=r2
         LA     R7,1(R7)           m=m+1
         B      LOOPM
ELOOPM   LA     R1,KVA             kva
         SLA    R1,2               *4
         L      R2,CUR-4(R1)       cur(kva)
         C      R2,S-4(R1)         if cur(kva)>=s(1,kva)
         BL     ENDIF
         LA     R1,KW              kw
         SLA    R1,2               *4
         L      R2,CUR-4(R1)       cur(kw)
         C      R2,SACKW           if cur(kw)<=sackw
         BH     ENDIF
         LA     R1,KV              kv
         SLA    R1,2               *4
         L      R2,CUR-4(R1)       cur(kv)
         C      R2,SACKV           if cur(kv)<=sackv
         BH     ENDIF
         LR     R6,R11             j=ns
LOOPJ    C      R6,=F'1'           do j=ns to 1 by -1
         BL     ELOOPJ
         LR     R1,R6              j
         MH     R1,=H'24'          *24
         LA     R2,S(R1)           s(j+1,1)
         LA     R3,S-24(R1)        s(j,1)
         MVC    0(24,R2),0(R3)     s(j+1,*)=s(j,*)
         BCTR   R6,0               j=j-1
         B      LOOPJ
ELOOPJ   LA     R1,KVA             kva
         SLA    R1,2               *4
         L      R2,CUR-4(R1)       cur(kva)
         ST     R2,S-4(R1)         s(1,kva)=cur(kva)
         LA     R1,KW              kw
         SLA    R1,2               *4
         L      R2,CUR-4(R1)       cur(kw)
         ST     R2,S-4(R1)         s(1,kw)=cur(kw)
         LA     R1,KV              kv
         SLA    R1,2               *4
         L      R2,CUR-4(R1)       cur(kv)
         ST     R2,S-4(R1)         s(1,kv)=cur(kv)
         LA     R1,KP              kp
         SLA    R1,2               *4
         ST     R10,S-4(R1)        s(1,kp)=ip
         LA     R1,KI              ki
         SLA    R1,2               *4
         ST     R9,S-4(R1)         s(1,ki)=ii
         LA     R1,KG              kg
         SLA    R1,2               *4
         ST     R8,S-4(R1)         s(1,kg)=ig
         L      R2,S               r2=s(1,1)
         C      R2,S+24            if s(1,1)>s(2,1)
         BNH    ELSE
         LA     R11,1              ns=1
         B      ENDIF
ELSE     LA     R11,1(R11)         ns+1
ENDIF    LA     R8,1(R8)           ig=ig+1
         B      LOOPIG
ELOOPIG  LA     R9,1(R9)           ii=ii+1
         B      LOOPII
ELOOPII  LA     R10,1(R10)         ip=ip+1
         B      LOOPIP
ELOOPIP  XPRNT  TITLE,72
         LA     R6,1               j=1
         LA     R3,S-4             [email protected]
LOOPJP   CR     R6,R11             do j=1 to ns
         BH     ELOOPJP
         LA     R3,4(R3)           ++
         L      R1,0(R3)           s(j,kva)
         XDECO  R1,PG              edit
         LA     R3,4(R3)           ++
         L      R1,0(R3)           s(j,kw)
         XDECO  R1,PG+12           edit
         LA     R3,4(R3)           ++
         L      R1,0(R3)           s(j,kv)
         XDECO  R1,PG+24           edit
         MVC    PG+20(2),PG+21     shift
         MVI    PG+22,C'.'         decimal point
         LA     R3,4(R3)           ++
         L      R1,0(R3)           s(j,kp)
         XDECO  R1,PG+36           edit
         MVC    PG+31(2),=C'0.'    decimal point
         LA     R3,4(R3)           ++
         L      R1,0(R3)           s(j,ki)
         XDECO  R1,PG+48           edit
         LA     R3,4(R3)           ++
         L      R1,0(R3)           s(j,kg)
         XDECO  R1,PG+60           edit
         XPRNT  PG,L'PG            print buffer
         LA     R6,1(R6)           j=j+1
         B      LOOPJP
ELOOPJP  L      R13,4(0,R13)       epilog
         LM     R14,R12,12(R13)    " restore
         XR     R15,R15            " rc=0
         BR     R14                exit
KVA      EQU    1
KW       EQU    2
KV       EQU    3
KP       EQU    4
KI       EQU    5
KG       EQU    6
SACKW    DC     F'250'
SACKV    DC     F'250'
PANACEA  DC     F'3000',F'3',F'25'
ICHOR    DC     F'1800',F'2',F'15'
GOLD     DC     F'2500',F'20',F'2'
XP       DS     F
XI       DS     F
XG       DS     F
CUR      DS     3F
S        DS     60F
TITLE    DC     CL36'       Value      Weight      Volume'
         DC     CL36'     Panacea       Ichor        Gold'
PG       DS     CL72
         YREGS
         END    KNAPSACK


with Ada.Text_IO;

procedure Knapsack_Unbounded is

   type Bounty is record
      Value  : Natural;
      Weight : Float;
      Volume : Float;
   end record;

   function Min (A, B : Float) return Float is
   begin
      if A < B then
         return A;
      else
         return B;
      end if;
   end Min;

   Panacea : Bounty := (3000,  0.3, 0.025);
   Ichor   : Bounty := (1800,  0.2, 0.015);
   Gold    : Bounty := (2500,  2.0, 0.002);
   Limits  : Bounty := (   0, 25.0, 0.250);
   Best    : Bounty := (   0,  0.0, 0.000);
   Current : Bounty := (   0,  0.0, 0.000);

   Best_Amounts : array (1 .. 3) of Natural := (0, 0, 0);

   Max_Panacea : Natural := Natural (Float'Floor (Min
                              (Limits.Weight / Panacea.Weight,
                               Limits.Volume / Panacea.Volume)));
   Max_Ichor   : Natural := Natural (Float'Floor (Min
                              (Limits.Weight / Ichor.Weight,
                               Limits.Volume / Ichor.Volume)));
   Max_Gold    : Natural := Natural (Float'Floor (Min
                              (Limits.Weight / Gold.Weight,
                               Limits.Volume / Gold.Volume)));

begin
   for Panacea_Count in 0 .. Max_Panacea loop
      for Ichor_Count in 0 .. Max_Ichor loop
         for Gold_Count in 0 .. Max_Gold loop
            Current.Value  := Panacea_Count * Panacea.Value +
                              Ichor_Count * Ichor.Value +
                              Gold_Count * Gold.Value;
            Current.Weight := Float (Panacea_Count) * Panacea.Weight +
                              Float (Ichor_Count) * Ichor.Weight +
                              Float (Gold_Count) * Gold.Weight;
            Current.Volume := Float (Panacea_Count) * Panacea.Volume +
                              Float (Ichor_Count) * Ichor.Volume +
                              Float (Gold_Count) * Gold.Volume;
            if Current.Value  >  Best.Value and
               Current.Weight <= Limits.Weight and
               Current.Volume <= Limits.Volume then
               Best := Current;
               Best_Amounts := (Panacea_Count, Ichor_Count, Gold_Count);
            end if;
         end loop;
      end loop;
   end loop;
   Ada.Text_IO.Put_Line ("Maximum value:" & Natural'Image (Best.Value));
   Ada.Text_IO.Put_Line ("Panacea:" & Natural'Image (Best_Amounts (1)));
   Ada.Text_IO.Put_Line ("Ichor:  " & Natural'Image (Best_Amounts (2)));
   Ada.Text_IO.Put_Line ("Gold:   " & Natural'Image (Best_Amounts (3)));
end Knapsack_Unbounded;


proc Shuffle(Array, Items, BytesPerItem);
int  Array, Items, BytesPerItem;
int  I, J;
char Temp(8);
[for I:= Items-1 downto 1 do
    [J:= Ran(I+1);      \range [0..I]
    CopyMem(Temp, Array+I*BytesPerItem, BytesPerItem);
    CopyMem(Array+I*BytesPerItem, Array+J*BytesPerItem, BytesPerItem);
    CopyMem(Array+J*BytesPerItem, Temp, BytesPerItem);
    ];
];

string 0;       \use zero-terminated strings
int A;  char B;  real C;
int I;
[A:= [1, 2, 3, 4, 5];
Shuffle(A, 5, 4 \bytes per int\);
for I:= 0 to 5-1 do
    [IntOut(0, A(I));  ChOut(0, ^ )];
CrLf(0);
B:= "12345";
Shuffle(B, 5, 1 \byte per char\);
for I:= 0 to 5-1 do
    [ChOut(0, B(I));  ChOut(0, ^ )];
CrLf(0);
C:= [1., 2., 3., 4., 5.];
Shuffle(addr C(0), 5, 8 \bytes per real\);
for I:= 0 to 5-1 do
    [RlOut(0, C(I));  ChOut(0, ^ )];
CrLf(0);
A:= [10];
Shuffle(A, 1, 4 \bytes per int\);
for I:= 0 to 1-1 do
    [IntOut(0, A(I));  ChOut(0, ^ )];
CrLf(0);
]


// Rosetta Code problem: https://www.rosettacode.org/wiki/Ramsey%27s_theorem
// by Jjuanhdez, 06/2022

dim array(52)
for i = 1 to arraysize(array(),1) : array(i) = i : next i

print "Starting array"
for i = 1 to arraysize(array(),1)
    print array(i) using "####";
next i

KnuthShuffle(array())

print "\n\nAfter Knuth shuffle downwards"
for i = 1 to arraysize(array(),1)
    print array(i) using "####";
next i
print
end

sub KnuthShuffle(a())
    local i, j, t, lb, ub
    lb = 1
    ub = arraysize(a(),1) - lb

    for i = lb to ub
        j = round(ran(i +1))
        t = a(lb + i)
        a(lb + i) = a(lb + j)
        a(lb + j) = t
    next i
end sub


fcn kshuffle(xs){
   foreach i in ([xs.len()-1..1,-1]){ xs.swap(i,(0).random(0,i+1)) }
   xs
}
fcn kshufflep(xs){
   [xs.len()-1..1,-1].pump(Void,'wrap(i){ xs.swap(i,(0).random(0,i+1)) })
   xs
}


MODE BOUNTY = STRUCT(STRING name, INT value, weight, volume);

[]BOUNTY items = (
               ("panacea", 3000,   3,  25),
               ("ichor",   1800,   2,  15),
               ("gold",    2500,  20,   2)
      );

BOUNTY sack := ("sack",       0, 250, 250);

OP * = ([]INT a,b)INT: ( # dot product operator #
    INT sum := 0;
    FOR i TO UPB a DO sum +:= a[i]*b[i] OD;
    sum
);

OP INIT = (REF[]INT vector)VOID:
    FOR index FROM LWB vector TO UPB vector DO
        vector[index]:=0
    OD;

OP INIT = (REF[,]INT matrix)VOID:
    FOR row index FROM LWB matrix TO UPB matrix DO
        INIT matrix[row index,]
    OD;

PROC total value = ([]INT items count, []BOUNTY items, BOUNTY sack) STRUCT(INT value, weight, volume):(
    ###
    Given the count of each item in the sack return -1 if they can"t be carried or their total value.

    (also return the negative of the weight and the volume so taking the max of a series of return
    values will minimise the weight if values tie, and minimise the volume if values and weights tie).
    ###
    INT weight = items count * weight OF items;
    INT volume = items count * volume OF items;
    IF weight > weight OF sack OR volume > volume OF sack THEN
        (-1, 0, 0)
    ELSE
        ( items count * value OF items, -weight, -volume)
    FI
);

PRIO WRAP = 5; # wrap negative array indices as per python's indexing regime #
OP WRAP = (INT index, upb)INT:
  IF index>=0 THEN index ELSE upb + index + 1 FI;

PROC knapsack dp = ([]BOUNTY items, BOUNTY sack)[]INT:(
    ###
    Solves the Knapsack problem, with two sets of weights,
    using a dynamic programming approach
    ###

    # (weight+1) x (volume+1) table #
    # table[w,v] is the maximum value that can be achieved #
    # with a sack of weight w and volume v. #
    # They all start out as 0 (empty sack) #
    [0:weight OF sack, 0:volume OF sack]INT table; INIT table;

    FOR w TO 1 UPB table DO
        FOR v TO 2 UPB table DO
            ### Consider the optimal solution, and consider the "last item" added
            to the sack. Removing this item must produce an optimal solution
            to the subproblem with the sack"s weight and volume reduced by that
            of the item. So we search through all possible "last items": ###
            FOR item index TO UPB items DO
                BOUNTY item := items[item index];
                # Only consider items that would fit: #
                IF w >= weight OF item AND v >= volume OF item THEN
                    # Optimal solution to subproblem + value of item: #
                    INT candidate := table[w-weight OF item,v-volume OF item] + value OF item;
                    IF candidate > table[w,v] THEN
                        table[w,v] := candidate
                    FI
                FI
            OD
        OD
    OD;

    [UPB items]INT result; INIT result;
    INT w := weight OF sack, v := volume OF sack;
    WHILE table[w,v] /= 0 DO
        # Find the last item that was added: #
        INT needle = table[w,v];
        INT item index;
        FOR i TO UPB items WHILE
            item index := i;
            BOUNTY item = items[item index];
            INT candidate = table[w-weight OF item WRAP UPB table, v-volume OF item WRAP 2 UPB table] + value OF item;
#       WHILE # candidate NE needle DO
          SKIP
        OD;
        # Record it in the result, and remove it: #
        result[item index] +:= 1;
        w -:= weight OF items[item index];
        v -:= volume OF items[item index]
    OD;
    result
);

[]INT max items = knapsack dp(items, sack);
STRUCT (INT value, weight, volume) max :=  total value(max items, items, sack);
max := (value OF max, -weight OF max, -volume OF max);

FORMAT d = $zz-d$;

printf(($"The maximum value achievable (by dynamic programming) is "gl$, value OF max));
printf(($"  The number of ("n(UPB items-1)(g", ")g") items to achieve this is: ("n(UPB items-1)(f(d)",")f(d)") respectively"l$,
    name OF items, max items));
printf(($"  The weight to carry is "f(d)", and the volume used is "f(d)l$,
    weight OF max, volume OF max))


Item  = Panacea,Ichor,Gold
Value = 3000,1800,2500
Weight= 3,2,20                         ; *10
Volume= 25,15,2                        ; *1000

StringSplit I, Item,  `,               ; Put input in arrays
StringSplit W, Weight,`,
StringSplit $, Value, `,
StringSplit V, Volume,`,

SetFormat Float, 0.3
W := 250, V := 250, sW:=.1, sV:=.001   ; limits for the total, scale factors
p := -1, Wp := -W1, Vp := -V1          ; initial values
While (Wp+=W1) <= W && (Vp+=V1) <= V {
   p++, Wi := Wp-W2, Vi := Vp-V2, i := -1
   While (Wi+=W2) <= W && (Vi+=V2) <= V {
      i++, Wg := Wi-W3, Vg := Vi-V3, g := -1
      While (Wg+=W3) <= W && (Vg+=V3) <= V
         If ($ <= Val := p*$1 + i*$2 + ++g*$3)
             t := ($=Val ? t "`n    " : "    ")
           . p "`t   " i "`t   " g "`t  " Wg*sW "`t   " Vg*sV
           , $ := Val
   }
}
MsgBox Value = %$%`n`nPanacea`tIchor`tGold`tWeight`tVolume`n%t%


(knapsack=
  ( things
  =   (panacea.3000.3/10.25/1000)
      (ichor.1800.2/10.15/1000)
      (gold.2500.2.2/1000)
  )
& 0:?maxvalue
& :?sack
& ( add
  =     cumwght
        cumvol
        cumvalue
        cumsack
        name
        wght
        val
        vol
        tings
        n
        ncumwght
        ncumvalue
        ncumvol
    .     !arg
        : ( ?cumwght
          . ?cumvol
          . ?cumvalue
          . ?cumsack
          . (?name.?val.?wght.?vol) ?tings
          )
      & -1:?n
      &   whl
        ' ( 1+!n:?n
          & !cumwght+!n*!wght:~>25:?ncumwght
          & !cumvol+!n*!vol:~>250/1000:?ncumvol
          & !cumvalue+!n*!val:?ncumvalue
          & (   !tings:
              & (   !ncumvalue:>!maxvalue:?maxvalue
                  &     !cumsack
                        ( !n:0&
                        |   ( !cumsack:&Take
                            | Finally
                            )
                            " take "
                            !n
                            " items of "
                            !name
                            ".\n"
                        )
                    : ?sack
                |
                )
            |   add
              $ ( !ncumwght
                . !ncumvol
                . !ncumvalue
                .   !cumsack
                    ( !n:0&
                    | "Take " !n " items of " !name ".\n"
                    )
                . !tings
                )
            )
          )
  )
& add$(0.0.0..!things)
& out$(str$(!sack "The value in the knapsack is " !maxvalue "."))
&
);

!knapsack;


#include <stdio.h>
#include <stdlib.h>

typedef struct {
    char *name;
    double value;
    double weight;
    double volume;
} item_t;

item_t items[] = {
    {"panacea", 3000.0, 0.3, 0.025},
    {"ichor",   1800.0, 0.2, 0.015},
    {"gold",    2500.0, 2.0, 0.002},
};

int n = sizeof (items) / sizeof (item_t);
int *count;
int *best;
double best_value;

void knapsack (int i, double value, double weight, double volume) {
    int j, m1, m2, m;
    if (i == n) {
        if (value > best_value) {
            best_value = value;
            for (j = 0; j < n; j++) {
                best[j] = count[j];
            }
        }
        return;
    }
    m1 = weight / items[i].weight;
    m2 = volume / items[i].volume;
    m = m1 < m2 ? m1 : m2;
    for (count[i] = m; count[i] >= 0; count[i]--) {
        knapsack(
            i + 1,
            value + count[i] * items[i].value,
            weight - count[i] * items[i].weight,
            volume - count[i] * items[i].volume
        );
    }
}

int main () {
    count = malloc(n * sizeof (int));
    best = malloc(n * sizeof (int));
    best_value = 0;
    knapsack(0, 0.0, 25.0, 0.25);
    int i;
    for (i = 0; i < n; i++) {
        printf("%d %s\n", best[i], items[i].name);
    }
    printf("best value: %.0f\n", best_value);
    free(count); free(best);
    return 0;
}


/*Knapsack

  This model finds the integer optimal packing of a knapsack

  Nigel_Galloway
  January 29th., 2012
*/
using Microsoft.SolverFoundation.Services;

namespace KnapU
{
    class Item {
        public string Name {get; set;}
        public int Value {get; set;}
        public double Weight {get; set;}
        public double Volume {get; set;}

        public Item(string name, int value, double weight, double volume) {
            Name = name;
            Value = value;
            Weight = weight;
            Volume = volume;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            SolverContext context = SolverContext.GetContext();
            Model model = context.CreateModel();
            Item[] Knapsack = new Item[] {
                new Item("Panacea", 3000, 0.3, 0.025),
                new Item("Ichor", 1800, 0.2, 0.015),
                new Item("Gold", 2500, 2.0, 0.002)
            };
            Set items = new Set(Domain.Any, "items");
            Decision take = new Decision(Domain.IntegerNonnegative, "take", items);
            model.AddDecision(take);
            Parameter value = new Parameter(Domain.IntegerNonnegative, "value", items);
            value.SetBinding(Knapsack, "Value", "Name");
            Parameter weight = new Parameter(Domain.RealNonnegative, "weight", items);
            weight.SetBinding(Knapsack, "Weight", "Name");
            Parameter volume = new Parameter(Domain.RealNonnegative, "volume", items);
            volume.SetBinding(Knapsack, "Volume", "Name");
            model.AddParameters(value, weight, volume);
            model.AddConstraint("knap_weight", Model.Sum(Model.ForEach(items, t => take[t] * weight[t])) <= 25);
            model.AddConstraint("knap_vol", Model.Sum(Model.ForEach(items, t => take[t] * volume[t])) <= 0.25);
            model.AddGoal("knap_value", GoalKind.Maximize, Model.Sum(Model.ForEach(items, t => take[t] * value[t])));
            Solution solution = context.Solve(new SimplexDirective());
            Report report = solution.GetReport();
            System.Console.Write("{0}", report);
        }
    }
}


(defstruct item :value :weight :volume)

(defn total [key items quantities]
  (reduce + (map * quantities (map key items))))

(defn max-count [item max-weight max-volume]
  (let [mcw (/ max-weight (:weight item))
        mcv (/ max-volume (:volume item))]
    (min mcw mcv)))


(defun fill-knapsack (items max-volume max-weight)
  "Items is a list of lists of the form (name value weight volume) where weight
and value are integers. max-volume and max-weight, also integers, are the
maximum volume and weight of the knapsack. fill-knapsack returns a list of the
form (total-value inventory total-volume total-weight) where total-value is the
total-value of a knapsack packed with inventory (a list whose elements are
elements of items), and total-weight and total-volume are the total weights and
volumes of the inventory."
  ;; maxes is a table indexed by volume and weight, where maxes[volume,weight]
  ;; is a list of the form (value inventory used-volume used-weight) where
  ;; inventory is a list of items of maximum value fitting within volume and
  ;; weight, value is the maximum value, and used-volume/used-weight are the
  ;; actual volume/weight of the inventory.
  (let* ((VV (1+ max-volume))
         (WW (1+ max-weight))
         (maxes (make-array (list VV WW))))
    ;; fill in the base cases where volume or weight is 0
    (dotimes (v VV) (setf (aref maxes v 0) (list 0 '() 0 0)))
    (dotimes (w WW) (setf (aref maxes 0 w) (list 0 '() 0 0)))
    ;; populate the rest of the table. The best value for a volume/weight
    ;; combination is the best way of adding an item to any of the inventories
    ;; from [volume-1,weight], [volume,weight-1], or [volume-1,weight-1], or the
    ;; best of these, if no items can be added.
    (do ((v 1 (1+ v))) ((= v VV) (aref maxes max-volume max-weight))
      (do ((w 1 (1+ w))) ((= w WW))
        (let ((options (sort (list (aref maxes v (1- w))
                                   (aref maxes (1- v) w)
                                   (aref maxes (1- v) (1- w)))
                             '> :key 'first)))
          (destructuring-bind (b-value b-items b-volume b-weight) (first options)
            (dolist (option options)
              (destructuring-bind (o-value o-items o-volume o-weight) option
                (dolist (item items)
                  (destructuring-bind (_ i-value i-volume i-weight) item
                    (declare (ignore _))
                    (when (and (<= (+ o-volume i-volume) v)
                               (<= (+ o-weight i-weight) w)
                               (>  (+ o-value  i-value)  b-value))
                      (setf b-value  (+ o-value  i-value)
                            b-volume (+ o-volume i-volume)
                            b-weight (+ o-weight i-weight)
                            b-items  (list* item o-items)))))))
            (setf (aref maxes v w)
                  (list b-value b-items b-volume b-weight))))))))


void main() @safe /*@nogc*/ {
    import std.stdio, std.algorithm, std.typecons, std.conv;

    static struct Bounty {
        int value;
        double weight, volume;
    }

    immutable Bounty panacea = {3000,  0.3, 0.025};
    immutable Bounty ichor =   {1800,  0.2, 0.015};
    immutable Bounty gold =    {2500,  2.0, 0.002};
    immutable Bounty sack =    {   0, 25.0, 0.25 };

    immutable maxPanacea = min(sack.weight / panacea.weight,
                               sack.volume / panacea.volume).to!int;
    immutable maxIchor   = min(sack.weight / ichor.weight,
                               sack.volume / ichor.volume).to!int;
    immutable maxGold    = min(sack.weight / gold.weight,
                               sack.volume / gold.volume).to!int;

    Bounty best = {0, 0, 0};
    Tuple!(int, int, int) bestAmounts;

    foreach (immutable nPanacea; 0 .. maxPanacea)
        foreach (immutable nIchor; 0 .. maxIchor)
            foreach (immutable nGold; 0 .. maxGold) {
                immutable Bounty current = {
                    value: nPanacea * panacea.value +
                           nIchor * ichor.value +
                           nGold * gold.value,
                    weight: nPanacea * panacea.weight +
                            nIchor * ichor.weight +
                            nGold * gold.weight,
                    volume: nPanacea * panacea.volume +
                            nIchor * ichor.volume +
                            nGold * gold.volume};

                if (current.value > best.value &&
                    current.weight <= sack.weight &&
                    current.volume <= sack.volume) {
                    best = Bounty(current.value, current.weight, current.volume);
                    bestAmounts = tuple(nPanacea, nIchor, nGold);
                }
            }

    writeln("Maximum value achievable is ", best.value);
    writefln("This is achieved by carrying (one solution) %d" ~
             " panacea, %d ichor and %d gold", bestAmounts[]);
    writefln("The weight to carry is %4.1f and the volume used is %5.3f",
             best.weight, best.volume);
}


pragma.enable("accumulator")

/** A data type representing a bunch of stuff (or empty space). */
def makeQuantity(value, weight, volume, counts) {
  def quantity {
    to __printOn(out) {
      for name => n in counts { out.print(`$n $name  `) }
      out.print(`(val=$value wt=$weight vol=$volume)`)
    }
    to value () { return value  }
    to weight() { return weight }
    to volume() { return volume }
    to counts() { return counts }
    to subtract(other) { return quantity + other * -1 }
    to add(other) {
      return makeQuantity(value  + other.value (),
                          weight + other.weight(),
                          volume + other.volume(),
                          accum counts for name => n in other.counts() { _.with(name, n+counts.fetch(name, fn {0})) })
    }
    to multiply(scalar) {
      return makeQuantity(value  * scalar,
                          weight * scalar,
                          volume * scalar,
                          accum [].asMap() for name => n in counts { _.with(name, n*scalar) })
    }
    /** a.fit(b) the greatest integer k such that a - b * k does not have negative weight or volume. */
    to fit(item) {
      return (weight // item.weight()) \
         .min(volume // item.volume())
    }
  }
  return quantity
}

/** Fill the space with the treasures, returning candidate results as spaceAvailable - the items. */
def fill(spaceAvailable, treasures) {
  if (treasures.size().isZero()) { # nothing to pick
    return [spaceAvailable]
  }

  # Pick one treasure type
  def [unit] + otherTreasures := treasures

  var results := []
  for count in (0..spaceAvailable.fit(unit)).descending() {
    results += fill(spaceAvailable - unit * count, otherTreasures)
    if (otherTreasures.size().isZero()) {
      break # If there are no further kinds, there is no point in taking less than the most
    }
  }
  return results
}

def chooseBest(emptyKnapsack, treasures) {
  var maxValue := 0
  var best := []
  for result in fill(emptyKnapsack, treasures) {
    def taken := emptyKnapsack - result # invert the backwards result fill() returns
    if (taken.value() > maxValue) {
      best := [taken]
      maxValue := taken.value()
    } else if (taken.value() <=> maxValue) {
      best with= taken
    }
  }
  return best
}

def printBest(emptyKnapsack, treasures) {
  for taken in chooseBest(emptyKnapsack, treasures) { println(`  $taken`) }
}

def panacea := makeQuantity(3000, 0.3, 0.025, ["panacea" => 1])
def ichor   := makeQuantity(1800, 0.2, 0.015, ["ichor"   => 1])
def gold    := makeQuantity(2500, 2.0, 0.002, ["gold"    => 1])
def emptyKnapsack \
            := makeQuantity(   0,  25, 0.250, [].asMap())

printBest(emptyKnapsack, [panacea, ichor, gold])


(require 'struct)
(require 'hash)
(require 'sql)

(define H null) ;; cache
(define T (make-table (struct goodies (name valeur poids volume ))))
(define-syntax-rule (name i) (table-xref T i 0))
(define-syntax-rule (valeur i) (table-xref T i 1))
(define-syntax-rule (poids i) (table-xref T i 2))
(define-syntax-rule (volume i) (table-xref T i 3))

(define goodies
  '(("🍁-panacea"  3000 300 25)
   ("🌵-ichor"    1800 200 15)
   ("⭐-gold"     2500 2000 2)))

(list->table goodies T)

;; i = item index, p= remaining weight, v = remaining volume

;;  make an unique hash-key from (i p v)
(define (t-key i p v)  (string-append i "|" p "|" v))

;; retrieve best core for item i
;; returns ( score . quantity)

(define (t-get i p v)
   (if ( < i 0) (cons 0 0)
      (hash-ref H (t-key i p v )))) ;; may be #f

;; compute best quantity.score (i), assuming best (i-1 p v) is known
(define (score-qty i p v (q) (score)(smax)(qmax))
	 (or
	 (t-get i p v) ;; already known
	 (begin
 		(set! q (min (quotient p (poids i)) (quotient v (volume i)))) ;; max possible q
 		(set! smax -Infinity)
		    ( for ((k (1+ q))) ;; try all legal quantities
		      (set! score (+
		         (first (score-qty (1- i) (- p (* k (poids i))) (- v (* k (volume i)))))
		         (* k (valeur i))))
		     #:continue (< score smax)
		      (set! smax score)
		      (set! qmax k))
		 (hash-set H (t-key i p v) (cons smax qmax)))))

;; compute best scores, starting from last item
(define (task P V)
        (define N (1- (table-count T)))
        (define qty 0)
        (set! H (make-hash))
	(writeln 'total-value (first (score-qty N P V)))

	(for/list  ((i (in-range N -1 -1)))
			(set! qty (rest (t-get i P V)))
			#:continue (= qty 0)
			(begin0
			(cons (name i) (t-get i P V))
			(set! P (- P (* (poids i) qty)))
			(set! V (- V (* (volume i) qty))))))

;; output
(task 25000 250)
total-value     54500
    → (("⭐-gold" 54500 . 11) ("🌵-ichor" 27000 . 15))

(length (hash-keys H)) ;; # entries in cache
    → 218


class
	KNAPSACK

create
	make

feature

	make
		do
			create panacea;
			panacea := [3000, 0.3, 0.025]
			create ichor;
			ichor := [1800, 0.2, 0.015]
			create gold;
			gold := [2500, 2.0, 0.002]
			create sack;
			sack := [0, 25.0, 0.25]
			find_solution
		end

feature {NONE}

	panacea: TUPLE [value: INTEGER; weight: REAL_64; volume: REAL_64]

	ichor: TUPLE [value: INTEGER; weight: REAL_64; volume: REAL_64]

	gold: TUPLE [value: INTEGER; weight: REAL_64; volume: REAL_64]

	sack: TUPLE [value: INTEGER; weight: REAL_64; volume: REAL_64]

	find_solution
			-- Solution for unbounded Knapsack Problem.
		local
			totalweight, totalvolume: REAL_64
			maxpanacea, maxichor, maxvalue, maxgold: INTEGER
			n: ARRAY [INTEGER]
			r: TUPLE [value: INTEGER; weight: REAL_64; volume: REAL_64]
		do
			maxpanacea := minimum (sack.weight / panacea.weight, sack.volume / panacea.volume).rounded
			maxichor := minimum (sack.weight / ichor.weight, sack.volume / ichor.volume).rounded
			maxgold := minimum (sack.weight / gold.weight, sack.volume / gold.volume).rounded
			create n.make_filled (0, 1, 3)
			create r
			across
				0 |..| maxpanacea as p
			loop
				across
					0 |..| maxichor as i
				loop
					across
						0 |..| maxgold as g
					loop
						r.value := g.item * gold.value + i.item * ichor.value + p.item * panacea.value
						r.weight := g.item * gold.weight + i.item * ichor.weight + p.item * panacea.weight
						r.volume := g.item * gold.volume + i.item * ichor.volume + p.item * panacea.volume
						if r.value > maxvalue and r.weight <= sack.weight and r.volume <= sack.volume then
							maxvalue := r.value
							totalweight := r.weight
							totalvolume := r.volume
							n [1] := p.item
							n [2] := i.item
							n [3] := g.item
						end
					end
				end
			end
			io.put_string ("Maximum value achievable is " + maxValue.out + ".%N")
			io.put_string ("This is achieved by carrying " + n [1].out + " panacea, " + n [2].out + " ichor and " + n [3].out + " gold.%N")
			io.put_string ("The weight is " + totalweight.out + " and the volume is " + totalvolume.truncated_to_real.out + ".")
		end

	minimum (a, b: REAL_64): REAL_64
			-- Smaller of 'a' and 'b'.
		do
			Result := a
			if a > b then
				Result := b
			end
		end

end


defmodule Item do
  defstruct volume: 0.0, weight: 0.0, value: 0
  def new(volume, weight, value) do
    %__MODULE__{volume: volume, weight: weight, value: value}
  end
end

defmodule Knapsack do
  def solve_unbounded(items, maximum) do
    {max_volume, max_weight} = {maximum.volume, maximum.weight}
    max_items = Enum.map(items, fn {name,item} ->
      {name, trunc(min(max_volume / item.volume, max_weight / item.weight))}
    end)
    Enum.map(max_items, fn {name,max} -> for i <- 0..max, do: {name,i} end)
    |> product
    |> total(items)
    |> Enum.filter(fn {_kw, {volume,weight,_}} -> volume <= max_volume and
                                                  weight <= max_weight end)
    |> Enum.group_by(fn {_kw, {_,_,value}} -> value end)
    |> Enum.max
    |> print
  end

  defp product([x]), do: x
  defp product([a,b]), do: for x <- a, y <- b, do: [x,y]
  defp product([h|t]), do: for x <- h, y <- product(t), do: [x | y]

  defp total(lists, items) do
    Enum.map(lists, fn kwlist ->
      total = Enum.reduce(kwlist, {0,0,0}, fn {name,n},{volume,weight,value} ->
        {volume + n * items[name].volume,
         weight + n * items[name].weight,
         value  + n * items[name].value}
      end)
      {kwlist, total}
    end)
  end

  defp print({max_value, data}) do
    IO.puts "Maximum value achievable is #{max_value}\tvolume  weight  value"
    Enum.each(data, fn {kw,{volume,weight,value}} ->
      :io.format "~s =>\t~6.3f, ~5.1f, ~6w~n", [(inspect kw), volume, weight, value]
    end)
  end
end

items = %{panacea: Item.new(0.025, 0.3, 3000),
          ichor:   Item.new(0.015, 0.2, 1800),
          gold:    Item.new(0.002, 2.0, 2500) }
maximum = Item.new(0.25, 25, 0)
Knapsack.solve_unbounded(items, maximum)


USING: accessors combinators kernel locals math math.order
math.vectors sequences sequences.product combinators.short-circuit ;
IN: knapsack

CONSTANT: values { 3000 1800 2500 }
CONSTANT: weights { 0.3 0.2 2.0 }
CONSTANT: volumes { 0.025 0.015 0.002 }

CONSTANT: max-weight 25.0
CONSTANT: max-volume 0.25

TUPLE: bounty amounts value weight volume ;

: <bounty> ( items -- bounty )
    [ bounty new ] dip {
        [ >>amounts ]
        [ values v. >>value ]
        [ weights v. >>weight ]
        [ volumes v. >>volume ]
    } cleave ;

: valid-bounty? ( bounty -- ? )
    { [ weight>> max-weight <= ]
      [ volume>> max-volume <= ] } 1&& ;

M:: bounty <=> ( a b -- <=> )
    a valid-bounty? [
        b valid-bounty? [
            a b [ value>> ] compare
        ] [ +gt+ ] if
    ] [ b valid-bounty? +lt+ +eq+ ? ] if ;

: find-max-amounts ( -- amounts )
    weights volumes [
        [ max-weight swap / ]
        [ max-volume swap / ] bi* min >integer
    ] 2map ;

: best-bounty ( -- bounty )
    find-max-amounts [ 1 + iota ] map <product-sequence>
    [ <bounty> ] [ max ] map-reduce ;


\ : value ; immediate
: weight cell+ ;
: volume 2 cells + ;
: number 3 cells + ;

\      item value weight volume number
create panacea 30 ,   3 ,  25 , 0 ,
create ichor   18 ,   2 ,  15 , 0 ,
create gold    25 ,  20 ,   2 , 0 ,
create sack     0 , 250 , 250 ,

: fits? ( item -- ? )
  dup weight @ sack weight @ > if drop false exit then
      volume @ sack volume @ > 0= ;

: add ( item -- )
  dup        @        sack        +!
  dup weight @ negate sack weight +!
  dup volume @ negate sack volume +!
  1 swap number +! ;

: take ( item -- )
  dup        @ negate sack        +!
  dup weight @        sack weight +!
  dup volume @        sack volume +!
  -1 swap number +! ;

variable max-value
variable max-pan
variable max-ich
variable max-au

: .solution
  cr
  max-pan @ . ." Panaceas, "
  max-ich @ . ." Ichors, and "
  max-au  @ . ." Gold for a total value of "
  max-value @ 100 * . ;

: check
  sack @ max-value @ <= if exit then
  sack           @ max-value !
  panacea number @ max-pan   !
  ichor   number @ max-ich   !
  gold    number @ max-au    !
  ( .solution ) ;    \ and change <= to < to see all solutions

: solve-gold
  gold fits? if gold add  recurse  gold take
  else check then ;

: solve-ichor
  ichor fits? if ichor add  recurse  ichor take then
  solve-gold ;

: solve-panacea
  panacea fits? if panacea add  recurse  panacea take then
  solve-ichor ;

solve-panacea .solution


PROGRAM KNAPSACK

  IMPLICIT NONE

  REAL :: totalWeight, totalVolume
  INTEGER :: maxPanacea, maxIchor, maxGold, maxValue = 0
  INTEGER :: i, j, k
  INTEGER :: n(3)

  TYPE Bounty
    INTEGER :: value
    REAL :: weight
    REAL :: volume
  END TYPE Bounty

  TYPE(Bounty) :: panacea, ichor, gold, sack, current

  panacea = Bounty(3000, 0.3, 0.025)
  ichor   = Bounty(1800, 0.2, 0.015)
  gold    = Bounty(2500, 2.0, 0.002)
  sack    = Bounty(0, 25.0, 0.25)

  maxPanacea = MIN(sack%weight / panacea%weight, sack%volume / panacea%volume)
  maxIchor = MIN(sack%weight / ichor%weight, sack%volume / ichor%volume)
  maxGold = MIN(sack%weight / gold%weight, sack%volume / gold%volume)

  DO i = 0, maxPanacea
     DO j = 0, maxIchor
        Do k = 0, maxGold
           current%value = k * gold%value + j * ichor%value + i * panacea%value
           current%weight = k * gold%weight + j * ichor%weight + i * panacea%weight
           current%volume = k * gold%volume + j * ichor%volume + i * panacea%volume
           IF (current%weight > sack%weight .OR. current%volume > sack%volume) CYCLE
           IF (current%value > maxValue) THEN
              maxValue = current%value
              totalWeight = current%weight
              totalVolume = current%volume
              n(1) = i ; n(2) = j ; n(3) = k
           END IF
        END DO
     END DO
  END DO

  WRITE(*, "(A,I0)") "Maximum value achievable is ", maxValue
  WRITE(*, "(3(A,I0),A)") "This is achieved by carrying ", n(1), " panacea, ", n(2), " ichor and ", n(3), " gold items"
  WRITE(*, "(A,F4.1,A,F5.3)") "The weight to carry is ", totalWeight, " and the volume used is ", totalVolume

END PROGRAM KNAPSACK


package main

import "fmt"

type Item struct {
	Name           string
	Value          int
	Weight, Volume float64
}

type Result struct {
	Counts []int
	Sum    int
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func Knapsack(items []Item, weight, volume float64) (best Result) {
	if len(items) == 0 {
		return
	}
	n := len(items) - 1
	maxCount := min(int(weight/items[n].Weight), int(volume/items[n].Volume))
	for count := 0; count <= maxCount; count++ {
		sol := Knapsack(items[:n],
			weight-float64(count)*items[n].Weight,
			volume-float64(count)*items[n].Volume)
		sol.Sum += items[n].Value * count
		if sol.Sum > best.Sum {
			sol.Counts = append(sol.Counts, count)
			best = sol
		}
	}
	return
}

func main() {
	items := []Item{
		{"Panacea", 3000, 0.3, 0.025},
		{"Ichor", 1800, 0.2, 0.015},
		{"Gold", 2500, 2.0, 0.002},
	}
	var sumCount, sumValue int
	var sumWeight, sumVolume float64

	result := Knapsack(items, 25, 0.25)

	for i := range result.Counts {
		fmt.Printf("%-8s x%3d  -> Weight: %4.1f  Volume: %5.3f  Value: %6d\n",
			items[i].Name, result.Counts[i], items[i].Weight*float64(result.Counts[i]),
			items[i].Volume*float64(result.Counts[i]), items[i].Value*result.Counts[i])

		sumCount += result.Counts[i]
		sumValue += items[i].Value * result.Counts[i]
		sumWeight += items[i].Weight * float64(result.Counts[i])
		sumVolume += items[i].Volume * float64(result.Counts[i])
	}

	fmt.Printf("TOTAL (%3d items) Weight: %4.1f  Volume: %5.3f  Value: %6d\n",
		sumCount, sumWeight, sumVolume, sumValue)
}


def totalWeight = { list -> list.collect{ it.item.weight * it.count }.sum() }
def totalVolume = { list -> list.collect{ it.item.volume * it.count }.sum() }
def totalValue = { list -> list.collect{ it.item.value * it.count }.sum() }

def knapsackUnbounded = { possibleItems, BigDecimal weightMax, BigDecimal volumeMax ->
    def n = possibleItems.size()
    def wm = weightMax.unscaledValue()
    def vm = volumeMax.unscaledValue()
    def m = (0..n).collect{ i -> (0..wm).collect{ w -> (0..vm).collect{ v -> [] } } }
    (1..wm).each { w ->
        (1..vm).each { v ->
            (1..n).each { i ->
                def item = possibleItems[i-1]
                def wi = item.weight.unscaledValue()
                def vi = item.volume.unscaledValue()
                def bi = [w.intdiv(wi),v.intdiv(vi)].min()
                m[i][w][v] = (0..bi).collect{ count ->
                    m[i-1][w - wi * count][v - vi * count] + [[item:item, count:count]]
                }.max(totalValue).findAll{ it.count }
            }
        }
    }
    m[n][wm][vm]
}


import Data.List (maximumBy)
import Data.Ord (comparing)

(maxWgt, maxVol) = (25, 0.25)
items =
   [Bounty  "panacea"  3000  0.3  0.025,
    Bounty  "ichor"    1800  0.2  0.015,
    Bounty  "gold"     2500  2.0  0.002]

data Bounty = Bounty
   {itemName :: String,
    itemVal :: Int,
    itemWgt, itemVol :: Double}

names = map itemName items
vals = map itemVal items
wgts = map itemWgt items
vols = map itemVol items

dotProduct :: (Num a, Integral b) => [a] -> [b] -> a
dotProduct factors = sum . zipWith (*) factors . map fromIntegral

options :: [[Int]]
options = filter fits $ mapM f items
  where f (Bounty _ _ w v) = [0 .. m]
          where m = floor $ min (maxWgt / w) (maxVol / v)
        fits opt = dotProduct wgts opt <= maxWgt &&
                   dotProduct vols opt <= maxVol

showOpt :: [Int] -> String
showOpt opt = concat (zipWith showItem names opt) ++
    "total weight: " ++ show (dotProduct wgts opt) ++
    "\ntotal volume: " ++ show (dotProduct vols opt) ++
    "\ntotal value: " ++ show (dotProduct vals opt) ++ "\n"
  where showItem name num = name ++ ": " ++ show num ++ "\n"

main = putStr $ showOpt $ best options
  where best = maximumBy $ comparing $ dotProduct vals


CHARACTER list*1000

NN = ALIAS($Panacea, $Ichor, $Gold, wSack, wPanacea, wIchor, wGold, vSack, vPanacea, vIchor, vGold)
NN =      (3000,     1800,   2500,  25,    0.3,      0.2,    2.0,   0.25,  0.025,    0.015,  0.002)
maxItems = ALIAS(maxPanacea, maxIchor, maxGold)
maxItems = ( MIN( wSack/wPanacea, vSack/vPanacea), MIN( wSack/wIchor, vSack/vIchor), MIN( wSack/wGold, vSack/vGold) )

maxValue = 0
DO Panaceas = 0, maxPanacea
  DO Ichors = 0, maxIchor
    DO Golds = 0, maxGold
      weight = Panaceas*wPanacea + Ichors*wIchor + Golds*wGold
      IF( weight <= wSack ) THEN
        volume = Panaceas*vPanacea + Ichors*vIchor + Golds*vGold
        IF( volume <= vSack ) THEN
          value =  Panaceas*$Panacea + Ichors*$Ichor + Golds*$Gold
          IF( value > maxValue ) THEN
            maxValue = value
            ! this restarts the list, removing all previous entries:
            WRITE(Text=list, Name) value, Panaceas, Ichors, Golds, weight, volume, $CR//$LF
          ELSEIF( value == maxValue ) THEN
            WRITE(Text=list, Name, APPend) value, Panaceas, Ichors, Golds, weight, volume, $CR//$LF
          ENDIF
        ENDIF
      ENDIF
    ENDDO
  ENDDO
ENDDO


package hu.pj.alg;

import hu.pj.obj.Item;
import java.text.*;

public class UnboundedKnapsack {

    protected Item []  items = {
                               new Item("panacea", 3000,  0.3, 0.025),
                               new Item("ichor"  , 1800,  0.2, 0.015),
                               new Item("gold"   , 2500,  2.0, 0.002)
                               };
    protected final int    n = items.length; // the number of items
    protected Item      sack = new Item("sack"   ,    0, 25.0, 0.250);
    protected Item      best = new Item("best"   ,    0,  0.0, 0.000);
    protected int  []  maxIt = new int [n];  // maximum number of items
    protected int  []    iIt = new int [n];  // current indexes of items
    protected int  [] bestAm = new int [n];  // best amounts

    public UnboundedKnapsack() {
        // initializing:
        for (int i = 0; i < n; i++) {
            maxIt [i] = Math.min(
                           (int)(sack.getWeight() / items[i].getWeight()),
                           (int)(sack.getVolume() / items[i].getVolume())
                        );
        } // for (i)

        // calc the solution:
        calcWithRecursion(0);

        // Print out the solution:
        NumberFormat nf = NumberFormat.getInstance();
        System.out.println("Maximum value achievable is: " + best.getValue());
        System.out.print("This is achieved by carrying (one solution): ");
        for (int i = 0; i < n; i++) {
            System.out.print(bestAm[i] + " " + items[i].getName() + ", ");
        }
        System.out.println();
        System.out.println("The weight to carry is: " + nf.format(best.getWeight()) +
                           "   and the volume used is: " + nf.format(best.getVolume())
                          );

    }

    // calculation the solution with recursion method
    // item : the number of item in the "items" array
    public void calcWithRecursion(int item) {
        for (int i = 0; i <= maxIt[item]; i++) {
            iIt[item] = i;
            if (item < n-1) {
                calcWithRecursion(item+1);
            } else {
                int    currVal = 0;   // current value
                double currWei = 0.0; // current weight
                double currVol = 0.0; // current Volume
                for (int j = 0; j < n; j++) {
                    currVal += iIt[j] * items[j].getValue();
                    currWei += iIt[j] * items[j].getWeight();
                    currVol += iIt[j] * items[j].getVolume();
                }

                if (currVal > best.getValue()
                    &&
                    currWei <= sack.getWeight()
                    &&
                    currVol <= sack.getVolume()
                )
                {
                    best.setValue (currVal);
                    best.setWeight(currWei);
                    best.setVolume(currVol);
                    for (int j = 0; j < n; j++) bestAm[j] = iIt[j];
                } // if (...)
            } // else
        } // for (i)
    } // calcWithRecursion()

    // the main() function:
    public static void main(String[] args) {
        new UnboundedKnapsack();
    } // main()

} // class


var gold = { 'value': 2500, 'weight': 2.0, 'volume': 0.002 },
    panacea = { 'value': 3000, 'weight': 0.3, 'volume': 0.025 },
    ichor = { 'value': 1800, 'weight': 0.2, 'volume': 0.015 },

    items = [gold, panacea, ichor],
    knapsack = {'weight': 25, 'volume': 0.25},
    max_val = 0,
    solutions = [],
    g, p, i, item, val;

for (i = 0; i < items.length; i += 1) {
    item = items[i];
    item.max = Math.min(
        Math.floor(knapsack.weight / item.weight),
        Math.floor(knapsack.volume / item.volume)
    );
}

for (g = 0; g <= gold.max; g += 1) {
    for (p = 0; p <= panacea.max; p += 1) {
        for (i = 0; i <= ichor.max; i += 1) {
            if (i * ichor.weight + g * gold.weight + p * panacea.weight > knapsack.weight) {
                continue;
            }
            if (i * ichor.volume + g * gold.volume + p * panacea.volume > knapsack.volume) {
                continue;
            }
            val = i * ichor.value + g * gold.value + p * panacea.value;
            if (val > max_val) {
                solutions = [];
                max_val = val;
            }
            if (val === max_val) {
                solutions.push([g, p, i]);
            }
        }
    }
}

document.write("maximum value: " + max_val + '
');
for (i = 0; i < solutions.length; i += 1) {
    item = solutions[i];
    document.write("(gold: " + item[0] + ", panacea: " + item[1] + ", ichor: " + item[2] + ")
");
}

output:

maximum value: 54500
(gold: 11, panacea: 0, ichor: 15)
(gold: 11, panacea: 3, ichor: 10)
(gold: 11, panacea: 6, ichor: 5)
(gold: 11, panacea: 9, ichor: 0)


def Item($name; $value; $weight; $volume):
  {$name, $value, $weight, $volume};

def items:[
    Item("panacea"; 3000; 0.3; 0.025),
    Item("ichor"; 1800; 0.2; 0.015),
    Item("gold"; 2500; 2; 0.002)
];

def array($init): [range(0; .) | $init];

# input: {count, best, bestvalue}
def knapsack($i; $value; $weight; $volume):
  (items|length) as $n
  | if $i == $n
    then if $value > .bestValue
         then .bestValue = $value
         | reduce range(0; $n) as $j (.; .best[$j] = .count[$j])
         else .
	 end
    else (($weight / items[$i].weight)|floor) as $m1
    | (($volume / items[$i].volume)|floor) as $m2
    | .count[$i] = ([$m1, $m2] | min)
    | until (.count[$i] < 0;
        knapsack(
            $i + 1;
            $value  + .count[$i] * (items[$i].value);
            $weight - .count[$i] * (items[$i].weight);
            $volume - .count[$i] * (items[$i].volume)
        )
        | .count[$i] += -1
    )
    end ;

def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;

def solve($maxWeight; $maxVolume):

  def rnd: 100 * . | round / 100;

  def rnd($width): if type == "string" then lpad($width) else rnd|lpad($width) end;

  def f(a;b;c;d;f):
     "\(a|lpad(11)) \(b|rnd(6)) \(c|rnd(6)) \(d|rnd(6)) \(f|rnd(6))" ;

  def f: . as [$a,$b,$c,$d,$f] | f($a;$b;$c;$d;$f);

  (items|length) as $n
  | def init:
     { count: ($n|array(0)),
       best : ($n|array(0)),
       bestValue: 0,
       maxWeight: $maxWeight,
       maxVolume: $maxVolume };

  f("Item Chosen"; "Number"; "Value"; "Weight"; "Volume"),
  "----------- ------ ------ ------ ------",
  ( init
    | knapsack(0; 0; $maxWeight; $maxVolume)
    | reduce range(0; $n) as $i (
        . + {itemCount:0, sumNumber:0, sumWeight:0, sumVolume:0 };
        if (.best[$i]) != 0
        then .itemCount  += 1
        | .name   = items[$i].name
        | .number = .best[$i]
        | .value  = items[$i].value  * .number
        | .weight = items[$i].weight * .number
        | .volume = items[$i].volume * .number
        | .sumNumber  += .number
        | .sumWeight  +=  .weight
        | .sumVolume  +=  .volume
	| .emit += [ f(.name; .number; .value; .weight; .volume) ]
        else .
        end)
    | .emit[],
      "----------- ------ ------ ------ ------",
      f(.itemCount; .sumNumber; .bestValue; .sumWeight; .sumVolume) );

solve(25; 0.25)


using JuMP
using GLPKMathProgInterface

model = Model(solver=GLPKSolverMIP())

@variable(model, vials_of_panacea >= 0, Int)
@variable(model, ampules_of_ichor >= 0, Int)
@variable(model, bars_of_gold >= 0, Int)

@objective(model, Max, 3000*vials_of_panacea + 1800*ampules_of_ichor + 2500*bars_of_gold)

@constraint(model, 0.3*vials_of_panacea + 0.2*ampules_of_ichor + 2.0*bars_of_gold <= 25.0)
@constraint(model, 0.025*vials_of_panacea + 0.015*ampules_of_ichor + 0.002*bars_of_gold <= 0.25)

println("The optimization problem to be solved is:")
println(model)

status = solve(model)

println("Objective value: ", getobjectivevalue(model))
println("vials of panacea = ", getvalue(vials_of_panacea))
println("ampules of ichor = ", getvalue(ampules_of_ichor))
println("bars of gold = ", getvalue(bars_of_gold))


// version 1.1.2

data class Item(val name: String, val value: Double, val weight: Double, val volume: Double)

val items = listOf(
    Item("panacea", 3000.0, 0.3, 0.025),
    Item("ichor", 1800.0, 0.2, 0.015),
    Item("gold", 2500.0, 2.0, 0.002)
)

val n = items.size
val count = IntArray(n)
val best  = IntArray(n)
var bestValue = 0.0

const val MAX_WEIGHT = 25.0
const val MAX_VOLUME = 0.25

fun knapsack(i: Int, value: Double, weight: Double, volume: Double) {
    if (i == n) {
        if (value > bestValue) {
            bestValue = value
            for (j in 0 until n) best[j] = count[j]
        }
        return
    }
    val m1 = Math.floor(weight / items[i].weight).toInt()
    val m2 = Math.floor(volume / items[i].volume).toInt()
    val m  = minOf(m1, m2)
    count[i] = m
    while (count[i] >= 0) {
        knapsack(
            i + 1,
            value  + count[i] * items[i].value,
            weight - count[i] * items[i].weight,
            volume - count[i] * items[i].volume
        )
        count[i]--
    }
}

fun main(args: Array<String>) {
    knapsack(0, 0.0, MAX_WEIGHT, MAX_VOLUME)
    println("Item Chosen  Number Value  Weight  Volume")
    println("-----------  ------ -----  ------  ------")
    var itemCount = 0
    var sumNumber = 0
    var sumWeight = 0.0
    var sumVolume = 0.0
    for (i in 0 until n) {
        if (best[i] == 0) continue
        itemCount++
        val name   = items[i].name
        val number = best[i]
        val value  = items[i].value  * number
        val weight = items[i].weight * number
        val volume = items[i].volume * number
        sumNumber += number
        sumWeight += weight
        sumVolume += volume
        print("${name.padEnd(11)}   ${"%2d".format(number)}    ${"%5.0f".format(value)}   ${"%4.1f".format(weight)}")
        println("    ${"%4.2f".format(volume)}")
    }
    println("-----------  ------ -----  ------  ------")
    print("${itemCount} items       ${"%2d".format(sumNumber)}    ${"%5.0f".format(bestValue)}   ${"%4.1f".format(sumWeight)}")
    println("    ${"%4.2f".format(sumVolume)}")
}


items = {   ["panaea"] = { ["value"] = 3000, ["weight"] = 0.3, ["volume"] = 0.025 },
            ["ichor"]  = { ["value"] = 1800, ["weight"] = 0.2, ["volume"] = 0.015 },
            ["gold"]   = { ["value"] = 2500, ["weight"] = 2.0, ["volume"] = 0.002 }
        }

max_weight = 25
max_volume = 0.25

max_num_items = {}
for i in pairs( items ) do
   max_num_items[i] = math.floor( math.min( max_weight / items[i].weight, max_volume / items[i].volume ) )
end

best = { ["value"] = 0.0, ["weight"] = 0.0, ["volume"] = 0.0 }
best_amounts = {}

for i = 1, max_num_items["panaea"] do
    for j = 1, max_num_items["ichor"] do
        for k = 1, max_num_items["gold"] do
            current = { ["value"]  = i*items["panaea"]["value"] + j*items["ichor"]["value"] + k*items["gold"]["value"],
                        ["weight"] = i*items["panaea"]["weight"] + j*items["ichor"]["weight"] + k*items["gold"]["weight"],
                        ["volume"] = i*items["panaea"]["volume"] + j*items["ichor"]["volume"] + k*items["gold"]["volume"]
                      }

            if current.value > best.value and current.weight <= max_weight and current.volume <= max_volume then
                best = { ["value"] = current.value, ["weight"] = current.weight, ["volume"] = current.volume }
                best_amounts = { ["panaea"] = i, ["ichor"] = j, ["gold"] = k }
            end
        end
    end
end

print( "Maximum value:", best.value )
for k, v in pairs( best_amounts ) do
    print( k, v )
end


%Knapsack problem/Unbounded. Nigel Galloway, August 13th., 2021
enum Items                     ={panacea,ichor,gold};
array[Items] of float: weight  =[0.3,0.2,2.0];        constraint sum(n in Items)(take[n]*weight[n])<=25.0;
array[Items] of int:   value   =[3000,1800,2500];
array[Items] of float: volume  =[0.025,0.015,0.002];  constraint sum(n in Items)(take[n]*volume[n])<=0.25;
array[Items] of var 0..floor(25.0/min(weight)): take;
solve maximize sum(n in Items)(value[n]*take[n]);
output(["Take "++show(take[panacea])++" vials of panacea\nTake "++show(take[ichor])++" ampules of ichor\nTake "++ show(take[gold])++" bars of gold\n"])


/*Knapsack

  This model finds the integer optimal packing of a knapsack

  Nigel_Galloway
  January 9th., 2012
*/

set Items;
param weight{t in Items};
param value{t in Items};
param volume{t in Items};

var take{t in Items}, integer, >=0;

knap_weight : sum{t in Items} take[t] * weight[t] <= 25;
knap_vol    : sum{t in Items} take[t] * volume[t] <= 0.25;

maximize knap_value: sum{t in Items} take[t] * value[t];

data;

param : Items          : weight   value     volume :=
         panacea          0.3     3000      0.025
         ichor            0.2	  1800	    0.015
         gold		  2.0	  2500      0.002
;

end;


MODULE Knapsack EXPORTS Main;

FROM IO IMPORT Put;
FROM Fmt IMPORT Int, Real;

TYPE Bounty = RECORD
  value: INTEGER;
  weight, volume: REAL;
END;

VAR totalWeight, totalVolume: REAL;
    maxPanacea, maxIchor, maxGold, maxValue: INTEGER := 0;
    n: ARRAY [1..3] OF INTEGER;
    panacea, ichor, gold, sack, current: Bounty;

BEGIN
  panacea := Bounty{3000, 0.3, 0.025};
  ichor   := Bounty{1800, 0.2, 0.015};
  gold    := Bounty{2500, 2.0, 0.002};
  sack    := Bounty{0, 25.0, 0.25};

  maxPanacea := FLOOR(MIN(sack.weight / panacea.weight, sack.volume / panacea.volume));
  maxIchor := FLOOR(MIN(sack.weight / ichor.weight, sack.volume / ichor.volume));
  maxGold := FLOOR(MIN(sack.weight / gold.weight, sack.volume / gold.volume));

  FOR i := 0 TO maxPanacea DO
    FOR j := 0 TO maxIchor DO
      FOR k := 0 TO maxGold DO
        current.value := k * gold.value + j * ichor.value + i * panacea.value;
        current.weight := FLOAT(k) * gold.weight + FLOAT(j) * ichor.weight + FLOAT(i) * panacea.weight;
        current.volume := FLOAT(k) * gold.volume + FLOAT(j) * ichor.volume + FLOAT(i) * panacea.volume;
        IF current.weight > sack.weight OR current.volume > sack.volume THEN
          EXIT;
        END;
        IF current.value > maxValue THEN
          maxValue := current.value;
          totalWeight := current.weight;
          totalVolume := current.volume;
          n[1] := i; n[2] := j; n[3] := k;
        END;
      END;
    END;
  END;
  Put("Maximum value achievable is " & Int(maxValue) & "\n");
  Put("This is achieved by carrying " & Int(n[1]) & " panacea, " & Int(n[2]) & " ichor and " & Int(n[3]) & " gold items\n");
  Put("The weight of this carry is " & Real(totalWeight) & " and the volume used is " & Real(totalVolume) & "\n");
END Knapsack.


# Knapsack unbounded. Brute force solution.

import lenientops   # Mixed float/int operators.
import strformat

type Bounty = tuple[value: int; weight, volume: float]

const
  Panacea: Bounty = (value: 3000, weight: 0.3, volume: 0.025)
  Ichor: Bounty = (value: 1800, weight: 0.2, volume: 0.015)
  Gold: Bounty = (value: 2500, weight: 2.0, volume: 0.002)
  Sack: Bounty = (value: 0, weight: 25.0, volume: 0.25)

  MaxPanacea = min(Sack.weight / Panacea.weight, Sack.volume / Panacea.volume).toInt
  MaxIchor = min(Sack.weight / Ichor.weight, Sack.volume / Ichor.volume).toInt
  MaxGold = min(Sack.weight / Gold.weight, Sack.volume / Gold.volume).toInt

var
  totalWeight, totalVolume: float
  n: array[1..3, int]   # Number of panacea, ichor and gold.
  maxValue = 0

for i in 0..MaxPanacea:
  for j in 0..MaxIchor:
    for k in 0..MaxGold:
      var current: Bounty
      current.value =  k * Gold.value  + j * Ichor.value  + i * Panacea.value
      current.weight = k * Gold.weight + j * Ichor.weight + i * Panacea.weight
      current.volume = k * Gold.volume + j * Ichor.volume + i * Panacea.volume
      if current.value > maxValue and current.weight <= Sack.weight and current.volume <= Sack.volume:
        maxvalue = current.value
        totalweight = current.weight
        totalvolume = current.volume
        n = [i, j, k]

echo fmt"Maximum value achievable is {maxValue}."
echo fmt"This is achieved by carrying {n[1]} panacea, {n[2]} ichor and {n[3]} gold items."
echo fmt"The weight of this carry is {totalWeight:6.3f} and the volume used is {totalVolume:6.4f}."