open StdLabels

let to_string (name,_,s,_) = (Printf.sprintf "%s (%d)" name s)

let take n li =
  let rec aux i acc = function
  | _ when i >= n -> (List.rev acc)
  | [] -> (List.rev acc)
  | x::xs -> aux (succ i) (x::acc) xs
  in
  aux 0 [] li ;;

let toprank data n =
  let len = List.length data in
  let h = Hashtbl.create len in
  List.iter data ~f:(fun ((_,_,_,dep) as employee) ->
    Hashtbl.add h dep employee);
  let deps =
    List.fold_left data ~init:[] ~f:
      (fun ac (_,_,_,v) -> if List.mem v ac then ac else v::ac) in
  let f dep =
    Printf.printf "Department: %s\n " dep;
    let l = Hashtbl.find_all h dep in
    let l2 = List.sort (fun (_,_,v1,_) (_,_,v2,_) -> compare v2 v1) l in
    let l3 = (take n l2) in
    print_endline(String.concat ", " (List.map to_string l3));
    print_newline()
  in
  List.iter f deps;
;;

let data = [
  "Tyler Bennett",   "E10297",  32000,  "D101";
  "John Rappl",      "E21437",  47000,  "D050";
  "George Woltman",  "E00127",  53500,  "D101";
  "Adam Smith",      "E63535",  18000,  "D202";
  "Claire Buckman",  "E39876",  27800,  "D202";
  "David McClellan", "E04242",  41500,  "D101";
  "Rich Holcomb",    "E01234",  49500,  "D202";
  "Nathan Adams",    "E41298",  21900,  "D050";
  "Richard Potter",  "E43128",  15900,  "D101";
  "David Motsinger", "E27002",  19250,  "D202";
  "Tim Sampair",     "E03033",  27000,  "D101";
  "Kim Arlich",      "E10001",  57000,  "D190";
  "Timothy Grove",   "E16398",  29900,  "D190";
]

let () =
  toprank data 3;
;;


Sub TheGameName(nombre As String)
    Dim As String x = Lcase(nombre)
    x = Ucase(Mid(x,1,1)) + (Mid(x,2,Len(x)-1))
    Dim As String x0 = Ucase(Mid(x,1,1))

    Dim As String y
    If x0 = "A" Or x0 = "E" Or x0 = "I" Or x0 = "O" Or x0 = "U" Then
        y = Lcase(x)
    Else
        y = Mid(x,2)
    End If

    Dim As String b = "b" + y, f = "f" + y, m = "m" + y

    Select Case x0
    Case "B" : b = y
    Case "F" : f = y
    Case "M" : m = y
    End Select

    Print x + ", " + x + ", bo-" + b
    Print "Banana-fana fo-" + f
    Print "Fee-fi-mo-" + m
    Print x + "!" + Chr(10)
End Sub

Dim listanombres(5) As String = {"Gary", "EARL", "billy", "FeLiX", "Mary", "ShirlEY"}
For i As Integer = 0 To Ubound(listanombres)
    TheGameName(listanombres(i))
Next i
Sleep


package main

import (
    "fmt"
    "strings"
)

func printVerse(name string) {
    x := strings.Title(strings.ToLower(name))
    y := x[1:]
    if strings.Contains("AEIOU", x[:1]) {
        y = strings.ToLower(x)
    }
    b := "b" + y
    f := "f" + y
    m := "m" + y
    switch x[0] {
    case 'B':
        b = y
    case 'F':
        f = y
    case 'M':
        m = y
    }
    fmt.Printf("%s, %s, bo-%s\n", x, x, b)
    fmt.Printf("Banana-fana fo-%s\n", f)
    fmt.Printf("Fee-fi-mo-%s\n", m)
    fmt.Printf("%s!\n\n", x)
}

func main() {
    names := [6]string{"gARY", "Earl", "Billy", "Felix", "Mary", "SHIRley"}
    for _, name := range names {
        printVerse(name)
    }
}


Object Class new: Employee(name, id, salary, dep)

Employee method: initialize  := dep  := salary := id := name ;
Employee method: salary  @salary ;
Employee method: dep     @dep ;
Employee method: <<      "[" << @dep << "," << @name << "," << @salary << "]" << ;

: topRank(n)
| employees |
   ListBuffer new ->employees

   Employee new("Tyler Bennett",   "E10297", 32000, "D101") employees add
   Employee new("John Rappl",      "E21437", 47000, "D050") employees add
   Employee new("George Woltman",  "E00127", 53500, "D101") employees add
   Employee new("Adam Smith",      "E63535", 18000, "D202") employees add
   Employee new("Claire Buckman",  "E39876", 27800, "D202") employees add
   Employee new("David McClellan", "E04242", 41500, "D101") employees add
   Employee new("Rich Holcomb",    "E01234", 49500, "D202") employees add
   Employee new("Nathan Adams",    "E41298", 21900, "D050") employees add
   Employee new("Richard Potter",  "E43128", 15900, "D101") employees add
   Employee new("David Motsinger", "E27002", 19250, "D202") employees add
   Employee new("Tim Sampair",     "E03033", 27000, "D101") employees add
   Employee new("Kim Arlich",      "E10001", 57000, "D190") employees add
   Employee new("Timothy Grove",   "E16398", 29900, "D190") employees add

   #dep employees sortBy groupWith( #dep )
   map(#[ sortBy(#[ salary neg ]) left(n) ]) apply(#println) ;


-- The Name Game, Ethan Riley, 22nd May 2018
import Data.Char

isVowel :: Char -> Bool
isVowel c
    | char == 'A' = True
    | char == 'E' = True
    | char == 'I' = True
    | char == 'O' = True
    | char == 'U' = True
    | otherwise = False
    where char = toUpper c

isSpecial :: Char -> Bool
isSpecial c
    | char == 'B' = True
    | char == 'F' = True
    | char == 'M' = True
    | otherwise = False
    where char = toUpper c

shorten :: String -> String
shorten name
    | isVowel $ head name = map toLower name
    | otherwise = map toLower $ tail name

line :: String -> Char -> String -> String
line prefix letter name
    | letter == char = prefix ++ shorten name ++ "\n"
    | otherwise = prefix ++ letter:[] ++ shorten name ++ "\n"
    where char = toLower $ head name

theNameGame :: String -> String
theNameGame name =
    line (name ++ ", " ++ name ++ ", bo-") 'b' name ++
    line "Banana-fana fo-" 'f' name ++
    line "Fee-fi-mo-" 'm' name ++
    name ++ "!\n"

main =
    mapM_ (putStrLn . theNameGame) ["Gary", "Earl", "Billy", "Felix", "Mike", "Steve"]


declare
  %% Create a list of employee records.
  Data = {Map
          [['Tyler Bennett' e10297 32000 d101]
           ['John Rappl' e21437 47000 d050]
           ['George Woltman' e00127 53500 d101]
           ['Adam Smith' e63535 18000 d202]
           ['Claire Buckman' e39876 27800 d202]
           ['David McClellan' e04242 41500 d101]
           ['Rich Holcomb' e01234 49500 d202]
           ['Nathan Adams' e41298 21900 d050]
           ['Richard Potter' e43128 15900 d101]
           ['David Motsinger' e27002 19250 d202]
           ['Tim Sampair' e03033 27000 d101]
           ['Kim Arlich' e10001 57000 d190]
           ['Timothy Grove' e16398 29900 d190]]

          fun {$ [Name Id Salary Department]}
             employee(name:Name id:Id salary:Salary department:Department)
          end}

  fun {TopEarners Employees N}
     {Record.map {GroupBy Employees department}
      fun {$ Employees}
     {List.take
      {Sort Employees CompareSalary}
      N}
      end}
  end

  fun {CompareSalary E1 E2}
     E1.salary > E2.salary
  end

  %% Groups the records Xs by the value of feature F and returns
  %% the result as a record that maps values of F to list of records.
  fun {GroupBy Xs F}
     Groups = {Dictionary.new}
  in
     for X in Xs do
        Groups.(X.F) := X|{CondSelect Groups X.F nil}
     end
     {Dictionary.toRecord unit Groups}
  end
in
  {Inspect {TopEarners Data 3}}


T=:TEMPLATE=: noun define
   (X), (X), bo-b(Y)
   Banana-fana fo-f(Y)
   Fee-fi-mo-m(Y)
   (X)!
)

nameGame=: monad define
 X=. y
 Y=. tolower }.^:('aeiouAEIOU' [email protected]:e.~ {.) y
 heady=. tolower {. y
 t=. TEMPLATE -. '()'
 'ix iy'=. I. 'XY' =/ t
 tbox=. ;/ t
 match=. heady = (<: iy){::"0 _ tbox
 remove =. match # iy
 special_rule_box=. a: (<: remove)}tbox
 ybox=. (< Y) iy} special_rule_box
 XBox=. (< X) ix} ybox
 ; XBox
)


import java.util.stream.Stream;

public class NameGame {
    private static void printVerse(String name) {
        StringBuilder sb = new StringBuilder(name.toLowerCase());
        sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
        String x = sb.toString();
        String y = "AEIOU".indexOf(x.charAt(0)) > -1 ? x.toLowerCase() : x.substring(1);
        String b = "b" + y;
        String f = "f" + y;
        String m = "m" + y;
        switch (x.charAt(0)) {
            case 'B':
                b = y;
                break;
            case 'F':
                f = y;
                break;
            case 'M':
                m = y;
                break;
            default:
                // no adjustment needed
                break;
        }
        System.out.printf("%s, %s, bo-%s\n", x, x, b);
        System.out.printf("Banana-fana fo-%s\n", f);
        System.out.printf("Fee-fi-mo-%s\n", m);
        System.out.printf("%s!\n\n", x);
    }

    public static void main(String[] args) {
        Stream.of("Gary", "Earl", "Billy", "Felix", "Mary", "Steve").forEach(NameGame::printVerse);
    }
}


function singNameGame(name) {

  // normalize name
  name = name.toLowerCase();
  name = name[0].toUpperCase() + name.slice(1);

  // ... and sometimes y
  // let's pray this works
  let firstVowelPos = (function() {
    let vowels =
      'aeiouàáâãäåæèéêëìíîïòóôõöøùúûüāăąēĕėęěĩīĭįıĳōŏőœũūŭůűų'
    .split('');
    function isVowel(char) {
      return vowels.indexOf(char) >= 0;
    }
    if (isVowel(name[0].toLowerCase())) return 0;
    if (name[0] == 'Y' && !isVowel(name[1])) return 0;
    if (name[0] == 'Y' && isVowel(name[1])) return 1;
    vowels = vowels.concat(vowels, 'yÿý'.split(''));
    for (let i = 1; i < name.length; i++)
      if (isVowel(name[i])) return i;
  })();

  let init  = name[0].toLowerCase(),
      trunk = name.slice(firstVowelPos).toLowerCase(),
      b = trunk, f = trunk, m = trunk;

  switch (init) {
    case 'b': f = 'f' + trunk; m = 'm' + trunk; break;
    case 'f': b = 'b' + trunk; m = 'm' + trunk; break;
    case 'm': b = 'b' + trunk; f = 'f' + trunk; break;
    default: b = 'b' + trunk; f = 'f' + trunk; m = 'm' + trunk;
  }

  return `

${name}, ${name}, bo-${b}

    Banana-fana fo-${f}

    Fee-fi-fo-mo-${m}

    ${name}!

  `
}

// testing
let names =
  'Gary Earl Billy Felix Mary Christine Brian Yvonne Yannick'.split(' ');
for (let i = 0; i < names.length; i++)
  document.write(singNameGame(names[i]));


program TopRankPerGroup(output);

uses
  Classes, Math;

type
  TData = record
            name:   string;
        ID:     string;
        salary: longint;
        dept:   string
      end;
  PTData = ^TData;

const
  data: array [1..13] of TData =
    ( (name: 'Tyler Bennett';   ID: 'E10297'; salary: 32000; dept: 'D101'),
      (name: 'John Rappl';      ID: 'E21437'; salary: 47000; dept: 'D050'),
      (name: 'George Woltman';  ID: 'E00127'; salary: 53500; dept: 'D101'),
      (name: 'Adam Smith';      ID: 'E63535'; salary: 18000; dept: 'D202'),
      (name: 'Claire Buckman';  ID: 'E39876'; salary: 27800; dept: 'D202'),
      (name: 'David McClellan'; ID: 'E04242'; salary: 41500; dept: 'D101'),
      (name: 'Rich Holcomb';    ID: 'E01234'; salary: 49500; dept: 'D202'),
      (name: 'Nathan Adams';    ID: 'E41298'; salary: 21900; dept: 'D050'),
      (name: 'Richard Potter';  ID: 'E43128'; salary: 15900; dept: 'D101'),
      (name: 'David Motsinger'; ID: 'E27002'; salary: 19250; dept: 'D202'),
      (name: 'Tim Sampair';     ID: 'E03033'; salary: 27000; dept: 'D101'),
      (name: 'Kim Arlich';      ID: 'E10001'; salary: 57000; dept: 'D190'),
      (name: 'Timothy Grove';   ID: 'E16398'; salary: 29900; dept: 'D190')
    );

function CompareSalary(Item1, Item2: PTData): longint;
  begin
    CompareSalary := Item2^.salary - Item1^.salary;
  end;

var
  depts   : TStringList;
  deptList: Tlist;
  number, i, j: integer;

begin
  write ('Enter the number of ranks: ');
  readln (number);
  depts := TStringList.Create;
  depts.Sorted := true;
  depts.Duplicates := dupIgnore;
  for i := low(data) to high(data) do
    depts.Add(data[i].dept);

  for i := 0 to depts.Count - 1 do
  begin
    writeln;
    writeln('Department: ', depts.Strings[i]);
    deptList := TList.Create;
    for j := low(data) to high(data) do
      if data[j].dept = depts.Strings[i] then
        deptList.Add(@data[j]);
    deptList.Sort(TListSortCompare(@CompareSalary));
    for j := 0 to min(deptList.count, number) - 1 do
    begin
      write (PTData(deptList.Items[j])^.name, ', ');
      write ('ID: ', PTData(deptList.Items[j])^.ID, ', ');
      write ('Salary: ', PTData(deptList.Items[j])^.Salary);
      writeln;
    end;
    deptList.Destroy;
  end;
end.


import Compat: uppercasefirst

