type bounty = { name:string; value:int; weight:float; volume:float }

let bounty n d w v = { name = n; value = d; weight = w; volume = v }

let items =
  [ bounty "panacea"  3000  0.3  0.025;
    bounty "ichor"    1800  0.2  0.015;
    bounty "gold"     2500  2.0  0.002; ]

let max_wgt = 25.0 and max_vol = 0.25

let itmax =
  let f it =
    let rec aux n =
      if float n *. it.weight >= max_wgt
      || float n *. it.volume >= max_vol
      then (n)
      else aux (succ n)
    in
    aux 0
  in
  List.map f items

let mklist n m =
  let rec aux i acc =
    if i > m then (List.rev acc)
    else aux (succ i) (i::acc)
  in
  aux n []

let comb_items = List.map (mklist 0) itmax

let combs ll =
  let f hd acc =
    List.concat
      (List.map (fun l -> List.map (fun v -> (v::l)) hd) acc)
  in
  List.fold_right f ll [[]]

let possibles = combs comb_items

let packs =
  let f l =
    let g (v, wgt, vol) n it =
      (v + n * it.value,
       wgt +. float n *. it.weight,
       vol +. float n *. it.volume)
    in
    List.fold_left2 g (0, 0.0, 0.0) l items
  in
  List.map f possibles

let packs = List.combine packs possibles

let results =
  let f (_, wgt, vol) = (wgt <= max_wgt && vol <= max_vol) in
  List.filter (fun v -> f(fst v)) packs

let best_results =
  let max_value = List.fold_left (fun v1 ((v2,_,_),_) -> max v1 v2) 0 results in
  List.filter (fun ((v,_,_),_) -> v = max_value) results

let items_name = List.map (fun it -> it.name) items

let print ((v, wgt, vol), ns) =
  Printf.printf "\
    Maximum value: %d \n \
    Total weight:  %g \n \
    Total volume:  %g \n \
    Containing:    " v wgt vol;
  let f n name = string_of_int n ^ " " ^ name in
  let ss = List.map2 f ns items_name in
  print_endline(String.concat ", " ss);
  print_newline()

let () = List.iter print best_results


