*      Josephus problem               10/02/2017
JOSEPH CSECT
       USING  JOSEPH,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
       LA     R7,1                    m=1
       DO WHILE=(C,R7,LE,=A(NPROB))   do m=1 to nprob
         LR     R1,R7                   m
         MH     R1,=H'6'                *6
         LH     R2,PROB-6(R1)
         ST     R2,N                    n=prob(m,1)
         LH     R2,PROB-4(R1)
         ST     R2,W                    w=prob(m,2)
         LH     R2,PROB-2(R1)
         ST     R2,S                    s=prob(m,3)
         MVC    PG,=CL80'josephus'      init buffer
         L      R1,N                    n
         XDECO  R1,DEC                  edit
         MVC    PG+8(4),DEC+8           output
         L      R1,W                    w
         XDECO  R1,DEC                  edit
         MVC    PG+12(4),DEC+8          output
         L      R1,S                    s
         XDECO  R1,DEC                  edit
         MVC    PG+16(4),DEC+8          output
         XPRNT  PG,L'PG                 print buffer
         MVI    DEAD,X'00'              dead(1)='0'B;
         MVC    DEAD+1(255),DEAD        dead(*)='0'B;
         L      R11,N                   nx=n
         L      R8,=F'-1'               p=-1
         DO UNTIL=(C,R11,EQ,S)          do until n=s
           SR     R9,R9                   found=0
           DO UNTIL=(C,R9,EQ,W)           do until found=w
             LA     R8,1(R8)                p=p+1
             IF C,R8,EQ,N THEN              if p=nn then
               SR     R8,R8                   p=0
             ENDIF  ,                       end if
             LA     R2,DEAD(R8)             @dead(p+1)
             IF CLI,0(R2),EQ,X'00' THEN     if not dead(p+1) then
               LA     R9,1(R9)                found=found+1
             ENDIF  ,                       end if
           ENDDO  ,                       end do
           LA     R2,DEAD(R8)             @dead(p+1)
           MVI    0(R2),X'01'             dead(p+1)='1'B
           BCTR   R11,0                   nx=nx-1
         ENDDO  ,                       end do
         MVC    PG,=CL80' '             clear buffer
         LA     R10,PG                  ipg=0
         L      R9,N                    nn
         BCTR   R9,0                    nn-1
         SR     R6,R6                   i=0
         DO WHILE=(CR,R6,LE,R9)         do i=0 to nn-1
           LA     R2,DEAD(R6)             @dead(i+1)
           IF CLI,0(R2),EQ,X'00' THEN     if not dead(i+1) then
             XDECO  R6,DEC                  edit i
             MVC    0(4,R10),DEC+8          output
             LA     R10,4(R10)              ipg=ipg+4
           ENDIF  ,                       end if
           LA     R6,1(R6)                i=i+1
         ENDDO  ,                       end do
         XPRNT  PG,L'PG                 print buffer
         LA     R7,1(R7)                m=m+1
       ENDDO  ,                       end do
       L      R13,4(0,R13)            epilog
       LM     R14,R12,12(R13)         " restore
       XR     R15,R15                 " rc=0
       BR     R14                     exit
PROB   DC     H'41',H'3',H'1'         round 1
       DC     H'41',H'3',H'3'         round 2
NPROB  EQU    (*-PROB)/6              number of rounds
N      DS     F                       n number of prisoners
W      DS     F                       w killing count
S      DS     F                       s number of prisoners to survive
PG     DS     CL80                    buffer
DEC    DS     CL12                    temp for xdeco
DEAD   DS     256X                    n max
       YREGS
       END    JOSEPH


JSEPHS: STA  $D0        ; n
        STX  $D1        ; k
        LDA  #$FF
        LDX  #$00
SETUP:  STA  $1000,X    ; populate array with hex FF
        INX
        CPX  $D0
        BEQ  KILL
        JMP  SETUP
KILL:   LDA  #$00       ; number killed so far
        STA  $D2
        LDX  #$00       ; position within array
        LDY  #$01       ; counting up to k
FIND:   INY
SCAN:   INX
        CPX  $D0
        BMI  TEST
        LDX  #$00       ; circle back around
TEST:   LDA  $1000,X
        CMP  #$FF
        BNE  SCAN       ; already been killed
        CPY  $D1
        BMI  FIND       ; if y < k keep going round
        LDA  $D2
        STA  $1000,X    ; mark as dead
        CLC
        ADC  #$01
        STA  $D2
        CMP  $D0        ; have we killed all but 1?
        BPL  RETURN
        LDY  #$00
        JMP  FIND
RETURN: TXA             ; a <- index of survivor
        RTS


/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program josephus64.s   */
/* run with josephus64 maxi intervalle */
/* example : josephus64 41 3

/*******************************************/
/* Constantes file                         */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"

.equ FIRSTNODE,        0              //identification first node

/*******************************************/
/* Structures                               */
/********************************************/
/* structure linkedlist*/
    .struct  0
llist_next:                            // next element
    .struct  llist_next + 8
llist_value:                           // element value
    .struct  llist_value + 8
llist_fin:
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessDebutPgm:          .asciz "Start program.\n"
szMessFinPgm:            .asciz "Program End ok.\n"
szRetourLigne:            .asciz "\n"
szMessValElement:        .asciz "Value : @ \n"
szMessListeVide:         .asciz "List empty.\n"
szMessImpElement:        .asciz "Node display: @ Value : @ Next @ \n"
szMessErrComm:           .asciz "Incomplete Command line  : josephus64 <maxi> <intervalle>\n"
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
sZoneConv:         .skip 100
.align 4
qDebutListe1:       .skip llist_fin
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                   // entry of program
    mov fp,sp                           // copy stack address  register x29 fp
    ldr x0,qAdrszMessDebutPgm
    bl affichageMess
    ldr x0,[fp]                         // parameter number command line
    cmp x0,#2                           // correct ?
    ble erreurCommande                  // error

    add x0,fp,#16                       // address parameter 2
    ldr x0,[x0]
    bl conversionAtoD
    add x22,x0,FIRSTNODE                // save maxi
    add x0,fp,#24                       // address parameter 3
    ldr x0,[x0]
    bl conversionAtoD
    mov x21,x0                          // save gap

    mov x0,FIRSTNODE                    // create first node
    mov x1,0
    bl createNode
    mov x25,x0                          // first node address
    mov x26,x0
    mov x24,FIRSTNODE + 1
    mov x23,1
1:                                      // loop create others nodes
    mov x0,x24                          // key value
    mov x1,0
    bl createNode
    str x0,[x26,llist_next]             // store current node address in prev node
    mov x26,x0
    add x24,x24,1
    add x23,x23,1
    cmp x23,x22                         // maxi ?
    blt 1b
    str x25,[x26,llist_next]            // store first node address in last pointer
    mov x24,x26
2:
    mov x20,1                           // counter for gap
3:
    ldr x24,[x24,llist_next]
    add x20,x20,1
    cmp x20,x21                         // intervalle ?
    blt 3b
    ldr x25,[x24,llist_next]            // removing the node from the list
    ldr x22,[x25,llist_value]
    ldr x27,[x25,llist_next]            // load pointer next
    str x27,[x24,llist_next]            // ans store in prev node
    //mov x0,x25
    //bl displayNode
    cmp x27,x24
    csel x24,x24,x27,ne                 // next node address
    bne 2b                              // and loop

    mov x0,x24
    bl displayNode                      // display last node

    b 100f
erreurCommande:
    ldr x0,qAdrszMessErrComm
    bl affichageMess
    mov x0,#1                          // error code
    b 100f
100:                                   // program end standard
    ldr x0,qAdrszMessFinPgm
    bl affichageMess
    mov x0,0                          // return code Ok
    mov x8,EXIT                       // system call "Exit"
    svc #0

qAdrszMessDebutPgm:      .quad szMessDebutPgm
qAdrszMessFinPgm:        .quad szMessFinPgm
qAdrszRetourLigne:       .quad szRetourLigne
qAdrqDebutListe1:        .quad qDebutListe1
qAdrszMessErrComm:       .quad szMessErrComm

/******************************************************************/
/*     create node                                             */
/******************************************************************/
/* x0 contains key   */
/* x1 contains zero or address next node */
/* x0 returns address heap node  */
createNode:
    stp x20,lr,[sp,-16]!        // save  registres
    stp x21,x22,[sp,-16]!       // save  registres
    mov x20,x0                  // save key
    mov x21,x1                  // save key
    mov x0,#0                   // allocation place heap
    mov x8,BRK                  // call system 'brk'
    svc #0
    mov x22,x0                  // save address heap for node
    add x0,x0,llist_fin         // reservation place node length
    mov x8,BRK                  // call system 'brk'
    svc #0
    cmp x0,#-1                  // allocation error
    beq 100f

    str x20,[x22,llist_value]
    str x21,[x22,llist_next]
    mov x0,x22
100:
    ldp x21,x22,[sp],16         // restaur des  2 registres
    ldp x20,lr,[sp],16          // restaur des  2 registres
    ret                         // retour adresse lr x30

/******************************************************************/
/*     display infos node                                     */
/******************************************************************/
/* x0 contains node address */
displayNode:
    stp x1,lr,[sp,-16]!        // save  registres
    stp x2,x3,[sp,-16]!        // save  registres
    mov x2,x0
    ldr x1,qAdrsZoneConv
    bl conversion16
    ldr x0,qAdrszMessImpElement
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc
    mov x3,x0
    ldr x0,[x2,llist_value]
    ldr x1,qAdrsZoneConv
    bl conversion10S
    mov x0,x3
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc
    mov x3,x0
    ldr x0,[x2,llist_next]
    ldr x1,qAdrsZoneConv
    bl conversion16
    mov x0,x3
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc
    bl affichageMess

100:
    ldp x2,x3,[sp],16          // restaur des  2 registres
    ldp x1,lr,[sp],16          // restaur des  2 registres
    ret                        // retour adresse lr x30
qAdrsZoneConv:               .quad sZoneConv
qAdrszMessImpElement:        .quad szMessImpElement
/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"


my $raw = <<'TABLE';
map			9	150
compass			13	35
water			153	200
sandwich		50	160
glucose			15	60
tin			68	45
banana			27	60
apple			39	40
cheese			23	30
beer			52	10
suntancream		11	70
camera			32	30
T-shirt			24	15
trousers		48	10
umbrella		73	40
waterproof trousers	42	70
waterproof overclothes	43	75
note-case		22	80
sunglasses		7	20
towel			18	12
socks			4	50
book			30	10
TABLE

my (@name, @weight, @value);
for (split "\n", $raw) {
    for ([ split /\t+/ ]) {
        push @name,   $_->[0];
        push @weight, $_->[1];
        push @value,  $_->[2];
    }
}

my $max_weight = 400;
my @p = map [map undef, 0 .. 1+$max_weight], 0 .. $#name;

sub optimal {
    my ($i, $w) = @_;
    return [0, []] if $i < 0;
    return $p[$i][$w] if $p[$i][$w];

    if ($weight[$i] > $w) {
        $p[$i][$w] = optimal($i - 1, $w)
    } else {
        my $x = optimal($i - 1, $w);
        my $y = optimal($i - 1, $w - $weight[$i]);

        if ($x->[0] > $y->[0] + $value[$i]) {
            $p[$i][$w] = $x
        } else {
            $p[$i][$w] = [  $y->[0] + $value[$i], [ @{$y->[1]}, $name[$i] ]]
        }
    }
    return $p[$i][$w]
}