function printverse(name::AbstractString)
    X = uppercasefirst(lowercase(name))
    Y = X[1] ∈ ('A', 'E', 'I', 'O', 'U') ? X : SubString(X, 2)
    b = X[1] == 'B' ? "" : "b"
    f = X[1] == 'F' ? "" : "f"
    m = X[1] == 'M' ? "" : "m"
    println("""\
    $(X), $(X), bo-$b$(Y)
    Banana-fana fo-$f$(Y)
    Fee-fi-mo-$m$(Y)
    $(X)!
    """)
    return nothing
end

foreach(TheNameGame.printverse, ("gARY", "Earl", "Billy", "Felix", "Mary", "sHIRley"))


// version 1.2.31

fun printVerse(name: String) {
    val x = name.toLowerCase().capitalize()
    val y = if (x[0] in "AEIOU") x.toLowerCase() else x.substring(1)
    var b = "b$y"
    var f = "f$y"
    var m = "m$y"
    when (x[0]) {
        'B'  -> b = "$y"
        'F'  -> f = "$y"
        'M'  -> m = "$y"
        else -> {} // no adjustment needed
    }
    println("$x, $x, bo-$b")
    println("Banana-fana fo-$f")
    println("Fee-fi-mo-$m")
    println("$x!\n")
}

fun main(args: Array<String>) {
    listOf("Gary", "Earl", "Billy", "Felix", "Mary", "Steve").forEach { printVerse(it) }
}


function printVerse(name)
    local sb = string.lower(name)
    sb = sb:gsub("^%l", string.upper)
    local x = sb
    local x0 = x:sub(1,1)

    local y
    if x0 == 'A' or x0 == 'E' or x0 == 'I' or x0 == 'O' or x0 == 'U' then
        y = string.lower(x)
    else
        y = x:sub(2)
    end

    local b = "b" .. y
    local f = "f" .. y
    local m = "m" .. y

    if x0 == 'B' then
        b = y
    elseif x0 == 'F' then
        f = y
    elseif x0 == 'M' then
        m = y
    end

    print(x .. ", " .. x .. ", bo-" .. b)
    print("Banana-fana fo-" .. f)
    print("Fee-fi-mo-" .. m)
    print(x .. "!")
    print()

    return nil
end

local nameList = { "Gary", "Earl", "Billy", "Felix", "Mary", "Steve" }
for _,name in pairs(nameList) do
    printVerse(name)
end


sub zip {
    my @a = @{shift()};
    my @b = @{shift()};
    my @l;
    push @l, shift @a, shift @b while @a and @b;
    return @l;
}

sub uniq {
    my %h;
    grep {!$h{$_}++} @_;
}

my @data =
    map {{ zip [qw(name id salary dept)], [split ','] }}
    split "\n",
    <<'EOF';
Tyler Bennett,E10297,32000,D101
John Rappl,E21437,47000,D050
George Woltman,E00127,53500,D101
Adam Smith,E63535,18000,D202
Claire Buckman,E39876,27800,D202
David McClellan,E04242,41500,D101
Rich Holcomb,E01234,49500,D202
Nathan Adams,E41298,21900,D050
Richard Potter,E43128,15900,D101
David Motsinger,E27002,19250,D202
Tim Sampair,E03033,27000,D101
Kim Arlich,E10001,57000,D190
Timothy Grove,E16398,29900,D190
EOF

my $N = shift || 3;

foreach my $d (uniq sort map {$_->{dept}} @data) {
    print "$d\n";
    my @es =
        sort {$b->{salary} <=> $a->{salary}}
        grep {$_->{dept} eq $d}
        @data;
    foreach (1 .. $N) {
        @es or last;
        my $e = shift @es;
        printf "%-15s | %-6s | %5d\n", @{$e}{qw(name id salary)};
    }
    print "\n";
}


ClearAll[NameGame]
NameGame[n_] := Module[{y, b, f, m},
  If[StringStartsQ[ToLowerCase[n], "a" | "e" | "i" | "u" | "o"],
   y = ToLowerCase[n]
   ,
   y = StringDrop[n, 1]
   ];
  b = "b" <> y;
  f = "f" <> y;
  m = "m" <> y;
  Switch[[email protected][n, 1],
   "b", b = y,
   "f", f = y,
   "m", m = y
   ];
  StringReplace["(X), (X), bo-(B)\nBanana-fana fo-(F)\nFee-fi-mo-(M)\n(X)! ", {"(X)" -> n, "(B)" -> b, "(F)" -> f, "(M)" -> m}]
]
NameGame["Gary"]
NameGame["Earl"]
NameGame["Billy"]
NameGame["Felix"]
NameGame["Mary"]
NameGame["Steve"]


("AEIOU" "" split swap in?) :vowel?

(
  :Name
  Name "" split first :L
  Name lowercase :name (L vowel?) (name "" split rest "" join @name) unless
  "b" :B
  "f" :F
  "m" :M
  (
    ((L "B" ==) ("" @B))
    ((L "F" ==) ("" @F))
    ((L "M" ==) ("" @M))
  ) case
  "$1, $1, bo-$3$2\nBanana-fana fo-$4$2\nFee-fi-mo-$5$2\n$1!\n"
  (Name name B F M) => % puts!
) :name-game

("Gary" "Earl" "Billy" "Felix" "Milton" "Steve") 'name-game foreach


MODULE NameGame;
FROM Strings IMPORT Concat;
FROM ExStrings IMPORT Lowercase;
FROM Terminal IMPORT WriteString, WriteLn, ReadChar;

PROCEDURE PrintVerse(name : ARRAY OF CHAR);
TYPE String = ARRAY[0..64] OF CHAR;
VAR y,b,f,m : String;
BEGIN
    Lowercase(name);

    CASE name[0] OF
        'a','e','i','o','u' : y := name;
    ELSE
        y := name[1..LENGTH(name)];
    END;

    Concat("b", y, b);
    Concat("f", y, f);
    Concat("m", y, m);

    CASE name[0] OF
        'b' : b := y; |
        'f' : f := y; |
        'm' : m := y;
    ELSE
    END;

    name[0] := CAP(name[0]);

    (* Line 1 *)
    WriteString(name);
    WriteString(", ");
    WriteString(name);
    WriteString(", bo-");
    WriteString(b);
    WriteLn;

    (* Line 2 *)
    WriteString("Banana-fana fo-");
    WriteString(f);
    WriteLn;

    (* Line 3 *)
    WriteString("Fee-fi-mo-");
    WriteString(m);
    WriteLn;

    (* Line 4 *)
    WriteString(name);
    WriteString("!");
    WriteLn;

    WriteLn;
END PrintVerse;

BEGIN
    PrintVerse("Gary");
    PrintVerse("Earl");
    PrintVerse("Billy");
    PrintVerse("Felix");
    PrintVerse("Mary");
    PrintVerse("Steve");

    ReadChar;
END NameGame.


with javascript_semantics
constant N=3

--                      Employee Name,Employee ID,Salary,Department
enum                    /*NAME,*/        /*ID,*/  SAL=3, DEPT=4
constant employees = {{"Tyler Bennett",  "E10297",32000,"D101"},
                      {"John Rappl",     "E21437",47000,"D050"},
                      {"George Woltman", "E00127",53500,"D101"},
                      {"Adam Smith",     "E63535",18000,"D202"},
                      {"Claire Buckman", "E39876",27800,"D202"},
                      {"David McClellan","E04242",41500,"D101"},
                      {"Rich Holcomb",   "E01234",49500,"D202"},
                      {"Nathan Adams",   "E41298",21900,"D050"},
                      {"Richard Potter", "E43128",15900,"D101"},
                      {"David Motsinger","E27002",19250,"D202"},
                      {"Tim Sampair",    "E03033",27000,"D101"},
                      {"Kim Arlich",     "E10001",57000,"D190"},
                      {"Timothy Grove",  "E16398",29900,"D190"}}

function by_dept_sal(integer i, j)
    return compare(employees[i][DEPT]&-employees[i][SAL],
                   employees[j][DEPT]&-employees[j][SAL])
end function

sequence tags = custom_sort(by_dept_sal,tagset(length(employees)))

string lastdep = ""
integer dcount = 0
printf(1,"Top %d salaries by department\n",{N})
for i=1 to length(employees) do
    object emp = employees[tags[i]]
    if emp[DEPT]!=lastdep then
        lastdep = emp[DEPT]
        dcount = 1
        printf(1,"\n")
    else
        dcount += 1
    end if
    if dcount<=N then
        ?emp
    end if
end for


def print_verse(n)
        l = {"b", "f", "m"}
        s = n.substring(1)
        if lower(n[0]) in l
                ind = l[lower(n[0])]
                l[ind] = ""
        else if n[0] in {"A", "E", "I", "O", "U"}
                s = lower(n)
        end

        println format("%s, %s, bo-%s%s", n, n, l[0], s)
        println format("Banana-fana fo-%s%s", l[1], s)
        println format("Fee-fi-mo-%s%s", l[2], s)
        println n + "!\n"
end

names = {"Gary", "Earl", "Billy", "Felix", "Mary"}
for n in names
        print_verse(n)
end


import strutils

const
  StdFmt = "$1, $1, bo-b$2\nBanana-fana fo-f$2\nFee-fi-mo-m$2\n$1!"
  WovelFmt = "$1, $1, bo-b$2\nBanana-fana fo-f$2\nFee-fi-mo-m$2\n$1!"
  BFmt = "$1, $1, bo-$2\nBanana-fana fo-f$2\nFee-fi-mo-m$2\n$1!"
  FFmt = "$1, $1, bo-b$2\nBanana-fana fo-$2\nFee-fi-mo-m$2\n$1!"
  MFmt = "$1, $1, bo-b$2\nBanana-fana fo-f$2\nFee-fi-mo-$2\n$1!"

proc lyrics(name: string): string =
  let tail = name[1..^1]
  result = case name[0].toUpperAscii
           of 'A', 'E', 'I', 'O', 'U', 'Y':
             WovelFmt.format(name, name.toLowerAscii)
           of 'B':
             BFmt.format(name, tail)
           of 'F':
             FFmt.format(name, tail)
           of 'M':
             MFmt.format(name, tail)
           else:
             StdFmt.format(name, tail)
  result = result.capitalizeAscii()

for name in ["Gary", "Earl", "Billy", "Felix", "Mary"]:
  echo name.lyrics()
  echo()


sub printVerse {
    $x  = ucfirst lc shift;
    $x0 = substr $x, 0, 1;
    $y  = $x0 =~ /[AEIOU]/ ? lc $x : substr $x, 1;
    $b  = $x0 eq 'B' ? $y : 'b' . $y;
    $f  = $x0 eq 'F' ? $y : 'f' . $y;
    $m  = $x0 eq 'M' ? $y : 'm' . $y;
    print "$x, $x, bo-$b\n" .
          "Banana-fana fo-$f\n" .
          "Fee-fi-mo-$m\n" .
          "$x!\n\n";
}

printVerse($_) for <Gary Earl Billy Felix Mary Steve>;


constant fmt = """
%s, %s, bo-%s
Banana-fana fo-%s
Fee-fi-mo-%s
%s!

"""
procedure printVerse(string name)
    string x = lower(name)
    integer x1 = upper(x[1]),
            vowel = find(x1,"AEIUO")!=0
    string y = x[2-vowel..$],
           b = 'b'&y, f = 'f'&y, m = 'm'&y
    x[1] = x1
    switch x1 do
        case 'B': b = y
        case 'F': f = y
        case 'M': m = y
    end switch
    printf(1,fmt,{x, x, b, f, m, x})
end procedure

constant tests = {"gARY", "Earl", "Billy", "Felix", "Mary", "SHIRley"}
for i=1 to length(tests) do printVerse(tests[i]) end for


$data = Array(
            Array("Tyler Bennett","E10297",32000,"D101"),
            Array("John Rappl","E21437",47000,"D050"),
            Array("George Woltman","E00127",53500,"D101"),
            Array("Adam Smith","E63535",18000,"D202"),
            Array("Claire Buckman","E39876",27800,"D202"),
            Array("David McClellan","E04242",41500,"D101"),
            Array("Rich Holcomb","E01234",49500,"D202"),
            Array("Nathan Adams","E41298",21900,"D050"),
            Array("Richard Potter","E43128",15900,"D101"),
            Array("David Motsinger","E27002",19250,"D202"),
            Array("Tim Sampair","E03033",27000,"D101"),
            Array("Kim Arlich","E10001",57000,"D190"),
            Array("Timothy Grove","E16398",29900,"D190")
            );
function top_sal($num){
    global $data;
    $depts = Array();
    foreach($data as $key => $arr){
        if(!isset($depts[$arr[3]])) $depts[$arr[3]] = Array();
        $depts[$arr[3]][] = $key;
    }
    function topsalsort($a,$b){
        global $data;
        if ($data[$a][2] == $data[$b][2]) {
            return 0;
        }
        return ($data[$a][2] < $data[$b][2]) ? 1 : -1;
    }
    foreach ($depts as $key => $val){
        usort($depts[$key],"topsalsort");
    }
    ksort($depts);
    echo '
';
    foreach ($depts as $key => $val){
        echo $key . '
';
        echo 'Name          ID      Salary
';
        $count = 0;
        foreach($val as $value){
            echo $data[$value][0] . '   ' . $data[$value][1] . '    ' . $data[$value][2] . '
';
            $count++;
            if($count>=$num) break;
        }
        echo '
';
    }
    echo '
';
}
top_sal(3);


print_name_game(Name), Name = [V|Rest], membchk(V, ['A', 'E', 'I', 'O', 'U'])  =>
    L = to_lowercase(V),
    Low = [L|Rest],
    print_verse(Name, [b|Low], [f|Low], [m|Low]).

print_name_game(Name), Name = ['B'|Rest] =>
    print_verse(Name, Rest, [f|Rest], [m|Rest]).

print_name_game(Name), Name = ['F'|Rest] =>
    print_verse(Name, [b|Rest], Rest, [m|Rest]).

print_name_game(Name), Name = ['M'|Rest] =>
    print_verse(Name, [b|Rest], [f|Rest], Rest).

print_name_game(Name), Name = [C|Rest] =>
    print_verse(Name, [b|Rest], [f|Rest], [m|Rest]).

print_verse(Full, B, F, M) =>
    printf("%w, %w, bo-%w\nBanana-fana fo-%w\nFee-fi-mo-%w\n%w!\n\n",
        Full,
        Full,
        B,
        F,
        M,
        Full
    ).