declare
  proc {Knapsack Sol}
     solution(panacea:P = {FD.decl}
              ichor:  I = {FD.decl}
              gold:   G = {FD.decl} ) = Sol
  in
                                           {Show 0#Sol}
      3 * P +  2 * I + 20 * G =<: 250      {Show 1#Sol}
     25 * P + 15 * I +  2 * G =<: 250      {Show 2#Sol}
     {FD.distribute naive Sol}             {Show d#Sol}
  end

  fun {Value solution(panacea:P ichor:I gold:G)}
     3000 * P + 1800 * I + 2500 * G
  end

  {System.showInfo "Search:"}
  [Best] = {SearchBest Knapsack proc {$ Old New}
                                   {Value Old} <: {Value New}
                                end}
in
  {System.showInfo "\nResult:"}
  {Show Best}
  {System.showInfo "total value: "#{Value Best}}


Program Knapsack(output);

uses
  math;

type
  bounty = record
    value: longint;
    weight, volume: real;
  end;

const
  panacea: bounty = (value:3000; weight:  0.3; volume: 0.025);
  ichor:   bounty = (value:1800; weight:  0.2; volume: 0.015);
  gold:    bounty = (value:2500; weight:  2.0; volume: 0.002);
  sack:    bounty = (value:   0; weight: 25.0; volume: 0.25);

var
  totalweight, totalvolume: real;
  maxpanacea, maxichor, maxgold: longint;
  maxvalue: longint = 0;
  n: array [1..3] of longint;
  current: bounty;
  i, j, k: longint;

begin
  maxpanacea := round(min(sack.weight / panacea.weight, sack.volume / panacea.volume));
  maxichor   := round(min(sack.weight / ichor.weight,   sack.volume / ichor.volume));
  maxgold    := round(min(sack.weight / gold.weight,    sack.volume / gold.volume));

  for i := 0 to maxpanacea do
    for j := 0 to maxichor do
      for k := 0 to maxgold do
      begin
        current.value  := k * gold.value  + j * ichor.value  + i * panacea.value;
        current.weight := k * gold.weight + j * ichor.weight + i * panacea.weight;
        current.volume := k * gold.volume + j * ichor.volume + i * panacea.volume;
        if (current.value > maxvalue)      and
	   (current.weight <= sack.weight) and
           (current.volume <= sack.volume) then
	begin
          maxvalue    := current.value;
          totalweight := current.weight;
          totalvolume := current.volume;
          n[1] := i;
	  n[2] := j;
	  n[3] := k;
        end;
      end;

  writeln ('Maximum value achievable is ', maxValue);
  writeln ('This is achieved by carrying ', n[1], ' panacea, ', n[2], ' ichor and ', n[3], ' gold items');
  writeln ('The weight of this carry is ', totalWeight:6:3, ' and the volume used is ', totalVolume:6:4);
end.


my (@names, @val, @weight, @vol, $max_vol, $max_weight, $vsc, $wsc);

if (1) { # change 1 to 0 for different data set
        @names  = qw(panacea    icor    gold);
        @val    = qw(3000       1800    2500);
        @weight = qw(3          2       20  );
        @vol    = qw(25         15      2   );
        $max_weight = 250;
        $max_vol = 250;
        $vsc = 1000;
        $wsc = 10;
} else { # with these numbers cache would have been useful
        @names  = qw(panacea    icor    gold    banana  monkey  );
        @val    = qw(17         11      5       3       34      );
        @weight = qw(14         3       2       2       10      );
        @vol    = qw(3          4       2       1       12      );
        $max_weight = 150;
        $max_vol = 100;
        $vsc = $wsc = 1;
}

my @cache;
my ($hits, $misses) = (0, 0);
sub solu {
        my ($i, $w, $v) = @_;
        return [0, []] if $i < 0;

        if ($cache[$i][$w][$v]) {
                $hits ++;
                return $cache[$i][$w][$v]
        }
        $misses ++;

        my $x = solu($i - 1, $w, $v);

        my ($w1, $v1);
        for (my $t = 1; ; $t++) {
                last if ($w1 = $w - $t * $weight[$i]) < 0;
                last if ($v1 = $v - $t * $vol[$i]) < 0;

                my $y = solu($i - 1, $w1, $v1);

                if ( (my $tmp = $y->[0] + $val[$i] * $t) > $x->[0] ) {
                        $x = [ $tmp, [ @{$y->[1]}, [$i, $t] ] ];
                }
        }

        $cache[$i][$w][$v] = $x
}

my $x = solu($#names, $max_weight, $max_vol);
print   "Max value $x->[0], with:\n",
        "    Item\tQty\tWeight   Vol    Value\n", '-'x 50, "\n";

my ($wtot, $vtot) = (0, 0);
for (@{$x->[1]}) {
        my $i = $_->[0];
        printf  "    $names[$i]:\t% 3d  % 8d% 8g% 8d\n",
                $_->[1],
                $weight[$i] * $_->[1] / $wsc,
                $vol[$i] * $_->[1] / $vsc,
                $val[$i] * $_->[1];

        $wtot += $weight[$i] * $_->[1];
        $vtot += $vol[$i] * $_->[1];
}
print   "-" x 50, "\n";
printf  "    Total:\t     % 8d% 8g% 8d\n",
        $wtot/$wsc, $vtot/$vsc, $x->[0];

print "\nCache hit: $hits\tmiss: $misses\n";


-- demo\rosetta\knapsack.exw
with javascript_semantics
function knapsack(sequence res, goodies, atom profit, weight, volume, at=1, sequence chosen={})
    atom {?,pitem,witem,vitem} = goodies[at]
    integer n = min(floor(weight/witem),floor(volume/vitem))
    chosen &= n
    profit += n*pitem   -- increase profit
    weight -= n*witem   -- decrease weight left
    volume -= n*vitem   -- decrease space left
    if at=length(goodies) then
        sequence pwvc = {profit,weight,volume,chosen}
        if length(res)=0 or profit>res[1][1] then
            res = {pwvc}
        elsif profit=res[1][1] then
            res = append(res,pwvc)
        end if
    else
        while n>=0 do
            res = knapsack(res,goodies,profit,weight,volume,at+1,deep_copy(chosen))
            n -= 1
            chosen[$] = n
            profit -= pitem
            weight += witem
            volume += vitem
        end while
    end if
    return res
end function

constant goodies = {-- item           profit weight volume
                    {"ichor",         1800,   0.2, 0.015},
                    {"panacea",       3000,   0.3, 0.025},
                    {"shiney shiney", 2500,   2.0, 0.002}},
        {descs,profits,wts,vols} = columnize(goodies)

--res is {{profit,(weight left),(space left),{counts}}}
sequence res = knapsack({},goodies,0,25,0.25)
for r=1 to length(res) do
    integer profit = res[r][1]
    sequence counts = res[r][4]
    atom weight = sum(sq_mul(counts,wts)), volume = sum(sq_mul(counts,vols))
    string what = join(apply(true,sprintf,{{"%2d %s"},columnize({counts,descs})}),", ")
    printf(1,"Profit %d: %s  [weight:%.1f, volume:%g]\n",{profit,what,weight,volume})
end for


import mip.

go =>
  data(Items,Value,Weight,Volume,MaxWeight,MaxVolume),
  knapsack_problem(Value,Weight,Volume,MaxWeight,MaxVolume, X,Z),

  println(z=Z),
  println(x=X),
  N = Items.len,

  foreach({Item,Num} in zip(Items,X), Num > 0)
     printf("Take %d of %w\n", Num,Item)
  end,

  print("\nTotal volume: "),
  println(sum([X[I]*Volume[I] : I in 1..N])),

  print("Total weight: "),
  println(sum([X[I]*Weight[I] : I in 1..N])),

  print("Total cost: "),
  println(sum([X[I]*Value[I] : I in 1..N])),

  nl.

knapsack_problem(Value,Weight,Volume,MaxWeight,MaxVolume, X,Z) =>
  println([max_weight=MaxWeight,max_volume=MaxVolume,z=Z]),
  N = Value.length,

  X = new_list(N),
  X :: 0..1000,

  Z #= sum([X[I]*Value[I] : I in 1..N]),

  foreach(I in 1..N)
      X[I] #>= 0
  end,

  limit(Weight, X, MaxWeight),
  limit(Volume, X, MaxVolume),

  if var(Z) then
    println(maximize),
    solve($[glpk,max(Z)], X)
  else
    solve($[glpk], X)
  end.

limit(W, Take, WTMax) =>
  sum([W[I]*Take[I] : I in 1..W.length]) #<= WTMax.

% data
data(Items,Value,Weight,Volume,MaxWeight,MaxVolume) =>
  Items  = ["panacea","ichor","gold"],
  Value  = [3000.0, 1800.0, 2500.0  ],
  Weight = [   0.3,    0.2,    2.0  ],
  Volume = [   0.025,  0.015,  0.002],
  MaxWeight = 25.0,
  MaxVolume = 0.25.


(de *Items
   ("panacea"  3  25  3000)
   ("ichor"    2  15  1800)
   ("gold"    20   2  2500) )

(de knapsack (Lst W V)
   (when Lst
      (let X (knapsack (cdr Lst) W V)
         (if (and (ge0 (dec 'W (cadar Lst))) (ge0 (dec 'V (caddar Lst))))
            (maxi
               '((L) (sum cadddr L))
               (list
                  X
                  (cons (car Lst) (knapsack (cdr Lst) W V))
                  (cons (car Lst) (knapsack Lst W V)) ) )
            X ) ) ) )

(let K (knapsack *Items 250 250)
   (for (L K  L)
      (let (N 1  X)
         (while (= (setq X (pop 'L)) (car L))
            (inc 'N) )
         (apply tab X (4 2 8 5 5 7) N "x") ) )
   (tab (14 5 5 7) NIL (sum cadr K) (sum caddr K) (sum cadddr K)) )


#  Define the items to pack
$Item = @(
    [pscustomobject]@{ Name = 'panacea'; Unit = 'vials'  ; value = 3000; Weight = 0.3; Volume = 0.025 }
    [pscustomobject]@{ Name = 'ichor'  ; Unit = 'ampules'; value = 1800; Weight = 0.2; Volume = 0.015 }
    [pscustomobject]@{ Name = 'gold'   ; Unit = 'bars'   ; value = 2500; Weight = 2.0; Volume = 0.002 }
    )

#  Define our maximums
$MaxWeight = 25
$MaxVolume = 0.25

#  Set our default value to beat
$OptimalValue = 0

#  Iterate through the possible quantities of item 0, without going over the weight or volume limit
ForEach ( $Qty0 in 0..( [math]::Min( [math]::Truncate( $MaxWeight / $Item[0].Weight ), [math]::Truncate( $MaxVolume / $Item[0].Volume ) ) ) )
    {
    #  Calculate the remaining space
    $RemainingWeight = $MaxWeight - $Qty0 * $Item[0].Weight
    $RemainingVolume = $MaxVolume - $Qty0 * $Item[0].Volume

    #  Iterate through the possible quantities of item 1, without going over the weight or volume limit
    ForEach ( $Qty1 in 0..( [math]::Min( [math]::Truncate( $RemainingWeight / $Item[1].Weight ), [math]::Truncate( $RemainingVolume / $Item[1].Volume ) ) ) )
        {
        #  Calculate the remaining space
        $RemainingWeight2 = $RemainingWeight - $Qty1 * $Item[1].Weight
        $RemainingVolume2 = $RemainingVolume - $Qty1 * $Item[1].Volume

        #  Calculate the maximum quantity of item 2 for the remaining space, without going over the weight or volume limit
        $Qty2 = [math]::Min( [math]::Truncate( $RemainingWeight2 / $Item[2].Weight ), [math]::Truncate( $RemainingVolume2 / $Item[2].Volume ) )

        #  Calculate the total value of the items packed
        $TrialValue =   $Qty0 * $Item[0].Value +
                        $Qty1 * $Item[1].Value +
                        $Qty2 * $Item[2].Value

        #  Describe the trial solution
        $Solution  = "$Qty0 $($Item[0].Unit) of $($Item[0].Name), "
        $Solution += "$Qty1 $($Item[1].Unit) of $($Item[1].Name), and "
        $Solution += "$Qty2 $($Item[2].Unit) of $($Item[2].Name) worth a total of $TrialValue."

        #  If the trial value is higher than previous most valuable trial...
        If ( $TrialValue -gt $OptimalValue )
            {
            #  Set the new number to beat
            $OptimalValue = $TrialValue

            #  Overwrite the previous optimal solution(s) with the trial solution
            $Solutions  = @( $Solution )
            }

        #  Else if the trial value matches the previous most valuable trial...
       ElseIf ( $TrialValue -eq $OptimalValue )
            {
            #  Add the trial solution to the list of optimal solutions
            $Solutions += @( $Solution )
            }
        }
    }

#  Show the results
$Solutions


:- use_module(library(simplex)).

% tuples (name, Explantion, Value, weights, volume).
knapsack :-
	L =[(	panacea, 'Incredible healing properties', 3000,	0.3,	0.025),
	    (	ichor,   'Vampires blood',                1800,	0.2,	0.015),
	    (	gold ,	 'Shiney shiney',	          2500,	2.0,	0.002)],

	 gen_state(S0),
	 length(L, N),
	 numlist(1, N, LN),

	 % to get statistics
	 time((create_constraint_N(LN, L, S0, S1, [], LVa, [], LW, [], LVo),
	       constraint(LW =< 25.0, S1, S2),
	       constraint(LVo =< 0.25, S2, S3),
	       maximize(LVa, S3, S4)
	      )),

	% we display the results
	compute_lenword(L, 0, Len),
	sformat(A0, '~~w~~t~~~w|', [3]),
	sformat(A1, '~~w~~t~~~w|', [Len]),
	sformat(A2, '~~t~~w~~~w|', [10]),
	sformat(A3, '~~t~~2f~~~w|', [10]),
	sformat(A4, '~~t~~3f~~~w|', [10]),
	sformat(A33, '~~t~~w~~~w|', [10]),
	sformat(A44, '~~t~~w~~~w|', [10]),

	sformat(W0, A0, ['Nb']),
	sformat(W1, A1, ['Items']),
	sformat(W2, A2, ['Value']),
	sformat(W3, A33, ['Weigth']),
	sformat(W4, A44, ['Volume']),
	format('~w~w~w~w~w~n', [W0, W1,W2,W3,W4]),

	print_results(S4, A0, A1, A2, A3, A4, L, LN, 0, 0, 0).

create_constraint_N([], [], S, S, LVa, LVa, LW, LW, LVo, LVo).

create_constraint_N([HN|TN], [(_, _,Va, W, Vo) | TL], S1, SF, LVa, LVaF, LW, LWF, LVo, LVoF) :-
	constraint(integral(x(HN)), S1, S2),
	constraint([x(HN)] >= 0, S2, S3),
	create_constraint_N(TN, TL, S3, SF,
			    [Va * x(HN) | LVa], LVaF,
			    [W * x(HN) | LW], LWF,
			    [Vo * x(HN) | LVo], LVoF).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
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, A0, A1, A2, A3, A4, [], [], VaM, WM, VoM) :-
	sformat(W0, A0, [' ']),
	sformat(W1, A1, [' ']),
	sformat(W2, A2, [VaM]),
	sformat(W3, A3, [WM]),
	sformat(W4, A4, [VoM]),
	format('~w~w~w~w~w~n', [W0, W1,W2,W3,W4]).

print_results(S, A0, A1, A2, A3, A4, [(Name, _, Va, W, Vo)|T], [N|TN], Va1, W1, Vo1) :-
	variable_value(S, x(N), X),
	(   X = 0 -> Va1 = Va2, W1 = W2, Vo1 = Vo2
	;
	    sformat(S0, A0, [X]),
	    sformat(S1, A1, [Name]),
	    Vatemp is X * Va,
	    Wtemp is X * W,
	    Votemp is X * Vo,
	    sformat(S2, A2, [Vatemp]),
	    sformat(S3, A3, [Wtemp]),
	    sformat(S4, A4, [Votemp]),
	    format('~w~w~w~w~w~n', [S0,S1,S2,S3,S4]),
	    Va2 is Va1 + Vatemp,
	    W2 is W1 + Wtemp,
	    Vo2 is Vo1 + Votemp ),
	print_results(S, A0, A1, A2, A3, A4, T, TN, Va2, W2, Vo2).


Define.f TotalWeight, TotalVolyme
Define.i maxPanacea, maxIchor, maxGold, maxValue
Define.i i, j ,k
Dim n.i(2)

Enumeration
  #Panacea
  #Ichor
  #Gold
  #Sack
  #Current
EndEnumeration

Structure Bounty
  value.i
  weight.f
  volyme.f
EndStructure

Dim Item.Bounty(4)
CopyMemory(?panacea,@Item(#Panacea),SizeOf(Bounty))
CopyMemory(?ichor,  @Item(#Ichor),  SizeOf(Bounty))
CopyMemory(?gold,   @Item(#gold),   SizeOf(Bounty))
CopyMemory(?sack,   @Item(#Sack),   SizeOf(Bounty))

Procedure.f min(a.f, b.f)
  If a<b
    ProcedureReturn a
  Else
    ProcedureReturn b
  EndIf
EndProcedure

maxPanacea=min(Item(#Sack)\weight/Item(#Panacea)\weight,Item(#Sack)\volyme/Item(#Panacea)\volyme)
maxIchor  =min(Item(#Sack)\weight/Item(#Ichor)\weight,  Item(#Sack)\volyme/Item(#Ichor)\volyme)
maxGold   =min(Item(#Sack)\weight/Item(#Gold)\weight,   Item(#Sack)\volyme/Item(#Gold)\volyme)

For i=0 To maxPanacea
  For j=0 To maxIchor
    For k=0 To maxGold
      Item(#Current)\value=k*Item(#Gold)\value  +j*item(#Ichor)\value +i*item(#Panacea)\value
      Item(#Current)\weight=k*Item(#Gold)\weight+j*Item(#Ichor)\weight+i*Item(#Panacea)\weight
      Item(#Current)\volyme=k*Item(#Gold)\volyme+j*Item(#Ichor)\volyme+i*Item(#Panacea)\volyme
      If Item(#Current)\weight>Item(#Sack)\weight Or Item(#Current)\volyme>Item(#Sack)\volyme
        Continue
      EndIf
      If Item(#Current)\value>maxValue
        maxValue=Item(#Current)\value
        TotalWeight=Item(#Current)\weight
        TotalVolyme=Item(#Current)\volyme
        n(#Panacea)=i: n(#Ichor)=j: n(#Gold)=k
      EndIf
    Next k
  Next j
Next i

If OpenConsole()
  Define txt$
  txt$="Maximum value achievable is "+Str(maxValue)+#CRLF$
  txt$+"This is achieved by carrying "+Str(n(#Panacea))+" panacea, "
  txt$+Str(n(#Ichor))+" ichor and "+Str(n(#Gold))+" gold items."+#CRLF$
  txt$+"The weight to carry is "+StrF(totalWeight,2)
  txt$+" and the volume used is "+StrF(TotalVolyme,2)
  PrintN(txt$)

  Print(#CRLF$+"Press Enter to quit"): Input()
EndIf

DataSection
panacea:
  Data.i 3000
  Data.f 0.3, 0.025
ichor:
  Data.i 1800
  Data.f 0.2, 0.015
gold:
  Data.i 2500
  Data.f 2.0, 0.002
sack:
  Data.i  0
  Data.f  25.0, 0.25
EndDataSection


# Define consts
weights <- c(panacea=0.3, ichor=0.2, gold=2.0)
volumes <- c(panacea=0.025, ichor=0.015, gold=0.002)
values <- c(panacea=3000, ichor=1800, gold=2500)
sack.weight <- 25
sack.volume <- 0.25
max.items <- floor(pmin(sack.weight/weights, sack.volume/volumes))

# Some utility functions
getTotalValue <- function(n) sum(n*values)
getTotalWeight <- function(n) sum(n*weights)
getTotalVolume <- function(n) sum(n*volumes)
willFitInSack <- function(n) getTotalWeight(n) <= sack.weight && getTotalVolume(n) <= sack.volume

# Find all possible combination, then eliminate those that won't fit in the sack
knapsack <- expand.grid(lapply(max.items, function(n) seq.int(0, n)))
ok <- apply(knapsack, 1, willFitInSack)
knapok <- knapsack[ok,]

# Find the solutions with the highest value
vals <- apply(knapok, 1, getTotalValue)
knapok[vals == max(vals),]


#lang racket

(struct item (name explanation value weight volume) #:prefab)

(define items
  (list
   (item "panacea (vials of)" "Incredible healing properties" 3000 0.3 0.025)
   (item "ichor (ampules of)" "Vampires blood"                1800 0.2 0.015)
   (item "gold (bars)"        "Shiney shiney"                 2500 2.0 0.002)))

(define (fill-sack items volume-left weight-left sack sack-value)
  (match items
    ['() (values (list sack) sack-value)]
    [(cons (and (item _ _ item-val weight volume) item) items)
     (define max-q-wgt (floor (/ weight-left weight)))
     (define max-q-vol (floor (/ volume-left volume)))
     (for/fold ([best (list sack)] [best-val sack-value])
               ([n (exact-round (add1 (min max-q-vol max-q-wgt)))])
       (define-values [best* best-val*]
         (fill-sack items
                    (- volume-left (* n volume))
                    (- weight-left (* n weight))
                    (cons (cons n item) sack)
                    (+ sack-value (* n item-val))))
       (cond [(> best-val* best-val) (values best* best-val*)]
             [(= best-val* best-val) (values (append best best*) best-val*)]
             [else                   (values best best-val)]))]))

(define (display-sack sack total)
  (for ([sk sack])
    (define qty (car sk))
    (define name (item-name (cdr sk)))
    (if (zero? qty)
      (printf "Leave ~a\n" name)
      (printf "Take ~a ~a\n" qty name)))
  (printf "GRAND TOTAL: ~a\n\n" total))

(call-with-values (λ() (fill-sack items 0.25 25 '() 0))
                  (λ(sacks total) (for ([s sacks]) (display-sack s total))))


class KnapsackItem {
  has $.volume;
  has $.weight;
  has $.value;
  has $.name;

  method new($volume,$weight,$value,$name) {
    self.bless(:$volume, :$weight, :$value, :$name)
  }
};

my KnapsackItem $panacea .= new: 0.025, 0.3, 3000, "panacea";
my KnapsackItem $ichor   .= new: 0.015, 0.2, 1800, "ichor";
my KnapsackItem $gold    .= new: 0.002, 2.0, 2500, "gold";
my KnapsackItem $maximum .= new: 0.25,  25,  0   , "max";

my $max_val = 0;
my @solutions;
my %max_items;

for $panacea, $ichor, $gold -> $item {
    %max_items{$item.name} = floor min
                            $maximum.volume / $item.volume,
			    $maximum.weight / $item.weight;
}

for 0..%max_items<panacea>
       X 0..%max_items<ichor>
           X 0..%max_items<gold>
 -> ($p, $i, $g)
{
  next if $panacea.volume * $p + $ichor.volume * $i + $gold.volume * $g > $maximum.volume;
  next if $panacea.weight * $p + $ichor.weight * $i + $gold.weight * $g > $maximum.weight;
  given $panacea.value * $p + $ichor.value * $i + $gold.value * $g {
    if $_ > $max_val { $max_val = $_; @solutions = (); }
    when $max_val    { @solutions.push: $[$p,$i,$g] }
  }
}

say "maximum value is $max_val\npossible solutions:";
say "panacea\tichor\tgold";
.join("\t").say for @solutions;


/*REXX program solves the knapsack/unbounded problem: highest value, weight, and volume.*/

                           /*   value                   weight                   volume */
maxPanacea= 0              /*  ═══════                  ══════                   ══════ */
maxIchor  = 0;      panacea.$ = 3000  ;      panacea.w =  0.3 ;       panacea.v = 0.025
maxGold   = 0;        ichor.$ = 1800  ;        ichor.w =  0.2 ;         ichor.v = 0.015
max$      = 0;         gold.$ = 2500  ;         gold.w =  2   ;          gold.v = 0.002
now.      = 0;         sack.$ =    0  ;         sack.w = 25   ;          sack.v = 0.25

maxPanacea= min(sack.w / panacea.w,     sack.v / panacea.v)
maxIchor  = min(sack.w /   ichor.w,     sack.v /   ichor.v)
maxGold   = min(sack.w /    gold.w,     sack.v /    gold.v)

  do     p=0  to maxPanacea
    do   i=0  to maxIchor
      do g=0  to maxGold
      now.$= g * gold.$     +     i * ichor.$     +     p * panacea.$
      now.w= g * gold.w     +     i * ichor.w     +     p * panacea.w
      now.v= g * gold.v     +     i * ichor.v     +     p * panacea.v
      if now.w > sack.w  |  now.v  > sack.v  then iterate
      if now.$ > max$  then do;   maxP= p;          maxI= i;            maxG= g
                                  max$= now.$;      maxW= now.w;        maxV= now.v
                            end
      end  /*g  (gold)   */
    end    /*i  (ichor)  */
  end      /*p  (panacea)*/

Ctot = maxP + maxI + maxG;                 L = length(Ctot) + 1
say '    panacea in sack:'     right(maxP, L)
say '     ichors in sack:'     right(maxI, L)
say ' gold items in sack:'     right(maxG, L)
say '════════════════════'     copies("═", L)
say 'carrying a total of:'     right(cTot, L)
                           say left('', 40)     "total  value: "        max$ / 1
                           say left('', 40)     "total weight: "        maxW / 1
                           say left('', 40)     "total volume: "        maxV / 1
                                                 /*stick a fork in it,  we're all done. */


KnapsackItem = Struct.new(:volume, :weight, :value)
panacea = KnapsackItem.new(0.025, 0.3, 3000)
ichor   = KnapsackItem.new(0.015, 0.2, 1800)
gold    = KnapsackItem.new(0.002, 2.0, 2500)
maximum = KnapsackItem.new(0.25,  25,  0)

max_items = {}
for item in [panacea, ichor, gold]
  max_items[item] = [(maximum.volume/item.volume).to_i, (maximum.weight/item.weight).to_i].min
end

maxval = 0
solutions = []

0.upto(max_items[ichor]) do |i|
  0.upto(max_items[panacea]) do |p|
    0.upto(max_items[gold]) do |g|
      break if i*ichor.weight + p*panacea.weight + g*gold.weight > maximum.weight
      break if i*ichor.volume + p*panacea.volume + g*gold.volume > maximum.volume
      val = i*ichor.value + p*panacea.value + g*gold.value
      if val > maxval
        maxval = val
        solutions = [[i, p, g]]
      elsif val == maxval
        solutions << [i, p, g]
      end
    end
  end
end

puts "The maximal solution has value #{maxval}"
solutions.each do |i, p, g|
  printf "  ichor=%2d, panacea=%2d, gold=%2d -- weight:%.1f, volume=%.3f\n",
    i, p, g,
    i*ichor.weight + p*panacea.weight + g*gold.weight,
    i*ichor.volume + p*panacea.volume + g*gold.volume
end


data one;
   wtpanacea=0.3;    wtichor=0.2;    wtgold=2.0;
   volpanacea=0.025; volichor=0.015; volgold=0.002;
   valpanacea=3000;  valichor=1800;  valgold=2500;
   maxwt=25; maxvol=0.25;

   /* we can prune the possible selections */
   maxpanacea = floor(min(maxwt/wtpanacea, maxvol/volpanacea));
   maxichor = floor(min(maxwt/wtichor, maxvol/volichor));
   maxgold = floor(min(maxwt/wtgold, maxvol/volgold));
   do i1 = 0 to maxpanacea;
      do i2 = 0 to maxichor;
         do i3 = 0 to maxgold;
            panacea = i1; ichor=i2; gold=i3; output;
         end;
      end;
   end;
run;
data one; set one;
   vals = valpanacea*panacea + valichor*ichor + valgold*gold;
   totalweight = wtpanacea*panacea + wtichor*ichor + wtgold*gold;
   totalvolume = volpanacea*panacea + volichor*ichor + volgold*gold;
   if (totalweight le maxwt) and (totalvolume le maxvol);
run;
proc sort data=one;
   by descending vals;
run;
proc print data=one (obs=4);
   var panacea ichor gold vals;
run;


import scala.annotation.tailrec

object UnboundedKnapsack extends App {
  private val (maxWeight, maxVolume) = (BigDecimal(25.0), BigDecimal(0.25))
  private val items = Seq(Item("panacea", 3000, 0.3, 0.025), Item("ichor", 1800, 0.2, 0.015), Item("gold", 2500, 2.0, 0.002))

  @tailrec
  private def packer(notPacked: Seq[Knapsack], packed: Seq[Knapsack]): Seq[Knapsack] = {
    def fill(knapsack: Knapsack): Seq[Knapsack] = items.map(i => Knapsack(i +: knapsack.bagged))

    def stuffer(Seq: Seq[Knapsack]): Seq[Knapsack] = // Cause brute force
      Seq.map(k => Knapsack(k.bagged.sortBy(_.name))).distinct

    if (notPacked.isEmpty) packed.sortBy(-_.totValue).take(4)
    else packer(stuffer(notPacked.flatMap(fill)).filter(_.isNotFull), notPacked ++ packed)
  }

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

  private case class Knapsack(bagged: Seq[Item]) {
    def isNotFull: Boolean = totWeight <= maxWeight && totVolume <= maxVolume

    override def toString = s"[${show(bagged)} | value: $totValue, weight: $totWeight, volume: $totVolume]"

    def totValue: Int = bagged.map(_.value).sum

    private def totVolume = bagged.map(_.volume).sum

    private def totWeight = bagged.map(_.weight).sum

    private def show(is: Seq[Item]) =
      (items.map(_.name) zip items.map(i => is.count(_ == i)))
        .map { case (i, c) => f"$i:$c%3d" }
        .mkString(", ")
  }

  packer(items.map(i => Knapsack(Seq(i))), Nil).foreach(println)
}


$ include "seed7_05.s7i";
  include "float.s7i";

const type: bounty is new struct
    var integer: value is 0;
    var float: weight is 0.0;
    var float: volume is 0.0;
  end struct;

const func bounty: bounty (in integer: value, in float: weight, in float: volume) is func
  result
    var bounty: bountyVal is bounty.value;
  begin
    bountyVal.value := value;
    bountyVal.weight := weight;
    bountyVal.volume := volume;
  end func;

const proc: main is func
  local
    const bounty: panacea is bounty(3000, 0.3, 0.025);
    const bounty: ichor   is bounty(1800, 0.2, 0.015);
    const bounty: gold    is bounty(2500, 2.0, 0.002);
    const bounty: sack    is bounty(0,   25.0, 0.25);
    const integer: maxPanacea is trunc(min(sack.weight / panacea.weight, sack.volume / panacea.volume));
    const integer: maxIchor   is trunc(min(sack.weight / ichor.weight,   sack.volume / ichor.volume));
    const integer: maxGold    is trunc(min(sack.weight / gold.weight,    sack.volume / gold.volume));
    var bounty: current is bounty.value;
    var bounty: best is bounty.value;
    var array integer: bestAmounts is 3 times 0;
    var integer: numPanacea is 0;
    var integer: numIchor is 0;
    var integer: numGold is 0;
  begin
    for numPanacea range 0 to maxPanacea do
      for numIchor range 0 to maxIchor do
        for numGold range 0 to maxGold do
          current.value  := numGold      * gold.value  + numIchor      * ichor.value  + numPanacea      * panacea.value;
          current.weight := flt(numGold) * gold.weight + flt(numIchor) * ichor.weight + flt(numPanacea) * panacea.weight;
          current.volume := flt(numGold) * gold.volume + flt(numIchor) * ichor.volume + flt(numPanacea) * panacea.volume;
          if current.value > best.value and current.weight <= sack.weight and current.volume <= sack.volume then
            best := current;
            bestAmounts := [] (numPanacea, numIchor, numGold);
          end if;
        end for;
      end for;
    end for;
    writeln("Maximum value achievable is " <& best.value);
    writeln("This is achieved by carrying " <& bestAmounts[1] <& " panacea, " <& bestAmounts[2] <& " ichor and " <& bestAmounts[3] <& " gold items");
    writeln("The weight of this carry is " <& best.weight <& " and the volume used is " <& best.volume digits 4);
  end func;


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

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

var (
    max_weight = 250,
    max_vol = 250,
    vsc = 1000,
    wsc = 10
)

func solve(i, w, v) is cached {
    return [0, []] if i.is_neg;

    var x = solve(i.dec, w, v);

    var (w1, v1);
    Inf.times { |t|
        var item = items[i];
        break if ((w1 = (w - t*item.weight)).is_neg)
        break if ((v1 = (v - t*item.volume)).is_neg)

        var y = solve(i.dec, w1, v1);
        if ((var tmp = (y[0] + t*item.value)) > x[0]) {
            x = [tmp, [y[1]..., [i, t]]];
        }
    }

    return x
}

var x = solve(items.end, max_weight, max_vol)

print <<"EOT"
Max value #{x[0]}, with:
    Item        Qty     Weight   Vol    Value
#{"-" * 50}
EOT

var (wtot=0, vtot=0);
x[1].each { |s|
    var item = items[s[0]];
    "    #{item.name}:\t% 3d  % 8d% 8g% 8d\n".printf(
        s[1],
        item.weight * s[1] / wsc,
        item.volume * s[1] / vsc,
        item.value  * s[1]
    );
    wtot += (item.weight * s[1]);
    vtot += (item.volume * s[1]);
}

print <<"EOT"
#{"-" * 50}
    Total:\t     #{"%8d%8g%8d" % (wtot/wsc, vtot/vsc, x[0])}
EOT


#!/usr/bin/env tclsh
proc main argv {
    array set value  {panacea 3000  ichor 1800  gold 2500}
    array set weight {panacea 0.3   ichor 0.2   gold 2.0   max 25}
    array set volume {panacea 0.025 ichor 0.015 gold 0.002 max 0.25}

    foreach i {panacea ichor gold} {
        set max($i) [expr {min(int($volume(max)/$volume($i)),
                               int($weight(max)/$weight($i)))}]
    }
    set maxval 0
    for {set i 0} {$i < $max(ichor)} {incr i} {
        for {set p 0} {$p < $max(panacea)} {incr p} {
            for {set g 0} {$g < $max(gold)} {incr g} {
                if {$i*$weight(ichor) + $p*$weight(panacea) + $g*$weight(gold)
                    > $weight(max)} continue
                if {$i*$volume(ichor) + $p*$volume(panacea) + $g*$volume(gold)
                    > $volume(max)} continue
                set val [expr {$i*$value(ichor)+$p*$value(panacea)+$g*$value(gold)}]
                if {$val == $maxval} {
                    lappend best [list i $i p $p g $g]
                } elseif {$val > $maxval} {
                    set maxval $val
                    set best [list [list i $i p $p g $g]]
                }
            }
        }
    }
    puts "maxval: $maxval, best: $best"
}
main $argv


#import nat
#import flo

vol = iprod/<0.025,0.015,0.002>+ float*
val = iprod/<3000.,1800.,2500.>+ float*
wgt = iprod/<0.3,0.2,2.0>+ float*

packings = ~&lrlrNCCPCS ~&K0=> iota* <11,17,13>

solutions = fleq$^rS&hl |=&l ^(val,~&)* (fleq\25.+ wgt)*~ (fleq\0.25+ vol)*~ packings

#cast %nmL

human_readable = ~&p/*<'panacea','ichor','gold'> solutions


Function Min(E1, E2): Min = IIf(E1 < E2, E1, E2): End Function 'small Helper-Function

Sub Main()
Const Value = 0, Weight = 1, Volume = 2, PC = 3, IC = 4, GC = 5
Dim P&, I&, G&, A&, M, Cur(Value To Volume)
Dim S As New Collection: S.Add Array(0) '<- init Solutions-Coll.

Const SackW = 25, SackV = 0.25
Dim Panacea: Panacea = Array(3000, 0.3, 0.025)
Dim Ichor:     Ichor = Array(1800, 0.2, 0.015)
Dim Gold:       Gold = Array(2500, 2, 0.002)

  For P = 0 To Int(Min(SackW / Panacea(Weight), SackV / Panacea(Volume)))
    For I = 0 To Int(Min(SackW / Ichor(Weight), SackV / Ichor(Volume)))
      For G = 0 To Int(Min(SackW / Gold(Weight), SackV / Gold(Volume)))
        For A = Value To Volume: Cur(A) = G * Gold(A) + I * Ichor(A) + P * Panacea(A): Next
        If Cur(Value) >= S(1)(Value) And Cur(Weight) <= SackW And Cur(Volume) <= SackV Then _
          S.Add Array(Cur(Value), Cur(Weight), Cur(Volume), P, I, G), , 1
  Next G, I, P

  Debug.Print "Value", "Weight", "Volume", "PanaceaCount", "IchorCount", "GoldCount"
  For Each M In S '<- enumerate the Attributes of the Maxima
    If M(Value) = S(1)(Value) Then Debug.Print M(Value), M(Weight), M(Volume), M(PC), M(IC), M(GC)
  Next
End Sub


import "/fmt" for Fmt

class Item {
    construct new(name, value, weight, volume) {
        _name   = name
        _value  = value
        _weight = weight
        _volume = volume
    }

    name   { _name   }
    value  { _value  }
    weight { _weight }
    volume { _volume }
}

var items = [
    Item.new("panacea", 3000, 0.3, 0.025),
    Item.new("ichor", 1800, 0.2, 0.015),
    Item.new("gold", 2500, 2, 0.002)
]

var n = items.count
var count = List.filled(n, 0)
var best = List.filled(n, 0)
var bestValue = 0
var maxWeight = 25
var maxVolume = 0.25

var knapsack // recursive
knapsack = Fn.new { |i, value, weight, volume|
    if (i == n) {
        if (value > bestValue) {
            bestValue = value
            for (j in 0...n) best[j] = count[j]
        }
        return
    }
    var m1 = (weight / items[i].weight).floor
    var m2 = (volume / items[i].volume).floor
    count[i] = m1.min(m2)
    while (count[i] >= 0) {
        knapsack.call(
            i + 1,
            value  + count[i] * items[i].value,
            weight - count[i] * items[i].weight,
            volume - count[i] * items[i].volume
        )
        count[i] = count[i] - 1
    }
}

knapsack.call(0, 0, maxWeight, maxVolume)
System.print("Item Chosen  Number Value  Weight  Volume")
System.print("-----------  ------ -----  ------  ------")
var itemCount = 0
var sumNumber = 0
var sumWeight = 0
var sumVolume = 0
for (i in 0... n) {
    if (best[i] != 0) {
        itemCount  = itemCount + 1
        var name   = items[i].name
        var number = best[i]
        var value  = items[i].value  * number
        var weight = items[i].weight * number
        var volume = items[i].volume * number
        sumNumber  = sumNumber + number
        sumWeight  = sumWeight + weight
        sumVolume  = sumVolume + volume
        Fmt.write("$-11s   $2d    $5.0f   $4.1f", name, number, value, weight)
        Fmt.print("    $4.2f", volume)
    }
}
System.print("-----------  ------ -----  ------  ------")
Fmt.write("$d items       $2d    $5.0f   $4.1f", itemCount, sumNumber, bestValue, sumWeight)
Fmt.print("    $4.2f", sumVolume)


panacea:=T(3000,  0.3, 0.025);  // (value,weight,volume)
ichor  :=T(1800,  0.2, 0.015);
gold   :=T(2500,  2.0, 0.002);
sack   :=T(   0, 25.0, 0.250);  const VAL=0, W=1, VOL=2;

maxes:=T(panacea,ichor,gold)
   .apply('wrap(t){ (sack[W]/t[W]).min(sack[VOL]/t[VOL]).toInt().walker() });
best:=Utils.Helpers.cprod3(maxes.xplode())
    .apply('wrap(t){
       T(T(panacea[VAL]*t[0] + ichor[VAL]*t[1] + gold[VAL]*t[2],
           panacea[W]  *t[0] + ichor[W]  *t[1] + gold[W]  *t[2],
           panacea[VOL]*t[0] + ichor[VOL]*t[1] + gold[VOL]*t[2]), t)
    })
    .filter('wrap(t){ t[0][W]<=sack[W] and t[0][VOL]<=sack[VOL] })
    .reduce(fcn(a,b){ a[0][VAL] > b[0][VAL] and a or b });

println("Maximum value achievable is %,d".fmt(best[0][VAL]));
println(("This is achieved by carrying (one solution):"
         "  %d panacea, %d ichor and %d gold").fmt(best[1].xplode()));
println("The weight to carry is %4.1f and the volume used is %5.3f"
        .fmt(best[0][1,*].xplode()));


rawio:	equ	6	; Raw console input
puts:	equ	9	; String output
bdos:	equ	5	; CP/M entry point
	org	100h
	jmp	demo
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	;;;	Routine: read 'Y' or 'N' from the keyboard.
	;;;	Output: carry flag clear if Y pressed, set if N pressed.
yesno:	mvi	c,rawio	; Read input from console
	mvi	e,-1
	call	bdos
	ana	a	; Read keys as long as a key is pressed
	jnz	yesno	; (wait until keyboard is clear)
yread:	mvi	c,rawio	; Then, wait for a key to be pressed
	mvi	e,-1
	call	bdos
	ana	a
	jz	yread
	ori	32	; Set bit 5 to make input letters lowercase
	cpi	'y'	; If the key is Y,
	rz		; then return (carry is clear here)
	cpi	'n'	; If the key is N,
	stc		; then set the carry flag and return
	rz
	jmp	yread	; If it wasn't Y or N, get another key
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	;;;	Demo code: use the routine to read Y or N, and then print
	;;;	'yes' or 'no'.
demo:	call	yesno	; Read Y or N
	mvi	c,puts
	lxi	d,yes
	jnc	bdos	; If carry clear, print 'Yes'
	lxi	d,no
	jmp	bdos	; Otherwise, print 'No'
yes:	db	'Yes$'
no:	db	'No$'


	.model small
	.stack 1024

        .data

        ;no data needed

	.code

start:
	mov ax,@code
        mov ds,ax

	call PRIMM
	BYTE "Exit program and return to MS-DOS? (Y/N)",0

	mov ax,0C00h
	int 21h			;flush keyboard buffer

forever:
	call waitKey
	;returns ASCII code in AL

	and AL,11011111b         ;ignore case
	cmp al,"Y"
	jz ReturnToMSDOS

	cmp al,"N"
	jz forever
	;normally this would jump somewhere else but for simplicity it will wait
	;for a yes response.
	jnz forever

ReturnToMSDOS:
	mov ax,0C00h
	int 21h			  ;flush keyboard buffer

	mov ax,4C00h
	int 21h			  ;end program
;-------------------------------------------------------------------
;  SUBROUTINES
;-------------------------------------------------------------------
waitKey:
	mov ah,01h
	int 16h
	jz waitKey
	ret
	;waits until a key is pressed.
	;return:
	; AL = ASCII CODE
	; AH = SCAN CODE (???)

;-------------------------------------------------------------------
PrintString:			;Print null-terminated strings
;input: string address = ds:si

	lodsb			;Load a letter
	cmp al,0		;Was that letter the terminator?
	jz PrintString_Done	;Yes? then RET
	call PrintChar		;Print to screen
	jmp PrintString		;Repeat
PrintString_Done:
	ret
;-------------------------------------------------------------------
PrintChar:
	push ax
		mov ah,0Eh
		int 10h			;print AL to the screen.
	pop ax
	ret
;-------------------------------------------------------------------

PrintSpace:
	mov al,' '
	jmp PrintChar	;JMP avoids a tail call.
	;ret		;"PrintChar"'s ret will do this for us.

;-------------------------------------------------------------------
NewLine:
	push dx
	push ax
		mov	ah, 02h
		mov	dl, 13	;CR
		int	21h
		mov	dl, 10	;LF
		int	21h
	pop ax
	pop dx
	ret
;-------------------------------------------------------------------
PRIMM:
	pop si
	push ax
	;get return address in si, this is the source offset for
	;the string that will be printed.
	;String must be null terminated.
	          call PrintString
	pop ax
	push si
	;PrintString adjusts the return address for us, it is now
	;just after the null terminator. So put it back on the stack.
	ret

;-------------------------------------------------------------------

	end start


\ get a yes or no response from the keyboard
: yes-no
	con:key $20 bor
	dup 'y n:= if ;; then
	dup 'n n:= if ;; then
	drop yes-no ;
: no? 'n n:= if "No" else "Yes" then . ;

"Yes or no? " con:print  yes-no no?
cr bye


Loop, 200  ; loop 200 times while not paused
{
  TrayTip, counting, %A_Index% press alt-p to pause
  Sleep, 1000
}

!p::  ; links alt-p key combination to the method pauseme() (system wide)
  pauseMe()
Return

!r::  ; links alt-r key combination to the method resume()  (system wide)
  resume()
Return

pauseMe()
{
  MsgBox, pausing`, press alt-r to resume
  Pause
}

resume()
{
  TrayTip, resume, resuming, 2
  Pause, off
}


PROC MAIN()
 Byte Key=764

 Printe("Press Y or N to continue")

 key=255

 Do
  Until Key=43 or Key=35
 Od

 Print("You pressed ")
 If Key=43 then Printe("Yes") Fi
 If Key=35 then Printe("No ") Fi

RETURN


   function Yes_Or_No (Prompt : String := "Your answer (Y/N): ") return Boolean is
      Answer : Character;
   begin
      Ada.Text_IO.Put (Prompt);
      loop
         Ada.Text_IO.Get_Immediate (Answer);
         case Answer is
            when 'Y'|'y' => return True;
            when 'N'|'n' => return False;
            when others  => null;
         end case;
      end loop;
   end Yes_Or_No;


Loop, {
	Input, Key, L1
	if (Key = "n" || Key = "y")
		break
}
MsgBox, % "The response was """ Key """."
ExitApp


# syntax: GAWK -f KEYBOARD_INPUT_OBTAIN_A_Y_OR_N_RESPONSE.AWK
BEGIN {
    printf("you entered %s\n",prompt_user())
    exit(0)
}
function prompt_user(  rec) {
# AWK lacks the ability to get keyboard input without pressing the enter key.
    while (1) {
      printf("enter Y or N ")
      getline rec <"con"
      gsub(/ /,"",rec) # optional
      if (rec ~ /^[nyNY]$/) {
        break
      }
    }
    return(rec)
}


      *KEY 1 |!|A
      *KEY 2 |!|B
      REPEAT
        key% = INKEY(1)
        CASE key% OF
          WHEN &81: PROCmethod1
          WHEN &82: PROCmethod2
        ENDCASE
      UNTIL FALSE
      END

      DEF PROCmethod1
      PRINT "You pressed F1"
      ENDPROC

      DEF PROCmethod2
      PRINT "You pressed F2"
      ENDPROC


#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>

int main()
{
  Display *d;
  XEvent event;

  d = XOpenDisplay(NULL);
  if ( d != NULL ) {
                /* or simply XK_F7 should work too */
    XGrabKey(d, XKeysymToKeycode(d, XStringToKeysym("F7")),
	     Mod1Mask, /* normally it's Alt */
	     DefaultRootWindow(d), True, GrabModeAsync, GrabModeAsync);
    XGrabKey(d, XKeysymToKeycode(d, XStringToKeysym("F6")),
	     Mod1Mask,
	     DefaultRootWindow(d), True, GrabModeAsync, GrabModeAsync);

    for(;;)
    {
      XNextEvent(d, &event);
      if ( event.type == KeyPress ) {
	KeySym s = XLookupKeysym(&event.xkey, 0);
	if ( s == XK_F7 ) {
	  printf("something's happened\n");
	} else if ( s == XK_F6 ) {
	  break;
	}
      }
    }

    XUngrabKey(d, XKeysymToKeycode(d, XStringToKeysym("F7")), Mod1Mask, DefaultRootWindow(d));
    XUngrabKey(d, XKeysymToKeycode(d, XStringToKeysym("F6")), Mod1Mask, DefaultRootWindow(d));
  }
  return EXIT_SUCCESS;
}


(ns hello-seesaw.core
  (:use seesaw.core))

(defn -main [& args]
  (invoke-later
    (-> (frame
           :listen [:key-pressed (fn [e] (println (.getKeyChar e) " key pressed"))]
           :on-close :exit)
     pack!
     show!)))


While getKey(0)
End

While 1
If getKey(15)
 Disp "N",i
 Return
ElseIf getKey(54)
 Disp "Y",i
 Return
End
End


10  LET C =  PEEK (49168): REM CLEAR KEYBOARD
20  PRINT "PRESS Y OR N TO CONTINUE"
30  GET K$
40  IF K$ <  > "Y" AND K$ <  > "N" THEN 30
50  PRINT "THE RESPONSE WAS ";K$


@echo off
choice
if errorlevel 2 echo You chose N
if errorlevel 1 echo You chose Y
>nul pause


#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>

void set_mode(int want_key)
{
	static struct termios old, new;
	if (!want_key) {
		tcsetattr(STDIN_FILENO, TCSANOW, &old);
		return;
	}

	tcgetattr(STDIN_FILENO, &old);
	new = old;
	new.c_lflag &= ~(ICANON);
	tcsetattr(STDIN_FILENO, TCSANOW, &new);
}

int get_key(int no_timeout)
{
	int c = 0;
	struct timeval tv;
	fd_set fs;
	tv.tv_usec = tv.tv_sec = 0;

	FD_ZERO(&fs);
	FD_SET(STDIN_FILENO, &fs);

	select(STDIN_FILENO + 1, &fs, 0, 0, no_timeout ? 0 : &tv);
	if (FD_ISSET(STDIN_FILENO, &fs)) {
		c = getchar();
		set_mode(0);
	}
	return c;
}

int main()
{
	int c;
	while(1) {
		set_mode(1);
		while (get_key(0)); /* clear buffer */
		printf("Prompt again [Y/N]? ");
		fflush(stdout);

		c = get_key(1);
		if (c == 'Y' || c == 'y') {
			printf("\n");
			continue;
		}

		if (c == 'N' || c == 'n') {
			printf("\nDone\n");
			break;
		}

		printf("\nYes or no?\n");
	}

	return 0;
}


program Key_Bindings_test;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Winapi.Windows,
  Messages,
  Classes;

type
  // Class of application without window
  TWindowlessApplication = class
  private
    Terminated: Boolean;
    F7_id: Word;
    F6_id: Word;
    WIN_A: Word;
    procedure HandleMessage;
  public
    Handle: THandle;
    constructor Create;
    destructor Destroy;
    procedure Run;
  end;

{ TWindowlessApplication }

constructor TWindowlessApplication.Create;
begin
  // Allocate handle to receve a mensages
  Handle := CreateWindowEx(WS_EX_TOOLWINDOW, 'TWindowlessApplication', '',
    WS_POPUP, 0, 0, 0, 0, 0, 0, HInstance, nil);

  // Set the key bind for WIN+A, F6 and F7
  WIN_A := GlobalAddAtom('Hotkey_WIN_A');
  F6_id := GlobalAddAtom('Hotkey_F6');
  F7_id := GlobalAddAtom('Hotkey_F7');

  RegisterHotKey(Handle, WIN_A, MOD_WIN, ord('A'));
  RegisterHotKey(Handle, F6_id, 0, VK_F6);
  RegisterHotKey(Handle, F7_id, 0, VK_F7);

  // Set flag to keep running application
  Terminated := false;
end;

destructor TWindowlessApplication.Destroy;
begin
  // Remove key bind
  UnRegisterHotKey(Handle, WIN_A);
  UnRegisterHotKey(Handle, F6_id);
  UnRegisterHotKey(Handle, F7_id);

  GlobalDeleteAtom(WIN_A);
  GlobalDeleteAtom(F6_id);
  GlobalDeleteAtom(F7_id);

  // Deallocate handle
  DeallocateHWnd(Handle);
end;

procedure TWindowlessApplication.Run;
begin
  // Application loop
  repeat
    // Deal with new messages
    HandleMessage();
  until Terminated;
end;

procedure TWindowlessApplication.HandleMessage;
var
  Msg: TMsg;
begin
  // Check for new messages
  if PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then
  begin
    // Extract it
    PeekMessageW(Msg, 0, 0, 0, PM_REMOVE);

    // Check if Msg is a HOTKEY mensage
    if Msg.message = WM_HOTKEY then
    begin
      // Check if the hotkey is for Win+A
      if Msg.wParam = WIN_A then
      begin
        // Report and terminate
        writeln('Win + A pressed !'#10);
        writeln('Bye bye');
        Terminated := true;
      end;

      // Check if the hotkey is for F6
      if Msg.wParam = F6_id then
      begin
        // Report and terminate
        writeln('F6 pressed !');
      end;

      // Check if the hotkey is for F7
      if Msg.wParam = F7_id then
      begin
        // Report and terminate
        writeln('F7 pressed !');
      end;
    end;
  end;
end;

var
  App: TWindowlessApplication;

begin
  App := TWindowlessApplication.Create;
  Writeln('Waiting user press F6 ou F7, then press WIN+A for terminate');
  App.Run;
  App.Destroy;
  readln;
end.


using System;

namespace Y_or_N
{
    class Program
    {
        static void Main()
        {
            bool response = GetYorN();
        }

        static bool GetYorN()
        {
            ConsoleKey response; // Creates a variable to hold the user's response.

            do
            {
                while (Console.KeyAvailable) // Flushes the input queue.
                    Console.ReadKey();

                Console.Write("Y or N? "); // Asks the user to answer with 'Y' or 'N'.
                response = Console.ReadKey().Key; // Gets the user's response.
                Console.WriteLine(); // Breaks the line.
            } while (response != ConsoleKey.Y && response != ConsoleKey.N); // If the user did not respond with a 'Y' or an 'N', repeat the loop.

             /*
              * Return true if the user responded with 'Y', otherwise false.
              *
              * We know the response was either 'Y' or 'N', so we can assume
              * the response is 'N' if it is not 'Y'.
              */
            return response == ConsoleKey.Y;
        }
    }
}


#include <conio.h>
#include <iostream>

using namespace std;

int main()
{
	char ch;
	_cputs( "Yes or no?" );
	do
	{
		ch = _getch();
		ch = toupper( ch );
	} while(ch!='Y'&&ch!='N');

	if(ch=='N')
	{
		cout << "You said no" << endl;
	}
	else
	{
		cout << "You said yes" << endl;
	}
	return 0;
}


package main

/*
#cgo LDFLAGS: -lX11
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>

static inline Window DefaultRootWindow_macro(Display *dpy) {
    return ScreenOfDisplay(dpy, DefaultScreen(dpy))->root;
}

static inline int getXEvent_type(XEvent event) {
    return event.type;
}

static inline XKeyEvent getXEvent_xkey(XEvent event) {
    return event.xkey;
}
*/
import "C"
import "fmt"
import "unsafe"

func main() {
    d := C.XOpenDisplay(nil)
    f7, f6 := C.CString("F7"), C.CString("F6")
    defer C.free(unsafe.Pointer(f7))
    defer C.free(unsafe.Pointer(f6))

    if d != nil {
        C.XGrabKey(d, C.int(C.XKeysymToKeycode(d, C.XStringToKeysym(f7))),
            C.Mod1Mask, /* normally it's Alt */
            C.DefaultRootWindow_macro(d), C.True, C.GrabModeAsync, C.GrabModeAsync)
        C.XGrabKey(d, C.int(C.XKeysymToKeycode(d, C.XStringToKeysym(f6))),
            C.Mod1Mask,
            C.DefaultRootWindow_macro(d), C.True, C.GrabModeAsync, C.GrabModeAsync)

        var event C.XEvent
        for {
            C.XNextEvent(d, &event)
            if C.getXEvent_type(event) == C.KeyPress {
                xkeyEvent := C.getXEvent_xkey(event)
                s := C.XLookupKeysym(&xkeyEvent, 0)
                if s == C.XK_F7 {
                    fmt.Println("something's happened")
                } else if s == C.XK_F6 {
                    break
                }
            }
        }

        C.XUngrabKey(d, C.int(C.XKeysymToKeycode(d, C.XStringToKeysym(f7))), C.Mod1Mask, C.DefaultRootWindow_macro(d))
        C.XUngrabKey(d, C.int(C.XKeysymToKeycode(d, C.XStringToKeysym(f6))), C.Mod1Mask, C.DefaultRootWindow_macro(d))
    } else {
        fmt.Println("XOpenDisplay did not succeed")
    }
}


(defun rosetta-y-or-n ()
  (clear-input *query-io*)
  (y-or-n-p))


import std.stdio: stdout, write, writefln;

extern (C) nothrow {
    void _STI_conio();
    void _STD_conio();
    int kbhit();
    int getch();
}

void main() {
    _STI_conio();
    write("Enter Y or N: ");
    stdout.flush();

    int c;
    do {
        while(!kbhit()) {}
        c = getch();

        // Visual feedback for each keypress.
        write(cast(char)c);
        stdout.flush();
    } while(c != 'Y' && c != 'y' && c != 'N' && c != 'n');

    writefln("\nResponse: %c", cast(char)c);
    _STD_conio();
}


program Obtain_a_Y_or_N_response;

{$APPTYPE CONSOLE}

uses
  System.Console;

function GetKey(acepted: string): Char;
var
  key: Char;
begin
  while True do
  begin
    if Console.KeyAvailable then
    begin
      key := UpCase(Console.ReadKey().KeyChar);
      if pos(key, acepted) > 0 then
        exit(key);
    end;
  end;
  Result := #0; // Never Enter condition
end;

begin
  Console.WriteLine('Press Y or N');
  case GetKey('YN') of
    'Y':
      Console.WriteLine('You pressed Yes');
    'N':
      Console.WriteLine('You pressed No');
  else
    Console.WriteLine('We have a error');
  end;
  Readln;
end.


V 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)]

V MAXWT = 15.0

V sorted_items = sorted(items.map((name, amount, value) -> (value / amount, amount, name)), reverse' 1B)
V wt = 0.0
V val = 0.0
[(String, Float, Float)] bagged

L(unit_value, amount, name) sorted_items
   V portion = min(MAXWT - wt, amount)
   wt += portion
   V addval = portion * unit_value
   val += addval
   bagged [+]= (name, portion, addval)
   I wt >= MAXWT
      L.break

print(‘    ITEM   PORTION VALUE’)
print(bagged.map((n, p, a) -> ‘#10 #3.2 #3.2’.format(n, p, a)).join("\n"))
print("\nTOTAL WEIGHT: #2.2\nTOTAL VALUE: #2.2".format(wt, val))


! bound to application
   CALL F2
   ! ...
 END

SUBROUTINE F2 ! this text shows as tooltip text. F2 ... F9 are possible
   !  synchronous call:     CALL F2
   ! asynchronous calls:    F2 key
   !                        mouse click on the F2 toolbar tool
   !                        ALARM( delay_seconds, 2 )

   ! check if a modifier key is pressed, or a lock key is activated to control program flow:
   KEY(SHift=shft, Control=cntl, ALt=alt, CApital=caps, Numlock=num, SCRoll=scrl)
   WRITE(ClipBoard, Name) shft, cntl, alt, caps, num, scrl
   ! shft=1; cntl=2; alt=4; caps=8; num=16; scrl=32;
   ! is copied to clipboard if all 6 keys are activated and the F2 tool is clicked

   ! Alarm methods F2 ... F9 suspend program flow, which is resumed when finished
   ! If Fn is running and Fm is called:
   !       Fn is suspended if m > n AND n <= 5, else Fm is queued
   ! ...
END


global kMap

procedure main()
    kMap := table()
    kMap["1"] := italicsOn
    kMap["2"] := italicsOff
    kMap["\x4"] := exit    # ^D terminates
    while writes(exec(getch()))
end

procedure exec(c)
    return (\kMap[c])() | c
end

procedure italicsOn()
    return "<i>"
end

procedure italicsOff()
    return "<\\i>"
end


package keybord.macro.demo;

import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

class KeyboardMacroDemo {
    public static void main( String [] args ) {
        final JFrame frame = new JFrame();

        String directions = "Ctrl-S to show frame title
"
                                 +"Ctrl-H to hide it";

        frame.add( new JLabel(directions));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.addKeyListener( new KeyAdapter(){
            public void keyReleased( KeyEvent e ) {
                if( e.isControlDown() && e.getKeyCode() == KeyEvent.VK_S){
                    frame.setTitle("Hello there");
                }else if( e.isControlDown() && e.getKeyCode() == KeyEvent.VK_H){
                    frame.setTitle("");
                }
            }
        });
        frame.pack();
        frame.setVisible(true);
    }
}


handler YesOrNoHandler type RUIhandler{initialUI =[ui], onConstructionFunction = start}

    ui Div { };

    const KEY_N int = 78;
    const KEY_Y int = 89;

    function start()
    	document.onKeyDown = d_onKeyDown;
    end

    function d_onKeyDown(e Event in)

	case (e.ch)
  	    when (KEY_N)
	        ui.innerText = "N pressed.";
	    when (KEY_Y)
	        ui.innerText = "Y pressed.";
	end

	e.preventDefault();

    end

end


import Char
import Graphics.Element exposing (Element, empty, show)
import Keyboard

view : Int -> Element
view keyCode =
  let
    char =
      Char.fromCode keyCode

    showChar =
      toString >> ((++) "The last (y/n) key pressed was: ") >> show
  in
    case char of
      'n' ->
        showChar char

      'y' ->
        showChar char

      _ ->
        empty

main : Signal Element
main =
  Signal.map view Keyboard.presses


!$KEY
................
! flush the keyboard buffer
! --------------------------------
! you can use POKE(198,0) in C-64
! ERRE version
! --------------------------------
REPEAT
  GET(K$)
UNTIL K$=""

PRINT("Press Y or N to continue")
REPEAT
  GET(K$)
UNTIL INSTR("YyNn",K$)<>0
!
! with C-64 you must write a line like
! UNTIL K$="Y" OR K$="N"
!

PRINT("The response was ";K$)
.................


integer key

puts(1,"Your answer? (Y/N)\n")
while get_key()!=-1 do
end while

while 1 do
    key = get_key()
    if key!=-1 and (key = 'Y' or key = 'y' or key = 'N' or key = 'n') then
        exit
    end if
end while

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


with Ada.Text_IO;
with Ada.Float_Text_IO;
with Ada.Strings.Unbounded;

procedure Knapsack_Continuous is
   package US renames Ada.Strings.Unbounded;

   type Item is record
      Name   : US.Unbounded_String;
      Weight : Float;
      Value  : Positive;
      Taken  : Float;
   end record;

   function "<" (Left, Right : Item) return Boolean is
   begin
      return Float (Left.Value) / Left.Weight <
             Float (Right.Value) / Right.Weight;
   end "<";

   type Item_Array is array (Positive range <>) of Item;

   function Total_Weight (Items : Item_Array) return Float is
      Sum : Float := 0.0;
   begin
      for I in Items'Range loop
         Sum := Sum + Items (I).Taken;
      end loop;
      return Sum;
   end Total_Weight;

   function Total_Value (Items : Item_Array) return Float is
      Sum : Float := 0.0;
   begin
      for I in Items'Range loop
         Sum := Sum + Float (Items (I).Value) / Items(I).Weight * Items (I).Taken;
      end loop;
      return Sum;
   end Total_Value;

   procedure Solve_Knapsack_Continuous
     (Items        : in out Item_Array;
      Weight_Limit : Float)
   is
   begin
      -- order items by value per weight unit
      Sorting : declare
         An_Item : Item;
         J       : Natural;
      begin
         for I in Items'First + 1 .. Items'Last loop
            An_Item := Items (I);
            J       := I - 1;
            while J in Items'Range and then Items (J) < An_Item loop
               Items (J + 1) := Items (J);
               J             := J - 1;
            end loop;
            Items (J + 1) := An_Item;
         end loop;
      end Sorting;
      declare
         Rest : Float := Weight_Limit;
      begin
         for I in Items'Range loop
            if Items (I).Weight <= Rest then
               Items (I).Taken := Items (I).Weight;
            else
               Items (I).Taken := Rest;
            end if;
            Rest := Rest - Items (I).Taken;
            exit when Rest <= 0.0;
         end loop;
      end;
   end Solve_Knapsack_Continuous;
    All_Items : Item_Array :=
     ((US.To_Unbounded_String ("beef"), 3.8, 36, 0.0),
      (US.To_Unbounded_String ("pork"), 5.4, 43, 0.0),
      (US.To_Unbounded_String ("ham"), 3.6, 90, 0.0),
      (US.To_Unbounded_String ("greaves"), 2.4, 45, 0.0),
      (US.To_Unbounded_String ("flitch"), 4.0, 30, 0.0),
      (US.To_Unbounded_String ("brawn"), 2.5, 56, 0.0),
      (US.To_Unbounded_String ("welt"), 3.7, 67, 0.0),
      (US.To_Unbounded_String ("salami"), 3.0, 95, 0.0),
      (US.To_Unbounded_String ("sausage"), 5.9, 98, 0.0));

begin
   Solve_Knapsack_Continuous (All_Items, 15.0);
   Ada.Text_IO.Put ("Total Weight: ");
   Ada.Float_Text_IO.Put (Total_Weight (All_Items), 0, 2, 0);
   Ada.Text_IO.New_Line;
   Ada.Text_IO.Put ("Total Value:  ");
   Ada.Float_Text_IO.Put (Total_Value (All_Items), 0, 2, 0);
   Ada.Text_IO.New_Line;
   Ada.Text_IO.Put_Line ("Items:");
   for I in All_Items'Range loop
      if All_Items (I).Taken > 0.0 then
         Ada.Text_IO.Put ("   ");
         Ada.Float_Text_IO.Put (All_Items (I).Taken, 0, 2, 0);
         Ada.Text_IO.Put_Line (" of " & US.To_String (All_Items (I).Name));
      end if;
   end loop;
end Knapsack_Continuous;


document.onkeydown = function(evt) {
  if (evt.keyCode === 118) {
    alert("You pressed F7!");
    return false;
  }
}


using Gtk

function keypresswindow()
    tcount = 0
    txt = "Press a Number Key"
    win = GtkWindow("Keyboard Macros Test", 300, 50) |> (GtkFrame() |> ((vbox = GtkBox(:v)) |> (lab = GtkLabel(txt))))
    function keycall(w, event)
        ch = Char(event.keyval)
        if isdigit(ch)
            set_gtk_property!(lab, :label, "Keyboard Macro Number $ch Invoked.")
        end
    end
    signal_connect(keycall, win, "key-press-event")

    cond = Condition()
    endit(w) = notify(cond)
    signal_connect(endit, win, :destroy)
    showall(win)
    wait(cond)
end

keypresswindow()


// version 1.2.31

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

fun main(args: Array<String>) {
    val directions = "Ctrl-S to show frame title
" +
                     "Ctrl-H to hide it"
    with (JFrame()) {
        add(JLabel(directions))
        defaultCloseOperation = JFrame.EXIT_ON_CLOSE
        addKeyListener(object : KeyAdapter() {
            override fun keyReleased(e: KeyEvent) {
                if (e.isControlDown() && e.keyCode == KeyEvent.VK_S)
                    title = "Hello there"
                 else if( e.isControlDown() && e.keyCode == KeyEvent.VK_H)
                    title = ""
            }
        })
        pack()
        isVisible = true
    }
}


Module CheckIt {
      \\ Scan statement exist from version 1
      \\ We can make targets and use function keys, in console
      \\ Scan track mouse click on targets and functions keys state
      \\ when any of these selected then a call to a global module happen
      \\ show$(hide$("&8%", "master",3), "code1", 10)="123"
      Global a$
      Module Global GetIt {
                  Input "Password:"; a$
                  if a$<>"" then a$<=show$(hide$(a$, "code1", 10), "master", 3)
      }
      Module Global myHelp {
            Print "Press F1 for help, F3 to enter password, F5 exit"
      }
      Fkey 1, "myHelp"
      Fkey 3, "GetIt"
      Fkey 5, {a$="---"}
      myHelp
      tries=0
      Repeat {
            Scan .1
            if a$="---" then 1000
            if a$="&8%" then Exit
            if a$<>"" then tries++ : if tries>2 then 1000
            a$<=""
      } Always
      Print "Enter ok"

      1000 Print "Exit ", tries : End
}
Checkit


open System

let rec yorn () =
    let rec flush () = if Console.KeyAvailable then ignore (Console.ReadKey()); flush ()
    flush ()

    printf "\nY or N? "
    match Console.ReadKey().Key with
    | ConsoleKey.Y -> 'Y'
    | ConsoleKey.N -> 'N'
    | _ -> yorn()

printfn "\nYour choice: %c" (yorn())


: flush ( -- )  \ discard pending input
  begin key? while key drop repeat ;

: y-or-n ( c-addr u -- f )
  flush begin
    cr 2dup type key bl or                  \ note 1.
    dup [char] y = swap [char] n = over or  \ note 2.
    if nip nip exit then
  drop again ;

\ Note 1. KEY BL OR returns a lowercase letter in the case that an
\ uppercase letter was entered, an unchanged lowercase letter in the
\ case that a lowercase letter was entered, and garbage otherwise.  BL
\ returns the ASCII code for a space, 32, which is incidentally the
\ "bit of difference" between ASCII uppercase and lowercase letters.

\ Note 2. this line has the stack effect ( x -- f1 f2 ), where F1 is
\ true only if x='y', and F2 is true only if x='y' OR if x='n'.

\ I think these expressions aren't too clever, but they _are_ rather
\ optimized for the task at hand.  This might be more conventional:

: y-or-n ( c-addr u -- f )
  flush begin
    cr 2dup type key case
      [char] y of 2drop true  exit endof
      [char] Y of 2drop true  exit endof
      [char] n of 2drop false exit endof
      [char] N of 2drop false exit endof
  endcase again ;


      CHARACTER*120 FUNCTION REPLY(QUERY)    !Obtain a text in reply.
Concocted by R.N.McLean (whom God preserve), December MM.
       CHARACTER*(*) QUERY	!The question.
       CHARACTER*120 TEXT	!Alas, oh for proper strings.
       INTEGER MSG,KEYS,LSTNB	!Let's hope everyone has the same type.
       COMMON /IOUNITS/ MSG,KEYS!Orifices.
        WRITE (MSG,1) QUERY(1:LSTNB(QUERY)),"?"!So, splurt.
    1   FORMAT (2A,$)		!A trailing text literal may not be rolled.
        READ (KEYS,1) TEXT	!Dare not use REPLY itself. Some implementations bungle.
        REPLY = TEXT		!So, shuffle.
       RETURN			!Take that.
      END 			!Others interpret the reply.

      REAL*8 FUNCTION REPLYN(QUERY)	!Obtain a number in reply.
Concocted by R.N.McLean (whom God preserve), December MM.
       CHARACTER*(*) QUERY	!The question.
       REAL X			!The answer, presumably not 42.
       INTEGER MSG,KEYS,LSTNB	!Let's hope everyone has the same type.
       COMMON /IOUNITS/ MSG,KEYS!Orifices.
    1   WRITE (MSG,2) QUERY(1:LSTNB(QUERY))	!No trailing spaces.
    2   FORMAT (A,$)		!The $ obviously suppresses the newline.
        READ (KEYS,*,ERR = 3) X	!Presume adequate testing for now.
        REPLYN = X		!The value!
       RETURN			!All done.
    3   WRITE (MSG,4)		!Or perhaps not.
    4   FORMAT ('Distasteful number. Try again...')	!All sorts of ways.
        GO TO 1			!My patience is unconditional.
      END			!One way or another, a number will be secured.

      LOGICAL FUNCTION YEA(QUERY)	!Obtain a Yes in reply?
Concocted by R.N.McLean (whom God preserve), December MM.
       CHARACTER*(*) QUERY	!The question.
       CHARACTER*120 WHAT,REPLY	!Quite so.
       CHARACTER*1 C		!Scratchpad.
       INTEGER MSG,KEYS		!Let's hope everyone has the same type.
       COMMON /IOUNITS/ MSG,KEYS!Orifices.
       INTEGER L		!A finger.
    1   WHAT = REPLY(QUERY)	!So, get an answer.
        DO L = 1,LEN(WHAT)	!Sigh. Oh for Trim(string)
          C = WHAT(L:L)		!Sniff a CHARACTER.
          IF (C .NE. ' ') GO TO 10	!A starter?
        END DO			!No. Try further on.
        WRITE (MSG,2)		!Surely not.
    2   FORMAT ('All blank?')	!Poke.
    3   WRITE (MSG,4) 		!Sigh.
    4   FORMAT ('I dig it not. Try Yes/Si/Da/Oui/Ja, or No')
        GO TO 1			!Get it right, this time?
   10   IF (INDEX('YySsDdOoJj',C) .GT. 0) THEN	!Yes/Si/Da/Oui/Ja...
          YEA = .TRUE.		!A decision.
        ELSE IF (INDEX('Nn',C) .GT. 0) THEN	!No,No,Nyet,Non...
          YEA = .FALSE.		!Even if negative.
        ELSE			!But if unrecognised,
          GO TO 3		!Try again.
        END IF			!So much for choices.
       RETURN			!Pass the word.
      END			!Enough of yes-beings.
      LOGICAL FUNCTION NAY(QUERY)	!Perhaps this reads better.
Concocted by R.N.McLean (whom God preserve), December MM.
       CHARACTER*(*) QUERY	!The question.
       LOGICAL YEA		!Let us hope so.
        NAY = .NOT.YEA(QUERY)	!Straightforward.
       RETURN			!Pass the inverted word.
      END			!So much for naysayers.


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


      INSTALL @lib$+"SORTSALIB"
      Sort% = FN_sortSAinit(1, 0) : REM Descending

      nItems% = 9
      maxWeight = 15.0

      DIM items{(nItems%-1) name$, weight, price, worth}
      FOR item% = 0 TO nItems%-1
        READ items{(item%)}.name$, items{(item%)}.weight, items{(item%)}.price
        items{(item%)}.worth = items{(item%)}.price / items{(item%)}.weight
      NEXT

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

      C% = nItems% : D% = 0
      CALL Sort%, items{()}, items{(0)}.worth

      TotalWeight = 0
      TotalPrice = 0
      FOR i% = 0 TO nItems%-1
        IF TotalWeight + items{(i%)}.weight < maxWeight THEN
          TotalWeight += items{(i%)}.weight
          TotalPrice += items{(i%)}.price
          PRINT "Take all the " items{(i%)}.name$
        ELSE
          weight = maxWeight - TotalWeight
          price = weight * items{(i%)}.worth
          TotalWeight += weight
          TotalPrice += price
          PRINT "Take "; weight " kg of " items{(i%)}.name$
          EXIT FOR
        ENDIF
      NEXT

      PRINT '"Total weight = " ; TotalWeight " kg"
      PRINT "Total price  = " ; TotalPrice
      END


SetOptions[EvaluationNotebook[], NotebookEventActions -> {{"KeyDown", "t"} :> Print["You pressed \"t\""]}]


import tables

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

type

  MacroProc = proc(app: App)
  MacroTable = Table[int, MacroProc]  # Mapping key values -> procedures.

  App = ref object of Application
    dispatchTable: MacroTable
    label: Label

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

proc addMacro(app: App; ch: char; macroProc: MacroProc) =
  ## Assign a procedure to a key.
  ## If the key is already assigned, nothing is done.
  let keyval = ord(ch)
  if keyval notin app.dispatchTable:
    app.dispatchTable[keyval] = macroProc

#---------------------------------------------------------------------------------------------------
# Macro procedures.

proc proc1(app: App) =
  app.label.setText("You called macro 1")

proc proc2(app: App) =
  app.label.setText("You called macro 2")

proc proc3(app: App) =
  app.label.setText("You called macro 3")

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

proc onKeyPress(window: ApplicationWindow; event: Event; app: App): bool =
  var keyval: int
  if not event.getKeyval(keyval): return false
  if keyval in app.dispatchTable:
    app.dispatchTable[keyval](app)
  result = true

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

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

  app.addMacro('1', proc1)
  app.addMacro('2', proc2)
  app.addMacro('3', proc3)

  let window = app.newApplicationWindow()
  window.setTitle("Keyboard macros")

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

  app.label = newLabel()
  app.label.setWidthChars(18)
  vbox.packStart(app.label, true, true, 5)

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

  window.showAll()

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

let app = newApplication(App, "Rosetta.KeyboardMacros")
discard app.connect("activate", activate)
discard app.run()


declare
  [QTk] = {Module.link ['x-oz://system/wp/QTk.ozf']}
  Label
  Window = {QTk.build td(label(text:"Hello" handle:Label))}
in
  {Window bind(event:"<Control-x><Control-s>"
	       action:proc {$}
			 {Label set(text:"This is not Emacs.")}
		      end
	      )}
  {Window bind(event:"<Control-x><Control-c>"
	       action:toplevel#close
	      )}
  {Window show}


use strict;
use warnings;
use Term::ReadKey;

ReadMode 4; # change to raw input mode

sub logger { my($message) = @_; print "$message\n" }

while (1) {
    if (my $c = ReadKey 0) { # read a single character
        if ($c eq 'q') { logger "QUIT"; last }
        elsif ($c =~ /\n|\r/) { logger "CR" }
        elsif ($c eq "j") { logger "down" }
        elsif ($c eq "k") { logger "up" }
        elsif ($c eq "h") { logger "left" }
        elsif ($c eq "l") { logger "right" }

        elsif ($c eq "J") { logger "DOWN" }
        elsif ($c eq "K") { logger "UP" }
        elsif ($c eq "H") { logger "LEFT" }
        elsif ($c eq "L") { logger "RIGHT" }

        elsif ($c eq "\e") { # handle a few escape sequences
            my $esc  = ReadKey 0;
               $esc .= ReadKey 0;
            if    ($esc eq "[A") { logger "up" }
            elsif ($esc eq "[B") { logger "down" }
            elsif ($esc eq "[C") { logger "right" }
            elsif ($esc eq "[D") { logger "left" }
            elsif ($esc eq "[5") { logger "page up" }
            elsif ($esc eq "[6") { logger "page down" }
            else { logger "Unrecognized escape: $esc"; }
        }

        else { logger "you typed: $c"; }
    }
}

ReadMode 0; # reset the terminal to normal mode


' FB 1.05.0 Win64

While InKey <> "" : Wend '' flush keyboard buffer
Print "Do you want to continue y/n : ";
Dim answer As String

Do
  answer = LCase(Inkey)
Loop Until answer = "y" OrElse answer = "n"

Print answer '' echo response to console
If answer = "y" Then
  Print "OK, continuing"
Else
  Print "OK, finishing"
End If

Sleep


void local fn DoDialog( ev as long )
  CFStringRef key

  select ( ev )
    case _windowKeyDown
      cls
      key = fn EventCharacters
      select ( lcase(key) )
        case @"y",@"n"
          printf @"You pressed the \"%@\" key",key
          DialogEventSetBool(YES)// we handled the event
      end select
  end select
end fn

subclass
window 1, @"Press \"Y\" or \"N\" keys", (0,0,550,400)

on dialog fn DoDialog

HandleEvents


if var.end=0 then
var.end=0
debug="Press the Y key or the N key to continue:"
endif
if pressed(Key.Y)and var.end=0 then
var.end=1
debug="You pressed the Y key."
endif
if pressed(Key.N)and var.end=0 then
var.end=1
debug="You pressed the N key."
endif


package main

import (
    "log"

    gc "code.google.com/p/goncurses"
)

func main() {
    s, err := gc.Init()
    if err != nil {
        log.Fatal("init:", err)
    }
    defer gc.End()
    var k gc.Key
    for {
        gc.FlushInput()
        s.MovePrint(20, 0, "Press y/n ")
        s.Refresh()
        switch k = s.GetChar(); k {
        default:
            continue
        case 'y', 'Y', 'n', 'N':
        }
        break
    }
    s.Printf("\nThanks for the %c!\n", k)
    s.Refresh()
    s.GetChar()
}


( ( fixed    {function to convert a rational number to fixed point notation.
                            The second argument is the number of decimals. }
  =   value decimals powerOf10
    .   !arg:(?value.?decimals)
      & 10^!decimals:?powerOf10
      &   str
        $ ( div$(!value.1)
            "."
              mod
            $ (div$(!value+1/2*!powerOf10^-1.!powerOf10^-1).!powerOf10)
          )
  )
&     (beef.38/10.36)
      (pork.54/10.43)
      (ham.36/10.90)
      (greaves.24/10.45)
      (flitch.40/10.30)
      (brawn.25/10.56)
      (welt.37/10.67)
      (salami.30/10.95)
      (sausage.59/10.98)
  : ?items
& 0:?sorteditems
&   whl
  ' ( !items:(?name.?mass.?price) ?items
    & (!mass*!price^-1.!mass.!name)+!sorteditems:?sorteditems
    )
& 0:?totalMass
& :?stolenItems
&   whl
  ' ( !sorteditems:(?massPerPriceunit.?mass.?name)+?sorteditems
    &   (!mass.!massPerPriceunit.!name) !stolenItems
      : ?stolenItems
    & !mass+!totalMass:?totalMass:~>15
    )
& !stolenItems:(?mass.?massPerPriceunit.?name) ?stolenItems
& 15+!mass+-1*!totalMass:?mass
& (!mass.!massPerPriceunit.!name) !stolenItems:?stolenItems
& 0:?totalPrice
& (   !stolenItems
    :   ?
        ( (?mass.?massPerPriceunit.?name)
        & out$(fixed$(!mass.1) "kg of" !name)
        & !mass*!massPerPriceunit^-1+!totalPrice:?totalPrice
        & ~
        )
        ?
  | out$(fixed$(!totalPrice.2))
  )
);


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

struct item { double w, v; const char *name; } items[] = {
	{ 3.8, 36, "beef" },
	{ 5.4, 43, "pork" },
	{ 3.6, 90, "ham" },
	{ 2.4, 45, "greaves" },
	{ 4.0, 30, "flitch" },
	{ 2.5, 56, "brawn" },
	{ 3.7, 67, "welt" },
	{ 3.0, 95, "salami" },
	{ 5.9, 98, "sausage" },
};

int item_cmp(const void *aa, const void *bb)
{
	const struct item *a = aa, *b = bb;
	double ua = a->v / a->w, ub = b->v / b->w;
	return ua < ub ? -1 : ua > ub;
}

int main()
{
	struct item *it;
	double space = 15;

	qsort(items, 9, sizeof(struct item), item_cmp);
	for (it = items + 9; it---items && space > 0; space -= it->w)
		if (space >= it->w)
			printf("take all %s\n", it->name);
		else
			printf("take %gkg of %g kg of %s\n",
				space, it->w, it->name);

	return 0;
}


include pGUI.e

function C_Keyed(Ihandle /*ih*/, atom /*c*/)
-- (Note without K_c below this does not respond to 'c', just 'C')
    ?"you pressed C"
    return IUP_DEFAULT
end function

procedure F2_keyed()
    ?"you pressed F2"
end procedure

function key_cb(Ihandle /*ih*/, atom c)
    if c=K_F2 then F2_keyed()
    elsif c=K_ESC then return IUP_CLOSE
    end if
    return IUP_DEFAULT
end function

IupOpen()
Ihandle dlg = IupDialog(IupLabel("hello"),"TITLE=\"Press F2\"")
IupSetCallback(dlg, "K_C", Icallback("C_Keyed"))
--IupSetCallback(dlg, "K_c", Icallback("C_Keyed"))
IupSetCallback(dlg, "K_ANY", Icallback("key_cb"))
IupShow(dlg)
if platform()!=JS then
    IupMainLoop()
    IupClose()
end if


(load "@lib/led.l" "@lib/term.l")

(fkey *XtF1
   (prinl "Initialized value to " (setq *Number 1)) )

(fkey *XtUp
   (prinl "Incremented to " (inc '*Number)) )

(fkey *XtDown
   (prinl "Decremented to " (dec '*Number)) )

(fkey *XtHome
   (prinl "Current value is " *Number) )


#Win   = 0
#Demo1 = 0
#Demo2 = 1

If OpenWindow(#Win,50,50,200,60,"PureBasic",#PB_Window_SystemMenu)
  ;
  AddKeyboardShortcut(#Win,#PB_Shortcut_F1, #Demo1)
  AddKeyboardShortcut(#Win,#PB_Shortcut_F|#PB_Shortcut_Alt, #Demo2)
  ;
  Repeat
    WEvent = WaitWindowEvent()
    Select  WEvent
      Case #PB_Event_Menu
        Select EventMenu()
          Case #Demo1
            MessageRequester("Info", "You Pressed F1")

          Case #Demo2
            MessageRequester("Info", "You Pressed Alt-F")

        EndSelect
      Case #PB_Event_CloseWindow
        Break
    EndSelect
  ForEver
EndIf


10 IF INKEY$<>"" THEN GOTO 10: REM flush the keyboard buffer
20 PRINT "Press Y or N to continue"
30 LET k$ = INKEY$
40 IF k$ <> "y" AND k$ <> "Y" AND k$ <> "n" AND k$ <> "N" THEN GOTO 30
50 PRINT "The response was "; k$


using System;  //[email protected]
class Program
{
    static void Main()
    {
        Console.WriteLine(knapSack(15) + "\n");
        var sw = System.Diagnostics.Stopwatch.StartNew();
        for (int i = 1000; i > 0; i--) knapSack(15);
        Console.Write(sw.Elapsed); Console.Read();    // 0.60 µs
    }

    static string knapSack(double w1)
    {
        int k = w.Length; var q = new double[k];
        for (int i = 0; i < k; ) q[i] = v[i] / w[i++];
        var c = new double[k];
        Array.Copy(q, c, k); Array.Sort(c, w);
        Array.Copy(q, c, k); Array.Sort(c, v);
        Array.Sort(q, items);
        string str = "";
        for (k--; k >= 0; k--)
            if (w1 - w[k] > 0) { w1 -= w[k]; str += items[k] + "\n"; }
            else break;
        return w1 > 0 && k >= 0 ? str + items[k] : str;
    }

    static double[] w = { 3.8, 5.4, 3.6, 2.4, 4.0, 2.5, 3.7, 3.0, 5.9 },

                    v = { 36, 43, 90, 45, 30, 56, 67, 95, 98 };

    static string[] items = {"beef","pork","ham","greaves","flitch",
                             "brawn","welt","salami","sausage"};
}


#!/usr/bin/env python
import curses

def print_message():
    stdscr.addstr('This is the message.\n')

stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.keypad(1)

stdscr.addstr('CTRL+P for message or q to quit.\n')
while True:
    c = stdscr.getch()
    if c == 16: print_message()
    elif c == ord('q'): break

curses.nocbreak()
stdscr.keypad(0)
curses.echo()
curses.endwin()


#lang racket

(define-syntax-rule (with-raw body ...)
  (let ([saved #f])
    (define (stty x) (system (~a "stty " x)) (void))
    (dynamic-wind (λ() (set! saved (with-output-to-string (λ() (stty "-g"))))
                       (stty "raw -echo opost"))
                  (λ() body ...)
                  (λ() (stty saved)))))

(define (->bytes x)
  (cond [(bytes? x)  x]
        [(string? x) (string->bytes/utf-8 x)]
        [(not (list? x)) (error '->bytes "don't know how to convert: ~e" x)]
        [(andmap byte? x) (list->bytes x)]
        [(andmap char? x) (->bytes (list->string x))]))
(define (open x)
  (open-input-bytes (->bytes x)))

(define macros (make-vector 256 #f))
(define (macro-set! seq expansion)
  (let loop ([bs (bytes->list (->bytes seq))] [v (vector macros)] [i 0])
    (if (null? bs)
      (vector-set! v i expansion)
      (begin (unless (vector-ref v i) (vector-set! v i (make-vector 256 #f)))
             (loop (cdr bs) (vector-ref v i) (car bs))))))

;; Some examples
(macro-set! "\3" exit)
(macro-set! "ME" "Random J. Hacker")
(macro-set! "EMAIL" (λ() (open "ME <[email protected]>")))
(macro-set! "\r" "\r\n")
(macro-set! "\n" "\r\n")
(for ([c "ABCD"]) (macro-set! (~a "\eO" c) (~a "\e[" c)))

(with-raw
  (printf "Type away, `C-c' to exit...\n")
  (let loop ([inps (list (current-input-port))] [v macros] [pending '()])
    (define b (read-byte (car inps)))
    (if (eq? b eof) (loop (cdr inps) v pending)
        (let mloop ([m (vector-ref v b)])
          (cond [(vector? m) (loop inps m (cons b pending))]
                [(input-port? m) (loop (cons m inps) macros '())]
                [(or (bytes? m) (string? m))
                 (display m) (flush-output) (loop inps macros '())]
                [(procedure? m) (mloop (m))]
                [(and m (not (void? m))) (error "bad macro mapping!")]
                [(pair? pending)
                 (define rp (reverse (cons b pending)))
                 (write-byte (car rp)) (flush-output)
                 (loop (if (null? (cdr rp)) inps
                           (cons (open (list->bytes (cdr rp))) inps))
                       macros '())]
                [else (write-byte b) (flush-output) (loop inps v '())])))))


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

sub log($mess) { print "$mess\r\n" }

INIT { shell "stty raw -echo min 1 time 1"; log "(raw mode)"; }
END { shell "stty sane"; log "(sane mode)"; }

loop {
    push @INPUT, $TTY.getc unless @INPUT;
    given @INPUT.shift {
        when "q" | "\c4" { log "QUIT"; last; }

        when "\r" { log "CR" }

        when "j" { log "down" }
        when "k" { log "up" }
        when "h" { log "left" }
        when "l" { log "right" }

        when "J" { log "DOWN" }
        when "K" { log "UP" }
        when "H" { log "LEFT" }
        when "L" { log "RIGHT" }

        when "\e" {
            my $esc = '';
            repeat until my $x ~~ /^<alpha>$/ {
                push @INPUT, $TTY.getc unless @INPUT;
                $x = @INPUT.shift;
                $esc ~= $x;
            }
            given $esc {
                when "[A" { log "up" }
                when "[B" { log "down" }
                when "[C" { log "right" }
                when "[D" { log "left" }
                when "[1;2A" { log "UP" }
                when "[1;2B" { log "DOWN" }
                when "[1;2C" { log "RIGHT" }
                when "[1;2D" { log "LEFT" }
                default { log "Unrecognized escape: $esc"; }
            }
        }
        default { log "Unrecognized key: $_"; }
    }
}


import System.IO

hFlushInput :: Handle -> IO ()
hFlushInput hdl = do
  r <- hReady hdl
  if r then do
    c <- hGetChar hdl
    hFlushInput hdl
  else
    return ()

yorn :: IO Char
yorn = do
  c <- getChar
  if c == 'Y' || c == 'N' then return c
  else if c == 'y' then return 'Y'
  else if c == 'n' then return 'N'
  else yorn

main :: IO ()
main = do
  hSetBuffering stdout NoBuffering
  putStr "Press Y or N to continue: "

  hSetBuffering stdin NoBuffering
  hSetEcho stdin False
  hFlushInput stdin
  answer <- yorn
  putStrLn [answer]


procedure main()
    write("Response was ",getResponse("OK? (Y or N): "))
end

procedure getResponse(prompt)
    while kbhit() do getch()   # flush input
    writes(prompt)
    repeat if map(answer := getch()) == ("y"|"n") then break
    return answer
end


Qwantz is a room.

When play begins:
	say "A wizard has turned you into a whale. Is this awesome (Y/N)? ";
	if the player consents, say "Awesome!";
	end the story.


#include<iostream>
#include<algorithm>
#include<string.h>

using namespace std;
double result;
double capacity = 15;
int NumberOfItems;
int number;

struct items
{
    char name[32];
    double weight;
    double price;
    double m;
} item[256];

bool cmp(items a,items b)
{
    return a.price/a.weight > b.price/b.weight; // the compare function for the sorting algorithm
}

int main()
{
NumberOfItems=9;
strcpy(item[1].name,"beef");
item[1].weight=3.8;
item[1].price=36;

strcpy(item[2].name,"pork");
item[2].weight=5.4;
item[2].price=43;

strcpy(item[3].name,"ham");
item[3].weight=3.6;
item[3].price=90;

strcpy(item[4].name,"greaves");
item[4].weight=2.4;
item[4].price=45;

strcpy(item[5].name,"flitch");
item[5].weight=4.0;
item[5].price=30;

strcpy(item[6].name,"brawn");
item[6].weight=2.5;
item[6].price=56;

strcpy(item[7].name,"welt");
item[7].weight=3.7;
item[7].price=67;

strcpy(item[8].name,"salami");
item[8].weight=3.0;
item[8].price=95;

strcpy(item[9].name,"sausage");
item[9].weight=5.9;
item[9].price=98;

sort(item+1,item+NumberOfItems+1,cmp); // We'll sort using Introsort from STL

 number = 1;
 while(capacity>0&&number<=NumberOfItems)
 {
  if(item[number].weight<=capacity)
    {
        result+=item[number].price;
        capacity-=item[number].weight;
        item[number].m=1;
    }
  else
  {
      result+=(item[number].price)*(capacity/item[number].weight);
      item[number].m=(capacity/item[number].weight);
      capacity=0;

  }
  ++number;
 }

cout<<"Total Value = "<<result<<'\n';
cout<<"Total Weight = "<<(double)15-capacity<<'\n';
cout<<"Items Used:\n";
for(int i=1;i<=NumberOfItems;++i)
    if(item[i].m)
    {
       cout<<"We took "<<item[i].m*item[i].weight<<"kg of \""<<item[i].name<<"\" and the value it brought is "<<item[i].price*item[i].m<<"\n";
    }

return 0;
}


rebol [
    Title: "Keyboard Macros"
    URL: http://rosettacode.org/wiki/Keyboard_macros
]

; Application specific keyboard bindings using REBOL VID
; dialect. Implementation of the "Averageman" calculator --
; See http://www.atariarchives.org/bcc2/showpage.php?page=63 for details.

view layout [
	style btn button coal 46
	across

	display: h1 100 red maroon right ""  return

; Key shortcuts are specified as character arguments to widget
; descriptions in the layout.

	btn "1" #"1" [set-face display "1"]
	btn "+" #"+" [set-face display ""]
	return

	pad 54
	btn "=" #"=" [set-face display "3"]

	pad 1x100 return
	text "(c) 1977 G. Beker"
]