my $solution = optimal($#name, $max_weight);
print "$solution->[0]: @{$solution->[1]}\n";


with Ada.Command_Line, Ada.Text_IO;

procedure Josephus is

   function Arg(Idx, Default: Positive) return Positive is -- read Argument(Idx)
      (if Ada.Command_Line.Argument_Count >= Index
         then Positive'Value(Ada.Command_Line.Argument(Index)) else Default);

   Prisoners:  constant Positive := Arg(Idx => 1, Default => 41);
   Steps:      constant Positive := Arg(Idx => 2, Default =>  3);
   Survivors:  constant Positive := Arg(Idx => 3, Default =>  1);
   Print:               Boolean := (Arg(Idx => 4, Default =>  1) = 1);

   subtype Index_Type is Natural range 0 .. Prisoners-1;
   Next: array(Index_Type) of Index_Type;
   X: Index_Type := (Steps-2) mod Prisoners;

begin
   Ada.Text_IO.Put_Line
     ("N =" & Positive'Image(Prisoners) & ",  K =" & Positive'Image(Steps) &
        (if Survivors > 1 then ",  #survivors =" & Positive'Image(Survivors)
        else ""));
   for Idx in Next'Range loop -- initialize Next
      Next(Idx) := (Idx+1) mod Prisoners;
   end loop;
   if Print then
      Ada.Text_IO.Put("Executed: ");
   end if;
   for Execution in reverse 1 .. Prisoners loop
      if Execution = Survivors then
         Ada.Text_IO.New_Line;
         Ada.Text_IO.Put("Surviving: ");
         Print := True;
      end if;
      if Print then
         Ada.Text_IO.Put(Positive'Image(Next(X)));
      end if;
      Next(X) := Next(Next(X)); -- "delete" a prisoner
      for Prisoner in 1 .. Steps-1 loop
         X := Next(X);
      end loop;
   end loop;
end Josephus;


-- demo\rosetta\knapsack0.exw
with javascript_semantics

bool terminate = false

integer attempts = 0
function knapsack(sequence res, goodies, atom points, weight, at=1, sequence chosen={})
    atom {?,witem,pitem} = goodies[at]
    integer n = iff(witem<=weight?1:0)
    chosen &= n
    points += n*pitem   -- increase value
    weight -= n*witem   -- decrease weight left
    if at=length(goodies) then
        attempts += 1
        if length(res)=0
        or res<{points,weight} then
            res = {points,weight,chosen}
        end if
        terminate = (n=1)
    else
--      while n>=0 do -- full exhaustive search
        while n>=0 and not terminate do -- optimised
            res = knapsack(res,goodies,points,weight,at+1,deep_copy(chosen))
            n -= 1
            chosen[$] = n
            points -= pitem
            weight += witem
        end while
    end if
    return res
end function

function byweightedvalue(object a, b)
    -- sort by weight/value
    return compare(a[2]/a[3],b[2]/b[3])
    -- nb other sort orders break the optimisation
end function

constant goodies = custom_sort(byweightedvalue,{
-- item                     weight value
{"map",                      9,     150},
{"compass",                  13,    35 },
{"water",                    153,   200},
{"sandwich",                 50,    160},
{"glucose",                  15,    60 },
{"tin",                      68,    45 },
{"banana",                   27,    60 },
{"apple",                    39,    40 },
{"cheese",                   23,    30 },
{"beer",                     52,    10 },
{"suntan cream",             11,    70 },
{"camera",                   32,    30 },
{"T-shirt",                  24,    15 },
{"trousers",                 48,    10 },
{"umbrella",                 73,    40 },
{"waterproof trousers",      42,    70 },
{"waterproof overclothes",   43,    75 },
{"note-case",                22,    80 },
{"sunglasses",               7,     20 },
{"towel",                    18,    12 },
{"socks",                    4,     50 },
{"book",                     30,    10 }})

atom t0 = time()
object {points,weight,counts} = knapsack({},goodies,0,400)
printf(1,"Value %d, weight %g [%d attempts, %3.2fs]:\n",{points,400-weight,attempts,time()-t0})
for i=1 to length(counts) do
    integer c = counts[i]
    if c then
        printf(1,"%s\n",{goodies[i][1]})
    end if
end for


BEGIN
   PROC josephus = (INT n, k, m) INT :
   CO Return m-th on the reversed kill list; m=0 is final survivor. CO
   BEGIN
      INT lm := m;			CO Local copy of m CO
      FOR a FROM m+1 WHILE a <= n DO lm := (lm+k) %* a OD;
      lm
   END;
   INT n = 41, k=3;
   printf (($"n = ", g(0), ", k = ", g(0), ", final survivor: ", g(0)l$,
	    n, k, josephus (n, k, 0)))
END


100 FUNCTION josephus (n, k, m)
110 ! Return m-th on the reversed kill list; m=0 is final survivor.
120    LET lm = m  ! Local copy OF m
130    FOR a = m+1  TO n
140       LET lm = MOD(lm+k, a)
150    NEXT a
160    LET josephus = lm
170 END FUNCTION
180 LET n = 41
190 LET k=3
200 PRINT "n =";n, "k =";k,"final survivor =";josephus(n, k, 0)
210 END


#########################################################
# 0-1 Knapsack Problem Solve with memoization optimize and index returns
# $w = weight of item
# $v = value of item
# $i = index
# $aW = Available Weight
# $m = Memo items array
# PHP Translation from Python, Memoization,
# and index return functionality added by Brian Berneker
#
#########################################################

function knapSolveFast2($w, $v, $i, $aW, &$m) {

	global $numcalls;
	$numcalls ++;
	// echo "Called with i=$i, aW=$aW
";

	// Return memo if we have one
	if (isset($m[$i][$aW])) {
		return array( $m[$i][$aW], $m['picked'][$i][$aW] );
	} else {

		// At end of decision branch
		if ($i == 0) {
			if ($w[$i] <= $aW) { // Will this item fit?
				$m[$i][$aW] = $v[$i]; // Memo this item
				$m['picked'][$i][$aW] = array($i); // and the picked item
				return array($v[$i],array($i)); // Return the value of this item and add it to the picked list

			} else {
				// Won't fit
				$m[$i][$aW] = 0; // Memo zero
				$m['picked'][$i][$aW] = array(); // and a blank array entry...
				return array(0,array()); // Return nothing
			}
		}

		// Not at end of decision branch..
		// Get the result of the next branch (without this one)
		list ($without_i, $without_PI) = knapSolveFast2($w, $v, $i-1, $aW, $m);

		if ($w[$i] > $aW) { // Does it return too many?

			$m[$i][$aW] = $without_i; // Memo without including this one
			$m['picked'][$i][$aW] = $without_PI; // and a blank array entry...
			return array($without_i, $without_PI); // and return it

		} else {

			// Get the result of the next branch (WITH this one picked, so available weight is reduced)
			list ($with_i,$with_PI) = knapSolveFast2($w, $v, ($i-1), ($aW - $w[$i]), $m);
			$with_i += $v[$i];  // ..and add the value of this one..

			// Get the greater of WITH or WITHOUT
			if ($with_i > $without_i) {
				$res = $with_i;
				$picked = $with_PI;
				array_push($picked,$i);
			} else {
				$res = $without_i;
				$picked = $without_PI;
			}

			$m[$i][$aW] = $res; // Store it in the memo
			$m['picked'][$i][$aW] = $picked; // and store the picked item
			return array ($res,$picked); // and then return it
		}
	}
}

$items4 = array("map","compass","water","sandwich","glucose","tin","banana","apple","cheese","beer","suntan cream","camera","t-shirt","trousers","umbrella","waterproof trousers","waterproof overclothes","note-case","sunglasses","towel","socks","book");
$w4 = array(9,13,153,50,15,68,27,39,23,52,11,32,24,48,73,42,43,22,7,18,4,30);
$v4 = array(150,35,200,160,60,45,60,40,30,10,70,30,15,10,40,70,75,80,20,12,50,10);

## Initialize
$numcalls = 0; $m = array(); $pickedItems = array();

## Solve
list ($m4,$pickedItems) = knapSolveFast2($w4, $v4, sizeof($v4) -1, 400, $m);

# Display Result
echo "Items:
".join(", ",$items4)."
";
echo "Max Value Found:
$m4 (in $numcalls calls)
";
echo "Array Indices:
".join(",",$pickedItems)."
";

echo "Chosen Items:
";
echo "
";
echo "
Item	Value	Weight
";
$totalVal = $totalWt = 0;
foreach($pickedItems as $key) {
	$totalVal += $v4[$key];
	$totalWt += $w4[$key];
	echo "
".$items4[$key]."	".$v4[$key]."	".$w4[$key]."
";
}
echo "
Totals	$totalVal	$totalWt
";
echo "

";


on josephus(n, k)
    set m to 0
    repeat with i from 2 to n
        set m to (m + k) mod i
    end repeat

    return m + 1
end josephus

josephus(41, 3) --> 31


/* ARM assembly AARCH64 Raspberry PI 3B */
/* ARM assembly Raspberry PI  */
/*  program josephus.s   */

/* REMARK 1 : this program use routines in a include file
   see task Include a file language arm assembly
   for the routine affichageMess conversion10
   see at end of this program the instruction include */

/*******************************************/
/* Constantes                              */
/*******************************************/
.equ STDOUT, 1           @ Linux output console
.equ EXIT,   1           @ Linux syscall
.equ WRITE,  4           @ Linux syscall
.equ BRK,    0x2d        @ Linux syscall
.equ CHARPOS,     '@'

.equ FIRSTNODE,        0              //identification first node

/*******************************************/
/* Structures                               */
/********************************************/
/* structure linkedlist*/
    .struct  0
llist_next:                            // next element
    .struct  llist_next + 4
llist_value:                           // element value
    .struct  llist_value + 4
llist_fin:
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessDebutPgm:          .asciz "Start program.\n"
szMessFinPgm:            .asciz "Program End ok.\n"
szRetourLigne:            .asciz "\n"
szMessValElement:        .asciz "Value : @ \n"
szMessListeVide:         .asciz "List empty.\n"
szMessImpElement:        .asciz "Node display: @ Value : @ Next @ \n"
szMessErrComm:           .asciz "Incomplete Command line  : josephus <maxi> <intervalle>\n"
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
sZoneConv:         .skip 24
.align 4
qDebutListe1:      .skip llist_fin
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                   // entry of program
    mov fp,sp                           // copy stack address  register r29 fp
    ldr r0,iAdrszMessDebutPgm
    bl affichageMess
    ldr r0,[fp]                        // parameter number command line
    cmp r0,#2                          // correct ?
    ble erreurCommande                 // error

    add r0,fp,#8                       // address parameter 2
    ldr r0,[r0]
    bl conversionAtoD
    add r2,r0,#FIRSTNODE               // save maxi
    add r0,fp,#12                      // address parameter 3
    ldr r0,[r0]
    bl conversionAtoD
    mov r8,r0                          // save gap

    mov r0,#FIRSTNODE                  // create first node
    mov r1,#0
    bl createNode
    mov r5,r0                          // first node address
    mov r6,r0
    mov r4,#FIRSTNODE + 1
    mov r3,#1
1:                                     // loop create others nodes
    mov r0,r4                          // key value
    mov r1,#0
    bl createNode
    str r0,[r6,#llist_next]             // store current node address in prev node
    mov r6,r0
    add r4,r4,#1
    add r3,r3,#1
    cmp r3,r2                          // maxi ?
    blt 1b
    str r5,[r6,#llist_next]            // store first node address in last pointer
    mov r4,r6
2:
    mov r2,#1                          // counter for gap
3:
    ldr r4,[r4,#llist_next]
    add r2,r2,#1
    cmp r2,r8                          // intervalle ?
    blt 3b
    ldr r5,[r4,#llist_next]            // removing the node from the list
    ldr r2,[r5,#llist_value]
    ldr r7,[r5,#llist_next]            // load pointer next
    str r7,[r4,#llist_next]            // ans store in prev node
    //mov r0,r25
    //bl displayNode
    cmp r7,r4
    moveq r4,r7
    bne 2b                              // and loop

    mov r0,r4
    bl displayNode                      // display last node

    b 100f
erreurCommande:
    ldr r0,iAdrszMessErrComm
    bl affichageMess
    mov r0,#1                          // error code
    b 100f
100:                                   // program end standard
    ldr r0,iAdrszMessFinPgm
    bl affichageMess
    mov r0,#0                          // return code Ok
    mov r7,#EXIT                       // system call "Exit"
    svc #0

iAdrszMessDebutPgm:      .int szMessDebutPgm
iAdrszMessFinPgm:        .int szMessFinPgm
iAdrszRetourLigne:       .int szRetourLigne
iAdrqDebutListe1:        .int qDebutListe1
iAdrszMessErrComm:       .int szMessErrComm

/******************************************************************/
/*     create node                                             */
/******************************************************************/
/* r0 contains key   */
/* r1 contains zero or address next node */
/* r0 returns address heap node  */
createNode:
    push {r1-r11,lr}            // save  registers
    mov r9,r0                   // save key
    mov r10,r1                  // save key
    mov r0,#0                   // allocation place heap
    mov r7,#BRK                 // call system 'brk'
    svc #0
    mov r11,r0                  // save address heap for node
    add r0,r0,#llist_fin        // reservation place node length
    mov r7,#BRK                 // call system 'brk'
    svc #0
    cmp r0,#-1                  // allocation error
    beq 100f

    str r9,[r11,#llist_value]
    str r10,[r11,#llist_next]
    mov r0,r11
100:
    pop {r1-r11,lr}            // restaur registers
    bx lr                      // return

/******************************************************************/
/*     display infos node                                     */
/******************************************************************/
/* r0 contains node address */
displayNode:
    push {r1-r4,lr}           // save  registers
    mov r2,r0
    ldr r1,iAdrsZoneConv
    bl conversion16
    mov r4,#0
    strb r4,[r1,r0]           // store zero final
    ldr r0,iAdrszMessImpElement
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc
    mov r3,r0
    ldr r0,[r2,#llist_value]
    ldr r1,iAdrsZoneConv
    bl conversion10S
    mov r4,#0
    strb r4,[r1,r0]           // store zero final
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc
    mov r3,r0
    ldr r0,[r2,#llist_next]
    ldr r1,iAdrsZoneConv
    bl conversion16
    mov r4,#0
    strb r4,[r1,#8]           // store zero final
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc
    bl affichageMess

100:
    pop {r1-r4,lr}            // restaur registers
    bx lr                     // return
iAdrsZoneConv:               .int sZoneConv
iAdrszMessImpElement:        .int szMessImpElement
/***************************************************/
/*      ROUTINES INCLUDE                 */
/***************************************************/
.include "../affichage.inc"


import mip,util.

go =>
  items(AllItems,MaxTotalWeight),
  [Items,Weights,Values] = transpose(AllItems),

  knapsack_01(Weights,Values,MaxTotalWeight, X,TotalWeight,TotalValues),
  print_solution(Items,Weights,Values, X,TotalWeight,TotalValues),
  nl.

% Print the solution
print_solution(Items,Weights,Values, X,TotalWeight,TotalValues) =>
  println("\nThese are the items to pick:"),
  println("  Item                   Weight Value"),

  foreach(I in 1..Items.len)
    if X[I] == 1 then
      printf("* %-25w %3d %3d\n", Items[I],Weights[I], Values[I])
     end
  end,
  nl,

  printf("Total weight: %d\n", TotalWeight),
  printf("Total value: %d\n", TotalValues),
  nl.

% Solve the knapsack problem
knapsack_01(Weights,Values,MaxTotalWeight, X,TotalWeight,TotalValues) =>
   NumItems = length(Weights),

   % Variables
   X = new_list(NumItems),
   X :: 0..1,

   % Constraints
   scalar_product(Weights,X,TotalWeight),
   scalar_product(Values,X,TotalValues),
   TotalWeight #=< MaxTotalWeight,

   % Search
   Vars = X ++ [TotalWeight, TotalValues],
   solve($[max(TotalValues)], Vars).

% data
items(Items,MaxTotalWeight) =>
           % Item          Weight   Value
  Items = [["map",           9,       150],
           ["compass",       13,       35],
           ["water",         153,     200],
           ["sandwich",      50,      160],
           ["glucose",       15,       60],
           ["tin",           68,       45],
           ["banana",        27,       60],
           ["apple",         39,       40],
           ["cheese",        23,       30],
           ["beer",          52,       10],
           ["suntancream",   11,       70],
           ["camera",        32,       30],
           ["T-shirt",       24,       15],
           ["trousers",      48,       10],
           ["umbrella",      73,       40],
           ["waterproof trousers",     42,      70],
           ["waterproof overclothes",  43,      75],
           ["note-case",     22,       80],
           ["sunglasses",     7,       20],
           ["towel",         18,       12],
           ["socks",          4,       50],
           ["book",          30,       10]],
  MaxTotalWeight = 400.


(de *Items
   ("map" 9 150)                    ("compass" 13 35)
   ("water" 153 200)                ("sandwich" 50 160)
   ("glucose" 15 60)                ("tin" 68 45)
   ("banana" 27 60)                 ("apple" 39 40)
   ("cheese" 23 30)                 ("beer" 52 10)
   ("suntan cream" 11 70)           ("camera" 32 30)
   ("t-shirt" 24 15)                ("trousers" 48 10)
   ("umbrella" 73 40)               ("waterproof trousers" 42 70)
   ("waterproof overclothes" 43 75) ("note-case" 22 80)
   ("sunglasses" 7 20)              ("towel" 18 12)
   ("socks" 4 50)                   ("book" 30 10) )

# Dynamic programming solution
(de knapsack (Lst W)
   (when Lst
      (cache '*KnapCache (cons W Lst)
         (let X (knapsack (cdr Lst) W)
            (if (ge0 (- W (cadar Lst)))
               (let Y (cons (car Lst) (knapsack (cdr Lst) @))
                  (if (> (sum caddr X) (sum caddr Y)) X Y) )
               X ) ) ) ) )

(let K (knapsack *Items 400)
   (for I K
      (apply tab I (3 -24 6 6) NIL) )
   (tab (27 6 6) NIL (sum cadr K) (sum caddr K)) )


josephus: function [n,k][
    p: new 0..n-1
    i: 0
    seq: []

    while [0 < size p][
        i: (i+k-1) % size p
        append 'seq p\[i]
        remove 'p .index i
    ]
    print ["Prisoner killing order:" chop seq]
    print ["Survivor:" last seq]
    print ""
]

print "josephus 5 2 =>"
josephus 5 2

print "josephus 41 3 =>"
josephus 41 3


; Since AutoHotkey is 1-based, we're numbering prisoners 1-41.
nPrisoners := 41
kth        := 3

; Build a list, purposefully ending with a separator
Loop % nPrisoners
	list .= A_Index . "|"

; iterate and remove from list
i := 1
Loop
{
	; Step by 2; the third step was done by removing the previous prisoner
	i += kth - 1
	if (i > nPrisoners)
		i := Mod(i, nPrisoners)
	; Remove from list
	end := InStr(list, "|", 0, 1, i)
	bgn := InStr(list, "|", 0, 1, i-1)
	list := SubStr(list, 1, bgn) . SubStr(list, end+1)
	nPrisoners--
}
Until (nPrisoners = 1)
MsgBox % RegExReplace(list, "\|") ; remove the final separator


:- use_module(library(clpfd)).

knapsack :-
        L = [
             item(map,  9,      150),
             item(compass,      13,     35),
             item(water,        153,    200),
             item(sandwich, 50,         160),
             item(glucose,      15,     60),
             item(tin,  68,     45),
             item(banana,       27,     60),
             item(apple,        39,     40),
             item(cheese,       23,     30),
             item(beer,         52,     10),
             item('suntan cream',       11,     70),
             item(camera,       32,     30),
             item('t-shirt',    24,     15),
             item(trousers, 48,         10),
             item(umbrella, 73,         40),
             item('waterproof trousers',        42,     70),
             item('waterproof overclothes',     43,     75),
             item('note-case',22,       80),
             item(sunglasses,   7,      20),
             item(towel,        18,     12),
             item(socks,        4,      50),
             item(book,         30,     10 )],
        length(L, N),
        length(R, N),
        R ins 0..1,
        maplist(arg(2), L, LW),
        maplist(arg(3), L, LV),
        scalar_product(LW, R, #=<, 400),
        scalar_product(LV, R, #=, VM),
        labeling([max(VM)], R),
        scalar_product(LW, R, #=, WM),
        %% affichage des résultats
        compute_lenword(L, 0, Len),
        sformat(A1, '~~w~~t~~~w|', [Len]),
        sformat(A2, '~~t~~w~~~w|', [4]),
        sformat(A3, '~~t~~w~~~w|', [5]),
        print_results(A1,A2,A3, L, R, WM, VM).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% to show the results in a good way
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
compute_lenword([], N, N).
compute_lenword([item(Name, _, _)|T], N, NF):-
        atom_length(Name, L),
        (   L > N -> N1 = L; N1 = N),
        compute_lenword(T, N1, NF).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
print_results(A1,A2,A3, [], [], WM, WR) :-
        sformat(W1, A1, [' ']),
        sformat(W2, A2, [WM]),
        sformat(W3, A3, [WR]),
        format('~w~w~w~n', [W1,W2,W3]).

print_results(A1,A2,A3, [_H|T], [0|TR], WM, VM) :-
        print_results(A1,A2,A3, T, TR, WM, VM).

print_results(A1, A2, A3, [item(Name, W, V)|T], [1|TR], WM, VM) :-
        sformat(W1, A1, [Name]),
        sformat(W2, A2, [W]),
        sformat(W3, A3, [V]),
        format('~w~w~w~n', [W1,W2,W3]),
        print_results(A1, A2, A3, T, TR, WM, VM).


# syntax: GAWK -f JOSEPHUS_PROBLEM.AWK
# converted from PL/I
BEGIN {
    main(5,2,1)
    main(41,3,1)
    main(41,3,3)
    exit(0)
}
function main(n,k,s,  dead,errors,found,i,killed,nn,p,survived) {
# n - number of prisoners
# k - kill every k'th prisoner
# s - number of survivors
    printf("\nn=%d k=%d s=%d\n",n,k,s) # show arguments
    if (s > n) { print("s>n"); errors++ }
    if (k <= 0) { print("k<=0"); errors++ }
    if (errors > 0) { return(0) }
    nn = n                             # wrap around boundary
    p = -1                             # start here
    while (n != s) {                   # until survivor count is met
      found = 0                        # start looking
      while (found != k) {             # until we have the k-th prisoner
        if (++p == nn) { p = 0 }       # wrap around
        if (dead[p] != 1) { found++ }  # if prisoner is alive increment found
      }
      dead[p] = 1                      # kill the unlucky one
      killed = killed p " "            # build killed list
      n--                              # reduce size of circle
    }
    for (i=0; i<=nn-1; i++) {
      if (dead[i] != 1) {
        survived = survived i " "      # build survivor list
      }
    }
    printf("killed: %s\n",killed)
    printf("survived: %s\n",survived)
    return(1)
}


Structure item
  name.s
  weight.i ;units are dekagrams (dag)
  Value.i
EndStructure

Structure memo
  Value.i
  List picked.i()
EndStructure

Global itemCount = 0 ;this will be increased as needed to match count
Global Dim items.item(itemCount)

Procedure addItem(name.s, weight, Value)
  If itemCount >= ArraySize(items())
    Redim items.item(itemCount + 10)
  EndIf
  With items(itemCount)
    \name = name
    \weight = weight
    \Value = Value
  EndWith
  itemCount + 1
EndProcedure

;build item list
addItem("map", 9, 150)
addItem("compass", 13, 35)
addItem("water", 153, 200)
addItem("sandwich", 50, 160)
addItem("glucose", 15, 60)
addItem("tin", 68, 45)
addItem("banana", 27, 60)
addItem("apple", 39, 40)
addItem("cheese", 23, 30)
addItem("beer", 52, 10)
addItem("suntan cream", 11, 70)
addItem("camera", 32, 30)
addItem("t-shirt", 24, 15)
addItem("trousers", 48, 10)
addItem("umbrella", 73, 40)
addItem("waterproof trousers", 42, 70)
addItem("waterproof overclothes", 43, 75)
addItem("note-case", 22, 80)
addItem("sunglasses", 7, 20)
addItem("towel", 18, 12)
addItem("socks", 4, 50)
addItem("book", 30, 10)

Procedure knapsackSolveFast(Array item.item(1), i, aw, Map m.memo())
  Protected.memo without_i, with_i, result, *tmp, memoIndex.s = Hex((i << 16) + aw, #PB_Long)
  If FindMapElement(m(), memoIndex)
    ProcedureReturn @m()
  Else
    If i = 0
      If item(0)\weight <= aw
        ;item fits
        m(memoIndex)\Value = item(0)\Value ;memo this item's value
        AddElement(m()\picked())
        m()\picked() = 0 ;memo item's index also
      Else
        ;item doesn't fit, memo a zero Value
        m(memoIndex)\Value = 0
      EndIf
      ProcedureReturn @m()
    EndIf

    ;test if a greater value results with or without item included
    *tmp = knapsackSolveFast(item(), i - 1, aw, m()) ;find value without this item
    CopyStructure(*tmp, @without_i, memo)
    If item(i)\weight > aw
      ;item weighs too much, memo without including this item
      m(memoIndex) = without_i
      ProcedureReturn @m()
    Else
      *tmp = knapsackSolveFast(item(), i - 1, aw - item(i)\weight, m()) ;find value when item is included
      CopyStructure(*tmp, @with_i, memo)
      with_i\Value + item(i)\Value
      AddElement(with_i\picked())
      with_i\picked() = i ;add item to with's picked list
    EndIf

    ;set the result to the larger value
    If with_i\Value > without_i\Value
      result = with_i
    Else
      result = without_i
    EndIf

    m(memoIndex) = result ;memo the result
    ProcedureReturn @m()
  EndIf
EndProcedure

Procedure.s knapsackSolve(Array item.item(1), i, aw)
  Protected *result.memo, output.s, totalWeight
  NewMap m.memo()
  *result = knapsackSolveFast(item(), i, aw, m())
  output = "Knapsack:" + #CRLF$
  ForEach *result\picked()
    output + LSet(item(*result\picked())\name, 24) + RSet(Str(item(*result\picked())\weight), 5) + RSet(Str(item(*result\picked())\Value), 5) + #CRLF$
    totalWeight + item(*result\picked())\weight
  Next
  output + LSet("TOTALS:", 24) + RSet(Str(totalWeight), 5) + RSet(Str(*result\Value), 5)
  ProcedureReturn output
EndProcedure

If OpenConsole()
  #maxWeight = 400
  Define *result.memo
  PrintN(knapsackSolve(items(), itemCount - 1, #maxWeight))

  Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
  CloseConsole()
EndIf


10 N=41
20 K=3
30 M=0
40 FOR I=M+1 TO N
50 M=INT(I*((M+K)/I-INT((M+K)/I))+0.5)
60 NEXT I
70 PRINT "Survivor is number";M


@echo off
setlocal enabledelayedexpansion

set "prison=41"		%== Number of prisoners ==%
set "step=3"		%== The step... ==%
set "survive=1"		%== Number of survivors ==%
call :josephus

set "prison=41"
set "step=3"
set "survive=3"
call :josephus
pause
exit /b 0

	%== The Procedure ==%
:josephus
set "surv_list="
for /l %%S in (!survive!,-1,1) do (
	set /a "m = %%S - 1"
	for /l %%X in (%%S,1,!prison!) do (
		set /a "m = (m + step) %% %%X"
	)
	if defined surv_list (
		set "surv_list=!surv_list! !m!"
	) else (
		set "surv_list=!m!"
	)
)
echo !surv_list!
goto :EOF


OPEN "knapsack.txt" FOR OUTPUT AS #1
N=7: L=5: a = 2^(N+1): RANDOMIZE TIMER 'knapsack.bas DANILIN
DIM L(N), C(N), j(N), q(a), q$(a), d(a)

FOR m=a-1 TO (a-1)/2 STEP -1: g=m: DO ' cipher 0-1
    q$(m)=LTRIM$(STR$(g MOD 2))+q$(m)
    g=g\2: LOOP UNTIL g=0
    q$(m)=MID$(q$(m), 2, LEN(q$(m)))
NEXT

FOR i=1 TO N: L(i)=INT(RND*3+1) ' mass & cost
C(i)=10+INT(RND*9): PRINT #1, i, L(i), C(i): NEXT ' origin

FOR h=a-1 TO (a-1)/2 STEP -1
    FOR k=1 TO N: j(k)=VAL(MID$(q$(h), k, 1)) ' j() = cipher
        q(h)=q(h)+L(k)*j(k)*C(k) ' 0 or 1
        d(h)=d(h)+L(k)*j(k)
    NEXT
    IF d(h) <= L THEN PRINT #1, d(h), q(h), q$(h)
NEXT
max=0: m=1: FOR i=1 TO a
    IF d(i)<=L THEN IF q(i) > max THEN max=q(i): m=i
NEXT
PRINT #1,: PRINT #1, d(m), q(m), q$(m): END


REM >josephus
PRINT "Survivor is number "; FNjosephus(41, 3, 0)
END
:
DEF FNjosephus(n%, k%, m%)
LOCAL i%
FOR i% = m% + 1 TO n%
  m% = (m% + k%) MOD i%
NEXT
= m%


#include <stdio.h>

// m-th on the reversed kill list; m = 0 is final survivor
int jos(int n, int k, int m) {
	int a;
	for (a = m + 1; a <= n; a++)
		m = (m + k) % a;
	return m;
}

typedef unsigned long long xint;

// same as jos(), useful if n is large and k is not
xint jos_large(xint n, xint k, xint m) {
	if (k <= 1) return n - m - 1;

	xint a = m;
	while (a < n) {
		xint q = (a - m + k - 2) / (k - 1);

		if (a + q > n)	q = n - a;
		else if (!q)	q = 1;

		m = (m + q * k) % (a += q);
	}

	return m;
}

int main(void) {
	xint n, k, i;

	n = 41;
	k = 3;
	printf("n = %llu, k = %llu, final survivor: %d\n", n, k, jos(n, k, 0));

	n = 9876543210987654321ULL;
	k = 12031;
	printf("n = %llu, k = %llu, three survivors:", n, k);

	for (i = 3; i--; )
		printf(" %llu", jos_large(n, k, i));
	putchar('\n');

	return 0;
}


from itertools import combinations

def anycomb(items):
    ' return combinations of any length from the items '
    return ( comb
             for r in range(1, len(items)+1)
             for comb in combinations(items, r)
             )

def totalvalue(comb):
    ' Totalise a particular combination of items'
    totwt = totval = 0
    for item, wt, val in comb:
        totwt  += wt
        totval += val
    return (totval, -totwt) if totwt <= 400 else (0, 0)

items = (
    ("map", 9, 150), ("compass", 13, 35), ("water", 153, 200), ("sandwich", 50, 160),
    ("glucose", 15, 60), ("tin", 68, 45), ("banana", 27, 60), ("apple", 39, 40),
    ("cheese", 23, 30), ("beer", 52, 10), ("suntan cream", 11, 70), ("camera", 32, 30),
    ("t-shirt", 24, 15), ("trousers", 48, 10), ("umbrella", 73, 40),
    ("waterproof trousers", 42, 70), ("waterproof overclothes", 43, 75),
    ("note-case", 22, 80), ("sunglasses", 7, 20), ("towel", 18, 12),
    ("socks", 4, 50), ("book", 30, 10),
    )
bagged = max( anycomb(items), key=totalvalue) # max val or min wt if values equal
print("Bagged the following items\n  " +
      '\n  '.join(sorted(item for item,_,_ in bagged)))
val, wt = totalvalue(bagged)
print("for a total value of %i and a total weight of %i" % (val, -wt))


namespace Josephus
{
    using System;
    using System.Collections;
    using System.Collections.Generic;

    public class Program
    {
        public static int[] JosephusProblem(int n, int m)
        {
            var circle = new List<int>();
            var order = new int[n];

            for (var i = 0; i < n; ++i)
            {
                circle.Add(i);
            }

            var l = 0;
            var j = 0;
            var k = 0;

            while (circle.Count != 0)
            {
                j++;
                if (j == m)
                {
                    order[k] = circle[l];
                    circle.RemoveAt(l);

                    k++;
                    l--;
                    j = 0;
                }

                if (k == n - 1)
                {
                    order[k] = circle[0];
                    circle.RemoveAt(0);
                }

                if (l == circle.Count - 1)
                {
                    l = 0;
                }
                else
                {
                    l++;
                }
            }

            return order;
        }

        static void Main(string[] args)
        {
            try
            {
                var n = 7;
                var m = 2;

                var result = JosephusProblem(n, m);

               for (var i = 0; i < result.Length; i++)
               {
                   Console.WriteLine(result[i]);//1 3 5 0 4 2 6
               }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            finally
            {
                Console.ReadLine();
            }
        }

    }
}


Full_Data<-structure(list(item = c("map", "compass", "water", "sandwich",
"glucose", "tin", "banana", "apple", "cheese", "beer", "suntan_cream",
"camera", "T-shirt", "trousers", "umbrella", "waterproof_trousers",
"waterproof_overclothes", "note-case", "sunglasses", "towel",
"socks", "book"), weigth = c(9, 13, 153, 50, 15, 68, 27, 39,
23, 52, 11, 32, 24, 48, 73, 42, 43, 22, 7, 18, 4, 30), value = c(150,
35, 200, 160, 60, 45, 60, 40, 30, 10, 70, 30, 15, 10, 40, 70,
75, 80, 20, 12, 50, 10)), .Names = c("item", "weigth", "value"
), row.names = c(NA, 22L), class = "data.frame")

Bounded_knapsack<-function(Data,W)
{
	K<-matrix(NA,nrow=W+1,ncol=dim(Data)[1]+1)
	0->K[1,]->K[,1]
	matrix_item<-matrix('',nrow=W+1,ncol=dim(Data)[1]+1)
	for(j in 1:dim(Data)[1])
	{
		for(w in 1:W)
		{
			wj<-Data$weigth[j]
			item<-Data$item[j]
			value<-Data$value[j]
			if( wj > w )
			{
				K[w+1,j+1]<-K[w+1,j]
				matrix_item[w+1,j+1]<-matrix_item[w+1,j]
			}
			else
			{
				if( K[w+1,j] >= K[w+1-wj,j]+value )
				{
					K[w+1,j+1]<-K[w+1,j]
					matrix_item[w+1,j+1]<-matrix_item[w+1,j]
				}
				else
				{
					K[w+1,j+1]<-K[w+1-wj,j]+value
					matrix_item[w+1,j+1]<-item
				}
			}
		}
	}
return(list(K=K,Item=matrix_item))
}

backtracking<-function(knapsack, Data)
{
	W<-dim(knapsack$K)[1]
	itens<-c()
	col<-dim(knapsack$K)[2]
	selected_item<-knapsack$Item[W,col]
	while(selected_item!='')
	{
		selected_item<-knapsack$Item[W,col]
		if(selected_item!='')
		{
			selected_item_value<-Data[Data$item == selected_item,]
			if(-knapsack$K[W - selected_item_value$weigth,col-1]+knapsack$K[W,col]==selected_item_value$value)
			{
				W <- W - selected_item_value$weigth
				itens<-c(itens,selected_item)
			}
			col <- col - 1
		}
	}
return(itens)
}

print_output<-function(Data,W)
{
	Bounded_knapsack(Data,W)->Knap
	backtracking(Knap, Data)->Items
	output<-paste('You must carry:', paste(Items, sep = ', '), sep=' ' )
	return(output)
}

print_output(Full_Data, 400)


#lang racket
; An ITEM a list of three elements:
;   a name, a weight, and, a value

; A SOLUTION to a knapsack01 problems is a list of three elements:
;   the total value, the total weight, and, names of the items to bag

(define (add i s) ; add an item i to the solution s
  (match-define (list in iw iv) i)
  (match-define (list v w is) s)
  (list (+ v iv) (+ w iw) (cons in is)))

(define (knapsack max-weight items)
  ; return a solution to the knapsack01 problem
  (define ht (make-hash)) ; (weight number-of-items) -> items
  (define (get w no-items) (hash-ref ht (list w no-items) #f))
  (define (update w is x)  (hash-set! ht (list w (length is)) is) x)
  (define (knapsack1 left items)
    ; return a solution to the (left, items) problem
    (cond
      ; if there are no items, then bag no items:
      [(empty? items) (list 0 0 '())]
      ; look up the best solution:
      [(or (get left (length items))
           ; the solution haven't been cached, so we
           ; must compute it and update the cache:
           (update
            left items
            (match items
              ; let us name the first item
              [(cons (and (list i w v) x) more)
               ; if the first item weighs more than the space left,
               ; we simply find a solution, where it is omitted:
               (cond [(> w left) (knapsack left more)]
                     ; there is room for the first item, but
                     ; we need to choose the best solutions
                     ; between those with it and that without:
                     [else
                      (define without (knapsack left more))
                      (define value-without (first without))
                      (define with (knapsack (- left w) more))
                      (define value-with (+ (first with) v))
                      ; choose the solutions with greatest value
                      (if (> value-without value-with)
                          without
                          (add x with))])])))]))
  (knapsack1 max-weight items))

(knapsack 400
          '((map 9 150) ; 9 is weight, 150 is value
            (compass 13 35) (water 153 200) (sandwich 50 160)
            (glucose 15 60) (tin 68 45)(banana 27 60) (apple 39 40)
            (cheese 23 30) (beer 52 10) (cream 11 70) (camera 32 30)
            (T-shirt 24 15) (trousers 48 10) (umbrella 73 40)
            (trousers 42 70) (overclothes 43 75) (notecase 22 80)
            (glasses 7 20) (towel 18 12) (socks 4 50) (book 30 10)))


#include <iostream>
#include <vector>

//--------------------------------------------------------------------------------------------------
using namespace std;
typedef unsigned long long bigint;

//--------------------------------------------------------------------------------------------------
class josephus
{
public:
    bigint findSurvivors( bigint n, bigint k, bigint s = 0 )
    {
	bigint i = s + 1;
	for( bigint x = i; x <= n; x++, i++ )
	    s = ( s + k ) % i;

	return s;
    }

    void getExecutionList( bigint n, bigint k, bigint s = 1 )
    {
	cout << endl << endl << "Execution list: " << endl;

	prisoners.clear();
	for( bigint x = 0; x < n; x++ )
	    prisoners.push_back( x );

	bigint index = 0;
	while( prisoners.size() > s )
	{
	    index += k - 1;
	    if( index >= prisoners.size() ) index %= prisoners.size();
	    cout << prisoners[static_cast<unsigned int>( index )] << ", ";

	    vector<bigint>::iterator it = prisoners.begin() + static_cast<unsigned int>( index );
	    prisoners.erase( it );
	}
    }

private:
    vector<bigint> prisoners;
};
//--------------------------------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
    josephus jo;
    bigint n, k, s;
    while( true )
    {
	system( "cls" );
	cout << "Number of prisoners( 0 to QUIT ): "; cin >> n;
	if( !n ) return 0;
	cout << "Execution step: "; cin >> k;
	cout << "How many survivors: "; cin >> s;

	cout << endl << "Survivor";
	if( s == 1 )
	{
	    cout << ": " << jo.findSurvivors( n, k );
	    jo.getExecutionList( n, k );
	}
	else
	{
	    cout << "s: ";
	    for( bigint x = 0; x < s; x++ )
		cout << jo.findSurvivors( n, k, x ) << ", ";

	    jo.getExecutionList( n, k, s );
	}

	cout << endl << endl;
	system( "pause" );
    }
    return 0;
}
//--------------------------------------------------------------------------------------------------


my class KnapsackItem { has $.name; has $.weight; has $.unit; }

multi sub pokem ([],           $,  $v = 0) { $v }
multi sub pokem ([$,  *@],     0,  $v = 0) { $v }
multi sub pokem ([$i, *@rest], $w, $v = 0) {
  my $key = "{[email protected]} $w $v";
  (state %cache){$key} or do {
    my @skip = pokem @rest, $w, $v;
    if $w >= $i.weight { # next one fits
      my @put = pokem @rest, $w - $i.weight, $v + $i.unit;
      return (%cache{$key} = |@put, $i.name).list if @put[0] > @skip[0];
    }
    return (%cache{$key} = |@skip).list;
  }
}

my $MAX_WEIGHT = 400;
my @table = flat map -> $name,  $weight,  $unit {
     KnapsackItem.new: :$name, :$weight, :$unit;
},
    'map',                      9, 150,
    'compass',                 13,  35,
    'water',                  153, 200,
    'sandwich',                50, 160,
    'glucose',                 15,  60,
    'tin',                     68,  45,
    'banana',                  27,  60,
    'apple',                   39,  40,
    'cheese',                  23,  30,
    'beer',                    52,  10,
    'suntan cream',            11,  70,
    'camera',                  32,  30,
    'T-shirt',                 24,  15,
    'trousers',                48,  10,
    'umbrella',                73,  40,
    'waterproof trousers',     42,  70,
    'waterproof overclothes',  43,  75,
    'note-case',               22,  80,
    'sunglasses',               7,  20,
    'towel',                   18,  12,
    'socks',                    4,  50,
    'book',                    30,  10;

my ($value, @result) = pokem @table, $MAX_WEIGHT;
say "Value = $value\nTourist put in the bag:\n  " ~ @result;


(defn rotate [n s] (lazy-cat (drop n s) (take n s)))

(defn josephus [n k]
   (letfn [(survivor [[ h & r :as l] k]
             (cond (empty? r) h
                   :else      (survivor (rest (rotate (dec k) l)) k)))]
     (survivor (range n) k)))

(let [n 41 k 3]
   (println (str "Given " n " prisoners in a circle numbered 1.." n
                 ", an executioner moving around the"))
   (println (str "circle " k " at a time will leave prisoner number "
                 (inc (josephus n k)) " as the last survivor.")))


(defun kill (n k &aux (m 0))
  (loop for a from (1+ m) upto n do
        (setf m (mod (+ m k) a)))
  m)


/*REXX program solves a  knapsack problem  (22  {+1}  items with a weight restriction). */
maxWeight=400                                    /*the maximum weight for the knapsack. */
     say 'maximum weight allowed for a knapsack:'  commas(maxWeight);          say
call [email protected]                                        /*generate the   @   array of choices. */
call sortD                                       /*  sort    "    "     "    "    "     */
call build                                       /*build some associative arrays from @.*/
call findBest                                    /*go ye forth and find the best choises*/
call results                                     /*display the best choices for knapsack*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
build:    do j=1  for obj; parse var @.j x w v . /*construct a list of knapsack choices.*/
          if w>maxWeight  then iterate           /*Is weight greater than max?   Ignore.*/
          totW=totW + w;        totV=totV + v    /*add the totals (for output alignment)*/
          maxL=max(maxL, length(x) )             /*determine maximum width for an item. */
          #=#+1;  i.#=x;  w.#=w;  v.#=v          /*bump the number of items (choices).  */
          end   /*j*/                            /* [↑]  build indexable arrays of items*/
      maxL= maxL + maxL%4 + 4                    /*extend width of name for shown table.*/
      maxW= max(maxW, length( commas(totW) ) )   /*find the maximum width for  weight.  */
      maxV= max(maxV, length( commas(totV) ) )   /*  "   "     "      "    "   value.   */
      call hdr 'potential knapsack items'        /*display a header for list of choices.*/
          do j=1  for obj; parse var @.j i w v . /*show all the choices in a nice format*/
          if w<=maxWeight  then call show i,w,v  /*Is weight within limits?  Then show. */
          end   /*j*/                            /* [↑]  display the list of choices.   */
      $=0
      say;  say 'number of allowable items: '  #
      return
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: procedure;  parse arg _;   n=_'.9';    #=123456789;     b=verify(n, #, "M")
        e=verify(n, #'0', , verify(n, #"0.", 'M')) - 4;         comma=','
           do j=e  to b  by -3;   _=insert(comma, _, j);   end  /*j*/;            return _
/*──────────────────────────────────────────────────────────────────────────────────────*/
findBest:                                m=maxWeight   /*items are in decreasing weight.*/
   do j1 =0          for #+1;                                 w1 =    w.j1 ; z1 =    v.j1
   do j2 =j1 +(j1 >0) to #; if w.j2 +w1 >m  then iterate j1 ; w2 =w1 +w.j2 ; z2 =z1 +v.j2
   do j3 =j2 +(j2 >0) to #; if w.j3 +w2 >m  then iterate j2 ; w3 =w2 +w.j3 ; z3 =z2 +v.j3
   do j4 =j3 +(j3 >0) to #; if w.j4 +w3 >m  then iterate j3 ; w4 =w3 +w.j4 ; z4 =z3 +v.j4
   do j5 =j4 +(j4 >0) to #; if w.j5 +w4 >m  then iterate j4 ; w5 =w4 +w.j5 ; z5 =z4 +v.j5
   do j6 =j5 +(j5 >0) to #; if w.j6 +w5 >m  then iterate j5 ; w6 =w5 +w.j6 ; z6 =z5 +v.j6
   do j7 =j6 +(j6 >0) to #; if w.j7 +w6 >m  then iterate j6 ; w7 =w6 +w.j7 ; z7 =z6 +v.j7
   do j8 =j7 +(j7 >0) to #; if w.j8 +w7 >m  then iterate j7 ; w8 =w7 +w.j8 ; z8 =z7 +v.j8
   do j9 =j8 +(j8 >0) to #; if w.j9 +w8 >m  then iterate j8 ; w9 =w8 +w.j9 ; z9 =z8 +v.j9
   do j10=j9 +(j9 >0) to #; if w.j10+w9 >m  then iterate j9 ; w10=w9 +w.j10; z10=z9 +v.j10
   do j11=j10+(j10>0) to #; if w.j11+w10>m  then iterate j10; w11=w10+w.j11; z11=z10+v.j11
   do j12=j11+(j11>0) to #; if w.j12+w11>m  then iterate j11; w12=w11+w.j12; z12=z11+v.j12
   do j13=j12+(j12>0) to #; if w.j13+w12>m  then iterate j12; w13=w12+w.j13; z13=z12+v.j13
   do j14=j13+(j13>0) to #; if w.j14+w13>m  then iterate j13; w14=w13+w.j14; z14=z13+v.j14
   do j15=j14+(j14>0) to #; if w.j15+w14>m  then iterate j14; w15=w14+w.j15; z15=z14+v.j15
   do j16=j15+(j15>0) to #; if w.j16+w15>m  then iterate j15; w16=w15+w.j16; z16=z15+v.j16
   do j17=j16+(j16>0) to #; if w.j17+w16>m  then iterate j16; w17=w16+w.j17; z17=z16+v.j17
   do j18=j17+(j17>0) to #; if w.j18+w17>m  then iterate j17; w18=w17+w.j18; z18=z17+v.j18
   do j19=j18+(j18>0) to #; if w.j19+w18>m  then iterate j18; w19=w18+w.j19; z19=z18+v.j19
   do j20=j19+(j19>0) to #; if w.j20+w19>m  then iterate j19; w20=w19+w.j20; z20=z19+v.j20
   do j21=j20+(j20>0) to #; if w.j21+w20>m  then iterate j20; w21=w20+w.j21; z21=z20+v.j21
   do j22=j21+(j21>0) to #; if w.j22+w21>m  then iterate j21; w22=w21+w.j22; z22=z21+v.j22
   if z22>$  then do;  ?=;  $=z22;    do j=1  for 22;  ?=? value("J"j);  end /*j*/;    end
   end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end;end
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
[email protected]:          @.  =                           ;     @.12= 'camera                 32  30'
               @.1 = 'map               9 150' ;     @.13= 'T-shirt                24  15'
               @.2 = 'compass          13  35' ;     @.14= 'trousers               48  10'
               @.3 = 'water           153 200' ;     @.15= 'umbrella               73  40'
               @.4 = 'sandwich         50 160' ;     @.16= 'waterproof_trousers    42  70'
               @.5 = 'glucose          15  60' ;     @.17= 'waterproof_overclothes 43  75'
               @.6 = 'tin              68  45' ;     @.18= 'note-case              22  80'
               @.7 = 'banana           27  60' ;     @.19= 'sunglasses              7  20'
               @.8 = 'apple            39  40' ;     @.20= 'towel                  18  12'
               @.9 = 'cheese           23  30' ;     @.21= 'socks                   4  50'
               @.10= 'beer             52  10' ;     @.22= 'book                   30  10'
               @.11= 'suntan_cream     11  70' ;     @.23= 'anvil              100000   1'
      maxL = length('potential knapsack items')  /*maximum width for the table items.   */
      maxW = length('weight')                    /*   "      "    "   "    "   weights. */
      maxV = length('value')                     /*   "      "    "   "    "   values.  */
      #=0;  i.=;  w.=0;  v.=0;  totW=0;  totV=0  /*initialize some REX variables stuff. */
      return
/*──────────────────────────────────────────────────────────────────────────────────────*/
hdr:    say;  call show center(arg(1),maxL),center('weight',maxW),center("value",maxV)
hdr2:         call show copies('═',maxL),copies('═',maxW),copies('═',maxV);       return
/*──────────────────────────────────────────────────────────────────────────────────────*/
results:          do #;  ?=strip( space(?), "L", 0);  end  /*h*/  /*elide leading zeroes*/
        bestC=?;    bestW=0;         totP=words(bestC);     say;    call hdr 'best choice'
                  do j=1  for totP;  _=word(bestC, j);      _w=w._;      _v=v._
                      do k=j+1  to totP;     __=word(bestC, k);   if i._\==i.__ then leave
                      j=j+1;  w._=w._ + _w;  v._=v._ + _v
                      end    /*k*/
                  call show i._, w._, v._;   bestW=bestW + w._
                  end        /*j*/
        call hdr2                   ;   say;                @bestTK= 'best total knapsack'
        call show @bestTK  'weight' ,   bestW    /*display a nicely formatted winner wt.*/
        call show @bestTK  'value'  ,,  $        /*     "  "    "       "     winner val*/
        call show @bestTK  'items'  ,,, totP     /*     "  "    "       "     pieces.   */
        return
/*──────────────────────────────────────────────────────────────────────────────────────*/
show:   parse arg _i,_w,_v,_p;  say translate( left(_i,maxL,'─'), , "_") ,
                                right(commas(_w),maxW) right(commas(_v),maxV) _p;   return
/*──────────────────────────────────────────────────────────────────────────────────────*/
sortD:     do j=1  while @.j\==''; y=word(@.j,2) /*process each of the knapsack choices.*/
                do k=j+1  while @.k\==''         /*find a possible heavier knapsack item*/
                ?=word(@.k,2);  if ?>y  then do; [email protected].k; @.[email protected].j; @.j=_; y=?; end  /*swap*/
                end   /*k*/
           end        /*j*/                      /* [↑]  sort choices by decreasing wt. */
        obj=j-1;                   return        /*decrement  J  for the  DO  loop index*/


n = ARGV.fetch(0, 41).to_i  # n default is 41 or ARGV[0]
k = ARGV.fetch(1,  3).to_i  # k default is 3 or ARGV[1]

prisoners = (0...n).to_a
while prisoners.size > 1; prisoners.rotate!(k-1).shift end
puts "From #{n} prisoners, eliminating each prisoner #{k} leaves prisoner #{prisoners.first}."


import std.stdio, std.algorithm, std.array, std.string, std.range;

T pop(T)(ref T[] items, in size_t i) pure /*nothrow*/ @safe /*@nogc*/ {
    auto aux = items[i];
    items = items.remove(i);
    return aux;
}

string josephus(in int n, in int k) pure /*nothrow*/ @safe {
    auto p = n.iota.array;
    int i;
    immutable(int)[] seq;
    while (!p.empty) {
        i = (i + k - 1) % p.length;
        seq ~= p.pop(i);
    }

    return format("Prisoner killing order:\n%(%(%d %)\n%)." ~
                  "\nSurvivor: %d",
                  seq[0 .. $ - 1].chunks(20), seq[$ - 1]);
}

void main() /*@safe*/ {
    josephus(5, 2).writeln;
    writeln;
    josephus(41, 3).writeln;
}


KnapsackItem = Struct.new(:name, :weight, :value)
potential_items = [
  KnapsackItem['map', 9, 150],              KnapsackItem['compass', 13, 35],
  KnapsackItem['water', 153, 200],          KnapsackItem['sandwich', 50, 160],
  KnapsackItem['glucose', 15, 60],          KnapsackItem['tin', 68, 45],
  KnapsackItem['banana', 27, 60],           KnapsackItem['apple', 39, 40],
  KnapsackItem['cheese', 23, 30],           KnapsackItem['beer', 52, 10],
  KnapsackItem['suntan cream', 11, 70],     KnapsackItem['camera', 32, 30],
  KnapsackItem['t-shirt', 24, 15],          KnapsackItem['trousers', 48, 10],
  KnapsackItem['umbrella', 73, 40],         KnapsackItem['waterproof trousers', 42, 70],
  KnapsackItem['waterproof overclothes', 43, 75], KnapsackItem['note-case', 22, 80],
  KnapsackItem['sunglasses', 7, 20],        KnapsackItem['towel', 18, 12],
  KnapsackItem['socks', 4, 50],             KnapsackItem['book', 30, 10],
]
knapsack_capacity = 400

class Array
  # do something for each element of the array's power set
  def power_set
    yield [] if block_given?
    self.inject([[]]) do |ps, elem|
      ps.each_with_object([]) do |i,r|
        r << i
        new_subset = i + [elem]
        yield new_subset if block_given?
        r << new_subset
      end
    end
  end
end

maxval, solutions = potential_items.power_set.group_by {|subset|
  weight = subset.inject(0) {|w, elem| w + elem.weight}
  weight>knapsack_capacity ? 0 : subset.inject(0){|v, elem| v + elem.value}
}.max

puts "value: #{maxval}"
solutions.each do |set|
  wt, items = 0, []
  set.each {|elem| wt += elem.weight; items << elem.name}
  puts "weight: #{wt}"
  puts "items: #{items.join(',')}"
end


;; input
(define N 41)
(define K 3)
(define prisoners (apply circular-list (iota N)))
(define last-one prisoners) ; current position

;; kill returns current position = last killed
(define (kill lst skip)
(cond
    ((eq? (mark? lst) '🔫 )(kill (cdr lst) skip)) ;; dead ? goto next
    ((zero? skip) (mark lst '🔫)) ;; all skipped ? kill
    (else (mark lst '😥 )  ;; relieved face
           (kill (cdr lst ) (1- skip))))) ;; skip 1 and goto next


class
	APPLICATION

create
	make

feature

	make
		do
			io.put_string ("Survivor is prisoner: " + execute (12, 4).out)
		end

	execute (n, k: INTEGER): INTEGER
			-- Survivor of 'n' prisoners, when every 'k'th is executed.
		require
			n_positive: n > 0
			k_positive: k > 0
			n_larger: n > k
		local
			killidx: INTEGER
			prisoners: LINKED_LIST [INTEGER]
		do
			create prisoners.make
			across
				0 |..| (n - 1) as c
			loop
				prisoners.extend (c.item)
			end
			io.put_string ("Prisoners are executed in the order:%N")
			killidx := 1
			from
			until
				prisoners.count <= 1
			loop
				killidx := killidx + k - 1
				from
				until
					killidx <= prisoners.count
				loop
					killidx := killidx - prisoners.count
				end
				io.put_string (prisoners.at (killidx).out + "%N")
				prisoners.go_i_th (killidx)
				prisoners.remove
			end
			Result := prisoners.at (1)
		ensure
			Result_in_range: Result >= 0 and Result < n
		end

end


use std::cmp;

struct Item {
    name: &'static str,
    weight: usize,
    value: usize
}

fn knapsack01_dyn(items: &[Item], max_weight: usize) -> Vec<&Item> {
    let mut best_value = vec![vec![0; max_weight + 1]; items.len() + 1];
    for (i, it) in items.iter().enumerate() {
        for w in 1 .. max_weight + 1 {
            best_value[i + 1][w] =
                if it.weight > w {
                    best_value[i][w]
                } else {
                    cmp::max(best_value[i][w], best_value[i][w - it.weight] + it.value)
                }
        }
    }

    let mut result = Vec::with_capacity(items.len());
    let mut left_weight = max_weight;

    for (i, it) in items.iter().enumerate().rev() {
        if best_value[i + 1][left_weight] != best_value[i][left_weight] {
            result.push(it);
            left_weight -= it.weight;
        }
    }

    result
}

fn main () {
    const MAX_WEIGHT: usize = 400;

    const ITEMS: &[Item] = &[
        Item { name: "map",                    weight: 9,   value: 150 },
        Item { name: "compass",                weight: 13,  value: 35 },
        Item { name: "water",                  weight: 153, value: 200 },
        Item { name: "sandwich",               weight: 50,  value: 160 },
        Item { name: "glucose",                weight: 15,  value: 60 },
        Item { name: "tin",                    weight: 68,  value: 45 },
        Item { name: "banana",                 weight: 27,  value: 60 },
        Item { name: "apple",                  weight: 39,  value: 40 },
        Item { name: "cheese",                 weight: 23,  value: 30 },
        Item { name: "beer",                   weight: 52,  value: 10 },
        Item { name: "suntancream",            weight: 11,  value: 70 },
        Item { name: "camera",                 weight: 32,  value: 30 },
        Item { name: "T-shirt",                weight: 24,  value: 15 },
        Item { name: "trousers",               weight: 48,  value: 10 },
        Item { name: "umbrella",               weight: 73,  value: 40 },
        Item { name: "waterproof trousers",    weight: 42,  value: 70 },
        Item { name: "waterproof overclothes", weight: 43,  value: 75 },
        Item { name: "note-case",              weight: 22,  value: 80 },
        Item { name: "sunglasses",             weight: 7,   value: 20 },
        Item { name: "towel",                  weight: 18,  value: 12 },
        Item { name: "socks",                  weight: 4,   value: 50 },
        Item { name: "book",                   weight: 30,  value: 10 }
    ];

    let items = knapsack01_dyn(ITEMS, MAX_WEIGHT);

    // We reverse the order because we solved the problem backward.
    for it in items.iter().rev() {
        println!("{}", it.name);
    }

    println!("Total weight: {}", items.iter().map(|w| w.weight).sum::<usize>());
    println!("Total value: {}", items.iter().map(|w| w.value).sum::<usize>());
}


/* create SAS data set */
data mydata;
   input item $1-23 weight value;
   datalines;
map                      9  150
compass                 13   35
water                  153  200
sandwich                50  160
glucose                 15   60
tin                     68   45
banana                  27   60
apple                   39   40
cheese                  23   30
beer                    52   10
suntan cream            11   70
camera                  32   30
T-shirt                 24   15
trousers                48   10
umbrella                73   40
waterproof trousers     42   70
waterproof overclothes  43   75
note-case               22   80
sunglasses               7   20
towel                   18   12
socks                    4   50
book                    30   10
;

/* call OPTMODEL procedure in SAS/OR */
proc optmodel;
   /* declare sets and parameters, and read input data */
   set <str> ITEMS;
   num weight {ITEMS};
   num value {ITEMS};
   read data mydata into ITEMS=[item] weight value;

   /* declare variables, objective, and constraints */
   var NumSelected {ITEMS} binary;
   max TotalValue = sum {i in ITEMS} value[i] * NumSelected[i];
   con WeightCon:
      sum {i in ITEMS} weight[i] * NumSelected[i] <= 400;

   /* call mixed integer linear programming (MILP) solver */
   solve;

   /* print optimal solution */
   print TotalValue;
   print {i in ITEMS: NumSelected[i].sol > 0.5} NumSelected;
quit;


defmodule Josephus do
  def find(n,k) do
    find(Enum.to_list(0..n-1),0..k-2,k..n)
  end

  def find([_|[r|_]],_,_..d) when d < 3 do
    IO.inspect r
  end

  def find(arr,a..c,b..d) when length(arr) >= 3 do
    find(Enum.slice(arr,b..d) ++ Enum.slice(arr,a..c),a..c,b..d-1)
  end
end

Josephus.find(41,3)


object Knapsack extends App {

  case class Item(name: String, weight: Int, value: Int)

  val elapsed: (=> Unit) => Long = f => {val s = System.currentTimeMillis; f; (System.currentTimeMillis - s)/1000}

  //===== brute force (caution: increase the heap!) ====================================
  val ks01b: List[Item] => Unit = loi => {
    val tw:Set[Item]=>Int=ps=>(ps:\0)((a,b)=>a.weight+b) //total weight
    val tv:Set[Item]=>Int=ps=>(ps:\0)((a,b)=>a.value+b) //total value
    val pis = (loi.toSet.subsets).toList.filterNot(_==Set())

   #[test]
fn test_dp_results() {
    let dp_results = knap_01_dp(items, 400);
    let dp_weights= dp_results.iter().fold(0, |a, &b| a + b.weight);
    let dp_values = dp_results.iter().fold(0, |a, &b| a + b.value);
    assert_eq!(dp_weights, 396);
    assert_eq!(dp_values, 1030);
} val res = pis.map(ss=>Pair(ss,tw(ss)))
      .filter(p=>p._2>350 && p._2<401).map(p=>Pair(p,tv(p._1)))
      .sortWith((s,t)=>s._2.compareTo(t._2) < 0)
      .last
    println{val h = "packing list of items (brute force):"; h+"\n"+"="*h.size}
    res._1._1.foreach{p=>print("  "+p.name+": weight="+p.weight+" value="+p.value+"\n")}
    println("\n"+"  resulting items: "+res._1._1.size+" of "+loi.size)
    println("  total weight: "+res._1._2+", total value: "+res._2)
  }

  //===== dynamic programming ==========================================================
  val ks01d: List[Item] => Unit = loi => {
    val W = 400
    val N = loi.size

    val m = Array.ofDim[Int](N+1,W+1)
    val plm = (List((for {w <- 0 to W} yield Set[Item]()).toArray)++(
                for {
                  n <- 0 to N-1
                  colN = (for {w <- 0 to W} yield Set[Item](loi(n))).toArray
                } yield colN)).toArray

    1 to N foreach {n =>
      0 to W foreach {w =>
        def in = loi(n-1)
        def wn = loi(n-1).weight
        def vn = loi(n-1).value
        if (w<wn) {
          m(n)(w) = m(n-1)(w)
          plm(n)(w) = plm(n-1)(w)
        }
        else {
          if (m(n-1)(w)>=m(n-1)(w-wn)+vn) {
            m(n)(w) = m(n-1)(w)
            plm(n)(w) = plm(n-1)(w)
          }
          else {
            m(n)(w) = m(n-1)(w-wn)+vn
	    plm(n)(w) = plm(n-1)(w-wn)+in
	  }
	}
      }
    }

    println{val h = "packing list of items (dynamic programming):"; h+"\n"+"="*h.size}
    plm(N)(W).foreach{p=>print("  "+p.name+": weight="+p.weight+" value="+p.value+"\n")}
    println("\n"+"  resulting items: "+plm(N)(W).size+" of "+loi.size)
    println("  total weight: "+(0/:plm(N)(W).toVector.map{item=>item.weight})(_+_)+", total value: "+m(N)(W))
  }

  val items = List(
     Item("map", 9, 150)
    ,Item("compass", 13, 35)
    ,Item("water", 153, 200)
    ,Item("sandwich", 50, 160)
    ,Item("glucose", 15, 60)
    ,Item("tin", 68, 45)
    ,Item("banana", 27, 60)
    ,Item("apple", 39, 40)
    ,Item("cheese", 23, 30)
    ,Item("beer", 52, 10)
    ,Item("suntan cream", 11, 70)
    ,Item("camera", 32, 30)
    ,Item("t-shirt", 24, 15)
    ,Item("trousers", 48, 10)
    ,Item("umbrella", 73, 40)
    ,Item("waterproof trousers", 42, 70)
    ,Item("waterproof overclothes", 43, 75)
    ,Item("note-case", 22, 80)
    ,Item("sunglasses", 7, 20)
    ,Item("towel", 18, 12)
    ,Item("socks", 4, 50)
    ,Item("book", 30, 10)
  )

  List(ks01b, ks01d).foreach{f=>
    val t = elapsed{f(items)}
    println("  elapsed time: "+t+" sec"+"\n")
  }
}


-module( josephus_problem ).

-export( [general_solution/3, task/0] ).

general_solution( Prisoners, Kill, Survive ) -> general_solution( Prisoners, Kill, Survive, erlang:length(Prisoners), [] ).

task() -> general_solution( lists:seq(0, 40), 3, 1 ).

general_solution( Prisoners, _Kill, Survive, Survive, Kills ) ->
        {Prisoners, lists:reverse(Kills)};
general_solution( Prisoners, Kill, Survive, Prisoners_length, Kills ) ->
        {Skipped, [Killed | Rest]} = kill( Kill, Prisoners, Prisoners_length ),
        general_solution( Rest ++ Skipped, Kill, Survive, Prisoners_length - 1, [Killed | Kills] ).

kill( Kill, Prisoners, Prisoners_length ) when Kill < Prisoners_length ->
    lists:split( Kill - 1, Prisoners );
kill( Kill, Prisoners, Prisoners_length ) ->
    kill_few( Kill rem Prisoners_length, Prisoners ).

kill_few( 0, Prisoners ) ->
    [Last | Rest] = lists:reverse( Prisoners ),
    {lists:reverse( Rest ), [Last]};
kill_few( Kill, Prisoners ) ->
    lists:split( Kill - 1, Prisoners ).


var raw = <<'TABLE'
map,                      9, 150
compass,                 13,  35
water,                  153, 200
sandwich,                50, 160
glucose,                 15,  60
tin,                     68,  45
banana,                  27,  60
apple,                   39,  40
cheese,                  23,  30
beer,                    52,  10
suntancream,             11,  70
camera,                  32,  30
T-shirt,                 24,  15
trousers,                48,  10
umbrella,                73,  40
waterproof trousers,     42,  70
waterproof overclothes,  43,  75
note-case,               22,  80
sunglasses,               7,  20
towel,                   18,  12
socks,                    4,  50
book,                    30,  10
TABLE

struct KnapsackItem {
    String name,
    Number weight,
    Number value,
}

var items = []
raw.each_line{ |row|
    var fields = row.split(/\s*,\s*/)
    items << KnapsackItem(
          name: fields[0],
        weight: fields[1].to_n,
         value: fields[2].to_n,
    )
}

var max_weight = 400
var p = [
    items.len.of { [[0, []], max_weight.of(nil)...] }...,
    max_weight.inc.of {[0, []]}
]

func optimal(i, w) {
    if (!defined p[i][w]) {
        var item = items[i];
        if (item.weight > w) {
            p[i][w] = optimal(i.dec, w)
        }
        else {
            var x = optimal(i.dec, w)
            var y = optimal(i.dec, w - item.weight)

            if (x[0] > (y[0] + item.value)) {
                p[i][w] = x;
            }
            else {
                p[i][w] = [y[0] + item.value, [y[1]..., item.name]]
            }
        }
    }
    return p[i][w]
}

var sol = optimal(items.end, max_weight)
say "#{sol[0]}: #{sol[1]}"


PROGRAM JOSEPHUS

!
! for rosettacode.org
!

!$INTEGER

DIM DEAD[100]

PROCEDURE MAIN(N,K,S->ERRORS)
! n - number of prisoners
! k - kill every k'th prisoner
! s - number of survivors
    LOCAL KILLED$,SURVIVED$,FOUND,P,NN,I
    ERRORS=0
    FOR I=0 TO 100 DO
        DEAD[I]=0
    END FOR   ! prepare array
    PRINT("N=";N,"K=";K,"S=";S)        ! show arguments
    IF S>N THEN PRINT("S>N";) ERRORS+=1 END IF
    IF K<=0 THEN PRINT("K<=0";) ERRORS+=1 END IF
    IF ERRORS>0 THEN EXIT PROCEDURE END IF
    NN=N                               ! wrap around boundary
    P=-1                               ! start here
    WHILE N<>S DO                      ! until survivor count is met
      FOUND=0                          ! start looking
      WHILE FOUND<>K DO                ! until we have the k-th prisoner
        P+=1
        IF P=NN THEN P=0 END IF        ! wrap around
        IF DEAD[P]<>1 THEN
            FOUND+=1
        END IF                         ! if prisoner is alive increment found
      END WHILE
      DEAD[P]=1                        ! kill the unlucky one
      KILLED$=KILLED$+STR$(P)          ! build killed list
      N-=1                             ! reduce size of circle
    END WHILE
    FOR I=0 TO NN-1 DO
      IF DEAD[I]<>1 THEN
        SURVIVED$=SURVIVED$+STR$(I)    ! build survivor list
      END IF
    END FOR
    PRINT("Killed:";KILLED$)
    PRINT("Survived:";SURVIVED$)
END PROCEDURE

BEGIN
    ERRORS=0
    MAIN(5,2,1->ERRORS)
    MAIN(41,3,1->ERRORS)
    MAIN(41,3,3->ERRORS)
END PROGRAM


USING: kernel locals math math.ranges sequences ;
IN: josephus

:: josephus ( k n -- m )
    n [1,b] 0 [ [ k + ] dip mod ] reduce ;


: josephus  0 1 begin dup 41 <= while  swap 3 + over mod swap  1+ repeat drop ;


WITH KnapsackItems (item, [weight], VALUE) AS
(
    SELECT 'map',9,  150
    UNION ALL SELECT 'compass',13,  35
    UNION ALL SELECT 'water',153,  200
    UNION ALL SELECT 'sandwich',50,  160
    UNION ALL SELECT 'glucose',15,  60
    UNION ALL SELECT 'tin',68,  45
    UNION ALL SELECT 'banana',27,  60
    UNION ALL SELECT 'apple',39,  40
    UNION ALL SELECT 'cheese',23,  30
    UNION ALL SELECT 'beer',52,  10
    UNION ALL SELECT 'suntan cream',11,  70
    UNION ALL SELECT 'camera',32,  30
    UNION ALL SELECT 'T-shirt',24,  15
    UNION ALL SELECT 'trousers',48,  10
    UNION ALL SELECT 'umbrella',73,  40
    UNION ALL SELECT 'waterproof trousers',42,  70
    UNION ALL SELECT 'waterproof overclothes',43,  75
    UNION ALL SELECT 'note-case',22,  80
    UNION ALL SELECT 'sunglasses',7,  20
    UNION ALL SELECT 'towel',18,  12
    UNION ALL SELECT 'socks',4,  50
    UNION ALL SELECT 'book',30,  10
)
SELECT *
INTO #KnapsackItems
FROM KnapsackItems;

WITH UNIQUEnTuples (n, Tuples, ID, [weight], VALUE) AS (
    SELECT 1, CAST(item AS VARCHAR(8000)), item, [weight], VALUE
    FROM #KnapsackItems
    UNION ALL
    SELECT 1 + n.n, t.item + ',' + n.Tuples, item, n.[weight] + t.[weight], n.VALUE + t.VALUE
    FROM UNIQUEnTuples n
    CROSS APPLY (
        SELECT item, [weight], VALUE
        FROM #KnapsackItems t
        WHERE t.item < n.ID AND n.[weight] + t.[weight] < 400) t
    )
SELECT TOP 5 *
FROM UNIQUEnTuples
ORDER BY VALUE DESC, n, Tuples;

GO
DROP TABLE #KnapsackItems;


program josephus
   implicit none
   integer :: n, i, k, p
   integer, allocatable :: next(:)
   read *, n, k
   allocate(next(0:n - 1))
   do i = 0, n - 2
      next(i) = i + 1
   end do
   next(n - 1) = 0
   p = 0
   do while(next(p) /= p)
      do i = 1, k - 2
         p = next(p)
      end do
      print *, "Kill", next(p)
      next(p) = next(next(p))
      p = next(p)
   end do
   print *, "Alive", p
   deallocate(next)
end program


Function Josephus (n As Integer, k As Integer, m As Integer) As Integer
    Dim As Integer lm = m
    For i As Integer = m + 1  To n
        lm = (lm + k) Mod i
    Next i
    Josephus = lm
End Function

Dim As Integer n = 41 'prisioneros
Dim As Integer k = 3  'orden de ejecución

Print "n ="; n, "k ="; k, "superviviente = "; Josephus(n, k, 0)


struct KnapsackItem {
  var name: String
  var weight: Int
  var value: Int
}

func knapsack(items: [KnapsackItem], limit: Int) -> [KnapsackItem] {
  var table = Array(repeating: Array(repeating: 0, count: limit + 1), count: items.count + 1)

  for j in 1..<items.count+1 {
    let item = items[j-1]

    for w in 1..<limit+1 {
      if item.weight > w {
        table[j][w] = table[j-1][w]
      } else {
        table[j][w] = max(table[j-1][w], table[j-1][w-item.weight] + item.value)
      }
    }
  }

  var result = [KnapsackItem]()
  var w = limit

  for j in stride(from: items.count, to: 0, by: -1) where table[j][w] != table[j-1][w] {
    let item = items[j-1]

    result.append(item)

    w -= item.weight
  }

  return result
}

let items = [
  KnapsackItem(name: "map", weight: 9, value: 150), KnapsackItem(name: "compass", weight: 13, value: 35),
  KnapsackItem(name: "water", weight: 153, value: 200), KnapsackItem(name: "sandwich", weight: 50, value: 160),
  KnapsackItem(name: "glucose", weight: 15, value: 60), KnapsackItem(name: "tin", weight: 68, value: 45),
  KnapsackItem(name: "banana", weight: 27, value: 60), KnapsackItem(name: "apple", weight: 39, value: 40),
  KnapsackItem(name: "cheese", weight: 23, value: 30), KnapsackItem(name: "beer", weight: 52, value: 10),
  KnapsackItem(name: "suntan cream", weight: 11, value: 70), KnapsackItem(name: "camera", weight: 32, value: 30),
  KnapsackItem(name: "t-shirt", weight: 24, value: 15), KnapsackItem(name: "trousers", weight: 48, value: 10),
  KnapsackItem(name: "umbrella", weight: 73, value: 40), KnapsackItem(name: "waterproof trousers", weight: 42, value: 70),
  KnapsackItem(name: "waterproof overclothes", weight: 43, value: 75), KnapsackItem(name: "note-case", weight: 22, value: 80),
  KnapsackItem(name: "sunglasses", weight: 7, value: 20), KnapsackItem(name: "towel", weight: 18, value: 12),
  KnapsackItem(name: "socks", weight: 4, value: 50), KnapsackItem(name: "book", weight: 30, value: 10)
]

let kept = knapsack(items: items, limit: 400)

print("Kept: ")

for item in kept {
  print("  \(item.name)")
}

let (tValue, tWeight) = kept.reduce((0, 0), { ($0.0 + $1.value, $0.1 + $1.weight) })

print("For a total value of \(tValue) and a total weight of \(tWeight)")


# The list of items to consider, as list of lists
set items {
    {map			9	150}
    {compass			13	35}
    {water			153	200}
    {sandwich			50	160}
    {glucose			15	60}
    {tin			68	45}
    {banana			27	60}
    {apple			39	40}
    {cheese			23	30}
    {beer			52	10}
    {{suntan cream}		11	70}
    {camera			32	30}
    {t-shirt			24	15}
    {trousers			48	10}
    {umbrella			73	40}
    {{waterproof trousers}	42	70}
    {{waterproof overclothes}	43	75}
    {note-case			22	80}
    {sunglasses			7	20}
    {towel			18	12}
    {socks			4	50}
    {book			30	10}
}

# Simple extraction functions
proc names {chosen} {
    set names {}
    foreach item $chosen {lappend names [lindex $item 0]}
    return $names
}
proc weight {chosen} {
    set weight 0
    foreach item $chosen {incr weight [lindex $item 1]}
    return $weight
}
proc value {chosen} {
    set value 0
    foreach item $chosen {incr value [lindex $item 2]}
    return $value
}

# Recursive function for searching over all possible choices of items
proc knapsackSearch {items {chosen {}}} {
    # If we've gone over the weight limit, stop now
    if {[weight $chosen] > 400} {
	return
    }
    # If we've considered all of the items (i.e., leaf in search tree)
    # then see if we've got a new best choice.
    if {[llength $items] == 0} {
	global best max
	set v [value $chosen]
	if {$v > $max} {
	    set max $v
	    set best $chosen
	}
	return
    }
    # Branch, so recurse for chosing the current item or not
    set this [lindex $items 0]
    set rest [lrange $items 1 end]
    knapsackSearch $rest $chosen
    knapsackSearch $rest [lappend chosen $this]
}

# Initialize a few global variables
set best {}
set max 0
# Do the brute-force search
knapsackSearch $items
# Pretty-print the results
puts "Best filling has weight of [expr {[weight $best]/100.0}]kg and score [value $best]"
puts "Best items:\n\t[join [lsort [names $best]] \n\t]"


function execute
    # If the list is empty, don't do anything.
    test (count $argv) -ge 2; or return
    # If the list has only one element, return it
    if test (count $argv) -eq 2
        echo $argv[2]
        return
    end
    # Rotate prisoners
    for i in (seq 2 $argv[1])
        set argv $argv[1 3..-1 2]
    end
    # Mention killed prisoner
    echo $argv[2]
    # Kill rest recursively
    execute $argv[1 3..-1]
end

echo Prisoner (execute 3 (seq 0 40))[-1] survived.


killingCycle[prisonerCount,killStep = 2] :=
{
   i = 0
   killed = new array
   prisoners = array[0 to prisonerCount - 1]
   while length[prisoners] > 1
   {
      i = (i + killStep - 1) mod length[prisoners]
      killed.push[prisoners.remove[i]] // Remove the killed prisoner from the prisoners array and add it to the killed array.
   }
   killedResult = "Killed:"
   for kill = killed // Loop through the killed array to format it nicely.
   {
      killedResult = killedResult + " " + kill
   }
   aliveResult = "Alive: " + [email protected] // Get the only item left in the array
   return """$killedResult
$aliveResult"""
}

println[killingCycle[41,3]] // Enter in total number of prisoners and the number to skip each cycle


package main

import "fmt"

// basic task function
func finalSurvivor(n, k int) int {
    // argument validation omitted
    circle := make([]int, n)
    for i := range circle {
        circle[i] = i
    }
    k--
    exPos := 0
    for len(circle) > 1 {
        exPos = (exPos + k) % len(circle)
        circle = append(circle[:exPos], circle[exPos+1:]...)
    }
    return circle[0]
}

// extra
func position(n, k, pos int) int {
    // argument validation omitted
    circle := make([]int, n)
    for i := range circle {
        circle[i] = i
    }
    k--
    exPos := 0
    for len(circle) > 1 {
        exPos = (exPos + k) % len(circle)
        if pos == 0 {
            return circle[exPos]
        }
        pos--
        circle = append(circle[:exPos], circle[exPos+1:]...)
    }
    return circle[0]
}

func main() {
    // show basic task function on given test case
    fmt.Println(finalSurvivor(41, 3))
    // show extra function on all positions of given test case
    fmt.Println("Position  Prisoner")
    for i := 0; i < 41; i++ {
        fmt.Printf("%5d%10d\n", i, position(41, 3, i))
    }
}


#import std
#import nat
#import flo
#import lin

#import nat

items = # name: (weight,value)

<
   'map': (9,150),
   'compass': (13,35),
   'water': (153,200),
   'sandwich': (50,160),
   'glucose': (15,60),
   'tin': (68,45),
   'banana': (27,60),
   'apple': (39,40),
   'cheese': (23,30),
   'beer': (52,10),
   'suntan cream': (11,70),
   'camera': (32,30),
   't-shirt': (24,15),
   'trousers': (48,10),
   'umbrella': (73,40),
   'waterproof trousers': (42,70),
   'waterproof overclothes': (43,75),
   'note-case': (22,80),
   'sunglasses': (7,20),
   'towel': (18,12),
   'socks': (4,50),
   'book': (30,10)>

system =

linear_system$[
   binaries: ~&nS,
   lower_bounds: {'(slack)': 0.}!,
   costs: * ^|/~& negative+ [email protected],
   equations: ~&iNC\400.+ :/(1.,'(slack)')+ * ^|rlX/~& [email protected]]

#show+

main = ~&tnS solution system items


'Knapsack problem/0-1 - 12/02/2017
Option Explicit
Const maxWeight = 400
Dim DataList As Variant
Dim xList(64, 3) As Variant
Dim nItems As Integer
Dim s As String, xss As String
Dim xwei As Integer, xval As Integer, nn As Integer

Sub Main()
    Dim i As Integer, j As Integer
    DataList = Array("map", 9, 150, "compass", 13, 35, "water", 153, 200, "sandwich", 50, 160, _
           "glucose", 15, 60, "tin", 68, 45, "banana", 27, 60, "apple", 39, 40, _
           "cheese", 23, 30, "beer", 52, 10, "suntan cream", 11, 70, "camera", 32, 30, _
           "T-shirt", 24, 15, "trousers", 48, 10, "umbrella", 73, 40, "book", 30, 10, _
           "waterproof trousers", 42, 70, "waterproof overclothes", 43, 75, _
           "note-case", 22, 80, "sunglasses", 7, 20, "towel", 18, 12, "socks", 4, 50)
    nItems = (UBound(DataList) + 1) / 3
    j = 0
    For i = 1 To nItems
        xList(i, 1) = DataList(j)
        xList(i, 2) = DataList(j + 1)
        xList(i, 3) = DataList(j + 2)
        j = j + 3
    Next i
    s = ""
    For i = 1 To nItems
        s = s & Chr(i)
    Next
    nn = 0
    Call ChoiceBin(1, "")
    For i = 1 To Len(xss)
        j = Asc(Mid(xss, i, 1))
        Debug.Print xList(j, 1)
    Next i
    Debug.Print "count=" & Len(xss), "weight=" & xwei, "value=" & xval
End Sub 'Main

Private Sub ChoiceBin(n As String, ss As String)
    Dim r As String
    Dim i As Integer, j As Integer, iwei As Integer, ival As Integer
    Dim ipct As Integer
    If n = Len(s) + 1 Then
        iwei = 0: ival = 0
        For i = 1 To Len(ss)
            j = Asc(Mid(ss, i, 1))
            iwei = iwei + xList(j, 2)
            ival = ival + xList(j, 3)
        Next
        If iwei <= maxWeight And ival > xval Then
            xss = ss: xwei = iwei: xval = ival
        End If
    Else
        r = Mid(s, n, 1)
        Call ChoiceBin(n + 1, ss & r)
        Call ChoiceBin(n + 1, ss)
    End If
End Sub 'ChoiceBin


' Knapsack problem/0-1 - 13/02/2017
dim w(22),v(22),m(22)
data=array( "map", 9, 150, "compass", 13, 35, "water", 153, 200, _
 "sandwich", 50, 160 , "glucose", 15, 60, "tin", 68, 45, _
 "banana", 27, 60, "apple", 39, 40 , "cheese", 23, 30, "beer", 52, 10, _
 "suntan cream", 11, 70, "camera", 32, 30 , "T-shirt", 24, 15, _
 "trousers", 48, 10, "umbrella", 73, 40, "book", 30, 10 , _
 "waterproof trousers", 42, 70, "waterproof overclothes", 43, 75 , _
 "note-case", 22, 80, "sunglasses", 7, 20, "towel", 18, 12, "socks", 4, 50)
ww=400
xw=0:iw=0:iv=0
w(1)=iw:v(1)=iv
for i1=0 to 1:m(1)=i1:j=0
 if i1=1 then
  iw=w(1)+data(j*3+1):iv=v(1)+data(j*3+2)
  if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
 end if 'i1
 if iw<=ww then
  w(2)=iw: v(2)=iv
  for i2=0 to 1:m(2)=i2:j=1
   if i2=1 then
    iw=w(2)+data(j*3+1):iv=v(2)+data(j*3+2)
    if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
   end if 'i2
   if iw<=ww then
    w(3)=iw: v(3)=iv
    for i3=0 to 1:m(3)=i3:j=2
     if i3=1 then
      iw=w(3)+data(j*3+1):iv=v(3)+data(j*3+2)
      if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
     end if 'i3
     if iw<=ww then
      w(4)=iw: v(4)=iv
      for i4=0 to 1:m(4)=i4:j=3
       if i4=1 then
        iw=w(4)+data(j*3+1):iv=v(4)+data(j*3+2)
        if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
       end if 'i4
       if iw<=ww then
        w(5)=iw: v(5)=iv
        for i5=0 to 1:m(5)=i5:j=4
         if i5=1 then
          iw=w(5)+data(j*3+1):iv=v(5)+data(j*3+2)
          if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
         end if 'i5
         if iw<=ww then
          w(6)=iw: v(6)=iv
          for i6=0 to 1:m(6)=i6:j=5
           if i6=1 then
            iw=w(6)+data(j*3+1):iv=v(6)+data(j*3+2)
            if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
           end if 'i6
           if iw<=ww then
            w(7)=iw: v(7)=iv
            for i7=0 to 1:m(7)=i7:j=6
             if i7=1 then
              iw=w(7)+data(j*3+1):iv=v(7)+data(j*3+2)
              if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
             end if 'i7
             if iw<=ww then
              w(8)=iw: v(8)=iv
              for i8=0 to 1:m(8)=i8:j=7
               if i8=1 then
                iw=w(8)+data(j*3+1):iv=v(8)+data(j*3+2)
                if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
               end if 'i8
               if iw<=ww then
                w(9)=iw: v(9)=iv
                for i9=0 to 1:m(9)=i9:j=8
                 if i9=1 then
                  iw=w(9)+data(j*3+1):iv=v(9)+data(j*3+2)
                  if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                 end if 'i9
                 if iw<=ww then
                  w(10)=iw: v(10)=iv
                  for i10=0 to 1:m(10)=i10:j=9
                   if i10=1 then
                    iw=w(10)+data(j*3+1):iv=v(10)+data(j*3+2)
                    if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                   end if 'i10
                   if iw<=ww then
                    w(11)=iw: v(11)=iv
                    for i11=0 to 1:m(11)=i11:j=10
                     if i11=1 then
                      iw=w(11)+data(j*3+1):iv=v(11)+data(j*3+2)
                      if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                     end if 'i11
                     if iw<=ww then
                      w(12)=iw: v(12)=iv
                      for i12=0 to 1:m(12)=i12:j=11
                       if i12=1 then
                        iw=w(12)+data(j*3+1):iv=v(12)+data(j*3+2)
                        if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                       end if 'i12
                       if iw<=ww then
                        w(13)=iw: v(13)=iv
                        for i13=0 to 1:m(13)=i13:j=12
                         if i13=1 then
                          iw=w(13)+data(j*3+1):iv=v(13)+data(j*3+2)
                          if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                         end if 'i13
                         if iw<=ww then
                          w(14)=iw: v(14)=iv
                          for i14=0 to 1:m(14)=i14:j=13
                           if i14=1 then
                            iw=w(14)+data(j*3+1):iv=v(14)+data(j*3+2)
                            if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                           end if 'i14
                           if iw<=ww then
                            w(15)=iw: v(15)=iv
                            for i15=0 to 1:m(15)=i15:j=14
                             if i15=1 then
                              iw=w(15)+data(j*3+1):iv=v(15)+data(j*3+2)
                              if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                             end if 'i15
                             if iw<=ww then
                              w(16)=iw: v(16)=iv
                              for i16=0 to 1:m(16)=i16:j=15
                               if i16=1 then
                                iw=w(16)+data(j*3+1):iv=v(16)+data(j*3+2)
                                if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                               end if 'i16
                               if iw<=ww then
                                w(17)=iw: v(17)=iv
                                for i17=0 to 1:m(17)=i17:j=16
                                 if i17=1 then
                                  iw=w(17)+data(j*3+1):iv=v(17)+data(j*3+2)
                                  if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                                 end if 'i17
                                 if iw<=ww then
                                  w(18)=iw: v(18)=iv
                                  for i18=0 to 1:m(18)=i18:j=17
                                   if i18=1 then
                                    iw=w(18)+data(j*3+1):iv=v(18)+data(j*3+2)
                                    if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                                   end if 'i18
                                   if iw<=ww then
                                    w(19)=iw: v(19)=iv
                                    for i19=0 to 1:m(19)=i19:j=18
                                     if i19=1 then
                                      iw=w(19)+data(j*3+1):iv=v(19)+data(j*3+2)
                                      if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                                     end if 'i19
                                     if iw<=ww then
                                      w(20)=iw: v(20)=iv
                                      for i20=0 to 1:m(20)=i20:j=19
                                       if i20=1 then
                                        iw=w(20)+data(j*3+1):iv=v(20)+data(j*3+2)
                                        if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                                       end if 'i20
                                       if iw<=ww then
                                        w(21)=iw: v(21)=iv
                                        for i21=0 to 1:m(21)=i21:j=20
                                         if i21=1 then
                                          iw=w(21)+data(j*3+1):iv=v(21)+data(j*3+2)
                                          if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                                         end if 'i21
                                         if iw<=ww then
                                          w(22)=iw: v(22)=iv
                                          for i22=0 to 1:m(22)=i22:j=21
                                           nn=nn+1
                                           if i22=1 then
                                            iw=w(22)+data(j*3+1):iv=v(22)+data(j*3+2)
                                            if iv>xv and iw<=ww then xw=iw:xv=iv:l=m
                                           end if 'i22
                                           if iw<=ww then
                                           end if 'i22
                                          next:m(22)=0
                                         end if 'i21
                                        next:m(21)=0
                                       end if 'i20
                                      next:m(20)=0
                                     end if 'i19
                                    next:m(19)=0
                                   end if 'i18
                                  next:m(18)=0
                                 end if 'i17
                                next:m(17)=0
                               end if 'i16
                              next:m(16)=0
                             end if 'i15
                            next:m(15)=0
                           end if 'i14
                          next:m(14)=0
                         end if 'i13
                        next:m(13)=0
                       end if 'i12
                      next:m(12)=0
                     end if 'i11
                    next:m(11)=0
                   end if 'i10
                  next:m(10)=0
                 end if 'i9
                next:m(9)=0
               end if 'i8
              next:m(8)=0
             end if 'i7
            next:m(7)=0
           end if 'i6
          next:m(6)=0
         end if 'i5
        next:m(5)=0
       end if 'i4
      next:m(4)=0
     end if 'i3
    next:m(3)=0
   end if 'i2
  next:m(2)=0
 end if 'i1
next:m(1)=0
for i=1 to 22
 if l(i)=1 then wlist=wlist&vbCrlf&data((i-1)*3)
next
Msgbox mid(wlist,3)&vbCrlf&vbCrlf&"weight="&xw&vbCrlf&"value="&xv,,"Knapsack - nn="&nn