main(Args) =>
    foreach (Name in Args)
        print_name_game(Name)
    end.


## Clear Host from old Ouput
Clear-Host

$Name = Read-Host "Please enter your name"
$Char = ($name.ToUpper())[0]
IF (($Char -eq "A") -or ($Char -eq "E") -or ($Char -eq "I") -or ($Char -eq "O") -or ($Char -eq "U"))
  {
    Write-Host "$Name, $Name, bo-b$($Name.ToLower())"
  }
else
  {
    IF ($Char -eq "B")
      {
        Write-Host "$Name, $Name, bo-$($Name.Substring(1))"
      }
    else
      {
        Write-Host "$Name, $Name, bo-b$($Name.Substring(1))"
      }
  }

  IF (($Char -eq "A") -or ($Char -eq "E") -or ($Char -eq "I") -or ($Char -eq "O") -or ($Char -eq "U"))
  {
    Write-Host "Banana-fana fo-f$($Name.ToLower())"
  }
else
  {
    IF ($Char -eq "F")
      {
        Write-Host "Banana-fana fo-$($Name.Substring(1))"
      }
    else
      {
        Write-Host "Banana-fana fo-f$($Name.Substring(1))"
      }
  }

  IF (($Name[0] -eq "A") -or ($Name[0] -eq "E") -or ($Name[0] -eq "I") -or ($Name[0] -eq "O") -or ($Name[0] -eq "U"))
  {
    Write-Host "Fee-fi-mo-m$($Name.tolower())"
  }
else
  {
    IF ($Char -eq "M")
      {
        Write-Host "Fee-fi-mo-$($Name.Substring(1))"
      }
    else
      {
        Write-Host "Fee-fi-mo-m$($Name.Substring(1))"
      }
  }
Write-Host "$Name"


map_name1(C, Cs, C, Cs).
map_name1(C, Cs, Fc, [Fc,C|Cs]) :- member(C, ['a','e','i','o','u']).
map_name1(C, Cs, Fc, [Fc|Cs]) :-
    \+ member(C, ['a','e','i','o','u']),
    dif(C, Fc).

map_name(C, Cs, Fc, Name) :-
    map_name1(C, Cs, Fc, NChars),
    atom_chars(Name, NChars).

song(Name) :-
   string_lower(Name, LName),
   atom_chars(LName, [First|Chars]),

   map_name(First, Chars, 'b', BName),
   map_name(First, Chars, 'f', FName),
   map_name(First, Chars, 'm', MName),

   maplist(write,
           [Name, ", ", Name, ", bo-", BName, '\n',
            "Banana-fana fo-", FName, '\n',
            "Fee-fi-mo-", MName, '\n',
            Name, "!\n\n"]).

test :-
    maplist(song, ["Gary", "Earl", "Billy", "Felix", "Mary"]).


def print_verse(n):
    l = ['b', 'f', 'm']
    s = n[1:]
    if str.lower(n[0]) in l:
        l[l.index(str.lower(n[0]))] = ''
    elif n[0] in ['A', 'E', 'I', 'O', 'U']:
        s = str.lower(n)
    print('{0}, {0}, bo-{2}{1}\nBanana-fana fo-{3}{1}\nFee-fi-mo-{4}{1}\n{0}!\n'.format(n, s, *l))

# Assume that the names are in title-case and they're more than one character long
for n in ['Gary', 'Earl', 'Billy', 'Felix', 'Mary']:
    print_verse(n)


# Employee Name, ID, Salary, Department
(de *Employees
   ("Tyler Bennett" E10297 32000 D101)
   ("John Rappl" E21437 47000 D050)
   ("George Woltman" E00127 53500 D101)
   ("Adam Smith" E63535 18000 D202)
   ("Claire Buckman" E39876 27800 D202)
   ("David McClellan" E04242 41500 D101)
   ("Rich Holcomb" E01234 49500 D202)
   ("Nathan Adams" E41298 21900 D050)
   ("Richard Potter" E43128 15900 D101)
   ("David Motsinger" E27002 19250 D202)
   ("Tim Sampair" E03033 27000 D101)
   ("Kim Arlich" E10001 57000 D190)
   ("Timothy Grove" E16398 29900 D190) )

(de topEmployees (N)
   (let Fmt (4 -16 -7 7)
      (for Dept (by cadddr group *Employees)
         (prinl "Department " (cadddr (car Dept)) ":")
         (tab Fmt NIL "Name" "ID" "Salary")
         (for (I . D) (flip (by caddr sort Dept))
            (tab Fmt (pack I ". ") (car D) (cadr D) (caddr D))
            (T (= I N)) )
         (prinl) ) ) )

(topEmployees 3)


(subrg, stringrange, stringsize):
rank: procedure options (main);   /* 10 November 2013 */

   declare 1 employee (13),
             2 name char (15) varying,
             2 ID   char (6),
             2 salary fixed (5),
             2 department char (4);
   declare done(hbound(employee)) bit (1);
   declare ptr(hbound(employee)) fixed binary;
   declare true bit(1) value ('1'b), false bit(1) value ('0'b);
   declare dept character (4);
   declare text character (80) varying;
   declare (i, j, l, k, m, n, p, t) fixed binary;
   declare in file input;

   open file (in) title ('/TOP-RANK.DAT, RECSIZE(80), TYPE(TEXT)' );

   on endfile (in) go to completed_input;
   j = 0;
   do forever;
      get file (in) edit (text) (L);
      j = j + 1;
      i = index(text, ',');
      name(j) = substr(text, 1, i-1);
      k = index(text, ',', i+1);
      ID(j) = substr(text, i+1, k-(i+1));
      i = k; k = index(text, ',', i+1);
      salary(j) = substr(text, i+1, k-(i+1));
      department(j) = substr(text, k+1);
   end;

completed_input:
   m = hbound(employee);
   put skip list ('How many highest-paid employees do you want?');
   get (n);
   put skip edit ('Looking for the ', trim(n),
                  ' highest-paid employees in each department') (a);
   done = false;
   do i = 1 to m;
      do j = 1 to m;
         if done(j) then iterate;
         dept = department(j);
          /* done(j) = true; */
         leave;
      end;
      /* Locate all the employees of this department. */
      k = 0;
      do j = 1 to m;
         if ^done(j) & (department(j) = dept) then
            do;
               k = k + 1;
               ptr(k) = j;
               done(j) = true;
            end;
      end;
      if k = 0 then leave; /* (No more departments.) */

      put skip list ('Employees in department ' || dept || ' are:-' );
      do j = 1 to k;
         put skip list (employee(ptr(j)));
      end;
      /* We now have k employees in "dept".  Now find the maximum n salaries. */
      /* ptr points to all of them. */
      /* Use a bubble sort to move n values to one end. */
      do p = 1 to min(n, k);
         do j = 1 to k-1;
            if salary(ptr(j)) > salary(ptr(j+1)) then
               do;
                  t = ptr(j+1); ptr(j+1) = ptr(j); ptr(j) = t;
               end;
         end;
      end;

      /* Having moved the largest n values to the end of our list, */
      /* we print them. */
      put skip list ('Highest-paid employees in department ' || dept || ':-');
      do j = k to k-min(k,n)+1 by -1;
         put skip list (employee(ptr(j)) );
      end;
   end;
   put skip list ('FINISHED');
end rank;


game_ssr:{[Name]
  V:raze 1 lower\"AEIOUY";                                        / vowels
  tn:lower((Name in V)?1b) _ Name;                                / truncated Name
  s3:{1(-1_)\x,"o-",x}lower first Name;                           / 3rd ssr
  s:"$1, $1, bo-b$2\nBanana-fana-fo-f$2\nFee-fimo-m$2\n$1!\n\n";
  (ssr/).(s;("$1";"$2";s3 0);(Name;tn;s3 1)) }


sub mangle ($name, $initial) {
    my $fl = $name.lc.substr(0,1);
    $fl ~~ /<[aeiou]>/
    ?? $initial~$name.lc
    !! $fl eq $initial
    ?? $name.substr(1)
    !! $initial~$name.substr(1)
}

sub name-game (Str $name) {
    qq:to/NAME-GAME/;
    $name, $name, bo-{ mangle $name, 'b' }
    Banana-fana fo-{ mangle $name, 'f' }
    Fee-fi-mo-{ mangle $name, 'm' }
    $name!
    NAME-GAME
}

say .&name-game for <Gary Earl Billy Felix Mike Steve>


/*REXX program  displays the  lyrics  of the  song  "The Name Game"  by Shirley Ellis.  */
parse arg $                                      /*obtain optional argument(s) from C.L.*/
if $=''  then $="gAry, eARL, billy, FeLix, MarY" /*Not specified?  Then use the default.*/
                                                 /* [↑]  names separated by commas.     */
      do j=1  until $='';    $=space($)          /*elide superfluous blanks from list.  */
      parse var  $  name','  $                   /*get name (could be 2 words) from list*/
      call song     name                         /*invoke subroutine to display lyrics. */
      end   /*j*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
song: arg c 2 1 z;  @b='b';    @f="f";    @m='m' /*obtain name;  assign three variables.*/
      @abc= 'abcdefghijklmnopqrstuvwxyz'; @[email protected]; upper @abcU    /*build 2 alphabets*/
      z=c || translate( substr(z, 2),@abc,@abcU) /*capitalize name, lowercase the rest. */
      parse var   z   f  2  ''  1  z             /*get name, 1st letter, rest of name.  */
      y=substr(z, 2);     zl=translate(z, @abc, @abcU)               /*lowercase 2 vars.*/
                  select
                  when pos(f, 'AEIOU')\==0  then do;  say z','  z", bo-b"zl
                                                      say 'Banana-fana fo-f'zl
                                                      say 'Fee-fi-mo-m'zl
                                                 end
                  when pos(f, 'BFM'  )\==0  then do;  if f=='B'  then @b=
                                                      if f=='F'  then @f=
                                                      if f=='M'  then @m=
                                                      say z','  z", bo-"@b || y
                                                      say 'Banana-fana fo-'@f || y
                                                      say 'Fee-fi-mo-'@m || y
                                                 end
                  otherwise                           say z','  z", bo-b"y
                                                      say 'Banana-fana fo-f'y
                                                      say 'Fee-fi-mo-m'y
                  end   /*select*/
      say z'!';                           say
      return


CREATE OR REPLACE PROCEDURE "Top rank per group"(TOP_N IN PLS_INTEGER DEFAULT 3) AS
  CURSOR CSR_EMP(TOP_N PLS_INTEGER) IS
    SELECT CASE LINE
             WHEN 10 THEN
              'Tot.' || LPAD(POPULATION, 2) || ' Employees in ' || TIE_COUNT ||
              ' deps.Avg salary:' || TO_CHAR(SALARY, '99990.99')
             WHEN 30 THEN
              '-'
             WHEN 50 THEN
              'Department: ' || DEPT_ID || ', pop: ' || POPULATION ||
              '. Avg Salary: ' || TO_CHAR(SALARY, '99990.99')
             WHEN 70 THEN
              LPAD('Employee ID', 14) || LPAD('Employee name', 20) ||
              LPAD('Salary', 9) || 'Rank'
             WHEN 90 THEN
              LPAD('+', 14, '-') || LPAD('+', 20, '-') || LPAD('+', 9, '-') ||
              LPAD('+', 4, '-')
             ELSE
              LPAD(' ', 8) || LPAD(EMP_ID, 6) || LPAD(EMP_NAME, 20) ||
              TO_CHAR(SALARY, '99990.99') ||
              LPAD(CASE WHEN TIE_COUNT = 1 THEN  ' ' ELSE 'T' END || RANK, 4)
           END "Top rank per group"
      FROM (SELECT 10 LINE
                  ,NULL EMP_ID
                  ,NULL EMP_NAME
                  ,' ' DEPT_ID
                  ,AVG(SALARY) SALARY
                  ,0 RANK
                  ,COUNT(DISTINCT DEPT_ID) TIE_COUNT
                  ,COUNT(*) POPULATION
              FROM EMP
            UNION ALL
            SELECT 30      LINE
                  ,NULL    EMP_ID
                  ,NULL    EMP_NAME
                  ,DEPT_ID
                  ,0       SALARY
                  ,0       RANK
                  ,0       TIE_COUNT
                  ,0       POPULATION
              FROM EMP
             GROUP BY DEPT_ID
            UNION ALL
            SELECT 50 LINE
                  ,NULL EMP_ID
                  ,NULL EMP_NAME
                  ,DEPT_ID
                  ,AVG(SALARY) SALARY
                  ,0 RANK
                  ,0 TIE_COUNT
                  ,COUNT(*) POPULATION
              FROM EMP
             GROUP BY DEPT_ID
            UNION ALL
            SELECT 70      LINE
                  ,NULL    EMP_ID
                  ,NULL    EMP_NAME
                  ,DEPT_ID
                  ,0       SALARY
                  ,0       RANK
                  ,0       TIE_COUNT
                  ,0       POPULATION
              FROM EMP
             GROUP BY DEPT_ID
            UNION ALL
            SELECT 90      LINE
                  ,NULL    EMP_ID
                  ,NULL    EMP_NAME
                  ,DEPT_ID
                  ,0       SALARY
                  ,0       RANK
                  ,0       TIE_COUNT
                  ,0       POPULATION
              FROM EMP
             GROUP BY DEPT_ID
            UNION ALL
            SELECT 110 LINE
                  ,EMP_ID
                  ,EMP_NAME
                  ,DEPT_ID
                  ,SALARY
                  ,(SELECT COUNT(DISTINCT EMP4.SALARY)
                      FROM EMP EMP4
                     WHERE EMP4.DEPT_ID = EMP3.DEPT_ID
                       AND EMP4.SALARY >= EMP3.SALARY) RANK
                  ,(SELECT COUNT(*)
                      FROM EMP EMP2
                     WHERE EMP2.DEPT_ID = EMP3.DEPT_ID
                       AND EMP2.SALARY = EMP3.SALARY) TIE_COUNT
                  ,0 POPULATION
              FROM EMP EMP3
             WHERE TOP_N >= -- Here is the meat, Correlated subquery
                   (SELECT COUNT(DISTINCT EMP4.SALARY)
                      FROM EMP EMP4
                     WHERE EMP4.DEPT_ID = EMP3.DEPT_ID
                       AND EMP4.SALARY >= EMP3.SALARY))
     ORDER BY DEPT_ID
             ,LINE
             ,SALARY DESC
             ,EMP_ID;

  V_EMP CSR_EMP%ROWTYPE;
