/*REXX program can re-define most keys (including  F  keys)  on a PC keyboard.*/
trace off
parse arg !
if !all(arg())  then exit
if !cms  then address ''

signal on halt
signal on noValue
signal on syntax

                                                   /*if not DOS, issue error. */
if \!dos     then call er 23,', DOS[environment]'

                                                   /*if not PC/REXX, issue err*/
if \!pcrexx  then call er 23,', PC/REXX[interpreter]'

                                                   /*if Windows/NT, issue err.*/
if !nt       then call er 23,!fn 'Windows/95/98/2000 REXX-program'

      /* This program requires  ANSI.SYS  if any keys are set or (re─)defined.*/
      /* ANSI.SYS won't function correctly under Windows/NT (XP, Vista, 7, 8).*/

call homeDrive                                     /*get the homeDrive envVar.*/

$home=p(!var('$HOME') homeDrive)                   /*get homeDrive of \$\ dir.*/
$home=appenda($home,':')                           /*make the drive ──► drive:*/
$path=p(!var('$PATH') '\$')                        /*get path name of \$  dir.*/
$path=prefixa($PATH,'\')                           /*make the path  ──► \dir  */
$path=appenda($path,'\')                           /*make the path  ──► dir\  */

if \hasCol($path)  then $path=$home || $path       /*prefix with  $HOME  ?    */

@DOSKEY    = 'DOSKEY'                              /*point to the DOSKEY   cmd*/
@ECHO      = 'ECHO'                                /*point to the ECHO     cmd*/
@TYPE      = 'TYPE'                                /*point to the TYPE     cmd*/
defFid     = #path'LOGS\'!fn".LOG"
oldFid     = #path'LOGS\'!fn".OLD"
tops       = '.BOX= .C=blue .H=darkcyan .E=1'
fops       = '.EF='defFid
functionKey= 0
autoEnter  =
useAuto    = 0
@offon     = 'OFF ON ,'
@warns     = 'WARNIFOFF WARNIFON ,'
sepLine    = copies('═',5)  copies('═',73)
y          = space(!!)

  do  forever                                      /*process any & all options*/
  parse var y k1 2 1 k y
  uk=k; upper uk

  if uk=='[ENTER]'    then do
                           useAuto=1
                           autoEnter=13
                           iterate
                           end

  if uk=='[NOENTER]'  then do
                           useAuto=1
                           autoEnter=
                           iterate
                           end

  if k1\=='.'         then leave
  tops=tops k
  fops=fops k
  end   /*forever*/

tops=space(tops)
fops=space(fops)
origk=space(k)
upper k

if k=='??'  |,
   k=="???" |,
   k=="????"  then do
                   !cls
                   if y==''      then y=defFid
                   @type y
                   say sepLine
                   if k=="???"   then call $defkey "ALLLOCKS , WARNIFON"

                   if k=="????"  then do
                                      call $t ".P=1 .C=blue" centre('DOSKEY macros',79,"─")
                                      @doskey '/macro'
                                      call $t ".C=blue" copies('─',79)
                                      end
                   exit rc
                   end

if k=='CLEARLOG' then do
                      lFID=defFid

                      if lFID==defFid  then do
                                            call dosdel oldFid
                                            call dosrename defFid,oldFid
                                            end
                                       else call dosdel lFID

                      call whenstamp lFID,'log file was cleared by' !fn"."
                      _='ECHO' sepLine">>"lFID
                      _
                      'ECHO  key         new value>>'lFID
                      _
                      exit
                      end

shiftkeys='NUMLOCK CAPSLOCK SCROLLLOCK ALLLOCKS'

if abbrev('BLINKLOCKKEYS',k,5)  then
     do
     parse var o . k times secs _
     if _\==''                            then call er 59
     if k=='' | k==","                    then k="ALLLOCKS"
     if wordpos(k,shiftkeys)==0           then call er 50,'shiftlock-key' origk
     if times=='' | times==','            then times="ANYKEY"
     if times\=='ANYKEY' & \isint(times)  then call er 53,times 'times'
     if secs=='' | secs==','              then secs=.1
     if \isNum(secs)                      then call er 53,times "seconds-delay-time"
     secs=secs/1
     if secs<.1 | secs>99                 then call er 81,.1 99 secs 'seconds-delay-time'
     dids=0

       do forever

         do j=1  for 3

           do jo=2  to 1  by -1
           dakey=word(shiftkeys,j)
           if k=='ALLLOCKS' | k==dakey then call "$DEFKEY" dakey word(@offon,jo)
           if secs\==0                 then call delay secs
           end   /*jo*/

         end     /*j*/

       dids=dids+1
       if times\=='ANYKEY' & dids>=times  then exit
                                          else if inkey("NOWAIT")\=='' then exit
       end   /*forever*/
     end

if wordpos(k,shiftkeys)\==0  then
     do
     _=words(y)
     if _>2  then call er 59
     onoff=
     warnif=0
     iswas='is'
     if y==','  then y=

     if y\==''  then do

                     if _==2 then do
                                  _=word(y,2)
                                  warnif=wordpos(translate(_),@warns)
                                  if warnif==0 then call er 55,_ k 'WARN'
                                  if warnif==3 then warnif=0
                                  y=subword(y,1,1)
                                  end

                     onoff=wordpos(translate(y),@offon)
                     if onoff==0 then call er 50,'ON-or-OFF' y
                     if onoff\==3 then iswas='was'
                     end

     if y==','  then y=

       do j=1  for 3
       dakey=word(shiftkeys,j)
       if warnif\==0  then if shiftstate(dakey)+1==warnif then call $t ".J=r" tops dakey iswas'('word(@offon,warnif)")"

       if k=="ALLLOCKS" | k==dakey  then
          do
          if y\=='' &,
             onoff\==3  then call shiftstate dakey,onoff-1
                        else if warnif==0 then call $t ".I=25" tops dakey 'is ('word(@offon,shiftstate(dakey)+1)")"
          end

       end   /*j*/

     exit
     end

if y==''  then call er 54
cod=
codz='Z'

if pos('-',k)\==0  then do
                        parse var k cod '-' k
                        _='S SHIFT C CTRL CONTROL A ALT ALTERNATE'
                        if cod=='' | wordpos(cod,_)==0  then call er 50,"key" origk
                        cod=left(cod,1)
                        codl=lower(cod)
                        codz=cod
                        if k==''  then call er 50,"key" origk
                        end

if abbrev('APOSTROPHE',k,5)               then k = "'"
if k=='ASTERISKKEYPAD' | k=='STARKEYPAD'  then k = "*KEYPAD"
if k=='BACKSLASH'                         then k = "\"
if k=='COMMA'                             then k = ","
if k=='DEL'                               then k = "DELETE"
if k=='DELKEYPAD'                         then k = "DELETEKEYPAD"
if k=='ENT'                               then k = "ENTER"
if k=='ENTKEYPAD'                         then k = "ENTERKEYPAD"
if k=='EQUAL'                             then k = "="
if k=='FIVEKEYPAD'                        then k = "5KEYPAD"
if k=="GRAVEACCENT" | k=='GRAVE'          then k = "`"
if k=='INSKEYPAD'                         then k = "INSKEYPAD"
if k=='LEFTBRACKET'                       then k = "["
if k=='MINUS'                             then k = "-"
if k=='MINUSKEYPAD'                       then k = "-KEYPAD"
if k=="PAUSE" | k=='BREAK'                then k = "PAUSEBREAK"
if k=='PGDN'                              then k = "PAGEDOWN"
if k=='PGDNKEYPAD'                        then k = "PAGEDOWNKEYPAD"
if k=='PGUP'                              then k = "PAGEUP"
if k=='PGUPKEYPAD'                        then k = "PAGEUPKEYPAD"
if k=='PLUSKEYPAD'                        then k = "+KEYPAD"
if k=='PRINTSCRN'                         then k = "PRINTSCREEN"
if k=='RIGHTBRACKET'                      then k = "]"
if k=='SEMICOLON'                         then k = ";"
if k=='SPACE' | k=="SPACEBAR"             then k = 'BLANK'

if wordpos(k,'PERIOD DOT DECIMAL DECIMALPOINT')\==0                       then k="."
if wordpos(k,'SLASH SOLIDUS VIRGULE OBELUS')\==0                          then k="/"
if wordpos(k,'SLASHKEYPAD SOLIDUSKEYPAD VIRGULEKEYPAD OBELUSKEYPAD')\==0  then k="/KEYPAD"
base=

  do 1                     /*the "1" enables the use of the LEAVE instruction.*/
  len1=(length(k)==1)
  uppc=isUpp(k)
  numb=isint(k)

  if len1 then do
               dkey=c2d(k)
               if uppc then do
                            if cod=='A' then do
                                             _='30 48 46 32 18 33 34 35 23 36 37 38 50 49 24 25 16 19 31 20 22 47 17 45 21 44'
                                             base='0;'word(_,dkey-96)
                                             end
                            d.z=21
                            d.s=0
                            d.c=-64
                            base=d.codz+dkey
                            end

               if numb then do
                            dakey=dkey-47
                            if cod=''   then base=dkey
                            if cod=='S' then base=word("41 33 64 35 36 37 94 38 42 49",dakey)

                            if cod=='A' then if k<3 then base="0;"word(129 120,dakey)
                                                    else base="0;"119+dakey

                            if cod=='C' then do
                                             if k==2 then base=0
                                             if k==6 then base=30
                                             end
                            end

               if base\==''  then leave
               call er 50,'key' origk
               end

  ik=wordpos(k,'DELETE DOWNARROW END HOME INSERT LEFTARROW PAGEDOWN PAGEUP RIGHTARROW UPARROW')

    select
    when left(k,1)=='F' then do
                        functionKey=1
                        fn=substr(k,2)
                        if \isint(fn) | fn<1 | fn>12  then call er 81,1 12 k "FunctionKey"
                        d.z=58
                        d.s=83
                        d.c=93
                        d.a=103
                        if fn<11  then base='0;' || (d.codz+fn)
                                  else do
                                       d.z=133-11
                                       d.s=135-11
                                       d.c=137-11
                                       d.a=139-11
                                       base='0;' || (d.codz+fn)
                                       end
                        end

    when ik\==0  then do
                      d.z='83 80 79 71 82 75 81 73 77 72'
                      d.s=d.z
                      d.c='147 145 117 119 146 115 118 132 116 141'
                      d.a='163 154 159 151 162 155 161 153 157 152'
                      base='224;'word(d.codz,ik)
                      end

    when k=='PRINTSCREEN' & cod="C"  then base='0;114'
    when k=='PAUSEBREAK'  & cod="C"  then base='0;0'
    when k=='NULL'        & cod==''  then base="0;3"

    when k=='BACKSPACE'  then do
                              d.z=8
                              d.s=8
                              d.c=127
                              d.a=0
                              base=d.codz
                              end

    when k=='TAB'   then do
                         d.z=9
                         d.s='0;15'
                         d.c='0;148'
                         d.z='0;165'
                         base=d.codz
                         end

    when k=='BLANK' then do
                         d.z=92
                         d.s=124
                         d.c=28
                         d.a='0;43'
                         base=d.codz
                         end

    when k=='ENTER' then do
                         d.z=13
                         d.s=
                         d.c=10
                         d.a='0;28'
                         base=d.codz
                         end

    when k=='-'  then do
                      d.z=45
                      d.s=95
                      d.c=31
                      d.a='0;130'
                      base=d.codz
                      end

    when k=='='  then do
                      d.z=61
                      d.s=43
                      d.c=
                      d.a='0;131'
                      base=d.codz
                      end

    when k=='['  then do
                      d.z=91
                      d.s=123
                      d.c=27
                      d.a='0;26'
                      base=d.codz
                      end

    when k==']'  then do
                      d.z=93
                      d.s=125
                      d.c=29
                      d.a='0;27'
                      base=d.codz
                      end

    when k=='\'  then do
                      d.z=92
                      d.s=124
                      d.c=28
                      d.a='0;43'
                      base=d.codz
                      end

    when k==';'  then do
                      d.z=59
                      d.s=58
                      d.c=
                      d.a='0;39'
                      base=d.codz
                      end

    when k=="'"  then do
                      d.z=39
                      d.s=34
                      d.c=
                      d.a='0;40'
                      base=d.codz
                      end

    when k==','  then do
                      d.z=44
                      d.s=60
                      d.c=
                      d.a='0;51'
                      base=d.codz
                      end

    when k=='.'  then do
                      d.z=46
                      d.s=62
                      d.c=
                      d.a='0;52'
                      base=d.codz
                      end

    when k=='/'  then do
                      d.z=47
                      d.s=63
                      d.c=
                      d.a='0;53'
                      base=d.codz
                      end

    when k=='`'  then do
                      d.z=96
                      d.s=126
                      d.c=
                      d.a='0;41'
                      base=d.codz
                      end

    when k=='HOMEKEYPAD'  then do
                               d.z='0;71'
                               d.s=55
                               d.c='0;119'
                               base=d.codz
                               end

    when k=='UPARROWKEYPAD'  then do
                                  d.z='0;72'
                                  d.s=55
                                  d.c='0;141'
                                  base=d.codz
                                  end

    when k=='PAGEUPKEYPAD'  then do
                                 d.z='0;73'
                                 d.s=57
                                 d.c='0;132'
                                 base=d.codz
                                 end

    when k=='LEFTARROWKEYPAD'  then do
                                    d.z='0;75'
                                    d.s=52
                                    d.c='0;115'
                                    base=d.codz
                                    end

    when k=='5KEYPAD'  then do
                            d.z='0;76'
                            d.s=53
                            d.c='0;143'
                            base=d.codz
                            end

    when k=='RIGHTARROWKEYPAD'  then do
                                     d.z='0;77'
                                     d.s=54
                                     d.c='0;116'
                                     base=d.codz
                                     end

    when k=='ENDKEYPAD'  then do
                              d.z='0;79'
                              d.s=49
                              d.c='0;117'
                              base=d.codz
                              end

    when k=='DOWNARROWKEYPAD'  then do
                                    d.z='0;80'
                                    d.s=50
                                    d.c='0;145'
                                    base=d.codz
                                    end

    when k=='PAGEDOWNKEYPAD'  then do
                                   d.z='0;81'
                                   d.s=51
                                   d.c='0;118'
                                   base=d.codz
                                   end

    when k=='INSERTKEYPAD'  then do
                                 d.z='0;82'
                                 d.s=48
                                 d.c='0;146'
                                 base=d.codz
                                 end

    when k=='DELETEKEYPAD'  then do
                                 d.z='0;83'
                                 d.s=46
                                 d.c='0;147'
                                 base=d.codz
                                 end

    when k=='ENTERKEYPAD'  then do
                                d.z=13
                                d.c=10
                                d.a='0;166'
                                base=d.codz
                                end

    when k=='/KEYPAD'  then do
                            d.z=47
                            d.s=d.z
                            d.c='0;142'
                            d.a='0;74'
                            base=d.codz
                            end

    when k=='*KEYPAD'  then do
                            d.z=42
                            d.s='o;144'
                            d.c='0;78'
                            base=d.codz
                            end

    when k=='-KEYPAD'  then do
                            d.z=45
                            d.s=d.z
                            d.c='0;149'
                            d.a='0;164'
                            base=d.codz
                            end

    when k=='+KEYPAD'  then do
                            d.z=43
                            d.s=d.z
                            d.c='0;150'
                            d.a='0;55'
                            base=d.codz
                            end
    otherwise  nop
    end   /*select*/

  if base\==''  then leave
  call er 50,'key' origk
  end    /*do 1*/

jy=words(y)
yy=

  do j=1  for jy
  w=word(y,j)
  lw=length(w)
  lc=left(w,1)
  rc2=right(w,2);  upper rc2

  if ((lc=='"' & rc2=='"X') | (lc=="'" & rc2=="'X")) & lw>3  then
     do
     if (lw-3)//2\==0  then call er 56,w 'hexdigits for the hexstring' w
     wm=substr(w,2,lw-3)
     if \isHex(wm)     then call er 40,w
     w=x2c(wm)
     end

  yy=yy w
  end   /*j*/
                                     /*if useAuto=1, then use AUTOENTER as is.*/
                                     /*if useAuto=0 & funcKey, then use ENTER.*/
if \useAuto & functionKey  then autoEnter=13
yy=substr(yy,2)
!!='1b'x"["                          /* ESC[s  ───►  save    cursor position. */
                                     /* ESC[u  ───►  restore cursor position. */
                                     /* ESC[1A ───►  move    cursor up 1 line.*/

@echo !!"s"!! || base';"'yy'";'autoEnter'p'!!"u"!!'1A'     /*issue the define.*/
nk=k
if cod\==''  then nk=codl"-"k

call $t '.Q=1' fops right(nk,max(length(nk),5)) "──►" yy
exit                                   /*stick a fork in it,  we're all done. */

/*═════════════════════════════one─liner subroutines══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════*/
!all:  !!=!;!=space(!);upper !;call !FID;!nt=right(!var('OS'),2)=="NT";!cls=word('CLS VMFCLEAR CLRSCREEN',1+!cms+!tso*2);if arg(1)\==1 then return 0;if wordpos(!,"? ?SAMPLES ?AUTHOR ?FLOW")==0 then return 0;!call=']$H';call '$H' !fn !;!call=;return 1
!cal:  if symbol('!CALL')\=="VAR"  then !call=; return !call
!env:  !env='ENVIRONMENT';  if !sys=='MSDOS' | !brexx | !r4 | !roo  then !env='SYSTEM';  if !os2  then !env='OS2'!env;  !ebcdic=1=='f0'x;   return
!FID:  parse upper source !sys !fun !FID . 1 . . !fn !ft !fm .; call !sys; if !dos  then do; _=lastpos('\',!fn); !fm=left(!fn,_); !fn=substr(!fn,_+1); parse var !fn !fn '.' !ft; end; return word(0 !fn !ft !fm,1+("0"arg(1)))
!rex:  parse upper version !ver !vernum !verdate .;  !brexx='BY'==!vernum;  !kexx='KEXX'==!ver;  !pcrexx='REXX/PERSONAL'==!ver | 'REXX/PC'==!ver;  !r4='REXX-R4'==!ver;  !regina='REXX-REGINA'==left(!ver,11);  !roo='REXX-ROO'==!ver;  call !env;  return
!sys:  !cms=!sys=='CMS';  !os2=!sys=="OS2";  !tso=!sys=='TSO' | !sys=="MVS";  !vse=!sys=='VSE';  !dos=pos("DOS",!sys)\==0 | pos('WIN',!sys)\==0 | !sys=="CMD";  call !rex;    return
!var:  call !FID;  if !kexx  then return space(dosenv(arg(1)));   return space(value(arg(1),,!env))

$defkey:   !call=']$DEFKEY';  call "$DEFKEY" arg(1);  !call=;     return result
$t:        !call=']$T';       call "$T" arg(1);       !call=;     return result
appenda:   procedure;  parse arg x,_;  if right(x,length(_))\==_  then x=x || _;            return x
er:        parse arg _1,_2;  call '$ERR' "14"p(_1) p(word(_1,2) !FID(1)) _2;  if _1<0  then return _1;    exit result
halt:      call er .1
hasCol:    return pos(':',arg(1))\==0
homeDrive: if symbol('HOMEDRIVE')\=="VAR"  then homeDrive=p(!var('HOMEDRIVE') 'C:');   return homeDrive
isHex:     return datatype(arg(1),'X')
isint:     return datatype(arg(1),'W')
isNum:     return datatype(arg(1),'N')
isUpp:     return datatype(arg(1),'U')
it:        "ARG"(1);if rc==0  then return;  call er 68,rc arg(1)
noValue:   !sigl=sigl;  call er 17,!FID(2) !FID(3) !sigl condition('D') sourceline(!sigl)
p:         return word(arg(1),1)
prefixa:   procedure;  parse arg x,_;  if left(x,length(_))\==_  then x=_ || x;   return x
squish:    return space(translate(arg(1),,word(arg(2) ',',1)),0)
syntax:    !sigl=sigl;  call er 13,!FID(2) !FID(3) !sigl !cal() condition('D') sourceline(!sigl)
whenstamp: arg whenFID;  call lineout whenFID,strip(left(date('U'),6)left(date("S"),4) time() arg(2));  call lineout whenFID,' ';  call lineout whenFID;   return


const readline = require('readline');
readline.emitKeypressEvents(process.stdin);
process.stdin.setRawMode(true);

var wait_key = async function() {
  return await new Promise(function(resolve,reject) {
    var key_listen = function(str,key) {
      process.stdin.removeListener('keypress', key_listen);
      resolve(str);
    }
    process.stdin.on('keypress', key_listen);
  });
}

var done = function() {
  process.exit();
}

var go = async function() {
  do {
    console.log('Press any key...');
    var key = await wait_key();
    console.log("Key pressed is",key);
    await new Promise(function(resolve) { setTimeout(resolve,1000); });
  } while(key != 'y');
  done();
}

go();


using Gtk.ShortNames

function keypresswindow()

    # This code creates  the Gtk widgets on the screen.
    txt = "Type Y or N"
    win = Window("Keypress Test", 250, 30) |> (Frame() |> ((vbox = Box(:v)) |> (lab = Label(txt))))

    # this is the keystroke processing code, a function and a callback for the function.
    function keycall(w, event)
        ch = Char(event.keyval)
        set_gtk_property!(lab,:label, ch in('n','N','y','Y') ? "You hit the $ch key." : txt)
    end
    Gtk.signal_connect(keycall, win, "key-press-event")

    # this code sets up a proper exit when the widow is closed.
    c = Condition()
    endit(w) = notify(c)
    Gtk.signal_connect(endit, win, :destroy)
    Gtk.showall(win)
    wait(c)
end

keypresswindow()


// version 1.0.6

import java.awt.event.KeyAdapter
import java.awt.event.KeyEvent
import javax.swing.JFrame
import javax.swing.SwingUtilities

class Test: JFrame() {
    init {
        while (System.`in`.available() > 0) System.`in`.read()
        println("Do you want to quit Y/N")
        addKeyListener(object: KeyAdapter() {
            override fun keyPressed(e: KeyEvent) {
                if (e.keyCode == KeyEvent.VK_Y) {
                    println("OK, quitting")
                    quit()
                } else if (e.keyCode == KeyEvent.VK_N) {
                    println("N was pressed but the program is about to end anyway")
                    quit()
                } else {
                    println("Only Y/N are acceptable, please try again")
                }
            }
        })
    }

    private fun quit() {
        isVisible = false
        dispose()
        System.exit(0)
    }
}

fun main(args: Array<String>) {
    SwingUtilities.invokeLater {
        val f = Test()
        f.isFocusable = true
        f.isVisible = true
    }
}


; Solve Continuous Knapsack Problem
; Nicolas Modrzyk
; January 2015

(def maxW 15.0)
(def items
  {:beef    [3.8 36]
   :pork    [5.4 43]
   :ham     [3.6 90]
   :greaves [2.4 45]
   :flitch  [4.0 30]
   :brawn   [2.5 56]
   :welt    [3.7 67]
   :salami  [3.0 95]
   :sausage [5.9 98]})

(defn rob [items maxW]
  (let[
    val-item
        (fn[key]
          (- (/ (second (items key)) (first (items key )))))
    compare-items
        (fn[key1 key2]
          (compare (val-item key1) (val-item key2)))
    sorted (into (sorted-map-by compare-items) items)]

  (loop [current (first sorted)
         array (rest sorted)
         value 0
         weight 0]
    (let[new-weight (first (val current))
         new-value (second (val current))]
    (if (> (- maxW weight new-weight) 0)
      (do
        (println "Take all " (key current))
        (recur
         (first array)
         (rest array)
         (+ value new-value)
         (+ weight new-weight)))
      (let [t (- maxW weight)] ; else
      (println
       "Take " t " of "
       (key current) "\n"
       "Total Value is:"
       (+ value (* t (/ new-value new-weight))))))))))

(rob items maxW)


load "guilib.ring"

app = new qApp {
      win = new qWidget() {
                setWindowTitle("Don't accept Spaces")
                move(100,100)    resize(400,400)
                new qLineedit(win) {
                    myfilter = new qAllEvents(win) {
                    setkeypressevent("keypress()")
                }
                installeventfilter(myfilter)
                }
                show()
            }
            exec()
      }

func keypress
     nKey = myfilter.getkeycode()
     switch nKey
            on 16777264 see "You pressed F1 " + nl
            on 16777265 see "You pressed F2 " + nl
     off


Shoes.app do
  @info = para "NO KEY is PRESSED."
  keypress do |k|
    @info.replace "#{k.inspect} was PRESSED."
  end
end


import java.awt.event.{KeyAdapter, KeyEvent}

import javax.swing.{JFrame, JLabel, WindowConstants}

object KeyboardMacroDemo extends App {
  val directions = "Ctrl-S to show frame title
" + "Ctrl-H to hide it"

  new JFrame {
    add(new JLabel(directions))

    addKeyListener(new KeyAdapter() {
      override def keyReleased(e: KeyEvent): Unit = {
        if (e.isControlDown && e.getKeyCode == KeyEvent.VK_S) setTitle("Hello there")
        else if (e.isControlDown && e.getKeyCode == KeyEvent.VK_H) setTitle("")
      }
    })

    pack()
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
    setVisible(true)
  }

}


nomainwin
open "Y/N" for graphics_nsb_nf as #1
#1 "trapclose Quit"
#1 "down;setfocus;when characterInput KeyCheck"
#1 "place 10 50;\Press Y or N"
Inkey$=""
wait

sub KeyCheck hndle$,k$
    k$=upper$(k$)
    #hndle$ "cls;place 10 50"
    select case k$
        case "Y"
        #hndle$ "\ Yes"
        case "N"
        #hndle$ "\No"
        case else
        #hndle$ "\Incorrect input. Press Y or N"
        end select
    end sub

sub Quit hndle$
    close #hndle$
    end
    end sub


on KeyDown k
    if toUpper(k) is among the items of "Y,N" then
        answer "Thanks for your response"
    else
        answer "You need to enter Y or N"
    end if
    put empty into me
end KeyDown


to yorn
  type [Press Y or N to continue: ]
  local "clear
  make "clear readchars 0 ; clear input buffer
  local "yorn
  do.until [make "yorn readchar] [or equal? :yorn "Y equal? :yorn "N]
  print :yorn
  output :yorn
end


Module Simple {
            \\ a small modification from BBC BASIC entry
            REPEAT {} UNTIL INKEY$ = ""
            PRINT "Press Y or N to continue"
            REPEAT {
                    k$ =Ucase$(Key$)
            }  UNTIL K$="Y" OR k$="N"
            PRINT "The response was "; k$
}
Simple


(defstruct item
  (name nil :type string)
  (weight nil :type real)
  (price nil :type real))

(defun price-per-weight (item)
  (/ (item-price item) (item-weight item)))

(defun knapsack (items total-weight)
  (loop with sorted = (sort items #'> :key #'price-per-weight)
        while (plusp total-weight)
        for item in sorted
        for amount = (min (item-weight item) total-weight)
        collect (list (item-name item) amount)
        do (decf total-weight amount)))

(defun main ()
  (let ((items (list (make-item :name "beef"    :weight 3.8 :price 36)
                     (make-item :name "pork"    :weight 5.4 :price 43)
                     (make-item :name "ham"     :weight 3.6 :price 90)
                     (make-item :name "greaves" :weight 2.4 :price 45)
                     (make-item :name "flitch"  :weight 4.0 :price 30)
                     (make-item :name "brawn"   :weight 2.5 :price 56)
                     (make-item :name "welt"    :weight 3.7 :price 67)
                     (make-item :name "salami"  :weight 3.0 :price 95)
                     (make-item :name "sausage" :weight 5.9 :price 98))))
    (loop for (name amount) in (knapsack items 15)
          do (format t "~8A: ~,2F kg~%" name amount))))


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

struct Item {
    string name;
    real amount, value;

    @property real valuePerKG() @safe const pure nothrow @nogc {
        return value / amount;
    }

    string toString() const pure /*nothrow*/ @safe {
        return format("%10s %7.2f %7.2f %7.2f",
                      name, amount, value, valuePerKG);
    }
}

real sumBy(string field)(in Item[] items) @safe pure nothrow @nogc {
    return reduce!("a + b." ~ field)(0.0L, items);
}

void main() /*@safe*/ {
    const items = [Item("beef",    3.8, 36.0),
                   Item("pork",    5.4, 43.0),
                   Item("ham",     3.6, 90.0),
                   Item("greaves", 2.4, 45.0),
                   Item("flitch",  4.0, 30.0),
                   Item("brawn",   2.5, 56.0),
                   Item("welt",    3.7, 67.0),
                   Item("salami",  3.0, 95.0),
                   Item("sausage", 5.9, 98.0)]
                  .schwartzSort!(it => -it.valuePerKG)
                  .release;

    immutable(Item)[] chosen;
    real space = 15.0;
    foreach (const item; items)
        if (item.amount < space) {
            chosen ~= item;
            space -= item.amount;
        } else {
            chosen ~= Item(item.name, space, item.valuePerKG * space);
            break;
        }

    writefln("%10s %7s %7s %7s", "ITEM", "AMOUNT", "VALUE", "$/unit");
    writefln("%(%s\n%)", chosen);
    Item("TOTAL", chosen.sumBy!"amount", chosen.sumBy!"value").writeln;
}


package require Tk
# Show off some emacs-like bindings...
pack [label .l -text "C-x C-s to save, C-x C-c to quit"]
focus .
bind . <Control-x><Control-s> {
    tk_messageBox -message "We would save here"
}
bind . <Control-x><Control-c> {exit}


// Configure a key to access menu item.
// The menu item may then contain the commands directly, or it may call a macro from disk.
// This has the advantage that the key binding is shown in the menu.
 Key_Add("Shft-F6","[MENU]TV", OK)

// Configure a key to perform visual mode edit operations (similar to recorded key macro):
 Key_Add("Numpad.Enter", "[CURSOR LEFT][LINE END][RETURN]", OK)

// Configure a key to execute macro language commands:
 Key_Add("Numpad+", '[VISUAL EXIT] if(BB!=-1) { RCB(10,BB,BE) BB(-1) S("|@(10)",SET+CONFIRM) } else { S("",CONFIRM) }', OK)

// Configure a key to call a macro from disk. The old key assignment is not removed.
 Key_Add("Ctrl-Shft-N",'[VISUAL EXIT] Call_File(100,"aspell.vdm","NEXT_ERROR")',INSERT+OK)

// Configure a two-key sequence (C-x C-c to save file).
 Key_Add("^X C","[MENU]FS", OK)

// Remove a key assignment. If INSERT option was used when the key was assigned, the old assignment will come in effect again.
 Key_Delete("Ctrl-Shft-N")


/* keyboard_macros.wren */

var GrabModeAsync = 1
var Mod1Mask      = 1 << 3
var KeyPress      = 2

var XK_F6 = 0xffc3
var XK_F7 = 0xffc4

foreign class XEvent {
    construct new() {}

    foreign eventType
}

foreign class XDisplay {
    construct openDisplay(displayName) {}

    foreign defaultRootWindow()

    foreign grabKey(keycode, modifiers, grabWindow, ownerEvents, pointerMode, keyboardMode)

    foreign ungrabKey(keycode, modifiers, grabWindow)

    foreign keysymToKeycode(keysym)

    foreign closeDisplay()

    foreign nextEvent(eventReturn)
}

class X {
    foreign static stringToKeysym(string)

    foreign static lookupKeysym(keyEvent, index)
}

var xd = XDisplay.openDisplay("")
if (xd == 0) {
    System.print("Cannot open display.")
    return
}
var drw = xd.defaultRootWindow()
xd.grabKey(xd.keysymToKeycode(X.stringToKeysym("F7")), Mod1Mask, drw, true, GrabModeAsync, GrabModeAsync)
xd.grabKey(xd.keysymToKeycode(X.stringToKeysym("F6")), Mod1Mask, drw, true, GrabModeAsync, GrabModeAsync)
var e = XEvent.new()
while (true) {
    xd.nextEvent(e)
    if (e.eventType == KeyPress) {
        var s = X.lookupKeysym(e, 0)
        if (s == XK_F7) {
            System.print("something's happened.")
        } else if (s == XK_F6) {
            break
        }
    }
}
xd.ungrabKey(xd.keysymToKeycode(X.stringToKeysym("F7")), Mod1Mask, drw)
xd.ungrabKey(xd.keysymToKeycode(X.stringToKeysym("F6")), Mod1Mask, drw)
xd.closeDisplay()


CreateDialog[TextCell["Yes or no?[Y/N]"],
  NotebookEventActions -> {
    "KeyDown" :> Switch[[email protected]["EventKey"],
      "Y", Print["You said yes"]; DialogReturn[],
      "N", Print["You said no"]; DialogReturn[]
      ]}];


'From:
'Andy Oneill, 2-6-2015, "Small Basic: Key Input,
'" TechNet, https://social.technet.microsoft.com/wiki/contents/articles/29850.small-basic-key-input.aspx, accessed 3-19-2018

GraphicsWindow.DrawText(10, 10, "Hit any key to dump.")
GraphicsWindow.KeyDown = OnKeyDown
Sub OnKeyDown
  TextWindow.WriteLine(GraphicsWindow.LastKey)
EndSub


// flush the keyboard
while key.available
    key.get
end while

// and now prompt and wait for Y or N
print "Press Y or N:"
k = ""
while k != "Y" and k != "N"
    k = key.get.upper
end while
print "You pressed: " + k


for  read !,"Enter Y or N to continue: ",input  quit:input?1(1"Y",1"y",1"N",1"n")


/* NetRexx */

options replace format comments java crossref savelog symbols binary

Say 'Please enter Y or N'
parse ask c
Select
  when c='Y' Then Say 'YES'
  when c='N' Then Say 'NO'
  otherwise       Say 'Undecided'
  End


(lib 'struct)
(lib 'sql) ;; for table

(define T (make-table (struct meal (name poids price))))

(define meals
  '((🐂-beef 	3.8 	36)
    (🍖-pork 	5.4 	43)
    (🍗-ham 	3.6 	90)
    (🐪-greaves 	2.4 	45)
    (flitch 	4.0 	30)
    (brawn 	2.5 	56)
    (welt 	3.7 	67)
    (🐃--salami 	3.0 	95)
    (🐖-sausage 	5.9 	98)))

(list->table meals T)
;; sort table according to best price/poids ratio
(define (price/poids a b  )
	(-  (//  (* (meal-price b) (meal-poids a)) (meal-price a) (meal-poids b)) 1))
(table-sort T price/poids)

(define-syntax-rule (name i) (table-xref T i 0))
(define-syntax-rule (poids i) (table-xref T i 1))

;; shop : add items in basket, in order, until W exhausted
(define (shop W )
	(for/list ((i (table-count T)))
	#:break (<= W 0)
		(begin0
		(cons (name i) (if  (<= (poids i) W) 'all W))
		(set! W (- W (poids i))))))

;; output
(shop 15)
   → ((🐃--salami . all) (🍗-ham . all) (brawn . all) (🐪-greaves . all) (welt . 3.5))


class
	CONTINUOUS_KNAPSACK

create
	make

feature

	make
		local
			tup: TUPLE [name: STRING; weight: REAL_64; price: REAL_64]
		do
			create tup
			create items.make_filled (tup, 1, 9)
			create sorted.make
			sorted.extend (-36.0 / 3.8)
			sorted.extend (-43.0 / 5.4)
			sorted.extend (-90.0 / 3.6)
			sorted.extend (-45.0 / 2.4)
			sorted.extend (-30.0 / 4.0)
			sorted.extend (-56.0 / 2.5)
			sorted.extend (-67.0 / 3.7)
			sorted.extend (-95.0 / 3.0)
			sorted.extend (-98.0 / 5.9)
			tup := ["beef", 3.8, 36.0]
			items [sorted.index_of (- tup.price / tup.weight, 1)] := tup
			tup := ["pork", 5.4, 43.0]
			items [sorted.index_of (- tup.price / tup.weight, 1)] := tup
			tup := ["ham", 3.6, 90.0]
			items [sorted.index_of (- tup.price / tup.weight, 1)] := tup
			tup := ["greaves", 2.4, 45.0]
			items [sorted.index_of (- tup.price / tup.weight, 1)] := tup
			tup := ["flitch", 4.0, 30.0]
			items [sorted.index_of (- tup.price / tup.weight, 1)] := tup
			tup := ["brawn", 2.5, 56.0]
			items [sorted.index_of (- tup.price / tup.weight, 1)] := tup
			tup := ["welt", 3.7, 67.0]
			items [sorted.index_of (- tup.price / tup.weight, 1)] := tup
			tup := ["salami", 3.0, 95.0]
			items [sorted.index_of (- tup.price / tup.weight, 1)] := tup
			tup := ["sausage", 5.9, 98.0]
			items [sorted.index_of (- tup.price / tup.weight, 1)] := tup
			find_solution
		end

	find_solution
			-- Solution for the continuous Knapsack Problem.
		local
			maxW, value: REAL_64
		do
			maxW := 15
			across
				items as c
			loop
				if maxW - c.item.weight > 0 then
					io.put_string ("Take all: " + c.item.name + ".%N")
					value := value + c.item.price
					maxW := maxW - c.item.weight
				elseif maxW /= 0 then
					io.put_string ("Take " + maxW.truncated_to_real.out + " kg off " + c.item.name + ".%N")
					io.put_string ("The total value is " + (value + (c.item.price / c.item.weight) * maxW).truncated_to_real.out + ".")
					maxW := 0
				end
			end
		end

	items: ARRAY [TUPLE [name: STRING; weight: REAL_64; price: REAL_64]]

	sorted: SORTED_TWO_WAY_LIST [REAL_64]

end


import strformat
import gintro/[glib, gobject, gtk, gio]
import gintro/gdk except Window

#---------------------------------------------------------------------------------------------------

proc onKeyPress(window: ApplicationWindow; event: Event; label: Label): bool =
  var keyval: int
  if not event.getKeyval(keyval): return false
  if keyval in [ord('n'), ord('y')]:
    label.setText(&"You pressed key '{chr(keyval)}'")
  result = true

#---------------------------------------------------------------------------------------------------

proc activate(app: Application) =
  ## Activate the application.

  let window = app.newApplicationWindow()
  window.setTitle("Y/N response")

  let hbox = newBox(Orientation.horizontal, 0)
  window.add(hbox)
  let vbox = newBox(Orientation.vertical, 10)
  hbox.packStart(vbox, true, true, 20)

  let label1 = newLabel("   Press 'y' or 'n' key   ")
  vbox.packStart(label1, true, true, 5)

  let label2 = newLabel()
  vbox.packStart(label2, true, true, 5)

  discard window.connect("key-press-event", onKeyPress, label2)

  window.showAll()

#———————————————————————————————————————————————————————————————————————————————————————————————————

let app = newApplication(Application, "Rosetta.YNResponse")
discard app.connect("activate", activate)
discard app.run()


10 PRINT "PRESS Y OR N TO CONTINUE."
20 IF INKEY$<>"Y" AND INKEY$<>"N" THEN GOTO 20
30 PRINT "THE RESPONSE WAS ";INKEY$;"."


let attrs = Unix.(tcgetattr stdin)
let buf = Bytes.create 1

let prompt switch =
    Unix.(tcsetattr stdin TCSAFLUSH)
      @@ if switch then { attrs with c_icanon = false } else attrs

let getchar () =
    let len = Unix.(read stdin) buf 0 1 in
      if len = 0 then raise End_of_file else Bytes.get buf 0


import: console

: YorN
| c |
   System.Console flush
   doWhile: [
      System.Console receiveChar toUpper ->c
      c 'Y' <> c 'N' <> and
      ]
   c ;


DEF VAR lanswer AS LOGICAL INITIAL ?.

DO WHILE lanswer = ?:
   READKEY.
   IF CHR( LASTKEY ) = "n" OR CHR( LASTKEY ) = "y" THEN
      lanswer = CHR( LASTKEY ) = "y".
END.

MESSAGE lanswer VIEW-AS ALERT-BOX.


defmodule KnapsackProblem do
  def select( max_weight, items ) do
    Enum.sort_by( items, fn {_name, weight, price} -> - price / weight end )
    |> Enum.reduce( {max_weight, []}, &select_until/2 )
    |> elem(1)
    |> Enum.reverse
  end

  def task( items, max_weight ) do
    IO.puts "The robber takes the following to maximize the value"
    Enum.each( select( max_weight, items ), fn {name, weight} ->
      :io.fwrite("~.2f of ~s~n", [weight, name])
    end )
  end

  defp select_until( {name, weight, _price}, {remains, acc} ) when remains > 0 do
    selected_weight = select_until_weight( weight, remains )
    {remains - selected_weight, [{name, selected_weight} | acc]}
  end
  defp select_until( _item, acc ), do: acc

  defp select_until_weight( weight, remains ) when weight < remains, do: weight
  defp select_until_weight( _weight, remains ), do: remains
end

items = [ {"beef",    3.8, 36},
          {"pork",    5.4, 43},
          {"ham",     3.6, 90},
          {"greaves", 2.4, 45},
          {"flitch",  4.0, 30},
          {"brawn",   2.5, 56},
          {"welt",    3.7, 67},
          {"salami",  3.0, 95},
          {"sausage", 5.9, 98} ]

KnapsackProblem.task( items, 15 )


-module( knapsack_problem_continuous ).

-export( [price_per_weight/1, select/2, task/0] ).

price_per_weight( Items ) -> [{Name, Weight, Price / Weight} || {Name, Weight, Price} <-Items].

select( Max_weight, Items ) ->
	{_Remains, Selected_items} = lists:foldr( fun select_until/2, {Max_weight, []}, lists:keysort(3, Items) ),
	Selected_items.

task() ->
	Items = items(),
	io:fwrite( "The robber takes the following to maximize the value~n" ),
	[io:fwrite("~.2f of ~p~n", [Weight, Name]) || {Name, Weight} <- select( 15, price_per_weight(Items) )].

items() ->
	[{"beef", 3.8, 36},
	{"pork", 5.4, 43},
	{"ham", 3.6, 90},
	{"greaves", 2.4, 45},
	{"flitch", 4.0, 30},
	{"brawn", 2.5, 56},
	{"welt", 3.7 , 67},
	{"salami", 3.0, 95},
	{"sausage",  5.9 , 98}
	].

select_until( {Name, Weight, _Price}, {Remains, Acc} ) when Remains > 0 ->
	Selected_weight = select_until_weight( Weight, Remains ),
	{Remains - Selected_weight, [{Name, Selected_weight} | Acc]};
select_until( _Item, Acc ) -> Acc.

select_until_weight( Weight, Remains ) when Weight < Remains -> Weight;
select_until_weight( _Weight, Remains ) -> Remains.


Program ObtainYN;

uses
  crt;

var
  key: char;

begin
  write('Your answer? (Y/N): ');
  repeat
    key := readkey;
  until (key in ['Y', 'y', 'N', 'n']);
  writeln;
  writeln ('Your answer was: ', key);
end.


use Term::ReadKey;

ReadMode 4; # change to raw input mode

my $key = '';

while($key !~ /(Y|N)/i) {
    1 while defined ReadKey -1; # discard any previous input
    print "Type Y/N: ";
    $key = ReadKey 0; # read a single character
    print "$key\n";
}

ReadMode 0; # reset the terminal to normal mode

print "\nYou typed: $key\n";


integer key

while get_key()!=-1 do end while -- flush

puts(1,"Your answer? (Y/N)")

while 1 do
    key = upper(get_key())
    if find(key,"YN") then exit end if
end while

printf(1,"\nYour response was %s\n",key)


//Fill a knapsack optimally - Nigel Galloway: February 1st., 2015
let items = [("beef", 3.8, 36);("pork", 5.4, 43);("ham", 3.6, 90);("greaves", 2.4, 45);("flitch" , 4.0, 30);("brawn", 2.5, 56);("welt", 3.7, 67);("salami" , 3.0, 95);("sausage", 5.9, 98)]
            |> List.sortBy(fun(_,weight,value) -> float(-value)/weight)

let knap items maxW=
  let rec take(n,g,a) =
    match g with
      | i::e -> let name, weight, value = i
                let total = n + weight
                if total <= maxW then
                  printfn "Take all %s" name
                  take(total, e, a+float(value))
                else
                  printfn "Take %0.2f kg of %s\nTotal value of swag is %0.2f" (maxW - n) name (a + (float(value)/weight)*(maxW - n))
      | []   -> printfn "Everything taken! Total value of swag is £%0.2f; Total weight of bag is %0.2fkg" a n
  take(0.0, items, 0.0)


include lib/selcsort.4th               \ use a tiny sorting algorithm

150 value left                         \ capacity in 1/10th kilo

create items                           \ list of items
  ," beef"     38 , 3600 ,             \ description, weight, price (cents)
  ," pork"     54 , 4300 ,             \ weight in 1/10 kilo
  ," ham"      36 , 9000 ,
  ," greaves"  24 , 4500 ,
  ," flitch"   40 , 3000 ,
  ," brawn"    25 , 5600 ,
  ," welt"     37 , 6700 ,
  ," salami"   30 , 9500 ,
  ," sausage"  59 , 9800 ,
  here items - 3 / constant #items     \ total number of items

:redo items swap 3 cells * + ;         \ calculate address of record

#items array (items)                   \ array for sorting
                                       ( a -- n)
: price/weight dup 2 cells + @c swap cell+ @c / ;
: [email protected] @ cell+ @c ;                 ( a -- n)
: .item @ @c count type cr ;           ( a --)
                                       \ how to sort: on price/weight
:noname >r price/weight r> price/weight > ; is precedes

: knapsack                             ( --)
  (items) dup #items dup 0 ?do i items (items) i th ! loop sort
  begin                                \ use the sorted array
     dup [email protected] left <=               \ still room in the knapsack?
  while
     ." Take all of the " dup .item    \ take all of the item
     left over [email protected] - to left cell+ \ adjust knapsack, increment item
  repeat left 100 * dup                \ so how much is left?
                                       \ if room, take as much as possible
  if ." Take " . ." grams of the " .item else drop drop then
;

knapsack


 yn: Proc Options(main):
 Dcl sysin stream input;
 Dcl sysprint stream output;
 Dcl c Char(1);
 Put Skip List('Please enter Y or N');
 Get Edit(c)(a(1));
 Select(c);
   When('Y','y','J','j')
     Put Skip List('YES');
   When('N','n')
     Put Skip List('NO');
   Otherwise
     Put Skip List('Undecided?');
   End;
 End;


do
{
    $keyPress = [System.Console]::ReadKey()
}
until ($keyPress.Key -eq "Y" -or $keyPress.Key -eq "N")

$keyPress | Format-Table -AutoSize


PrintN("Press Y or N to continue")

Repeat
  ; Get the key being pressed, or a empty string.
  Key$=UCase(Inkey())
  ;
  ; To Reduce the problems with an active loop
  ; a Delay(1) will release the CPU for the rest
  ; of this quanta if no key where pressed.
  Delay(1)
Until   Key$="Y" Or Key$="N"
PrintN("The response was "+Key$)


program KNAPSACK_CONTINUOUS
  implicit none

  real, parameter :: maxweight = 15.0
  real :: total_weight = 0, total_value = 0, frac
  integer :: i, j

  type Item
    character(7) :: name
    real :: weight
    real :: value
  end type Item

  type(Item) :: items(9), temp

  items(1) = Item("beef",    3.8, 36.0)
  items(2) = Item("pork",    5.4, 43.0)
  items(3) = Item("ham",     3.6, 90.0)
  items(4) = Item("greaves", 2.4, 45.0)
  items(5) = Item("flitch",  4.0, 30.0)
  items(6) = Item("brawn",   2.5, 56.0)
  items(7) = Item("welt",    3.7, 67.0)
  items(8) = Item("salami",  3.0, 95.0)
  items(9) = Item("sausage", 5.9, 98.0)

  ! sort items in descending order of their value per unit weight
  do i = 2, size(items)
     j = i - 1
     temp = items(i)
     do while (j>=1 .and. items(j)%value / items(j)%weight < temp%value / temp%weight)
       items(j+1) = items(j)
       j = j - 1
     end do
    items(j+1) = temp
  end do

  i = 0
  write(*, "(a4, a13, a6)") "Item", "Weight", "Value"
  do while(i < size(items) .and. total_weight < maxweight)
    i = i + 1
    if(total_weight+items(i)%weight < maxweight) then
      total_weight = total_weight + items(i)%weight
      total_value = total_value + items(i)%value
      write(*, "(a7, 2f8.2)") items(i)
    else
      frac = (maxweight-total_weight) / items(i)%weight
      total_weight = total_weight + items(i)%weight * frac
      total_value = total_value + items(i)%value * frac
      write(*, "(a7, 2f8.2)") items(i)%name, items(i)%weight * frac, items(i)%value * frac
    end if
  end do

  write(*, "(f15.2, f8.2)") total_weight, total_value

end program KNAPSACK_CONTINUOUS


#!/usr/bin/env python

try:
    from msvcrt import getch
except ImportError:
    def getch():
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch

print "Press Y or N to continue"
while True:
    char = getch()
    if char.lower() in ("y", "n"):
        print char
        break


WHILE INKEY$ <> "": WEND '                                  Flushes keyboard buffer.
PRINT "Do you want to continue? (Y/N)"
DO
    k$ = UCASE$(INKEY$) '                                   Forces key response to upper case.
LOOP UNTIL k$ = "Y" OR k$ = "N"
PRINT "You pressed " + CHR$(34) + k$ + CHR$(34) + "." '     CHR$(34) prints quotation marks.


; Stores result in cell 2; 1 if yes, 0 if no.
:YORN
PRINT YORNMSG
:YORN1
INPUT >2
AND *2,$5F,'Y >2 /YORN2
AND *2,,'N \YORN1
:YORN2
PRINTC *2
PRINTC 13
AND *2,1 >2
RETURN
:YORNMSG " (Y/N)? \


#lang racket

;; GUI version
(require racket/gui)
(message-box "Yes/No example" "Yes or no?" #f '(yes-no))

;; Text version, via stty
(define stty
  (let ([exe (find-executable-path "stty")])
    (λ args (void (apply system* exe args)))))
(define tty-settings (string-trim (with-output-to-string (λ() (stty "-g")))))
(printf "Yes or no? ") (flush-output)
(stty "-icanon" "-echo" "min" "1")
(let loop () (when (char-ready?) (loop)))
(let loop ()
  (define ch (read-char))
  (case (char-downcase ch)
    [(#\y #\Y #\n #\N) (displayln ch) (if (memq ch '(#\y #\Y)) 'yes 'no)]
    [else (loop)]))
(stty tty-settings)


#define PesoMax  15.0
Type Knapsack
    articulo As String*7
    peso As Double
    precio As Double
End Type
'build item list
Dim item(1 To 9) As Knapsack => { _
("beef",    3.8, 36), ("pork",    5.4, 43), ("ham",     3.6, 90), _
("greaves", 2.4, 45), ("flitch",  4.0, 30), ("brawn",   2.5, 56), _
("welt",    3.7, 67), ("salami",  3.0, 95), ("sausage", 5.9, 98)}

Dim As Boolean Roba(Ubound(item))
Dim As Double PrecioXPeso(Ubound(item))
Dim As Integer i, MejorArticulo
Dim As Double Mejor, PesoArtic, TotalPeso = 0, TPeso = 0, TPrecio = 0, temp

For i = 1 To Ubound(item)
    PrecioXPeso(i) = item(i).precio / item(i).peso
    Roba(i) = False
Next i

Print "You can carry the following materials in the knapsack: "
Do
    Mejor = 0
    For i = 1 To Ubound(item)
        If Not Roba(i) And PrecioXPeso(i) > Mejor Then
            Mejor = PrecioXPeso(i)
            MejorArticulo = i
        End If
    Next i
    Roba(MejorArticulo) = True             'take item
    PesoArtic = item(MejorArticulo).peso   'get its weight
    TotalPeso += PesoArtic                 'add to total weight
    If TotalPeso > PesoMax Then            'if total is too much, reduce
        PesoArtic -= TotalPeso - PesoMax   'item weight by amount it's over
    End If
    Print Using "##.# kg of "; PesoArtic;  'show weight and item
    TPeso += PesoArtic
    Print item(MejorArticulo).articulo;
    temp = PesoArtic * item(MejorArticulo).precio / item(MejorArticulo).peso
    TPrecio += temp
    Print Chr(9); Using "(Value = ##.###)"; temp
Loop Until TotalPeso >= PesoMax            'all we can steal

Print !"\nMaximal weight:"; PesoMax;  " kg"
Print Using "Total weight:  ###.## kg"; TPeso
Print Using "Total value:   ###.##"; TPrecio
Sleep


⍝ Data
Items←'beef' 'pork' 'ham' 'greaves' 'flitch' 'brawn' 'welt' 'salami' 'sausage'
Weights←3.8 5.4 3.6 2.4 4 2.5 3.7 3 5.9
Prices←36 43 90 45 30 56 67 95 98

⍝ Solution
Order←⍒Worth←Prices÷Weights                    ⍝ 'Worth' is each item value for 1 kg.
diff←{¯1↓(⍵,0)-0,⍵}                             ⍝ 'diff' between each item and the prev item (the inverse of '+\').
Filter←×Selected←diff 15⌊+\Weights[Order]      ⍝ 'Selected' weights totaling 15kg, others 0.
Table←⊃{⍺,⍪⍵}/Items Weights Selected[⍋Order]
Take←Filter[⍋Order]/[1]Table
TotalCost←+/Prices×Selected[⍋Order]÷Weights

⍝ Output
⎕←'ITEM' 'WEIGHT AVAILABLE' 'WEIGHT SELECTED' ⍪ Take
⎕←''
⎕←'total cost:' TotalCost


my $TTY = open("/dev/tty");

sub prompt-char($prompt) {
    ENTER shell "stty raw -echo min 1 time 1";
    LEAVE shell "stty sane";

    print $prompt;
    $TTY.read(1).decode('latin1');
}

say so prompt-char("Y or N? ") ~~ /:i y/;


/*REXX program tests for a    Y  or  N    key when entered from keyboard after a prompt.*/

  do queued();   pull;   end                     /*flush the stack if anything is queued*/

prompt = 'Please enter   Y  or  N   for verification:'   /*this is the  PROMPT  message.*/

  do  until  pos(ans,'NY')\==0 & length(ans)==1  /*keep looking for a  Y  or  N  answer.*/
  say;       say prompt                          /*display blank line;  display prompt. */
  pull ans                                       /*get the answer(s)  and  uppercase it.*/
  ans=space(ans, 0)                              /*elide all blanks.                    */
  end   /*until*/
                                                 /*stick a fork in it,  we're all done. */


while true
      give c
      if c = "Y" see "You said yes!" + nl
      but c = "N" see "You said no!" + nl
      else see "Try again!" + nl ok
end


def yesno
  begin
    system("stty raw -echo")
    str = STDIN.getc
  ensure
    system("stty -raw echo")
  end
  if str == "Y"
    return true
  elsif str == "N"
    return false
  else
    raise "Invalid character."
  end
end


[loop] cls                ' Clear screen
html "Click Y or N"                      ' no other options
      button #y, "Y", [Y]                '   they either click [Y]
      button #n, "N", [N]                '   or they click [N]
html "<br>";msg$                         ' print message showing what they entered
wait
[Y] msg$ = "You entered [Y]es": goto [loop]
[N] msg$ = "You entered [N]o" : goto [loop]


package main

import (
    "fmt"
    "sort"
)

type item struct {
    item   string
    weight float64
    price  float64
}

type items []item

var all = items{
    {"beef", 3.8, 36},
    {"pork", 5.4, 43},
    {"ham", 3.6, 90},
    {"greaves", 2.4, 45},
    {"flitch", 4.0, 30},
    {"brawn", 2.5, 56},
    {"welt", 3.7, 67},
    {"salami", 3.0, 95},
    {"sausage", 5.9, 98},
}

// satisfy sort interface
func (z items) Len() int      { return len(z) }
func (z items) Swap(i, j int) { z[i], z[j] = z[j], z[i] }
func (z items) Less(i, j int) bool {
    return z[i].price/z[i].weight > z[j].price/z[j].weight
}

func main() {
    left := 15.
    sort.Sort(all)
    for _, i := range all {
        if i.weight <= left {
            fmt.Println("take all the", i.item)
            if i.weight == left {
                return
            }
            left -= i.weight
        } else {
            fmt.Printf("take %.1fkg %s\n", left, i.item)
            return
        }
    }
}


import static java.math.RoundingMode.*

def knapsackCont = { list, maxWeight = 15.0 ->
    list.sort{ it.weight / it.value }
    def remainder = maxWeight
    List sack = []
    for (item in list) {
        if (item.weight < remainder) {
            sack << [name: item.name, weight: item.weight,
                        value: (item.value as BigDecimal).setScale(2, HALF_UP)]
        } else {
            sack << [name: item.name, weight: remainder,
                        value: (item.value * remainder / item.weight).setScale(2, HALF_UP)]
            break
        }
        remainder -= item.weight
    }
    sack
}


//cargo-deps: ncurses

extern crate ncurses;
use ncurses::*;

fn main() {
    initscr();
    loop {
        printw("Yes or no? ");
        refresh();

        match getch() as u8 as char {
            'Y'|'y' => {printw("You said yes!");},
            'N'|'n' => {printw("You said no!");},
            _ => {printw("Try again!\n"); continue;},
        }
        break
    }
    refresh();
    endwin();
}


println(if (scala.io.StdIn.readBoolean) "Yes typed." else "Something else.")


$ include "seed7_05.s7i";
  include "keybd.s7i";

const func boolean: yesOrNo (in string: prompt) is func
  result
    var boolean: yes is FALSE;
  local
    var char: answer is ' ';
  begin
    while keypressed(KEYBOARD) do
      ignore(getc(KEYBOARD));
    end while;
    write(prompt);
    repeat
      answer := lower(getc(KEYBOARD));
    until answer in {'y', 'n'};
    yes := answer = 'y';
  end func;

const proc: main is func
  begin
    writeln(yesOrNo("Press Y or N to continue "));
  end func;


func prompt_yn {
    static rk = frequire('Term::ReadKey');
    rk.ReadMode(4);     # change to raw input mode

    var key = '';
    while (key !~ /[yn]/i) {
        while (rk.ReadKey(-1) != nil) {};   # discard any previous input
        print "Type Y/N: ";
        say (key = rk.ReadKey(0));          # read a single character
    }

    rk.ReadMode(0);     # reset the terminal to normal mode
    return key.uc;
}

var key = prompt_yn();
say "You typed: #{key}";


proc yesno {{message "Press Y or N to continue"}} {
    fconfigure stdin -blocking 0
    exec stty raw
    read stdin ; # flush
    puts -nonewline "${message}: "
    flush stdout
    while {![eof stdin]} {
        set c [string tolower [read stdin 1]]
        if {$c eq "y" || $c eq "n"} break
    }
    puts [string toupper $c]
    exec stty -raw
    fconfigure stdin -blocking 1
    return [expr {$c eq "y"}]
}

set yn [yesno "Do you like programming (Y/N)"]


import Data.List (sortBy)
import Data.Ord (comparing)
import Text.Printf (printf)
import Control.Monad (forM_)
import Data.Ratio (numerator, denominator)

maxWgt :: Rational
maxWgt = 15

data Bounty = Bounty
  { itemName :: String
  , itemVal, itemWgt :: Rational
  }

items :: [Bounty]
items =
  [ Bounty "beef" 36 3.8
  , Bounty "pork" 43 5.4
  , Bounty "ham" 90 3.6
  , Bounty "greaves" 45 2.4
  , Bounty "flitch" 30 4.0
  , Bounty "brawn" 56 2.5
  , Bounty "welt" 67 3.7
  , Bounty "salami" 95 3.0
  , Bounty "sausage" 98 5.9
  ]

solution :: [(Rational, Bounty)]
solution = g maxWgt $ sortBy (flip $ comparing f) items
  where
    g room (b@(Bounty _ _ w):bs) =
      if w < room
        then (w, b) : g (room - w) bs
        else [(room, b)]
    f (Bounty _ v w) = v / w

main :: IO ()
main = do
  forM_ solution $ \(w, b) -> printf "%s kg of %s\n" (mixedNum w) (itemName b)
  (printf "Total value: %s\n" . mixedNum . sum) $ f <$> solution
  where
    f (w, Bounty _ v wtot) = v * (w / wtot)
    mixedNum q =
      if b == 0
        then show a
        else printf "%d %d/%d" a (numerator b) (denominator b)
      where
        a = floor q
        b = q - toEnum a


link printf

procedure main()
room := 15
every (x := !(choices := get_items())).uprice := x.price / x.weight
choices := reverse(sortf(choices,4))

every (value := 0, x := !choices) do {
   if x.weight <= room then {
      printf("Take all of the %s (%r kg) worth $%r\n",x.name,x.weight,x.price)
      value +:= x.price
      room -:= x.weight
      }
   else {
      fvalue := x.uprice * room
      printf("Take (%r kg) of the %s worth $%r\n",room,x.name,fvalue)
      value +:= fvalue
      break
   }
}
printf("Total value of a full knapsack is $%r\n",value)
end

record item(name,weight,price,uprice)

procedure get_items()
   return [  item("beef", 3.8, 36),
             item("pork", 5.4, 43),
             item("ham", 3.6, 90),
             item("greaves", 2.4, 45),
             item("flitch", 4.0, 30),
             item("brawn", 2.5, 56),
             item("welt", 3.7, 67),
             item("salami", 3.0, 95),
             item("sausage", 5.9, 98) ]
end


(with-resources ((tio-orig (tcgetattr) (tcsetattr tio-orig)))
  (let ((tio (copy tio-orig)))
    tio.(go-raw)
    (tcsetattr tio tcsaflush) ;; third arg optional, defaults to tcsadrain
    (whilet ((k (get-char))
             ((not (member k '(#\y #\n #\Y #\N))))))))


getkey() {
  local stty="$(stty -g)"
  trap "stty $stty; trap SIGINT; return 128" SIGINT
  stty cbreak -echo
  local key
  while true; do
    key=$(dd count=1 2>/dev/null) || return $?
    if [ -z "$1" ] || [[ "$key" == [$1] ]]; then
      break
    fi
  done
  stty $stty
  echo "$key"
  return 0
}

yorn() {
  echo -n "${1:-Press Y or N to continue: }" >&2
  local yorn="$(getkey YyNn)" || return $?
  case "$yorn" in
    [Yy]) echo >&2 Y; return 0;;
    [Nn]) echo >&2 N; return 1;;
  esac
}


OPTION EXPLICIT
DIM T AS INTEGER
T = MSGBOX("Click on yes or no", 4, "Option")
PRINT "The response is ";
IF T = 6 THEN PRINT "yes"; ELSE PRINT "no";
PRINT "."
END


Key_Purge()                                     // flush keyboard buffer
do {
    #1 = Get_Key("Are you sure? (Y/N): ")       // prompt for a key
    #1 &= 0xdf                                  // to upper case
} while (#1 != 'Y' && #1 != 'N')


'names numbers'=:|:;:;._2]0 :0
beef      3.8  36
pork      5.4  43
ham       3.6  90
greaves   2.4  45
flitch    4.0  30
brawn     2.5  56
welt      3.7  67
salami    3.0  95
sausage   5.9  98
)
'weights prices'=:|:".numbers
order=: \:prices%weights
take=: 15&<.&.(+/\) order{weights
result=: (*take)#(order{names),.' ',.":,.take


package hu.pj.alg.test;

import hu.pj.alg.ContinuousKnapsack;
import hu.pj.obj.Item;
import java.util.*;
import java.text.*;

public class ContinousKnapsackForRobber {
    final private double tolerance = 0.0005;

    public ContinousKnapsackForRobber() {
        ContinuousKnapsack cok = new ContinuousKnapsack(15); // 15 kg

        // making the list of items that you want to bring
        cok.add("beef",     3.8, 36); // marhahús
        cok.add("pork",     5.4, 43); // disznóhús
        cok.add("ham",      3.6, 90); // sonka
        cok.add("greaves",  2.4, 45); // tepertő
        cok.add("flitch",   4.0, 30); // oldalas
        cok.add("brawn",    2.5, 56); // disznósajt
        cok.add("welt",     3.7, 67); // hurka
        cok.add("salami",   3.0, 95); // szalámi
        cok.add("sausage",  5.9, 98); // kolbász

        // calculate the solution:
        List<Item> itemList = cok.calcSolution();

        // write out the solution in the standard output
        if (cok.isCalculated()) {
            NumberFormat nf  = NumberFormat.getInstance();

            System.out.println(
                "Maximal weight           = " +
                nf.format(cok.getMaxWeight()) + " kg"
            );
            System.out.println(
                "Total weight of solution = " +
                nf.format(cok.getSolutionWeight()) + " kg"
            );
            System.out.println(
                "Total value (profit)     = " +
                nf.format(cok.getProfit())
            );
            System.out.println();
            System.out.println(
                "You can carry the following materials " +
                "in the knapsack:"
            );
            for (Item item : itemList) {
                if (item.getInKnapsack() > tolerance) {
                    System.out.format(
                        "%1$-10s %2$-15s %3$-15s \n",
                        nf.format(item.getInKnapsack()) + " kg ",
                        item.getName(),
                        "(value = " + nf.format(item.getInKnapsack() *
                                                (item.getValue() / item.getWeight())) + ")"
                    );
                }
            }
        } else {
            System.out.println(
                "The problem is not solved. " +
                "Maybe you gave wrong data."
            );
        }

    }

    public static void main(String[] args) {
        new ContinousKnapsackForRobber();
    }

} // class


import term.ui as tui

struct App {
mut:
	tui &tui.Context = 0
}

fn event(e &tui.Event, x voidptr) {
	mut app := &App(x)
	app.tui.clear()
	app.tui.set_cursor_position(0, 0)
	app.tui.write('V term.input event viewer (type `y`, `Y`, `n`, or `N` to exit)\n\n')
	if e.typ == .key_down {
        mut cap := ''
        if !e.modifiers.is_empty() && e.modifiers.has(.shift) {
            cap = 'capital'
        }
        match e.code {
            .y {
		        app.tui.write('You typed $cap y')
            }
            .n {
                app.tui.write('You typed $cap n')
            }
            else {
                app.tui.write("You didn't type n or y")
            }
        }
	}
	app.tui.flush()

    if e.typ == .key_down && (e.code == .y || e.code==.n) {
		exit(0)
	}
}

fn main() {
	mut app := &App{}
	app.tui = tui.init(
		user_data: app
		event_fn: event
		window_title: 'V term.ui event viewer'
		hide_cursor: true
		capture_events: true
		frame_rate: 60
		use_alternate_buffer: false
	)
	println('V term.input event viewer (type `y`, `Y`, `n`, or `N` to exit)\n\n')
	app.tui.run()?
}


print 1 "Enter Y for yes, or N for no. (not case sensitive)"
let loop=0
let keycode=0
while loop=0
let keycode=key()
if keycode=121
let response$="y"
let loop=1
elseif keycode=89
let response$="Y"
let loop=1
elseif keycode=110
let response$="n"
let loop=1
elseif keycode=78
let response$="N"
let loop=1
endif
wend
print 1 "You entered"+response$
end


import "io" for Stdin, Stdout

Stdin.isRaw = true // input is neither echoed nor buffered in this mode

System.print("Press Y or N")
Stdout.flush()

var byte
while ((byte = Stdin.readByte()) && !"YNyn".bytes.contains(byte)) {}
var yn = String.fromByte(byte)
System.print(yn)

Stdin.isRaw = false


include c:\cxpl\codes;          \intrinsic 'code' declarations
loop    [OpenI(1);              \flush any pending keystroke
        case ChIn(1) of         \get keystroke
         ^Y,^y: Text(0, "yes");
         ^N,^n: Text(0, "no");
         $1B:   quit            \Esc key terminates program
        other ChOut(0, 7\bel\);
        CrLf(0);
        ]


wait_for_key_input:
call &BB06 ;bios call, waits until key is pressed, returns key's ASCII code into A
and %11011111        ;converts to upper case
cp 'Y'
jp z,User_Chose_Yes
cp 'N'
jp z,User_Chose_No
jp wait_for_key_input

User_Chose_Yes:
;your code for what happens when the user types "Y" goes here
ret

User_Chose_No:
;your code for what happens when the user types "N" goes here
ret


# continuous_knapsack(W) expects the input to be
# an array of objects {"name": _, "weight": _, "value": _}
# where "value" is the value of the given weight of the object.

def continuous_knapsack(W):
  map( .price = (if .weight > 0 then (.value/.weight) else 0 end) )
  | sort_by( .price )
  | reverse
  | reduce .[] as $item
      # state: [array, capacity]
      ([[], W];
       .[1] as $c
       | if $c <= 0 then .
         else ( [$item.weight, $c] | min) as $min
              | [.[0] + [ $item | (.weight = $min) | .value = (.price * $min)],
                ($c - $min) ]
         end)
  | .[1] as $remainder
  | .[0]
  | (.[] | {name, weight}),
    "Total value: \( map(.value) | add)",
    "Total weight: \(W - $remainder)" ;


using Printf

struct KPCSupply{T<:Real}
    item::String
    weight::T
    value::T
    uvalue::T
end
function KPCSupply(item::AbstractString, weight::Real, value::Real)
    w, v = promote(weight, value)
    KPCSupply(item, w, v, v / w)
end

Base.show(io::IO, s::KPCSupply) = print(io, s.item, @sprintf " (%.2f kg, %.2f €, %.2f €/kg)" s.weight s.value s.uvalue)
Base.isless(a::KPCSupply, b::KPCSupply) = a.uvalue < b.uvalue

function solve(store::Vector{KPCSupply{T}}, capacity::Real) where T<:Real
    sack = similar(store, 0) # vector like store, but of length 0
    kweight = zero(T)
    for s in sort(store, rev = true)
        if kweight + s.weight ≤ capacity
            kweight += s.weight
            push!(sack, s)
        else
            w = capacity - kweight
            v = w * s.uvalue
            push!(sack, KPCSupply(s.item, w, v, s.value))
            break
        end
    end
    return sack
end


// version 1.1.2

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

val items = mutableListOf(
    Item("beef", 3.8, 36.0),
    Item("pork", 5.4, 43.0),
    Item("ham", 3.6, 90.0),
    Item("greaves", 2.4, 45.0),
    Item("flitch", 4.0, 30.0),
    Item("brawn", 2.5, 56.0),
    Item("welt", 3.7, 67.0),
    Item("salami", 3.0, 95.0),
    Item("sausage", 5.9, 98.0)
)

const val MAX_WEIGHT = 15.0

fun main(args: Array<String>) {
    // sort items by value per unit weight in descending order
    items.sortByDescending { it.value / it.weight }
    println("Item Chosen   Weight  Value  Percentage")
    println("-----------   ------ ------  ----------")
    var w = MAX_WEIGHT
    var itemCount = 0
    var sumValue = 0.0
    for (item in items) {
        itemCount++
        if (item.weight <= w) {
           sumValue += item.value
           print("${item.name.padEnd(11)}     ${"%3.1f".format(item.weight)}   ${"%5.2f".format(item.value)}")
           println("    100.00")
        }
        else {
           val value  = Math.round((w / item.weight * item.value * 100.0)) / 100.0
           val percentage = Math.round((w / item.weight * 10000.0)) / 100.0
           sumValue += value
           print("${item.name.padEnd(11)}     ${"%3.1f".format(w)}   ${"%5.2f".format(value)}")
           println("     $percentage")
           break
        }
        w -= item.weight
        if (w == 0.0) break
    }
    println("-----------   ------ ------")
    println("${itemCount} items        15.0  ${"%6.2f".format(sumValue)}")
}


Module Knapsack {
      Form 60, 40
      Cls 5, 0
      Pen 14
      Class Quick {
      Private:
            partition=lambda-> {
                  Read &A(), p, r : i = p-1 : x=A(r)
                  For j=p to r-1 {If .LE(A(j), x) Then i++:Swap A(i),A(j)
                  } : Swap A(i+1), A(r) :  Push  i+2, i
            }
      Public:
            LE=Lambda->Number<=Number
            \\ module for strings erased here
            Function quicksort {
                 Read ref$
                 {
                         loop : If Stackitem() >= Stackitem(2) Then Drop 2 : if  empty then {Break} else continue
                         over 2,2 : call .partition(ref$) :shift 3
                 }
            }
      }
      Class Item {
            name$, weight, aValue  ' can't use Value has other meaning
            class:
            Module Item (.name$, .weight, .aValue) {}
      }
      Def Double max_weight=15, total_weight, total_value, frac
      Def long I
      Dim Items(1 to 9)
      Flush  ' empty stack
      \\ now fill stack
      Data  "beef", 3.8, 36,"pork", 5.4, 43,"ham", 3.6, 90, "greaves", 2.4, 45, "flitch", 4, 30
      Data "brawn", 2.5, 56, "welt", 3.7, 67, "salami", 3, 95, "sausage", 5.9, 98
      For i=1 to 9 : Items(i)=Item(Letter$, Number, Number): Next i
      \\ Setup QuickSort
      Quick=Quick()
      Quick.LE=lambda (b, a)-> {
            =a.avalue/a.weight<=b.avalue/b.weight
      }
      Call Quick.QuickSort(&items(), 1, 9)
      \\ So now we have a sorted array of objects
      i=0
      \\ Setup console to print
      Dim Back(-1 to 0)
      Back(-1)=#666666, #444444
      Alter=True
      \\ $("0.00", 20) Set number rounding for print, and 14 chars column width
      \\ $(2) set center justify for non proportional print
      \\ $(0) set default - strings justify left, numbers right
      Print  $("0.00", 20),$(2),"", "Knapsack"
      Pen 0 {
            Print @(pos, row,width,row+1, 7),"Item", "Weight (Kg)", "Price (value)", $(0)
      }
      While i<Len(Items()) and total_weight<max_weight {
            i++
            if total_weight+items(i).weight<max_weight Then {
                  total_weight+=items(i).weight
                  total_value+=items(i).avalue
                  WriteItem(i, 1)
            } Else {
                  frac=(max_weight-total_weight)/items(i).weight
                  total_weight+=items(i).weight*frac
                  total_value+=items(i).avalue*frac
                  WriteItem(i, frac )
            }
      }
      Print
      Pen 0 {
            Print @(pos+1, row,width,row+1, 7, 7), "Total Weight",total_weight
            Print @(pos+1, row,width,row+1, 7, 7), "Total Value", total_value
      }
      End
      Sub WriteItem(i, frac)
            For Items(i) {
                  Print @(pos+1, row,width,row+1, back(alter), 14),  .name$, .weight*frac, .avalue*frac
                  Alter~
            }
      End Sub
}
Knapsack


Knapsack[shop_, capacity_] :=  Block[{sortedTable, overN, overW, output},
 sortedTable = SortBy[{#1, #2, #3, #3/#2} & @@@ shop, -#[[4]] &];
 overN = Position[Accumulate[sortedTable[[1 ;;, 2]]], a_ /; a > capacity, 1,1][[1, 1]];
 overW = Accumulate[sortedTable[[1 ;;, 2]]][[overN]] - capacity;

 output = [email protected][[Ordering[sortedTable[[1 ;;, 4]], -overN]]];
 output[[-1, 2]] = output[[-1, 2]] - overW;
 output[[-1, 3]] = output[[-1, 2]] output[[-1, 4]];
 Append[output[[1 ;;, 1 ;; 3]], {"Total",Sequence @@ Total[output[[1 ;;, 2 ;; 3]]]}]]


/*Knapsack

  This model finds the optimal packing of a knapsack

  Nigel_Galloway
  January 10th., 2012
*/
set Items;
param weight{t in Items};
param value{t in Items};

var take{t in Items}, >=0, <=weight[t];

knap_weight : sum{t in Items} take[t] <= 15;

maximize knap_value: sum{t in Items} take[t] * (value[t]/weight[t]);

data;

param : Items          : weight   value :=
        beef 	          3.8     36
        pork 	          5.4	  43
        ham 		  3.6	  90
        greaves           2.4     45
        flitch 	          4.0     30
        brawn 	          2.5     56
        welt 	          3.7     67
        salami 	          3.0     95
        sausage           5.9     98
        ;
end;


%Knapsack Continuous. Nigel Galloway: October 7th., 2020.
enum Items={beef,pork,ham,greaves,flitch,brawn,welt,salami,sausage};
array[Items] of float: weight=[3.8,5.4,3.6,2.4,4.0,2.5,3.7,3.0,5.9];
array[Items] of int: value =[36,43,90,45,30,56,67,95,9];
float: maxWeight=15.0;
var float: wTaken=sum(n in Items)(quantity[n]);
var float: wValue=sum(n in Items)(value[n]*quantity[n]/weight[n]);
array[Items] of var 0.0..(max(weight)): quantity; constraint forall(n in Items)(quantity[n]<=weight[n]);
constraint wTaken <= maxWeight;
solve maximize wValue;
output[concat([let {string: g=show(quantity[n])} in "Take "++(if g==show(weight[n]) then "all" else g endif)++" of \(n)\n" | n in Items where show(quantity[n])!="0.0"])++"\nTotal Weight=\(wTaken) Total Value="++show_float(4,2,wValue)]


import algorithm
import strformat

type Item = object
  name: string
  weight: float
  price: float
  unitPrice: float

var items = @[Item(name: "beef", weight: 3.8, price: 36.0),
              Item(name: "pork", weight: 5.4, price: 43.0),
              Item(name: "ham", weight: 3.6, price: 90.0),
              Item(name: "greaves", weight: 2.4, price: 45.0),
              Item(name: "flitch", weight: 4.0, price: 30.0),
              Item(name: "brawn", weight: 2.5, price: 56.0),
              Item(name: "welt", weight: 3.7, price: 67.0),
              Item(name: "salami", weight: 3.0, price: 95.0),
              Item(name: "sausage", weight: 5.9, price: 98.0)
             ]
                        ]
# Compute unit prices and sort items by decreasing unit price.
for item in items.mitems:
  item.unitPrice = item.price / item.weight
items.sort(proc (x, y: Item): int = cmp(x.unitPrice, y.unitPrice), Descending)

var remaining = 15.0
var value = 0.0
for item in items:
  if item.weight <= remaining:
    echo fmt"Take all {item.name}"
    value += item.price
    remaining -= item.weight
  else:
    echo fmt"Take {remaining} kg of {item.name}"
    value += remaining * item.unitPrice
    break

echo fmt"Total value: {value:.2f}"


let items =
  [ "beef",     3.8,  36;
    "pork",     5.4,  43;
    "ham",      3.6,  90;
    "greaves",  2.4,  45;
    "flitch",   4.0,  30;
    "brawn",    2.5,  56;
    "welt",     3.7,  67;
    "salami",   3.0,  95;
    "sausage",  5.9,  98; ]

let () =
  let items = List.map (fun (name, w, p) -> (name, w, p, float p /. w)) items in
  let items = List.sort (fun (_,_,_,v1) (_,_,_,v2) -> compare v2 v1) items in
  let rec loop acc weight = function
  | ((_,w,_,_) as item) :: tl ->
      if w +. weight > 15.0
      then (weight, acc, item)
      else loop (item::acc) (w +. weight) tl
  | [] -> assert false
  in
  let weight, res, (last,w,p,v) = loop [] 0.0 items in
  print_endline "    Items  Weight Price";
  let price =
    List.fold_left (fun price (name,w,p,_) ->
      Printf.printf " %7s: %6.2f %3d\n" name w p;
      (p + price)
    ) 0 res
  in
  let rem_weight = 15.0 -. weight in
  let last_price = v *. rem_weight in
  Printf.printf " %7s: %6.2f %6.2f\n" last rem_weight last_price;
  Printf.printf " Total Price: %.3f\n" (float price +. last_price);
;;


[
   [ "beef",    3.8, 36 ], [ "pork",    5.4, 43 ], [ "ham",     3.6, 90 ],
   [ "greaves", 2.4, 45 ], [ "flitch",  4.0, 30 ], [ "brawn",  	2.5, 56 ],
   [ "welt",  	3.7, 67 ], [ "salami",  3.0, 95 ], [ "sausage", 5.9, 98 ]
] const: Items

: rob
| item value |
  0.0 ->value
  15.0 #[ dup second swap third / ] Items sortBy forEach: item [
     dup 0.0 == ifTrue: [ return ]
     dup item second >= ifTrue: [
        "Taking" . item first . " :" . item second dup .cr -
        item third value + ->value continue
        ]
     "And part of" . item first . " :" . dup .cr
     item third * item second / value + "Total value :" . .cr break
     ] ;


/*--------------------------------------------------------------------
* 20.09.2014 Walter Pachl translated from REXX version 2
*            utilizing ooRexx features like objects, array(s) and sort
*-------------------------------------------------------------------*/
  maxweight = 15.0
  items=.array~new
  items~append(.item~new('beef',    3.8, 36.0))
  items~append(.item~new('pork',    5.4, 43.0))
  items~append(.item~new('ham',     3.6, 90.0))
  items~append(.item~new('greaves', 2.4, 45.0))
  items~append(.item~new('flitch',  4.0, 30.0))
  items~append(.item~new('brawn',   2.5, 56.0))
  items~append(.item~new('welt',    3.7, 67.0))
  items~append(.item~new('salami',  3.0, 95.0))
  items~append(.item~new('sausage', 5.9, 98.0))

  /* show the input */
  Say '#    vpu name    weight   value'
  i=0
  Do x over items
    i+=1
    Say i format(x~vpu,2,3) left(x~name,7) format(x~weight,2,3) format(x~value,3,3)
    End

  /* sort the items by descending value per unit of weight */
  items~sortWith(.DescendingComparator~new)

  total_weight=0
  total_value =0
  Say ' '
  Say 'Item     Weight   Value'
  i=0
  Do x over items
    i+=1
    Parse Var item.i name '*' weight '*' value
    if total_weight+x~weight<maxweight then Do
      total_weight = total_weight + x~weight
      total_value  = total_value + x~value
      Say left(x~name,7) format(x~weight,3,3) format(x~value,3,3)
      End
    Else Do
      weight=maxweight-total_weight
      value=weight*x~vpu
      total_value = total_value + value
      total_weight = maxweight
      Say left(x~name,7) format(weight,3,3) format(value,3,3)
      Leave
      End
    End
  Say copies('-',23)
  Say 'total ' format(total_weight,4,3) format(total_value,3,3)
  Exit

::class item
  ::attribute vpu
  ::attribute name
  ::attribute weight
  ::attribute value

::method init
  Expose vpu
  Use Arg name, weight, value
  self~name=name
  self~weight=weight
  self~value=value
  self~vpu=value/weight

::CLASS 'DescendingComparator' MIXINCLASS Comparator
::METHOD compare
use strict arg a, b
Select
  When (a~vpu)<(b~vpu) Then res='1'
  Otherwise res='-1'
  End
Return res


with javascript_semantics
constant meats = {
--Item  Weight (kg)     Price (Value)
{"beef",    3.8,    36},
{"pork",    5.4,    43},
{"ham",     3.6,    90},
{"greaves", 2.4,    45},
{"flitch",  4.0,    30},
{"brawn",   2.5,    56},
{"welt",    3.7,    67},
{"salami",  3.0,    95},
{"sausage", 5.9,    98}}

function by_weighted_value(integer i, j)
    atom {?,weighti,pricei} = meats[i],
         {?,weightj,pricej} = meats[j]
    return compare(pricej/weightj,pricei/weighti)
end function

sequence tags = custom_sort(by_weighted_value,tagset(length(meats)))

atom weight = 15, worth = 0
for i=1 to length(tags) do
    object {desc,wi,price} = meats[tags[i]]
    atom amt = min(wi,weight)
    printf(1,"%3.1fkg %s %s\n",{amt,iff(amt=wi?"(all the)":"of"),desc})
    worth += (amt/wi)*price
    weight -= amt
    if weight=0 then exit end if
end for
printf(1,"Total value: %f\n",{worth})


/* Added by @1x24. Translated from C++. Uses the PHP 7.x spaceship operator */
$data = [
			[
				'name'=>'beef',
				'weight'=>3.8,
				'cost'=>36,
			],
			[
				'name'=>'pork',
				'weight'=>5.4,
				'cost'=>43,
			],
			[
				'name'=>'ham',
				'weight'=>3.6,
				'cost'=>90,
			],
			[
				'name'=>'greaves',
				'weight'=>2.4,
				'cost'=>45,
			],
			[
				'name'=>'flitch',
				'weight'=>4.0,
				'cost'=>30,
			],
			[
				'name'=>'brawn',
				'weight'=>2.5,
				'cost'=>56,
			],
			[
				'name'=>'welt',
				'weight'=>3.7,
				'cost'=>67,
			],
			[
				'name'=>'salami',
				'weight'=>3.0,
				'cost'=>95,
			],
			[
				'name'=>'sausage',
				'weight'=>5.9,
				'cost'=>98,
			],
		];

uasort($data, function($a, $b) {
    return ($b['cost']/$b['weight']) <=> ($a['cost']/$a['weight']);
});

$limit = 15;

foreach ($data as $item):
	if ($limit >= $item['weight']):
		echo "Take all the {$item['name']}
";
	else:
		echo "Take $limit kg of {$item['name']}
";
		break;
	endif;
	$limit -= $item['weight'];
endforeach;


go =>
  items(Items),
  weights(Weights),
  values(Values),
  knapsack_max_weight(MaxWeight),

  knapsack(Weights,Values,MaxWeight, X,TotalWeight,TotalValue),
  nl,

  printf("Total weight: %0.2f Total value: %0.2f\n", TotalWeight,TotalValue),
  foreach(I in 1..Items.len)
     if X[I] > 0.0 then
       printf("%-8w: ",Items[I]),
       if X[I] == Weights[I] then
         printf("%0.2f (%w)", Weights[I], all)
       else
         printf("%-0.2f",X[I])
       end,
       nl
     end
  end,
  nl.

knapsack(Weights,Values,MaxWeight, X,TotalWeight,TotalValue) =>
  N = Weights.len,

  X = new_list(N),
  X :: 0.0..max(Weights),

  TotalWeight #= sum(X),
  TotalWeight #<= MaxWeight,
  foreach(I in 1..N)
     X[I] #<= Weights[I]
  end,

  WeightsInv = [1/Weights[I] : I in 1..N],
  TotalValue #= sum([X[I]*Values[I]*WeightsInv[I] : I in 1..N]),

  Vars = X ++ [TotalWeight],
  solve($[glpk,max(TotalValue)],Vars).

% data
knapsack_max_weight(15.0).
items([beef,pork,ham,greaves,flitch,brawn,welt,salami,sausage]).
weights([3.8,5.4,3.6,2.4,4.0,2.5,3.7,3.0,5.9]).
values([36,43,90,45,30,56,67,95,98]).


(scl 2)

(de *Items
   ("beef" 3.8 36.0)
   ("pork" 5.4 43.0)
   ("ham" 3.6 90.0)
   ("greaves" 2.4 45.0)
   ("flitch" 4.0 30.0)
   ("brawn" 2.5 56.0)
   ("welt" 3.7 67.0)
   ("salami" 3.0 95.0)
   ("sausage" 5.9 98.0) )

(let K
   (make
      (let Weight 0
         (for I (by '((L) (*/ (caddr L) -1.0 (cadr L))) sort *Items)
            (T (= Weight 15.0))
            (inc 'Weight (cadr I))
            (T (> Weight 15.0)
               (let W (- (cadr I) Weight -15.0)
                  (link (list (car I) W (*/ W (caddr I) (cadr I)))) ) )
            (link I) ) ) )
   (for I K
      (tab (3 -9 8 8)
         NIL
         (car I)
         (format (cadr I) *Scl)
         (format (caddr I) *Scl) ) )
   (tab (12 8 8)
      NIL
      (format (sum cadr K) *Scl)
      (format (sum caddr K) *Scl) ) )


*process source xref attributes;
 KNAPSACK_CONTINUOUS: Proc Options(main);
 /*--------------------------------------------------------------------
 * 19.09.2014 Walter Pachl translated from FORTRAN
 *-------------------------------------------------------------------*/
  Dcl (divide,float,hbound,repeat) Builtin;
  Dcl SYSPRINT Print;

  Dcl maxweight Dec Fixed(15,3);
  maxweight = 15.0;
  Dcl (total_weight,total_value) Dec Fixed(15,3) Init(0);
  Dcl vpu  Dec Float(15);
  Dcl (i,j) Bin Fixed(31);

  Dcl 1 item(9),
       2 name   Char(7),
       2 weight Dec Fixed(15,3),
       2 value  Dec Fixed(15,3);
  Dcl temp Like item;

  Call init_item(1,'beef',    3.8, 36.0);
  Call init_item(2,'pork',    5.4, 43.0);
  Call init_item(3,'ham',     3.6, 90.0);
  Call init_item(4,'greaves', 2.4, 45.0);
  Call init_item(5,'flitch',  4.0, 30.0);
  Call init_item(6,'brawn',   2.5, 56.0);
  Call init_item(7,'welt',    3.7, 67.0);
  Call init_item(8,'salami',  3.0, 95.0);
  Call init_item(9,'sausage', 5.9, 98.0);

  /* sort item in descending order of their value per unit weight */
  do i = 2 To hbound(item);
    j = i - 1;
    temp = item(i);
    do while(j>=1&item(j).value/item(j).weight<temp.value/temp.weight);
      item(j+1) = item(j);
      j = j - 1;
      end;
    item(j+1) = temp;
  end;
  Do i=1 To hbound(item);
    Put Edit(i,item(i))(Skip,f(2),x(2),a(7),2(f(8,3)));
    End;
  i = 0;
  Put Skip;
  Put Edit('Item     Weight   Value')(Skip,a);
  do i=1 By 1 while(i < hbound(item) & total_weight < maxweight);
    if total_weight+item(i).weight < maxweight then Do;
      total_weight = total_weight + item(i).weight;
      total_value  = total_value + item(i).value;
      Put Edit(item(i))(Skip,a(7),2(f(8,3)));
      End;
    Else Do;
      vpu=divide(item(i).value,item(i).weight,15,8);
      item(i).weight=maxweight-total_weight;
      item(i).value=float(item(i).weight)*vpu;
      total_value = total_value + item(i).value;
      total_weight = total_weight + item(i).weight;
      Put Edit(item(i).name, item(i).weight, item(i).value)
              (Skip,a(7),2(f(8,3)));
      Leave Loop;
      end;
    end;
  Put Edit(repeat('-',22))(Skip,a);
  Put Edit('total',total_weight, total_value)(Skip,a(6),f(9,3),f(8,3));

 init_item: Proc(i,name,weight,value);
 Dcl i Bin Fixed(31);
 Dcl name Char(*);
 Dcl (weight,value) Dec Fixed(15,3);
 item(i).name   = name;
 item(i).weight = weight;
 item(i).value  = value;
 End;
 End;


:- use_module(library(simplex)).
% tuples (name, weights, value).
knapsack :-
	L = [(   beef, 	  3.8, 	36),
	     (   pork, 	  5.4, 	43),
	     (   ham, 	  3.6, 	90),
	     (   greaves, 2.4, 	45),
	     (   flitch,  4.0, 	30),
	     (   brawn,   2.5, 	56),
	     (   welt, 	  3.7, 	67),
	     (   salami,  3.0, 	95),
	     (   sausage, 5.9, 	98)],

	 gen_state(S0),
	 length(L, N),
	 numlist(1, N, LN),
	 (   (  create_constraint_N(LN, L, S0, S1, [], LW, [], LV),
		constraint(LW =< 15.0, S1, S2),
		maximize(LV, S2, S3)
	      )),
	compute_lenword(L, 0, Len),
	sformat(A1, '~~w~~t~~~w|', [Len]),
	sformat(A2, '~~t~~2f~~~w|', [10]),
	sformat(A3, '~~t~~2f~~~w|', [10]),
	print_results(S3, A1,A2,A3, L, LN, 0, 0).

create_constraint_N([], [], S, S, LW, LW, LV, LV).

create_constraint_N([HN|TN], [(_, W, V) | TL], S1, SF, LW, LWF, LV, LVF) :-
	constraint([x(HN)] >= 0, S1, S2),
	constraint([x(HN)] =< W, S2, S3),
	X is V/W,
	create_constraint_N(TN, TL, S3, SF, [x(HN) | LW], LWF, [X * x(HN) | LV], LVF).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
compute_lenword([], N, N).
compute_lenword([(Name, _, _)|T], N, NF):-
	atom_length(Name, L),
	(   L > N -> N1 = L; N1 = N),
	compute_lenword(T, N1, NF).

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

print_results(S, A1, A2, A3, [(Name, W, V)|T], [N|TN], W1, V1) :-
	variable_value(S, x(N), X),
	(   X = 0 -> W1 = W2, V1 = V2
	;
	    sformat(S1, A1, [Name]),
	    sformat(S2, A2, [X]),
	    Vtemp is X * V/W,
	    sformat(S3, A3, [Vtemp]),
	    format('~w~w~w~n', [S1,S2,S3]),
	    W2 is W1 + X,
	    V2 is V1 + Vtemp ),
	print_results(S, A1, A2, A3, T, TN, W2, V2).


Structure item
  name.s
  weight.f   ;units are kilograms (kg)
  Value.f
  vDensity.f ;the density of the value, i.e. value/weight, and yes I made up the term ;)
EndStructure

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

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

;build item list
addItem("beef", 3.8, 36)
addItem("pork", 5.4, 43)
addItem("ham", 3.6, 90)
addItem("greaves", 2.4, 45)
addItem("flitch", 4.0, 30)
addItem("brawn", 2.5, 56)
addItem("welt", 3.7, 67)
addItem("salami", 3.0, 95)
addItem("sausage", 5.9, 98)
SortStructuredArray(items(), #PB_Sort_descending, OffsetOf(item\vDensity), #PB_Sort_Float, 0, itemCount - 1)

Define TotalWeight.f, TotalValue.f, i
NewList knapsack.item()
For i = 0 To itemCount
  If TotalWeight + items(i)\weight < #maxWeight
    AddElement(knapsack())
    knapsack() = items(i)
    TotalWeight + items(i)\weight
    TotalValue + items(i)\Value
  Else
    AddElement(knapsack())
    knapsack() = items(i)
    knapsack()\weight = #maxWeight - TotalWeight
    knapsack()\Value = knapsack()\weight * knapsack()\vDensity
    TotalWeight = #maxWeight
    TotalValue + knapsack()\Value
    Break
  EndIf
Next

If OpenConsole()
  PrintN(LSet("Maximal weight", 26, " ") + "= " + Str(#maxWeight) + " kg")
  PrintN(LSet("Total weight of solution", 26, " ") + "= " + Str(#maxWeight) + " kg")
  PrintN(LSet("Total value", 26, " ") + "= " + StrF(TotalValue, 3) + " " + #CRLF$)
  PrintN("You can carry the following materials in the knapsack: ")
  ForEach knapsack()
    PrintN(RSet(StrF(knapsack()\weight, 1), 5, " ") + " kg  " + LSet(knapsack()\name, 10, " ") + "  (Value = " + StrF(knapsack()\Value, 3) + ")")
  Next

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


#        NAME, WEIGHT, VALUE (for this weight)
items = [("beef",    3.8, 36.0),
         ("pork",    5.4, 43.0),
         ("ham",     3.6, 90.0),
         ("greaves", 2.4, 45.0),
         ("flitch",  4.0, 30.0),
         ("brawn",   2.5, 56.0),
         ("welt",    3.7, 67.0),
         ("salami",  3.0, 95.0),
         ("sausage", 5.9, 98.0)]

MAXWT = 15.0

sorted_items = sorted(((value/amount, amount, name)
                       for name, amount, value in items),
                      reverse = True)
wt = val = 0
bagged = []
for unit_value, amount, name in sorted_items:
    portion = min(MAXWT - wt, amount)
    wt     += portion
    addval  = portion * unit_value
    val    += addval
    bagged += [(name, portion, addval)]
    if wt >= MAXWT:
        break

print("    ITEM   PORTION VALUE")
print("\n".join("%10s %6.2f %6.2f" % item for item in bagged))
print("\nTOTAL WEIGHT: %5.2f\nTOTAL VALUE: %5.2f" % (wt, val))


knapsack<- function(Value, Weight, Objects, Capacity){
  Fraction = rep(0, length(Value))
  Cost = Value/Weight
  #print(Cost)
  W = Weight[order(Cost, decreasing = TRUE)]
  Obs = Objects[order(Cost, decreasing = TRUE)]
  Val = Value[order(Cost, decreasing = TRUE)]
  #print(W)
  RemainCap = Capacity
  i = 1
  n = length(Cost)
  if (W[1] <= Capacity){
    Fits <- TRUE
  }
  else{
    Fits <- FALSE
  }
  while (Fits && i <= n ){
    Fraction[i] <- 1
    RemainCap <- RemainCap - W[i]
    i <- i+1
    #print(RemainCap)
    if (W[i] <= RemainCap){
      Fits <- TRUE
    }
    else{
      Fits <- FALSE
    }
  }
  #print(RemainCap)
  if (i <= n){
    Fraction[i] <- RemainCap/W[i]
  }
  names(Fraction) = Obs
  Quantity_to_take = W*Fraction
  Total_Value = sum(Val*Fraction)
  print("Fraction of available quantity to take:")
  print(round(Fraction, 3))
  print("KG of each to take:")
  print(Quantity_to_take)
  print("Total value of tasty meats:")
  print(Total_Value)
}


#lang racket
(define shop-inventory
  '((beef 	3.8 	36)
    (pork 	5.4 	43)
    (ham 	3.6 	90)
    (greaves 	2.4 	45)
    (flitch 	4.0 	30)
    (brawn 	2.5 	56)
    (welt 	3.7 	67)
    (salami 	3.0 	95)
    (sausage 	5.9 	98)))

(define (continuous-knapsack shop sack sack-capacity sack-total-value)
  ;; solved by loading up on the highest value item...
  (define (value/kg item) (/ (third item) (second item)))
  (if (zero? sack-capacity)
      (values (reverse sack) sack-total-value)
      (let* ((best-value-item (argmax value/kg shop))
             (bvi-full-weight (second best-value-item))
             (amount-can-take (min sack-capacity bvi-full-weight))
             (bvi-full-value  (third best-value-item))
             (bvi-taken-value (* bvi-full-value (/ amount-can-take bvi-full-weight))))
        (continuous-knapsack (remove best-value-item shop)
                             (cons (list (first best-value-item)
                                         (if (= amount-can-take bvi-full-weight)
                                             'all-of amount-can-take) bvi-taken-value)
                                   sack)
                             (- sack-capacity amount-can-take)
                             (+ sack-total-value bvi-taken-value)))))

(define (report-knapsack sack total-value)
  (for-each (lambda (item)
              (if (eq? 'all-of (second item))
                  (printf "Take all of the ~a (for ~a)~%"
                          (first item) (third item))
                  (printf "Take ~a of the ~a (for ~a)~%"
                          (real->decimal-string (second item))
                          (first item)
                          (real->decimal-string (third item)))))
            sack)
  (printf "For a grand total of: ~a" (real->decimal-string total-value)))

(call-with-values (lambda () (continuous-knapsack shop-inventory null 15 0))
                  report-knapsack)


class KnapsackItem {
  has $.name;
  has $.weight is rw;
  has $.price is rw;
  has $.ppw;

  method new (Str $n, Rat $w, Int $p) {
    self.bless(:name($n), :weight($w), :price($p), :ppw($w/$p))
  }

  method cut-maybe ($max-weight) {
    return False if $max-weight > $.weight;
    $.price = $max-weight / $.ppw;
    $.weight = $.ppw * $.price;
    return True;
  }

  method gist () { sprintf "%8s %1.2f   %3.2f",
                            $.name,
                                $.weight,
                                        $.price }
}

my $max-w = 15;
say    "Item    Portion Value";

.say for gather
    for < beef    3.8 36
          pork    5.4 43
          ham     3.6 90
          greaves 2.4 45
          flitch  4.0 30
          brawn   2.5 56
          welt    3.7 67
          salami  3.0 95
          sausage 5.9 98 >
        ==> map({ KnapsackItem.new($^a, $^b, $^c) })
        ==> sort *.ppw
    {
        my $last-one = .cut-maybe($max-w);
        take $_;
        $max-w -= .weight;
        last if $last-one;
    }


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


items = [ [:beef   , 3.8, 36],
          [:pork   , 5.4, 43],
          [:ham    , 3.6, 90],
          [:greaves, 2.4, 45],
          [:flitch , 4.0, 30],
          [:brawn  , 2.5, 56],
          [:welt   , 3.7, 67],
          [:salami , 3.0, 95],
          [:sausage, 5.9, 98] ].sort_by{|item, weight, price| -price / weight}
maxW, value = 15.0, 0
items.each do |item, weight, price|
  if (maxW -= weight) > 0
    puts "Take all #{item}"
    value += price
  else
    puts "Take %gkg of %s" % [t=weight+maxW, item], "",
         "Total value of swag is %g" % (value+(price/weight)*t)
    break
  end
end