BEGIN
  FOR V_EMP IN CSR_EMP(TOP_N)
  LOOP
    DBMS_OUTPUT.PUT_LINE(v_emp."Top rank per group");
  END LOOP;
END;


#!/usr/bin/env ruby

def print_verse(name)
  first_letter_and_consonants_re = /^.[^aeiyou]*/i

  full_name = name.capitalize # X
  suffixed  = case full_name[0] # Y
              when 'A','E','I','O','U'
                name.downcase
              else
                full_name.sub(first_letter_and_consonants_re, '')
              end

  b_name = "b#{suffixed}"
  f_name = "f#{suffixed}"
  m_name = "m#{suffixed}"

  case full_name[0]
  when 'B'
    b_name = suffixed
  when 'F'
    f_name = suffixed
  when 'M'
    m_name = suffixed
  end

  puts <<~END_VERSE
    #{full_name}, #{full_name}, bo-#{b_name}
    Banana-fana fo-#{f_name}
    Fee-fi-mo-#{m_name}
    #{full_name}!

  END_VERSE
end

%w[Gary Earl Billy Felix Mary Steve Chris Byron].each do |name|
    print_verse name
end


object NameGame extends App {
  private def printVerse(name: String): Unit = {
    val x = name.toLowerCase.capitalize

    val y = if ("AEIOU" contains x.head) x.toLowerCase else x.tail

    val (b, f, m) = x.head match {
      case 'B' => (y, "f" + y, "m" + y)
      case 'F' => ("b" + y, y, "m" + y)
      case 'M' => ("b" + y, "f" + y, y)
      case _   => ("b" + y, "f" + y, "m" + y)
    }

    printf("%s, %s, bo-%s\n", x, x, b)
    printf("Banana-fana fo-%s\n", f)
    println(s"Fee-fi-mo-$m")
    println(s"$x!\n")
  }

  Stream("gAry", "earl", "Billy", "Felix", "Mary", "Steve").foreach(printVerse)
}


function New-Employee ($Name, $ID, $Salary, $Department) {
    New-Object PSObject `
        | Add-Member -PassThru NoteProperty EmployeeName $Name `
        | Add-Member -PassThru NoteProperty EmployeeID $ID `
        | Add-Member -PassThru NoteProperty Salary $Salary `
        | Add-Member -PassThru NoteProperty Department $Department
}

$data = (New-Employee 'Tyler Bennett'    E10297  32000  D101),
        (New-Employee 'John Rappl'       E21437  47000  D050),
        (New-Employee 'George Woltman'   E00127  53500  D101),
        (New-Employee 'Adam Smith'       E63535  18000  D202),
        (New-Employee 'Claire Buckman'   E39876  27800  D202),
        (New-Employee 'David McClellan'  E04242  41500  D101),
        (New-Employee 'Rich Holcomb'     E01234  49500  D202),
        (New-Employee 'Nathan Adams'     E41298  21900  D050),
        (New-Employee 'Richard Potter'   E43128  15900  D101),
        (New-Employee 'David Motsinger'  E27002  19250  D202),
        (New-Employee 'Tim Sampair'      E03033  27000  D101),
        (New-Employee 'Kim Arlich'       E10001  57000  D190),
        (New-Employee 'Timothy Grove'    E16398  29900  D190)

function Get-TopRank ($n) {
    $data `
        | Group-Object Department `
        | ForEach-Object {
              $_.Group `
                  | Sort-Object Salary -Descending `
                  | Select-Object -First $n
          } `
        | Format-Table -GroupBy Department
}


#!/usr/bin/env bash
namegame() {
  local name=$1 b=b f=f m=m
  local rhyme=${name#[^AaEeIiOoUu]}
  while [[ $rhyme == [^AaEeIiOoUuYy]* ]]; do
    rhyme=${rhyme#?}
  done
  if [[ "$rhyme" == [AEIOU]* ]]; then
    rhyme=$(tr A-Z a-z <<<"$rhyme")
  fi
  if [[ $name == [Bb]* ]]; then
    b=
  fi
  if [[ $name == [Ff]* ]]; then
    f=
  fi
  if [[ $name == [Mm]* ]]; then
    m=
  fi
  printf '%s, %s, bo-%s%s\n' "$name" "$name" "$b" "$rhyme"
  printf 'Banana-fana fo-%s%s\n' "$f" "$rhyme"
  printf 'Fee-fi-mo-%s%s\n' "$m" "$rhyme"
  printf '%s!\n' "$name"
}

for name in Gary Earl Billy Felix Mark Frank; do
  namegame "$name"
  echo
done


Option Explicit

Sub Main()
Dim a, r, i As Integer
Const SCHEM As String = "(X), (X), bo-b(Y)^Banana-fana fo-f(Y)^Fee-fi-mo-m(Y)^(X)!^"
   'init
   a = Array("GaRY", "Earl", "Billy", "Felix", "Mary", "Mike", "Frank")
   'compute
   r = TheGameName(a, SCHEM)
   'return
   For i = LBound(r) To UBound(r)
      Debug.Print r(i)
   Next i
End Sub

Private Function TheGameName(MyArr, S As String) As String()
Dim i As Integer, s1 As String, s2 As String, tp As String, t() As String
   ReDim t(UBound(MyArr))
   For i = LBound(MyArr) To UBound(MyArr)
      tp = Replace(S, "^", vbCrLf)
      s2 = LCase(Mid(MyArr(i), 2)): s1 = UCase(Left(MyArr(i), 1)) & s2
      Select Case UCase(Left(MyArr(i), 1))
         Case "A", "E", "I", "O", "U": tp = Replace(tp, "(Y)", LCase(MyArr(i)))
         Case "B", "F", "M"
            tp = Replace(tp, "(Y)", s2)
            tp = Replace(tp, LCase(MyArr(i)), s2)
         Case Else: tp = Replace(tp, "(Y)", s2)
      End Select
      t(i) = Replace(tp, "(X)", s1)
   Next
   TheGameName = t
End Function


Option Strict On

Imports System.Text

Module Module1

    Sub PrintVerse(name As String)
        Dim sb As New StringBuilder(name.ToLower())
        sb(0) = Char.ToUpper(sb(0))

        Dim x = sb.ToString()
        Dim y = If("AEIOU".IndexOf(x(0)) > -1, x.ToLower(), x.Substring(1))
        Dim b = "b" + y
        Dim f = "f" + y
        Dim m = "m" + y
        Select Case x(0)
            Case "B"c
                b = y
                Exit Select
            Case "F"c
                f = y
                Exit Select
            Case "M"c
                m = y
                Exit Select
        End Select

        Console.WriteLine("{0}, {0}, bo-{1}", x, b)
        Console.WriteLine("Banana-fana fo-{0}", f)
        Console.WriteLine("Fee-fi-mo-{0}", m)
        Console.WriteLine("{0}!", x)
        Console.WriteLine()
    End Sub

    Sub Main()
        Dim nameList As New List(Of String) From {"Gary", "Earl", "Billy", "Felix", "Mary", "Steve"}
        nameList.ForEach(AddressOf PrintVerse)
    End Sub

End Module


% emp(name,id,salary,dpt)
emp('Tyler Bennett','E10297',32000,'D101').
emp('John Rappl','E21437',47000,'D050').
emp('George Woltman','E00127',53500,'D101').
emp('Adam Smith','E63535',18000,'D202').
emp('Claire Buckman','E39876',27800,'D202').
emp('David McClellan','E04242',41500,'D101').
emp('Rich Holcomb','E01234',49500,'D202').
emp('Nathan Adams','E41298',21900,'D050').
emp('Richard Potter','E43128',15900,'D101').
emp('David Motsinger','E27002',19250,'D202').
emp('Tim Sampair','E03033',27000,'D101').
emp('Kim Arlich','E10001',57000,'D190').
emp('Timothy Grove','E16398',29900,'D190').

departments(Depts) :-  % Find the set of departments
  findall(Dpt, emp(_,_,_,Dpt), DList), list_to_set(DList, Depts).

greater(emp(_,_,Sal1,_), emp(_,_,Sal2,_)) :-
  Sal1 > Sal2.  % First employee salary greater than second

% Maintains a decreasing ordered list of employees truncated after (N) items.
%  Rule 1: For N=0, always return an empty set.
%  Rule 2: Add employee with greater salary at start of list, call with N-1
%  Rule 3: Try to add new employee at N-1
%  Rule 4: for an empty input list regardless of N, add the new employee
topSalary(0, _, _, []).
topSalary(N, Emp, [E|R], [Emp|Res]) :-
  greater(Emp,E), N0 is N - 1, !, topSalary(N0, E, R, Res).
topSalary(N, Emp, [E|R], [E|Res]) :-
  N0 is N - 1, !, topSalary(N0, Emp, R, Res).
topSalary(_, Emp, [], [Emp]).

% For each employee, add him to the list if top salary
topEmps(N, [Emp|Emps], R, Res) :-
  topSalary(N, Emp, R, Rt), !, topEmps(N, Emps, Rt, Res).
topEmps(_, [], Res, Res).

% For each department, find the list of top employees in that department
topDeps(N, [Dept|T], [dept(Dept,Ro)|Res]) :-
  findall(emp(Name, Id, Sal, Dept), emp(Name, Id, Sal, Dept), Emps),
  topEmps(N, Emps, [], Ro), !, topDeps(N, T, Res).
topDeps(_, [], []).

% Calculate and report the list of highest salaried employees per department
topDeps(N) :-
  departments(D), topDeps(N, D, Res),
  member(dept(Dept,R), Res),
  writef('Department: %w\n', [Dept]),
  member(emp(Name,Id,Sal,_), R),
  writef('  ID: %w\t%w\tSalary: %w\n', [Id,Name,Sal]),
  fail.
topDeps(_).


import "/str" for Str

var printVerse = Fn.new { |name|
    var x = Str.capitalize(Str.lower(name))
    var z = x[0]
    var y = "AEIOU".contains(z) ? Str.lower(x) : x[1..-1]
    var b = "b%(y)"
    var f = "f%(y)"
    var m = "m%(y)"
    if (z == "B") {
        b = y
    } else if (z == "F") {
        f = y
    } else if (z == "M") {
        m = y
    }
    System.print("%(x), %(x), bo-%(b)")
    System.print("Banana-fana fo-%(f)")
    System.print("Fee-fi-mo-%(m)")
    System.print("%(x)!\n")
}

["Gary", "Earl", "Billy", "Felix", "Mary", "Steve"].each { |name| printVerse.call(name) }


fcn printVerse(name){
   z,x := name[0].toLower(), z.toUpper() + name[1,*].toLower();
   y:=( if("aeiou".holds(z)) name.toLower() else x[1,*] );
   b,f,m := T("b","f","m").apply('wrap(c){ z==c and y or c+y });
   println("%s, %s, bo-%s".fmt(x,x,b));
   println("Banana-fana fo-",f);
   println("Fee-fi-mo-",m);
   println(x,"!\n");
}


Structure Employees
  Name$
  ID$
  Salary.i
  Department$
EndStructure

Procedure displayTopEarners(List MyEmployees.Employees(), n)
  Protected filename$ = OpenFileRequester("Top rank per group", "DataFile.txt", "", 0)
  If ReadFile(0, filename$)
    Protected InData.Employees, txt.s, MaxNameLength

    While Eof(0) = 0
      AddElement(MyEmployees())
      txt = ReadString(0)
      With MyEmployees()
        \Name$ = StringField(txt, 1, ",")
        \ID$ = StringField(txt, 2, ",")
        \Salary = Val(StringField(txt, 3, ","))
        \Department$ = StringField(txt, 4, ",")
        If Len(\Name$) > MaxNameLength: MaxNameLength = Len(\Name$): EndIf
      EndWith
    Wend
    CloseFile(0)
  Else
    MessageRequester("Information", "Couldn't open the file!")
    End
  EndIf

  If OpenConsole()
    Protected OldDepartment$, count

    SortStructuredList(MyEmployees(), #PB_Sort_Descending, OffsetOf(Employees\Salary), #PB_Sort_integer)
    SortStructuredList(MyEmployees(), #PB_Sort_Ascending, OffsetOf(Employees\Department$), #PB_Sort_String)
    ForEach MyEmployees()
      With MyEmployees()
        If \Department$ <> OldDepartment$
          If OldDepartment$ <> ""
            PrintN(#CRLF$)
          EndIf
          OldDepartment$ = \Department$
          PrintN("Department " + \Department$ + #CRLF$ + "---------------")
          PrintN(LSet("Name", MaxNameLength + 3) + LSet("ID", 7) + LSet("Salary", 7))
          count = 0
        EndIf
        count + 1
        If count <= n
          PrintN(LSet(\Name$, MaxNameLength + 1) + " " + RSet(\ID$, 7) + " $" + Str(\Salary))
        EndIf
      EndWith
    Next
    PrintN(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
  EndIf
EndProcedure

NewList MyEmployees.Employees()

displayTopEarners(MyEmployees(), 3)


from collections import defaultdict
from heapq import nlargest

data = [('Employee Name', 'Employee ID', 'Salary', 'Department'),
        ('Tyler Bennett', 'E10297', 32000, 'D101'),
        ('John Rappl', 'E21437', 47000, 'D050'),
        ('George Woltman', 'E00127', 53500, 'D101'),
        ('Adam Smith', 'E63535', 18000, 'D202'),
        ('Claire Buckman', 'E39876', 27800, 'D202'),
        ('David McClellan', 'E04242', 41500, 'D101'),
        ('Rich Holcomb', 'E01234', 49500, 'D202'),
        ('Nathan Adams', 'E41298', 21900, 'D050'),
        ('Richard Potter', 'E43128', 15900, 'D101'),
        ('David Motsinger', 'E27002', 19250, 'D202'),
        ('Tim Sampair', 'E03033', 27000, 'D101'),
        ('Kim Arlich', 'E10001', 57000, 'D190'),
        ('Timothy Grove', 'E16398', 29900, 'D190')]

departments = defaultdict(list)
for rec in data[1:]:
    departments[rec[-1]].append(rec)

N = 3
format = " %-15s " * len(data[0])
for department, recs in sorted(departments.items()):
    print ("Department %s" % department)
    print (format % data[0])
    for rec in nlargest(N, recs, key=lambda rec: rec[-2]):
        print (format % rec)
    print('')


dfr <- read.csv(tc <- textConnection(
"Employee Name,Employee ID,Salary,Department
Tyler Bennett,E10297,32000,D101
John Rappl,E21437,47000,D050
George Woltman,E00127,53500,D101
Adam Smith,E63535,18000,D202
Claire Buckman,E39876,27800,D202
David McClellan,E04242,41500,D101
Rich Holcomb,E01234,49500,D202
Nathan Adams,E41298,21900,D050
Richard Potter,E43128,15900,D101
David Motsinger,E27002,19250,D202
Tim Sampair,E03033,27000,D101
Kim Arlich,E10001,57000,D190
Timothy Grove,E16398,29900,D190")); close(tc)


#lang racket

(struct employee (name id salary dept))
(define employees
  (list (employee "Tyler Bennett"   "E10297" 32000 "D101")
        (employee "John Rappl"      "E21437" 47000 "D050")
        (employee "George Woltman"  "E00127" 53500 "D101")
        (employee "Adam Smith"      "E63535" 18000 "D202")
        (employee "Claire Buckman"  "E39876" 27800 "D202")
        (employee "David McClellan" "E04242" 41500 "D101")
        (employee "Rich Holcomb"    "E01234" 49500 "D202")
        (employee "Nathan Adams"    "E41298" 21900 "D050")
        (employee "Richard Potter"  "E43128" 15900 "D101")
        (employee "David Motsinger" "E27002" 19250 "D202")
        (employee "Tim Sampair"     "E03033" 27000 "D101")
        (employee "Kim Arlich"      "E10001" 57000 "D190")
        (employee "Timothy Grove"   "E16398" 29900 "D190")))

(define (top/dept N)
  (for/list ([dept (remove-duplicates (map employee-dept employees))])
    (define people
      (filter (λ(e) (equal? dept (employee-dept e))) employees))
    (cons dept (take (sort people > #:key employee-salary) N))))

(for ([dept (top/dept 2)])
  (printf "Department ~a:\n" (car dept))
  (for ([e (cdr dept)])
    (printf "  $~a: ~a (~a)\n"
            (employee-salary e)
            (employee-name e)
            (employee-id e))))


my @data = do for q:to/---/.lines -> $line {
        E10297  32000   D101    Tyler Bennett
        E21437  47000   D050    John Rappl
        E00127  53500   D101    George Woltman
        E63535  18000   D202    Adam Smith
        E39876  27800   D202    Claire Buckman
        E04242  41500   D101    David McClellan
        E01234  49500   D202    Rich Holcomb
        E41298  21900   D050    Nathan Adams
        E43128  15900   D101    Richard Potter
        E27002  19250   D202    David Motsinger
        E03033  27000   D101    Tim Sampair
        E10001  57000   D190    Kim Arlich
        E16398  29900   D190    Timothy Grove
        ---

  $%( < Id      Salary  Dept    Name >
      Z=>
      $line.split(/ \s\s+ /)
    )
}

sub MAIN(Int $N = 3) {
    for @data.classify({ .<Dept> }).sort».value {
        my @es = .sort: { -.<Salary> }
        say '' if (state $bline)++;
        say .< Dept Id Salary Name > for @es[^$N]:v;
    }
}


/*REXX program displays the top   N   salaries in each department (internal table).     */
parse arg topN .                                 /*get optional # for the top N salaries*/
if topN=='' | topN==","  then topN= 1            /*Not specified?  Then use the default.*/
say 'Finding the top '   topN   " salaries in each department.";            say
@.=                          /*════════ employee name      ID    salary   dept. ═══════ */
                                @.1 = "Tyler Bennett    ,E10297,  32000,  D101"
                                @.2 = "John Rappl       ,E21437,  47000,  D050"
                                @.3 = "George Woltman   ,E00127,  53500,  D101"
                                @.4 = "Adam Smith       ,E63535,  18000,  D202"
                                @.5 = "Claire Buckman   ,E39876,  27800,  D202"
                                @.6 = "David McClellan  ,E04242,  41500,  D101"
                                @.7 = "Rich Holcomb     ,E01234,  49500,  D202"
                                @.8 = "Nathan Adams     ,E41298,  21900,  D050"
                                @.9 = "Richard Potter   ,E43128,  15900,  D101"
                               @.10 = "David Motsinger  ,E27002,  19250,  D202"
                               @.11 = "Tim Sampair      ,E03033,  27000,  D101"
                               @.12 = "Kim Arlich       ,E10001,  57000,  D190"
                               @.13 = "Timothy Grove    ,E16398,  29900,  D190"
depts=                                           /*build people database from  @  array.*/
              do j=1  until @.j=='';  parse var @.j name.j ',' id.j "," sal.j ',' dept.j .
              if wordpos(dept.j, depts)==0  then depts= depts dept.j       /*a new DEPT?*/
              end   /*j*/
employees= j-1                                   /*adjust for the bumped  DO loop index.*/
say 'There are '   employees   "employees, "    words(depts)     'departments: '     depts
say
   do dep=1  for words(depts);       say         /*process each of the departments.     */
   Xdept= word(depts, dep)                       /*current department being processed.  */
      do topN;        h= 0;          highSal= 0  /*process the top  N  salaries.        */
               do e=1  for employees             /*process each employee in department. */
               if dept.e\==Xdept | sal.e<highSal then iterate  /*is this the wrong info?*/
               highSal= sal.e;        h= e       /*a higher salary was just discovered. */
               end   /*e*/
      if h==0  then iterate                      /*do we have no highest paid this time?*/
      say 'department:  '      dept.h       " $" || sal.h+0        id.h      space(name.h)
      dept.h=                                    /*make sure we see the employee again. */
      end         /*topN*/
   end             /*dep*/                       /*stick a fork in it,  we're all done. */


# Project : Top rank per group

load "stdlib.ring"
salary = "Tyler Bennett,E10297,32000,D101
John Rappl,E21437,47000,D050
George Woltman,E00127,53500,D101
Adam Smith,E63535,18000,D202
Claire Buckman,E39876,27800,D202
David McClellan,E04242,41500,D101
Rich Holcomb,E01234,49500,D202
Nathan Adams,E41298,21900,D050
Richard Potter,E43128,15900,D101
David Motsinger,E27002,19250,D202
Tim Sampair,E03033,27000,D101
Kim Arlich,E10001,57000,D190
Timothy Grove,E16398,29900,D190"

temp = substr(salary, ",", nl)
temp = str2list(temp)
depsal = newlist(13,4)
for n = 1 to len(temp)
     n1 = ceil(n/4)
     n2 = n%4
     if n2 = 0
        n2 = 4
     ok
     depsal[n1][n2] = temp[n]
next
for n = 1 to len(depsal)-1
     for m = n+1 to len(depsal)
          if strcmp(depsal[m][4], depsal[n][4]) < 0
              tmp = depsal[n]
              depsal[n] = depsal[m]
              depsal[m] = tmp
          ok
      next
next
for n = 1 to len(depsal)-1
     for m = n+1 to len(depsal)
           if (depsal[m][4] = depsal[n][4]) and (depsal[m][3] > depsal[n][3])
               tmp = depsal[n]
               depsal[n] = depsal[m]
               depsal[m] = tmp
           ok
      next
next
see "Department : " + depsal[1][4] + nl
see "Name                   " + "Id             " + "Salary" + nl + nl
see "" + depsal[1][1] + "      " + depsal[1][2] + "      " + depsal[1][3]+ nl
for n = 1 to len(depsal)-1
    if (depsal[n+1][4] != depsal[n][4])
        see nl
        see "Department : " + depsal[n+1][4] + nl
        see "Name                   " + "Id             " + "Salary" + nl + nl
        see "" + depsal[n+1][1] + "      " + depsal[n+1][2] + "      " + depsal[n+1][3]+ nl
     else
        see "" + depsal[n+1][1] + "      " + depsal[n+1][2] + "      " + depsal[n+1][3]+ nl
     ok
next


require "csv"

data = <<EOS
Employee Name,Employee ID,Salary,Department
Tyler Bennett,E10297,32000,D101
John Rappl,E21437,47000,D050
George Woltman,E00127,53500,D101
Adam Smith,E63535,18000,D202
Claire Buckman,E39876,27800,D202
David McClellan,E04242,41500,D101
Rich Holcomb,E01234,49500,D202
Nathan Adams,E41298,21900,D050
Richard Potter,E43128,15900,D101
David Motsinger,E27002,19250,D202
Tim Sampair,E03033,27000,D101
Kim Arlich,E10001,57000,D190
Timothy Grove,E16398,29900,D190
EOS

def show_top_salaries_per_group(data, n)
  table = CSV.parse(data, :headers=>true, :header_converters=>:symbol)
  groups = table.group_by{|emp| emp[:department]}.sort
  groups.each do |dept, emps|
    puts dept
    # max by salary
    emps.max_by(n) {|emp| emp[:salary].to_i}.each do |e|
      puts "    %-16s %6s %7d" % [e[:employee_name], e[:employee_id], e[:salary]]
    end
    puts
  end
end

show_top_salaries_per_group(data, 3)


perSal$ = "Tyler Bennett,E10297,32000,D101
John Rappl,E21437,47000,D050;
George Woltman,E00127,53500,D101
Adam Smith,E63535,18000,D202;
Claire Buckman,E39876,27800,D202
David McClellan,E04242,41500,D101
Rich Holcomb,E01234,49500,D202
Nathan Adams,E41298,21900,D050
Richard Potter,E43128,15900,D101
David Motsinger,E27002,19250,D202
Tim Sampair,E03033,27000,D101
Kim Arlich,E10001,57000,D190
Timothy Grove,E16398,29900,D190"

while word$(perSal$,n+1,chr$(13)) <> "" : n = n + 1 : wend   ' get count of employees
dim depSal$(n)
for i = 1 to n
  depSal$(i) = word$(perSal$,i,chr$(13))
next i
sw = 1
while sw = 1
  sw = 0
  for i = 1 to n -1
    if word$(depSal$(i),4,",")+word$(depSal$(i),3,",") > word$(depSal$(i+1),4,",")+word$(depSal$(i+1),3,",") then
      temp$        = depSal$(i)
      depSal$(i)   = depSal$(i+1)
      depSal$(i+1) = temp$
      sw           = 1
    end if
  next i
wend
print "Employee Name";chr$(9);"ID";chr$(9);"Salary"
for i = 1 to n
  if dep$ <> word$(depSal$(i),4,",") then
    dep$ = word$(depSal$(i),4,",")
    print : print"Department:";dep$
  end if
print word$(depSal$(i),1,",");chr$(9);word$(depSal$(i),2,",");chr$(9);word$(depSal$(i),3,",")
next i


#[derive(Debug)]
struct Employee<S> {
    // Allow S to be any suitable string representation
    id: S,
    name: S,
    department: S,
    salary: u32,
}

impl<S> Employee<S> {
    fn new(name: S, id: S, salary: u32, department: S) -> Self {
        Self {
            id,
            name,
            department,
            salary,
        }
    }
}

#[rustfmt::skip]
fn load_data() -> Vec<Employee<&'static str>> {
    vec![
        Employee::new("Tyler Bennett",    "E10297", 32000, "D101"),
        Employee::new("John Rappl",       "E21437", 47000, "D050"),
        Employee::new("George Woltman",   "E00127", 53500, "D101"),
        Employee::new("Adam Smith",       "E63535", 18000, "D202"),
        Employee::new("Claire Buckman",   "E39876", 27800, "D202"),
        Employee::new("David McClellan",  "E04242", 41500, "D101"),
        Employee::new("Rich Holcomb",     "E01234", 49500, "D202"),
        Employee::new("Nathan Adams",     "E41298", 21900, "D050"),
        Employee::new("Richard Potter",   "E43128", 15900, "D101"),
        Employee::new("David Motsinger",  "E27002", 19250, "D202"),
        Employee::new("Tim Sampair",      "E03033", 27000, "D101"),
        Employee::new("Kim Arlich",       "E10001", 57000, "D190"),
        Employee::new("Timothy Grove",    "E16398", 29900, "D190"),
        // Added to demonstrate various tie situations
        Employee::new("Kim Tie",          "E16400", 57000, "D190"),
        Employee::new("Timothy Tie",      "E16401", 29900, "D190"),
        Employee::new("Timothy Kim",      "E16401", 19900, "D190"),
    ]
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let n = {
        println!("How many top salaries to list? ");
        let mut buf = String::new();
        std::io::stdin().read_line(&mut buf)?;
        buf.trim().parse::<u32>()?
    };

    let mut employees = load_data();

    // Reverse order, then just pick top N employees
    employees.sort_by(|a, b| b.salary.cmp(&a.salary));

    let sorted = employees
        .into_iter()
        .fold(std::collections::BTreeMap::new(), |mut acc, next| {
            // We store the number of unique salaries as well to handle
            // ties (and list always all employees with the same salary)
            let mut bucket = acc
                .entry(next.department)
                .or_insert_with(|| (0, Vec::<Employee<_>>::new()));

            match bucket.1.last().map(|e| e.salary) {
                Some(last_salary) if last_salary == next.salary => {
                    if bucket.0 <= n {
                        bucket.1.push(next);
                    }
                }

                _ => {
                    if bucket.0 < n {
                        bucket.0 += 1; // Next unique salary
                        bucket.1.push(next);
                    }
                }
            }

            acc
        });

    for (department, (_, employees)) in sorted {
        println!("{}", department);

        employees
            .iter()
            .for_each(|employee| println!("    {:?}", employee));
    }

    Ok(())
}


import scala.io.Source
import scala.language.implicitConversions
import scala.language.reflectiveCalls
import scala.collection.immutable.TreeMap

object TopRank extends App {
  val topN = 3

  val rawData = """Employee Name;Employee ID;Salary;Department
               |Tyler Bennett;E10297;32000;D101
               |John Rappl;E21437;47000;D050
               |George Woltman;E00127;53500;D101
               |Adam Smith;E63535;18000;D202
               |Claire Buckman;E39876;27800;D202
               |David McClellan;E04242;41500;D101
               |Rich Holcomb;E01234;49500;D202
               |Nathan Adams;E41298;21900;D050
               |Richard Potter;E43128;15900;D101
               |David Motsinger;E27002;19250;D202
               |Tim Sampair;E03033;27000;D101
               |Kim Arlich;E10001;57000;D190
               |Timothy Grove;E16398;29900;D190""".stripMargin

  class Employee(name: String, id: String,
                 val salary: Int,
                 val department: String) {
    override def toString = s"$id\t$salary\t$name"
  }

  // A TreeMap has sorted keys
  val data: TreeMap[String, Seq[TopRank.Employee]] = // TreeMap is a sorted map
    TreeMap((Source.fromString(rawData) getLines ()).toSeq // Runtime parsing
      .drop(1) // Drop header
      .map(_.split(";")) //read fields into list of employees
      .map(emp => new Employee(emp(0), emp(1), emp(2).toInt, emp(3)))
      .groupBy(_.department).toSeq: _*)

  implicit def iterableWithAvg[T: Numeric](data: Iterable[T]) = new {
    def average[T](ts: Iterable[T])(implicit num: Numeric[T]) = {
      num.toDouble(ts.sum) / ts.size
    }
    def avg = average(data)
  }

  val a = data.flatMap { case (_, emps) => emps.map(_.salary) }.avg

  println(s"Reporting top $topN salaries in each department.\n")

  println(s"Total of ${data.foldLeft(0)(_ + _._2.size)} employees in ${data.size} departments")

  println(f"Average salary: $a%8.2f\n")

  data.foreach {
    case (dep, emps) => println(f"Department: $dep  pop: ${emps.size} avg: ${emps.map(_.salary).avg}%8.2f\n"
      + emps.sortBy(-_.salary).take(topN)
      .map(_.toString).mkString("\t", "\n\t", ""))
  }
}


(use gauche.record)

;;  This will let us treat a list as though it is a structure (record).
(define-record-type (employee (pseudo-rtd <list>)) #t #t
  name id salary dept)

(define (get-fields str)
  (map (^x (if (#/^\d/ x) (string->number x) x))
       (string-split str #\,)))

(define (print-record column-widths record)
  (display "  ")
  (print (string-join
    (map
      (^(x width)
        (if (number? x)
          (format "~vD" width x)
          (format "~vA" width x)))
      record
      column-widths))))

(define (get-column-widths records)
  (apply
    map
      (lambda column
        (apply max (map (compose string-length x->string) column)))
      records))

(define records
  (map get-fields
    (string-split
      "Tyler Bennett,E10297,32000,D101
      John Rappl,E21437,47000,D050
      George Woltman,E00127,53500,D101
      Adam Smith,E63535,18000,D202
      Claire Buckman,E39876,27800,D202
      David McClellan,E04242,41500,D101
      Rich Holcomb,E01234,49500,D202
      Nathan Adams,E41298,21900,D050
      Richard Potter,E43128,15900,D101
      David Motsinger,E27002,19250,D202
      Tim Sampair,E03033,27000,D101
      Kim Arlich,E10001,57000,D190
      Timothy Grove,E16398,29900,D190"
      #/\s*\n\s*/)))

(define (top-salaries n records)
  (let ((departments (sort (delete-duplicates (map employee-dept records))))
        (col-widths (get-column-widths records))
        (sorted-by-salary (sort records > employee-salary)))
    (dolist (dept departments)
      (print dept)
      (let1 matches (filter (^x (string=? dept (employee-dept x)))
                            sorted-by-salary)
        (for-each
          (pa$ print-record col-widths)
          (take* matches n))))))


var data = <<'EOF'.lines.map{ <name id salary dept> ~Z .split(',') -> flat.to_h }
Tyler Bennett,E10297,32000,D101
John Rappl,E21437,47000,D050
George Woltman,E00127,53500,D101
Adam Smith,E63535,18000,D202
Claire Buckman,E39876,27800,D202
David McClellan,E04242,41500,D101
Rich Holcomb,E01234,49500,D202
Nathan Adams,E41298,21900,D050
Richard Potter,E43128,15900,D101
David Motsinger,E27002,19250,D202
Tim Sampair,E03033,27000,D101
Kim Arlich,E10001,57000,D190
Timothy Grove,E16398,29900,D190
EOF

var n = (ARGV ? Num(ARGV[0]) : "usage: #{__MAIN__} [n]\n".die)

for d in (data.map {|h| h{:dept} }.uniq.sort) {
    var es = data.grep { _{:dept} == d }.sort_by { -Num(_{:salary}) }
    say d
    n.times {
        es || break
        printf("%-15s | %-6s | %5d\n", es.shift(){<name id salary>...})
    }
    print "\n"
}


table: Employees
----------------
empID
dept
empName
salary


CREATE TABLE EMP
(
EMP_ID  varchar2(6 CHAR),
EMP_NAMEvarchar2(20 CHAR),
DEPT_ID varchar2(4 CHAR),
SALARY  NUMBER(10,2)
);

INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E21437','John Rappl','D050',47000);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E10297','Tyler Bennett','D101',32000);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E00127','George Woltman','D101',53500);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E63535','Adam Smith','D202',18000);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E39876','Claire Buckman','D202',27800);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E04242','David McClellan','D101',41500);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E41298','Nathan Adams','D050',21900);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E43128','Richard Potter','D101',15900);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E27002','David Motsinger','D202',19250);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E03033','Tim Sampair','D101',27000);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E10001','Kim Arlich','D190',57000);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E16398','Timothy Grove','D190',29900);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E01234','Rich Holcomb','D202',49500);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E16399','Timothy Grave','D190',29900);
INSERT INTO EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
 VALUES ('E16400','Timothy Grive','D190',29900);
COMMIT;


import delimited employees.csv
local k 2
bysort department (salary): list salary if _N-_n<`k'


struct Employee {
  var name: String
  var id: String
  var salary: Int
  var department: String
}

let employees = [
  Employee(name: "Tyler Bennett", id: "E10297", salary: 32000, department: "D101"),
  Employee(name: "John Rappl", id: "E21437", salary: 47000, department: "D050"),
  Employee(name: "George Woltman", id: "E00127", salary: 53500, department: "D101"),
  Employee(name: "Adam Smith", id: "E63535", salary: 18000, department: "D202"),
  Employee(name: "Claire Buckman", id: "E39876", salary: 27800, department: "D202"),
  Employee(name: "David McClellan", id: "E04242", salary: 41500, department: "D101"),
  Employee(name: "Rich Holcomb", id: "E01234", salary: 49500, department: "D202"),
  Employee(name: "Nathan Adams", id: "E41298", salary: 21900, department: "D050"),
  Employee(name: "Richard Potter", id: "E43128", salary: 15900, department: "D101"),
  Employee(name: "David Motsinger", id: "E27002", salary: 19250, department: "D202"),
  Employee(name: "Tim Sampair", id: "E03033", salary: 27000, department: "D101"),
  Employee(name: "Kim Arlich", id: "E10001", salary: 57000, department: "D190"),
  Employee(name: "Timothy Grove", id: "E16398", salary: 29900, department: "D190")
]

func highestSalaries(employees: [Employee], n: Int = 1) -> [String: [Employee]] {
  return employees.reduce(into: [:], {acc, employee in
    guard var cur = acc[employee.department] else {
      acc[employee.department] = [employee]

      return
    }

    if cur.count < n {
      cur.append(employee)
    } else if cur.last!.salary < employee.salary {
      cur[n - 1] = employee
    }

    acc[employee.department] = cur.sorted(by: { $0.salary > $1.salary })
  })
}

for (dept, employees) in highestSalaries(employees: employees, n: 3) {
  let employeeString = employees.map({ "\($0.name): \($0.salary)" }).joined(separator: "\n\t")

  print("\(dept)'s highest paid employees are: \n\t\(employeeString)")
}


package require Tcl 8.5

set text {Tyler Bennett,E10297,32000,D101
John Rappl,E21437,47000,D050
George Woltman,E00127,53500,D101
Adam Smith,E63535,18000,D202
Claire Buckman,E39876,27800,D202
David McClellan,E04242,41500,D101
Rich Holcomb,E01234,49500,D202
Nathan Adams,E41298,21900,D050
Richard Potter,E43128,15900,D101
David Motsinger,E27002,19250,D202
Tim Sampair,E03033,27000,D101
Kim Arlich,E10001,57000,D190
Timothy Grove,E16398,29900,D190}

set data [dict create]
foreach line [split $text \n] {
    lassign [split $line ,] name id salary dept
    dict lappend data $dept [list $name $id $salary]
}

proc top_n_salaries {n data} {
    incr n -1
    dict for {dept employees} $data {
        puts "Department $dept"
        foreach emp [lrange [lsort -integer -decreasing -index 2 $employees] 0 $n] {
            puts [format "   %-20s %-8s %8d" {*}$emp]
        }
        puts ""
    }
}

top_n_salaries 3 $data


#lang transd

MainModule: {
tbl : String(
`EmployeeName,EmployeeID,Salary:Int,Department
Tyler Bennett,	E10297,32000,D101
John Rappl,	E21437,47000,D050
George Woltman,	E00127,53500,D101
Adam Smith,	E63535,18000,D202
Claire Buckman,	E39876,27800,D202
David McClellan,E04242,41500,D101
Rich Holcomb,	E01234,49500,D202
Nathan Adams,	E41298,21900,D050
Richard Potter,	E43128,15900,D101
David Motsinger,E27002,19250,D202
Tim Sampair,	E03033,27000,D101
Kim Arlich,	E10001,57000,D190
Timothy Grove,	E16398,29900,D190`),

    N: 2,
    _start: (λ
    (with tabl Table()
        (load-table tabl tbl)
        (build-index tabl "Department")
        (with rows (tsd-query tabl
            select: ["Department"]
            as: [[String()]] :distinct sortby: "Department" )
        (for row in rows do
            (with recs (tsd-query tabl
                select: all
                    as: [[String(), String(), Int(), String()]]
            satisfying: (lambda Department String()
                            (eq Department (get row 0)))
                sortby: "Salary" :desc
                 limit: N)
           (for rec in recs do (textout rec "\n")))))))
}


$$ MODE TUSCRIPT
MODE DATA
$$ SET dates=*
Tyler Bennett,E10297,32000,D101
John Rappl,E21437,47000,D050
George Woltman,E00127,53500,D101
Adam Smith,E63535,18000,D202
Claire Buckman,E39876,27800,D202
David McClellan,E04242,41500,D101
Rich Holcomb,E01234,49500,D202
Nathan Adams,E41298,21900,D050
Richard Potter,E43128,15900,D101
David Motsinger,E27002,19250,D202
Tim Sampair,E03033,27000,D101
Kim Arlich,E10001,57000,D190
Timothy Grove,E16398,29900,D190
$$ MODE TUSCRIPT
SET nix=SPLIT (dates,":,:",EmployeeName,Employee_ID,Salary,Department)
SET d=MIXED_SORT (department),d=REDUCE(d)
SET index=DIGIT_INDEX(salary), index=REVERSE(index)
SET employeeName=INDEX_SORT (employeeName,index)
SET employee_ID =INDEX_SORT (employee_ID,index)
SET Salary=INDEX_SORT (salary,index)
SET Department=INDEX_SORT (Department,index)
COMPILE
LOOP l=d
PRINT "Department ", l
SET rtable=QUOTES (l)
BUILD R_TABLE pos = rtable
SET id=FILTER_INDEX (department,pos,-)
RELEASE R_TABLE pos
SET en  =SELECT (employeeName,#id)
SET ei  =SELECT (employee_ID,#id)
SET sal =SELECT (salary,#id)
SET he  =CENTER ("employeeName",-16)
SET hi  =CENTER ("employee ID",-11)
SET hs  =CENTER ("Salary",+10)
SET line=REPEAT ("-",37)
PRINT he,hi,hs
PRINT line
 LOOP e=en,i=ei,s=sal
 SET e=CENTER (e,-16), i=CENTER (i,-11), s=CENTER (s,+10)
 PRINT e,i,s
 ENDLOOP
PRINT " "
ENDLOOP
ENDCOMPILE


@(next :args)
@{n-param}
@(next "top-rank-per-group.dat")
Employee Name,Employee ID,Salary,Department
@(collect :vars (record))
@name,@id,@salary,@dept
@(bind record (@(int-str salary) dept name id))
@(end)
@(bind (dept salary dept2 name id)
  @(let* ((n (int-str n-param))
          (dept-hash [group-by second record :equal-based])
          (dept (hash-keys dept-hash))
          (ranked (collect-each ((rec (hash-values dept-hash)))
                    [apply mapcar list [[sort rec > first] 0..n]])))
     (cons dept [apply mapcar list ranked])))
@(output)
@  (repeat)
Department: @dept
@    (repeat)
  @{name 15} (@id)  [email protected]{salary -6}
@    (end)
@  (end)
@(end)


#import std
#import nat

data =

-[
Employee Name,Employee ID,Salary,Department
Tyler Bennett,E10297,32000,D101
John Rappl,E21437,47000,D050
George Woltman,E00127,53500,D101
Adam Smith,E63535,18000,D202
Claire Buckman,E39876,27800,D202
David McClellan,E04242,41500,D101
Rich Holcomb,E01234,49500,D202
Nathan Adams,E41298,21900,D050
Richard Potter,E43128,15900,D101
David Motsinger,E27002,19250,D202
Tim Sampair,E03033,27000,D101
Kim Arlich,E10001,57000,D190
Timothy Grove,E16398,29900,D190]-

top "n" = @tt sep`,*; mat0+ ^C(~&hz,mat`,*yS)*+ take/*"n"+ *zK2 (nleq+ %np~~)-<x&yzNC

#show+

main = top3 data


Private Sub top_rank(filename As String, n As Integer)
    Workbooks.OpenText filename:=filename, Comma:=True
    Dim ws As Worksheet
    Set ws = Sheets.Add: ws.Name = "output"
    ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
        "data!R1C1:R14C4", Version:=6).CreatePivotTable TableDestination:= _
        "output!R3C1", TableName:="TableName", DefaultVersion:=6
    With Sheets("output").PivotTables("TableName")
        .InGridDropZones = True
        .RowAxisLayout xlTabularRow
        .AddDataField Sheets("output").PivotTables("TableName"). _
                PivotFields("Salary"), "Top rank", xlSum
        .PivotFields("Department").Orientation = xlRowField
        .PivotFields("Department").Position = 1
        .PivotFields("Salary").Orientation = xlRowField
        .PivotFields("Salary").Position = 2
        .PivotFields("Employee Name").Orientation = xlRowField
        .PivotFields("Employee Name").Position = 3
        .PivotFields("Employee ID").Orientation = xlRowField
        .PivotFields("Employee ID").Position = 4
        .PivotFields("Salary").PivotFilters.Add2 Type:=xlTopCount, _
            DataField:=Sheets("output").PivotTables("TableName"). _
            PivotFields("Top rank"), Value1:=n
        .PivotFields("Salary").Subtotals = Array(False, False, False, False, _
            False, False, False, False, False, False, False, False)
        .PivotFields("Employee Name").Subtotals = Array(False, False, False, _
            False, False, False, False, False, False, False, False, False)
        .PivotFields("Department").Subtotals = Array(False, False, False, False, _
            False, False, False, False, False, False, False, False)
        .ColumnGrand = False
        .PivotFields("Salary").AutoSort xlDescending, "Salary"
    End With
End Sub

Public Sub main()
    top_rank filename:="D:\data.txt", n:=3
End Sub


import "/dynamic" for Tuple
import "/sort" for Sort, Cmp
import "/seq" for Lst
import "/fmt" for Fmt

var Employee = Tuple.create("Employee", ["name", "id", "salary", "dept"])

var N = 2 // say

var employees = [
    Employee.new("Tyler Bennett", "E10297", 32000, "D101"),
    Employee.new("John Rappl", "E21437", 47000, "D050"),
    Employee.new("George Woltman" , "E00127", 53500, "D101"),
    Employee.new("Adam Smith", "E63535", 18000, "D202"),
    Employee.new("Claire Buckman", "E39876", 27800, "D202"),
    Employee.new("David McClellan", "E04242", 41500, "D101"),
    Employee.new("Rich Holcomb", "E01234", 49500, "D202"),
    Employee.new("Nathan Adams", "E41298", 21900, "D050"),
    Employee.new("Richard Potter", "E43128", 15900, "D101"),
    Employee.new("David Motsinger", "E27002", 19250, "D202"),
    Employee.new("Tim Sampair", "E03033", 27000, "D101"),
    Employee.new("Kim Arlich", "E10001", 57000, "D190"),
    Employee.new("Timothy Grove", "E16398", 29900, "D190")
]
var cmpByDept = Fn.new { |employee1, employee2| Cmp.string.call(employee1.dept, employee2.dept) }
Sort.insertion(employees, cmpByDept)
var groupsByDept = Lst.groups(employees) { |e| e.dept }
System.print("Highest %(N) salaries by department:\n")
for (group in groupsByDept) {
    var dept = group[0]
    var groupEmployees = group[1].map { |i| i[0] }.toList
    var cmpBySalary = Fn.new { |employee1, employee2| Cmp.numDesc.call(employee1.salary, employee2.salary) }
    Sort.insertion(groupEmployees, cmpBySalary)
    var topRanked = groupEmployees.take(N)
    System.print("Dept %(dept) => ")
    topRanked.each { |e| Fmt.print("$-15s $s $d", e.name, e.id, e.salary) }
    System.print()
}


proc Sort(Array, Field, Size);  \Sort Array in descending order by Field
int  Array, Field, Size, I, J, T;
[for J:= Size-1 downto 0 do
    for I:= 0 to J-1 do
        if Array(I,Field) < Array(I+1,Field) then
            [T:= Array(I);  Array(I):= Array(I+1);  Array(I+1):= T];
];

int Data, I, I0, Dept, N, Cnt;
[Data:=[["Tyler Bennett",   "E10297", 32000, 101],
        ["John Rappl",      "E21437", 47000, 050],
        ["George Woltman",  "E00127", 53500, 101],
        ["Adam Smith",      "E63535", 18000, 202],
        ["Claire Buckman",  "E39876", 27800, 202],
        ["David McClellan", "E04242", 41500, 101],
        ["Rich Holcomb",    "E01234", 49500, 202],
        ["Nathan Adams",    "E41298", 21900, 050],
        ["Richard Potter",  "E43128", 15900, 101],
        ["David Motsinger", "E27002", 19250, 202],
        ["Tim Sampair",     "E03033", 27000, 101],
        ["Kim Arlich",      "E10001", 57000, 190],
        ["Timothy Grove",   "E16398", 29900, 190],
        [0,                  0,       0,     000]];     \sentinel
I:= 0;                  \find number of employees = Data size
while Data(I,0) # 0 do I:= I+1;
Sort(Data, 3, I);       \sort by department field (3)
I:= 0;                  \sort by salary within each department
while Data(I,0) do
        [Dept:= Data(I,3);
        I0:= I;
        repeat I:= I+1 until Data(I,3) # Dept;
        Sort(@Data(I0), 2, I-I0);
        ];
N:= IntIn(0);                           \get parameter
I:= 0;
loop    [Dept:= Data(I,3);              \for each department
        Text(0, "Department D");
        if Dept < 100 then ChOut(0, ^0);  IntOut(0, Dept);  Text(0, ":^m^j");
        Cnt:= 0;
        loop    [if Cnt >= N then
                    while Data(I,3) = Dept do I:= I+1;  \skip any remaining
                if Data(I,3) # Dept then quit;
                IntOut(0, Data(I,2)); Text(0, "   ");   \salary
                Text(0, Data(I,1));   Text(0, "   ");   \ID
                Text(0, Data(I,0));   CrLf(0);          \name
                Cnt:= Cnt+1;
                I:= I+1;
                ];
        if Data(I,0) = 0 then quit;
        ];
]


fcn setAppend(d,[(key,data)]){ d[key]=d.find(key,T).append(data) } //-->(key,(data,data...))

fcn topNsalaries(n){
   File("data.txt").pump(setAppend.fp(data:=D()),fcn(line){ //-->Dictionary(dept:salaries)
      line=line.strip().split(",");
      T(line[-1],line[-2]); //-->(dept,salary)
   });
   dss:=data.pump(List,fcn([(dept,ss)],N){ //-->(dept,(salaries), dept...)
      T(dept).append(ss.sort()[-N,*].reverse());
   }.fp1(n)).sort(fcn(a,b){a[0]<b[0]});
   foreach d,ss in (dss){
      "%s: %s".fmt(d,ss.concat(",")).println();
   }
}(3);


V gifts = |‘A partridge in a pear tree.
            Two turtle doves
            Three french hens
            Four calling birds
            Five golden rings
            Six geese a-laying
            Seven swans a-swimming
            Eight maids a-milking
            Nine ladies dancing
            Ten lords a-leaping
            Eleven pipers piping
            Twelve drummers drumming’.split("\n")

V days = ‘first second third fourth fifth sixth seventh eighth ninth tenth eleventh twelfth’.split(‘ ’)

L(day) days
   V n = L.index + 1
   V g = reversed(gifts[0 .< n])
   print("\nOn the #. day of Christmas\nMy true love gave to me:\n".format(day)‘’g[0 .< (len)-1].join("\n")‘’(I n > 1 {" and\n"g.last} E g.last))


CR:	equ	13
LF:	equ	10
puts:	equ	9	; CP/M function to write a string to the console
bdos:	equ	5	; CP/M entry point
	org	100h
	mvi	e,0	; Start with first verse
	;;;	Print verse
verse:	lxi	h,onthe	; On the
	call	pstr
	lxi	h,ordtab
	call	ptabs	; Nth
	lxi 	h,doc
	call	pstr	; day of Christmas, my true love gave to me
	lxi	h,vrstab
	call	ptabs	; ...whatever stuff
	inr	e	; next verse
	mov	a,e
	cpi	12	; if at 12, stop
	jnz	verse	; otherwise, print another verse
	ret
	;;;	Print the E'th string from the table under HL,
	;;;	preserving DE registers.
ptabs:	push 	d	; Save DE registers
	mvi	d,0	; Add E*2 to HL, looking up the pointer
	dad	d
	dad	d
	mov	a,m	; Load low byte of pointer
	inx	h
	mov	h,m	; Load high byte of pointer
	mov	l,a
	xchg		; Store pointer in DE
	mvi	c,puts	; Print string in DE using CP/M
	call	bdos
	pop	d	; Restore registers
	ret
	;;;	Print the string under HL, preserving DE registers.
pstr:	push	d
	xchg
	mvi	c,puts
	call	bdos
	pop	d
	ret
ordtab:	dw	first,second,third,forth,fifth,sixth
	dw	_7th,eighth,ninth,tenth,_11th,_12th
vrstab:	dw	one,two,three,four,five,six,seven,eight
	dw	nine,ten,eleven,twelve
onthe:	db	'On the $'
first:	db	'first$'
second:	db	'second$'
third:	db	'third$'
forth:	db	'forth$'
fifth:	db	'fifth$'
sixth:	db	'sixth$'
_7th:	db	'seventh$'
eighth:	db	'eighth$'
ninth:	db	'ninth$'
tenth:	db	'tenth$'
_11th:	db	'eleventh$'
_12th:	db	'twelfth$'
doc:	db	' day of Christmas',CR,LF
	db	'My true love gave to me:',CR,LF,'$'
twelve:	db	'Twelve drummers drumming',CR,LF
eleven:	db	'Eleven pipers piping',CR,LF
ten:	db	'Ten lords a-leaping',CR,LF
nine:	db	'Nine ladies dancing',CR,LF
eight:	db	'Eight maids a-milking',CR,LF
seven:	db	'Seven swans a-swimming',CR,LF
six:	db	'Six geese a-laying',CR,LF
five:	db	'Five golden rings',CR,LF
four: 	db	'Four calling birds',CR,LF
three:	db	'Three french hens',CR,LF
two:	db	'Two turtle doves and',CR,LF
one:	db	'A partridge in a pear tree.',CR,LF
	db	CR,LF,'$'


CR:	equ	10
LF:	equ	13
puts:	equ	9	; MS-DOS syscall to print string
	cpu	8086
	bits	16
	org	100h
section	.text
	xor	cx,cx		; Start with first verse
verse:	mov	dx,onthe	; On the...
	call	pstr
	mov	si,ord.tab	; Nth
	call	ptabs
	mov	dx,doc		; day of Christmas, my true love
	call	pstr		; gave to me...
	mov	si,vrs.tab	; the gifts
	call	ptabs
	inc	cx		; Next verse
	cmp	cx,12		; If not last verse,
	jb	verse		; then print next verse.
	ret
	;;;	Print the CX'th string from the table in [SI].
ptabs:	mov	bx,cx		; BX = CX*2
	shl	bx,1		; (Each entry is 2 bytes wide)
	mov	dx,[bx+si]	; Retrieve table entry
	;;;	Print the string in DX.
pstr:	mov	ah,puts		; Tell DOS to print the string
	int	21h
	ret
section	.data
onthe:	db	'On the $'
ord:
.n1:	db	'first$'
.n2:	db	'second$'
.n3:	db	'third$'
.n4:	db	'forth$'
.n5:	db	'fifth$'
.n6:	db	'sixth$'
.n7:	db	'seventh$'
.n8:	db	'eighth$'
.n9:	db	'ninth$'
.n10:	db	'tenth$'
.n11:	db	'eleventh$'
.n12:	db	'twelfth$'
.tab:	dw	.n1,.n2,.n3,.n4,.n5,.n6
	dw	.n7,.n8,.n9,.n10,.n11,.n12
doc:	db	' day of Christmas',CR,LF
	db	'My true love gave to me:',CR,LF,'$'
vrs:
.n12:	db	'Twelve drummers drumming',CR,LF
.n11:	db	'Eleven pipers piping',CR,LF
.n10:	db	'Ten lords a-leaping',CR,LF
.n9:	db	'Nine ladies dancing',CR,LF
.n8:	db	'Eight maids a-milking',CR,LF
.n7:	db	'Seven swans a-swimming',CR,LF
.n6:	db	'Six geese a-laying',CR,LF
.n5:	db	'Five golden rings',CR,LF
.n4: 	db	'Four calling birds',CR,LF
.n3:	db	'Three french hens',CR,LF
.n2:	db	'Two turtle doves and',CR,LF
.n1:	db	'A partridge in a pear tree.',CR,LF
	db	CR,LF,'$'
.tab:	dw	.n1,.n2,.n3,.n4,.n5,.n6
	dw	.n7,.n8,.n9,.n10,.n11,.n12


PROC Wait(BYTE frames)
  BYTE RTCLOK=$14
  frames==+RTCLOK
  WHILE frames#RTCLOK DO OD
RETURN

PROC Main()
  DEFINE PTR="CARD"
  PTR ARRAY num(12),obj(12)
  BYTE i,j

  num(0)="first" num(1)="second" num(2)="third"
  num(3)="fourth" num(4)="fifth" num(5)="sixth"
  num(6)="seventh" num(7)="eight" num(8)="ninth"
  num(9)="tenth" num(10)="eleventh" num(11)="Twelfth"

  obj(0)="And a partridge in a pear tree."
  obj(1)="Two turtle doves"
  obj(2)="Three french hens"
  obj(3)="Four calling birds"
  obj(4)="Five golden rings"
  obj(5)="Six geese a-laying"
  obj(6)="Seven swans a-swimming"
  obj(7)="Eight maids a-milking"
  obj(8)="Nine ladies dancing"
  obj(9)="Ten lords a-leaping"
  obj(10)="Eleven pipers piping"
  obj(11)="Twelve drummers drumming"

  FOR i=0 TO 11
  DO
    PrintF("On the %S day of Christmas,%E",num(i))
    PrintE("My true love gave to me:")
    IF i=0 THEN
      PrintE("A partridge in a pear tree.")
    ELSE
      j=i+1
      WHILE j>0
      DO
        j==-1
        PrintE(obj(j))
      OD
    FI
    PutE()
    Wait(50)
  OD
RETURN


package {

    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;
    import flash.ui.Keyboard;

    public class TwelveDaysOfChristmas extends Sprite {

        private var _textArea:TextField = new TextField();

        public function TwelveDaysOfChristmas() {
            if ( stage ) _init();
            else addEventListener(Event.ADDED_TO_STAGE, _init);
        }

        private function _init(e:Event = null):void {

            removeEventListener(Event.ADDED_TO_STAGE, _init);

            _textArea = new TextField();
            _textArea.x = 10;
            _textArea.y = 10;
            _textArea.autoSize = TextFieldAutoSize.LEFT;
            _textArea.wordWrap = true;
            _textArea.width = stage.stageWidth - 20;
            _textArea.height = stage.stageHeight - 10;
            _textArea.multiline = true;

            var format:TextFormat = new TextFormat();
            format.size = 14;
            _textArea.defaultTextFormat = format;

            var verses:Vector.<String> = new Vector.<String>(12, true);
            var lines:Vector.<String>;

            var days:Vector.<String> = new Vector.<String>(12, true);
            var gifts:Vector.<String> = new Vector.<String>(12, true);

            days[0] = 'first';
            days[1] = 'second';
            days[2] = 'third';
            days[3] = 'fourth';
            days[4] = 'fifth';
            days[5] = 'sixth';
            days[6] = 'seventh';
            days[7] = 'eighth';
            days[8] = 'ninth';
            days[9] = 'tenth';
            days[10] = 'eleventh';
            days[11] = 'twelfth';

            gifts[0] = 'A partridge in a pear tree';
            gifts[1] = 'Two turtle doves';
            gifts[2] = 'Three french hens';
            gifts[3] = 'Four calling birds';
            gifts[4] = 'Five golden rings';
            gifts[5] = 'Six geese a-laying';
            gifts[6] = 'Seven swans a-swimming';
            gifts[7] = 'Eight maids a-milking';
            gifts[8] = 'Nine ladies dancing';
            gifts[9] = 'Ten lords a-leaping';
            gifts[10] = 'Eleven pipers piping';
            gifts[11] = 'Twelve drummers drumming';

            var i:uint, j:uint, k:uint, line:String;

            for ( i = 0; i < 12; i++ ) {

                lines = new Vector.<String>(i + 2, true);
                lines[0] = "On the " + days[i] + " day of Christmas, my true love gave to me";

                j = i + 1;
                k = 0;
                while ( j-- > 0 )
                    lines[++k] = gifts[j];

                verses[i] = lines.join('\n');

                if ( i == 0 )
                    gifts[0] = 'And a partridge in a pear tree';

            }

            var song:String = verses.join('\n\n');
            _textArea.text = song;
            addChild(_textArea);

            _textArea.addEventListener(MouseEvent.MOUSE_WHEEL, _onMouseWheel);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, _onKeyDown);

        }

        private function _onKeyDown(e:KeyboardEvent):void {
            if ( e.keyCode == Keyboard.DOWN )
                _textArea.y -= 40;
            else if ( e.keyCode == Keyboard.UP )
                _textArea.y += 40;
        }

        private function _onMouseWheel(e:MouseEvent):void {
            _textArea.y += 20 * e.delta;
        }

    }

}


with Ada.Text_IO;           use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

procedure Twelve_Days_Of_Christmas is
   type Days is (First, Second, Third, Fourth, Fifth, Sixth,
		 Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth);

   package E_IO is new Ada.Text_IO.Enumeration_IO(Days);
   use E_IO;

   Gifts : array (Days) of Unbounded_String :=
     (To_Unbounded_String(" A partridge in a pear-tree."),
      To_Unbounded_String(" Two turtle doves"),
      To_Unbounded_String(" Three French hens"),
      To_Unbounded_String(" Four calling birds"),
      To_Unbounded_String(" Five golden rings"),
      To_Unbounded_String(" Six geese a-laying"),
      To_Unbounded_String(" Seven swans a-swimming"),
      To_Unbounded_String(" Eight maids a-milking"),
      To_Unbounded_String(" Nine ladies dancing"),
      To_Unbounded_String(" Ten lords a-leaping"),
      To_Unbounded_String(" Eleven pipers piping"),
      To_Unbounded_String(" Twelve drummers drumming"));
begin
   for Day in Days loop
      Put("On the "); Put(Day, Set => Lower_Case); Put(" day of Christmas,");
      New_Line; Put_Line("My true love gave to me:");
      for D in reverse Days'First..Day loop
	 Put_Line(To_String(Gifts(D)));
      end loop;
      if Day = First then
	 Replace_Slice(Gifts(Day), 2, 2, "And a");
      end if;
      New_Line;
   end loop;
end Twelve_Days_Of_Christmas;


BEGIN
  []STRING labels = ("first", "second", "third",    "fourth",
                     "fifth", "sixth",  "seventh",  "eighth",
                     "ninth", "tenth",  "eleventh", "twelfth");

  []STRING gifts = ("A partridge in a pear tree.",
                    "Two turtle doves, and",
                    "Three French hens,",
                    "Four calling birds,",
                    "Five gold rings,",
                    "Six geese a-laying,",
                    "Seven swans a-swimming,",
                    "Eight maids a-milking,",
                    "Nine ladies dancing,",
                    "Ten lords a-leaping,",
                    "Eleven pipers piping,",
                    "Twelve drummers drumming,");
  FOR day TO 12 DO
    print(("On the ", labels[day],
           " day of Christmas, my true love sent to me:", newline));
    FOR gift FROM day BY -1 TO 1 DO
      print((gifts[gift], newline))
    OD;
    print(newline)
  OD
END


set gifts to {"A partridge in a pear tree.", "Two turtle doves, and", ¬
	"Three French hens,", "Four calling birds,", ¬
	"Five gold rings,", "Six geese a-laying,", ¬
	"Seven swans a-swimming,", "Eight maids a-milking,", ¬
	"Nine ladies dancing,", "Ten lords a-leaping,", ¬
	"Eleven pipers piping,", "Twelve drummers drumming"}

set labels to {"first", "second", "third", "fourth", "fifth", "sixth", ¬
	"seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth"}

repeat with day from 1 to 12
	log "On the " & item day of labels & " day of Christmas, my true love sent to me:"
	repeat with gift from day to 1 by -1
		log item gift of gifts
	end repeat
	log ""
end repeat


gifts: [
    "A partridge in a pear tree."
    "Two turtle doves"
    "Three french hens"
    "Four calling birds"
    "Five golden rings"
    "Six geese a-laying"
    "Seven swans a-swimming"
    "Eight maids a-milking"
    "Nine ladies dancing"
    "Ten lords a-leaping"
    "Eleven pipers piping"
    "Twelve drummers drumming"
]

days: ["first" "second" "third" "fourth" "fifth" "sixth"
       "seventh" "eighth" "ninth" "tenth" "eleventh" "twelfth"]

loop.with:'n days 'day [
    g: reverse slice gifts 0 n
    print ~"On the |day| day of Christmas\n" ++
          "My true love gave to me:\n" ++
          (join.with:"\n" chop g) ++
          (n>0)? -> " and \n" ++ last g
                 -> capitalize last g
    print ""
]


nth := ["first","second","third","fourth","fifth","sixth","seventh","eighth","ninth","tenth","eleventh","twelfth"]
lines := ["A partridge in a pear tree."
		,"Two turtle doves and"
		,"Three french hens"
		,"Four calling birds"
		,"Five golden rings"
		,"Six geese a-laying"
		,"Seven swans a-swimming"
		,"Eight maids a-milking"
		,"Nine ladies dancing"
		,"Ten lords a-leaping"
		,"Eleven pipers piping"
		,"Twelve drummers drumming"]

full:="", mid:=""
loop % lines.MaxIndex()
{
	top:="On the " . nth[A_Index] . " day of Christmas,`nMy true love gave to me:"
	mid:= lines[A_Index] . "`n" . mid
	full:= full . top . "`n" . mid . ((A_Index<lines.MaxIndex())?"`n":"")
}
MsgBox % full


# syntax: GAWK -f THE_TWELVE_DAYS_OF_CHRISTMAS.AWK
BEGIN {
    gifts[++i] = "a partridge in a pear tree."
    gifts[++i] = "two turtle doves, and"
    gifts[++i] = "three french hens,"
    gifts[++i] = "four calling birds,"
    gifts[++i] = "five golden rings,"
    gifts[++i] = "six geese a-laying,"
    gifts[++i] = "seven swans a-swimming,"
    gifts[++i] = "eight maids a-milking,"
    gifts[++i] = "nine ladies dancing,"
    gifts[++i] = "ten lords a-leaping,"
    gifts[++i] = "eleven pipers piping,"
    gifts[++i] = "twelve drummers drumming,"
    split("first second third fourth fifth sixth seventh eighth ninth tenth eleventh twelfth",days_arr," ")
    for (i=1; i<=12; i++) {
      printf("On the %s day of Christmas,\n",days_arr[i])
      print("my true love gave to me:")
      for (j=i; j>0; j--) {
        printf("%s\n",gifts[j])
      }
      print("")
    }
    exit(0)
}


:: The Twelve Days of Christmas
:: Batch File Implementation

@echo off

::Pseudo-array for Days
set "day1=First"
set "day2=Second"
set "day3=Third"
set "day4=Fourth"
set "day5=Fifth"
set "day6=Sixth"
set "day7=Seventh"
set "day8=Eighth"
set "day9=Nineth"
set "day10=Tenth"
set "day11=Eleventh"
set "day12=Twelveth"

::Pseudo-array for Gifts
set "gift12=Twelve drummers drumming"
set "gift11=Eleven pipers piping"
set "gift10=Ten loards a-leaping"
set "gift9=Nine ladies dancing"
set "gift8=Eight maids a-milking"
set "gift7=Seven swans a-swimming"
set "gift6=Six geese a-laying"
set "gift5=Five golden rings"
set "gift4=Four calling birds"
set "gift3=Three french hens"
set "gift2=Two turtle doves"
set "gift1=A partridge in a pear tree"

::Display It!
setlocal enabledelayedexpansion
for /l %%i in (1,1,12) do (
	echo On the !day%%i! day of Christmas
        echo My true love gave to me:

	for /l %%j in (%%i,-1,1) do (
		if %%j equ 1 (
			if %%i neq 1 <nul set /p ".=And "
			echo !gift1!.
		) else (
			echo !gift%%j!,
		)
	)
	echo(
)
exit /b


10 DEFINT I,J: DEFSTR N,V: DIM N(12),V(12)
20 FOR I=1 TO 12: READ N(I): NEXT
30 FOR I=1 TO 12: READ V(I): NEXT
40 FOR I=1 TO 12
50 PRINT "On the ";N(I);" day of Christmas"
60 PRINT "My true love gave to me:"
70 FOR J=I TO 1 STEP -1: PRINT V(J): NEXT
75 PRINT
80 NEXT
90 END
100 DATA first,second,third,fourth,fifth,sixth
110 DATA seventh,eighth,ninth,tenth,eleventh,twelfth
120 DATA "A partridge in a pear tree."
130 DATA "Two turtle doves and"
140 DATA "Three french hens"
150 DATA "Four calling birds"
160 DATA "Five golden rings"
170 DATA "Six geese a-laying"
180 DATA "Seven swans a-swimming"
190 DATA "Eight maids a-milking"
200 DATA "Nine ladies dancing"
210 DATA "Ten lords a-leaping"
220 DATA "Eleven pipers piping"
230 DATA "Twelve drummers drumming"


dim dia$ = {"first","second","third","fourth","fifth","sixth","seventh","eighth","ninth","tenth","eleventh","twelfth"}

dim gift$ = {"A partridge in a pear tree.","Two turtle doves and","Three french hens","Four calling birds","Five golden rings","Six geese a-laying","Seven swans a-swimming","Eight maids a-milking","Nine ladies dancing","Ten lords a-leaping","Eleven pipers piping","Twelve drummers drumming"}

for i = 0 to 11
    print "On the "; dia$[i]; " dia of Christmas,"
    print "My true love gave to me:"
    for j = i to 1 step -1
        print gift$[j]
    next j
    print
next i


get "libhdr"

let ordinal(n) =
    n=1 -> "first",     n=2 -> "second",    n=3 -> "third",
    n=4 -> "fourth",    n=5 -> "fifth",     n=6 -> "sixth",
    n=7 -> "seventh",   n=8 -> "eighth",    n=9 -> "ninth",
    n=10 -> "tenth",    n=11 -> "eleventh", n=12 -> "twelfth",
    valof finish

let gift(n) =
    n=1 -> "A partridge in a pear tree.",
    n=2 -> "Two turtle doves, and",
    n=3 -> "Three french hens,",
    n=4 -> "Four calling birds,",
    n=5 -> "Five golden rings,",
    n=6 -> "Six geese a-laying,",
    n=7 -> "Seven swans a-swimming,",
    n=8 -> "Eight maids a-milking,",
    n=9 -> "Nine ladies dancing,",
    n=10 -> "Ten lords a-leaping,",
    n=11 -> "Eleven pipers piping,",
    n=12 -> "Twelve drummers drumming,",
    valof finish

let verse(n) be
$(  writef("On the %S day of Christmas,*N", ordinal(n))
    writes("My true love gave to me:*N")
    for i=n to 1 by -1 do writef("%S*N", gift(i))
    wrch('*N')
$)

let start() be for n=1 to 12 do verse(n)


0246*+00p20#v_:#`2#g+#0:#0<>\#%"O"/#:3#:+#< g48*- >1-:!#v_\1+::"O"%\"O"/v
>-#11#\0#50#< g2-:00p4v   >\#%"O"/#::$#<3#$+g48*-v^\,+*+ 55!:*!!-"|":g+3<
             ^02_>#`>#< 2 5 3 1 0 \1-:#^\_^#:-1\+<[email protected]#:>#<$<
(On the ?|A partridge in a pear tree.||&first% andL day of Christmas,|My true l
ove gave to me:2|Two turtle doves'second3|Three french hens&third4|Four calling
 birds'fourth3|Five golden rings&fifth4|Six geese a-laying&sixth8|Seven swans a
-swimming(seventh7|Eight maids a-milking'eighth5|Nine ladies dancing&ninth5|Ten
 lords a-leaping&tenth6|Eleven pipers piping)eleventh:|Twelve drummers drumming
(twelfth


(     first
      second
      third
      fourth
      fifth
      sixth
      seventh
      eighth
      ninth
      tenth
      eleventh
      twelveth
  : ?days
&     "A partridge in a pear tree."
      "Two turtle doves and"
      "Three french hens,"
      "Four calling birds,"
      "Five golden rings,"
      "Six geese a-laying,"
      "Seven swans a-swimming,"
      "Eight maids a-milking,"
      "Nine ladies dancing,"
      "Ten lords a-leaping,"
      "Eleven pipers piping,"
      "Twelve drummers drumming,"
  : ?gifts
& :?given
&   whl
  ' ( !gifts:%?gift ?gifts
    & !gift \n !given:?given
    & !days:%?day ?days
    &   out
      $ ( str
        $ ("\nOn the " !day " day of Christmas my true love gave to me:
" !given)
        )
    )
);