(defn words
  "Split string into words"
  [^String str]
  (.split (.stripLeading str) "\\s+"))

(defn join-words
  "Join words into a single string"
  ^String [strings]
  (String/join " " strings))

;; SOURCE: https://www.stackoverflow.com/a/38947571/12947681
(defn starts-with-ignore-case
  "Does string start with prefix (ignoring case)?"
  ^Boolean [^String string, ^String prefix]
  (.regionMatches string true 0 prefix 0 (count prefix)))

(defrecord CommandWord [^String word, ^long min-abbr-size])

(defn parse-cmd-table
  "Parse list of strings in command table into list of words and numbers
   If number is missing for any word, then the word is not included"
  ([cmd-table]
   (parse-cmd-table cmd-table 0 []))
  ([cmd-table i ans]
   (let [cmd-count (count cmd-table)]
     (if (= i cmd-count)
       ans
       (let [word (nth cmd-table i),
             [i num] (try [(+ i 2)
                           (Integer/parseInt ^String (nth cmd-table (inc i)))]
                          (catch NumberFormatException _
                            [(inc i) 0]))]
         (recur cmd-table i (conj ans (CommandWord. word num))))))))

;; cmd-table is a list of objects of type CommandWord (defined above)
(def cmd-table
  (->
   "add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3
   compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate
   3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2
   forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load
   locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2
   msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3
   refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left
   2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1"
   words
   parse-cmd-table))

(defn abbr?
  "Is abbr a valid abbreviation of this command?"
  ^Boolean [^String abbr, ^CommandWord cmd]
  (let [{:keys [word min-abbr-size]} cmd]
    (and (<= min-abbr-size (count abbr) (count word))
         (starts-with-ignore-case word abbr))))

(defn solution
  "Find word matching each abbreviation in input (or *error* if not found),
   and join results into a string"
  ^String [^String str]
  (join-words (for [abbr (words str)]
                (if-let [{:keys [word]} (first (filter #(abbr? abbr %) cmd-table))]
                  (.toUpperCase ^String word)
                  "*error*"))))

;; Print solution for given test case
(println (solution "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"))


|=  [[email protected] [email protected]]
?:  =(m 0)
  +(n)
?:  =(n 0)
  $(n 1, m (dec m))
$(m (dec m), n $(n (dec n)))


// Note that the following function is for odd numbers only
// Use "for (unsigned i = 2; i*i <= n; i++)" for even and odd numbers

def sum_proper_divisors_of_odd(n: int) -> int:
    var sum = 1
    var i = 3
    let limit = sqrt(n) + 1
    while i < limit:
        if n % i == 0:
            sum += i
            let j = n / i
            if i != j:
                sum += j
        i += 2
    return sum

def abundant_odd_numbers():
    var n = 1
    var c = 0
    print "index: number proper_sum"
    while c < 25:
        let s = sum_proper_divisors_of_odd(n)
        if n < s:
            c += 1
            print concat_string([string(c), ": ", string(n), ", ", string(s)], "")
        n += 2
    var s = 1
    while c < 1000:
        s = sum_proper_divisors_of_odd(n)
        if n < s:
            c += 1
        n += 2
    print concat_string(["1000: ", string(n), ", ", string(s)], "")
    n =  999999999
    while n >= s:
        n += 2
        s = sum_proper_divisors_of_odd(n)
    print concat_string(["The first abundant odd number above one billion is: ", string(n), ", ", string(s)], "")

abundant_odd_numbers()


-- Return the sum of the proper divisors of x
function sumDivs (x)
  local sum, sqr = 1, math.sqrt(x)
  for d = 2, sqr do
    if x % d == 0 then
      sum = sum + d
      if d ~= sqr then sum = sum + (x/d) end
    end
  end
  return sum
end

-- Return a table of odd abundant numbers
function oddAbundants (mode, limit)
  local n, count, divlist, divsum = 1, 0, {}
  repeat
    n = n + 2
    divsum = sumDivs(n)
    if divsum > n then
      table.insert(divlist, {n, divsum})
      count = count + 1
      if mode == "Above" and n > limit then return divlist[#divlist] end
    end
  until count == limit
  if mode == "First" then return divlist end
  if mode == "Nth" then return divlist[#divlist] end
end

-- Write a result to stdout
function showResult (msg, t)
  print(msg .. ": the proper divisors of " .. t[1] .. " sum to " .. t[2])
end

-- Main procedure
for k, v in pairs(oddAbundants("First", 25)) do  showResult(k, v) end
showResult("1000", oddAbundants("Nth", 1000))
showResult("Above 1e6", oddAbundants("Above", 1e6))


COMMAND_TABLE =
  "add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3
   compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate
   3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2
   forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load
   locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2
   msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3
   refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left
   2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1"

def parse_command_table(input : String)
    cmds = {} of String => String
    table = input.strip.split

    word = table[0].upcase
    table.each do |item|
        if /[0-9]+/.match(item)
            abbreviation_length = item.to_i
            (0..word.size-abbreviation_length).each do |i|
                cmds[word[(0..abbreviation_length-1+i)]] = word
            end
        else
            word = item.upcase
            cmds[word] = word
        end
    end
    return cmds
end

def parse_user_input(input : String?, commands)
    output = ""
    unless input.nil?
        user_commands = input.strip.split
        user_commands.each do |command|
            command = command.upcase
            if commands.has_key?(command)
                output += commands[command]
            else
                output += "*error*"
            end
            output += " "
        end
    end
    return output
end

cmds = parse_command_table(COMMAND_TABLE)
puts "Input:"
user_input = gets
puts "Output:"
puts parse_user_input(user_input, cmds)


class Abbreviations
{
	import std.array: split, join;
	import std.uni:toUpper;

	string[string] replaces;

	this(string table)
	{
		import std.ascii;
		import std.conv:parse;

		string saved;
		auto add = (string word){ if(word.length) replaces[word] = word; };

		foreach(word; table.toUpper.split)
			if(isDigit(word[0]))
			{
				for(int length=parse!int(word); length<=saved.length; ++length)
					replaces[saved[0..length]] = saved;
			} else
			{
				add(saved);
				saved = word;
			}
		add(saved);
	}

	string expand(string input) // pre-filled hashtable is used
	{
		import std.algorithm: map;
		return input.toUpper.split.map!(word => word in replaces ? replaces[word] : "*error*").join(" ");
	}
}

string table = "
   add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3
   compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate
   3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2
   forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load
   locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2
   msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3
   refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left
   2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1";

string input = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin";
string expected = "RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT";

unittest // 'dmd -unittest ...' to activate it
{
	auto expander = new Abbreviations(table);
	assert(expander.expand(input) == expected);
	assert(expander.expand("") == "");
	assert(expander.expand("addadd") == "*error*");
}

void main()
{
	import std.stdio:writeln;

	writeln("Input : ", input);
	writeln("Output: ", new Abbreviations(table).expand(input));
}


procedure acker(i, j)
   static memory

   initial {
      memory := table()
      every memory[0 to 100] := table()
      }

   if i = 0 then return j + 1

   if j = 0 then /memory[i][j] := acker(i - 1, 1)
   else /memory[i][j] := acker(i - 1, acker(i, j - 1))

   return memory[i][j]

end

procedure main()
   every m := 0 to 3 do {
      every n := 0 to 8 do {
         writes(acker(m, n) || " ")
         }
      write()
      }
end


            NORMAL MODE IS INTEGER

            INTERNAL FUNCTION(ND)
            ENTRY TO ODDSUM.
            SUM = 1
            SQN = SQRT.(ND)
            THROUGH CHECK, FOR CN=3, 2, CN.G.SQN
            TM = ND/CN
            WHENEVER TM*CN.E.ND
                SUM = SUM + CN
                WHENEVER TM.NE.CN, SUM = SUM + TM
CHECK       END OF CONDITIONAL
            FUNCTION RETURN SUM
            END OF FUNCTION

            SEEN = 0
            NUM = 1

            THROUGH SHOW, FOR NUM=1, 2, SEEN.G.1000
            WHENEVER NUM.L.ODDSUM.(NUM)
                SEEN = SEEN + 1
                WHENEVER SEEN.LE.25 .OR. SEEN.E.1000,
          0         PRINT FORMAT OUTFMT,SEEN,NUM,ODDSUM.(NUM)
SHOW        END OF CONDITIONAL

BILION      THROUGH BILION, FOR NUM=NUM, 2,
          0     NUM.G.1000000000 .AND. NUM.L.ODDSUM.(NUM)

            PRINT FORMAT HUGENO,NUM,ODDSUM.(NUM)

            VECTOR VALUES OUTFMT =
          0     $4HNO. ,I4,S1,3HIS ,I6,S1,7HDIVSUM ,I6*$
            VECTOR VALUES HUGENO =
          0     $25HFIRST ABOVE 1 BILLION IS ,I10,S1,7HDIVSUM ,I10*$
            END OF PROGRAM


with(NumberTheory):

# divisorSum returns the sum of the divisors of x not including x
divisorSum := proc(x::integer)
 return SumOfDivisors(x) - x;
end proc:

# abundantNumber returns true if x is an abundant number and false otherwise
abundantNumber := proc(x::integer)
 if (SumOfDivisors(x) > 2*x) then return true
 else return false end if;
end proc:

count := 0:
number := 1:

cat("First 25 abundant odd numbers");

while count < 25 do
 if (abundantNumber(number)) then
  count += 1:
  print(cat(count, ": ", number, " sum of divisors  ", SumOfDivisors(number), " sum of proper divisors ", divisorSum(number)));
 else end if;
 number += 2:
end:

while (count < 1000) do
 if (abundantNumber(number)) then
  count += 1:
 else end if:
 number += 2:
end:

cat("The 1000th odd abundant number is ", number - 2, ", its sum of divisors is ", SumOfDivisors(number - 2), ", and its sum of proper divisors is ", divisorSum(number - 2));

for number from 10^9 + 1 by 2 to infinity while not abundantNumber(number) do end:

cat("First abundant odd number > 10^9 is ", number, ", its sum of divisors is  ", SumOfDivisors(number), ", and its sum of proper divisors is  ",divisorSum(number));


ClearAll[AbundantQ]
AbundantQ[n_] := TrueQ[Greater[Total @ Most @ Divisors @ n, n]]
res = {};
i = 1;
While[Length[res] < 25,
  If[AbundantQ[i],
   AppendTo[res, {i, Total @ Most @ Divisors @ i}];
   ];
  i += 2;
  ];
res

res = {};
i = 1;
While[Length[res] < 1000,
  If[AbundantQ[i],
   AppendTo[res, {i, Total @ Most @ Divisors @ i}];
   ];
  i += 2;
  ];
res[[-1]]

res = {};
i = 1000000001;
While[Length[res] < 1,
  If[AbundantQ[i],
   AppendTo[res, {i, Total @ Most @ Divisors @ i}];
   ];
  i += 2;
  ];
res


program Abraviation_simple;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

type
  TCommand = record
    value: string;
    len: integer;
  end;

function ReadTable(table: string): TArray<TCommand>;
begin
  var fields := table.Split([' '], TStringSplitOptions.ExcludeEmpty);
  var i := 0;
  var max := Length(fields);
  while i < max do
  begin
    var cmd := fields[i];
    var cmdLen := cmd.Length;
    inc(i);

    if i < max then
    begin
      var num: Integer;
      if TryStrToInt(fields[i], num) and (1 <= num) and (num < cmdLen) then
      begin
        cmdLen := num;
        inc(i);
      end;
    end;

    SetLength(result, Length(result) + 1);
    with result[High(result)] do
    begin
      value := cmd;
      len := cmdLen;
    end;
  end;
end;

function ValidateCommands(Commands: TArray<TCommand>; Words: TArray<string>):
  TArray<string>;
begin
  SetLength(result, 0);
  for var wd in Words do
  begin
    var matchFound := false;
    var wLen := wd.Length;
    for var i := 0 to High(Commands) do
    begin
      var command := Commands[i];
      if (command.len = 0) or (wLen < command.len) or (wLen > command.value.Length) then
        Continue;
      var c := command.value.ToUpper;
      var w := wd.ToUpper;
      if c.StartsWith(w) then
      begin
        SetLength(result, Length(result) + 1);
        result[High(result)] := c;
        matchFound := true;
        Break;
      end;
    end;
    if not matchFound then
    begin
      SetLength(result, Length(result) + 1);
      result[High(result)] := '*error*';
    end;
  end;
end;

procedure PrintResults(words, results: TArray<string>);
begin
  Writeln('user words:');
  for var w in words do
    write(^I, w);
  Writeln(#10, 'full words:'^I, string.join(^I, results));
end;

const
  table = '' +
    'add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3 ' +
    'compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate ' +
    '3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2 ' +
    'forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load ' +
    'locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2 ' +
    'msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3 ' +
    'refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left ' +
    '2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1 ';

const
  SENTENCE = 'riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin';

begin
  var Commands := ReadTable(table);
  var Words := SENTENCE.Split([' '], TStringSplitOptions.ExcludeEmpty);

  var results := ValidateCommands(Commands, Words);

  PrintResults(Words, results);

  Readln;
end.


A : Nat -> Nat -> Nat
A Z n = S n
A (S m) Z = A m (S Z)
A (S m) (S n) = A m (A (S m) n)


block([k: 0, n: 1, l: []],
    while k < 25 do (
        n: n+2,
        if divsum(n,-1) > 2 then (
            k: k+1,
            l: append(l, [[n,divsum(n)]])
        )
    ),
    return(l)
);


from math import sqrt
import strformat

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

proc sumProperDivisors(n: int): int =
  ## Compute the sum of proper divisors.
  ## "n" is supposed to be odd.
  result = 1
  for d in countup(3, sqrt(n.toFloat).int, 2):
    if n mod d == 0:
      inc result, d
      if n div d != d:
        inc result, n div d

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

iterator oddAbundant(start: int): tuple[n, s: int] =
  ## Yield the odd abundant numbers and the sum of their proper
  ## divisors greater or equal to "start".
  var n = start + (start and 1 xor 1)   # Start with an odd number.
  while true:
    let s = n.sumProperDivisors()
    if s > n:
      yield (n, s)
    inc n, 2

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

echo "List of 25 first odd abundant numbers."
echo "Rank  Number  Proper divisors sum"
echo "----  -----   -------------------"
var rank = 0
for (n, s) in oddAbundant(1):
  inc rank
  echo fmt"{rank:2}:   {n:5}   {s:5}"
  if rank == 25:
    break

echo ""
rank = 0
for (n, s) in oddAbundant(1):
  inc rank
  if rank == 1000:
    echo fmt"The 1000th odd abundant number is {n}."
    echo fmt"The sum of its proper divisors is {s}."
    break

echo ""
for (n, s) in oddAbundant(1_000_000_000):
  if n > 1_000_000_000:
    echo fmt"The first odd abundant number greater than 1000000000 is {n}."
    echo fmt"The sum of its proper divisors is {s}."
    break


genit(brk1,brk2,brk3)={tcnt=0;
print("First 25 abundant odd numbers:");
forstep(n=1,999999999999999999,2,
if(tcnt==brk2&&n<brk3,next);
if(sigma(n)<=2*n,next);
tcnt+=1;
if(tcnt>brk1&&tcnt<brk2,next);
if(n>=brk3 && sigma(n)>2*n,print("The first odd abundant number greater than 1000000000 is ",n," with sigma = ",sigma(n) );break);
if(tcnt==brk2,print("The 1000th odd abundant number is ",n," with sigma = ",sigma(n) );next);
print(n," with sigma = ",sigma(n)));}

Output:

(11:14) gp > genit(25,1000,1000000000 )
First 25 abundant odd numbers:
945 with sigma = 1920
1575 with sigma = 3224
2205 with sigma = 4446
2835 with sigma = 5808
3465 with sigma = 7488
4095 with sigma = 8736
4725 with sigma = 9920
5355 with sigma = 11232
5775 with sigma = 11904
5985 with sigma = 12480
6435 with sigma = 13104
6615 with sigma = 13680
6825 with sigma = 13888
7245 with sigma = 14976
7425 with sigma = 14880
7875 with sigma = 16224
8085 with sigma = 16416
8415 with sigma = 16848
8505 with sigma = 17472
8925 with sigma = 17856
9135 with sigma = 18720
9555 with sigma = 19152
9765 with sigma = 19968
10395 with sigma = 23040
11025 with sigma = 22971
The 1000th odd abundant number is 492975 with sigma = 1012336
The first odd abundant number greater than 1000000000 is 1000000575 with sigma = 2083561584
(11:24) gp >


USING: arrays assocs combinators formatting fry grouping.extras
kernel literals math math.parser multiline sequences
splitting.extras unicode ;
IN: rosetta-code.abbr-simple

CONSTANT: input $[
"riG   rePEAT copies  put mo   rest    types   fup.    6       "
"poweRin" append
]

<<     ! Make the following two words available at parse time.

: abbr-pair ( first second -- seq/f )
    {
        { [ 2dup drop [ digit? ] all? ] [ 2drop f ] }
        {
            [ 2dup nip [ Letter? ] all? ]
            [ drop >upper 0 2array ]
        }
        [ [ >upper ] [ string>number ] bi* 2array ]
    } cond ;

: parse-commands ( seq -- seq )
    " \n" split-harvest [ abbr-pair ] 2clump-map sift ;

>>

CONSTANT: commands $[
HEREDOC: END
add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange
Cinsert 2  Clast 3 compress 4 copy 2 count 3 Coverlay 3 cursor 3
delete 3 Cdelete 2  down 1  duplicate 3 xEdit 1 expand 3 extract
3 find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2 forward
2  get  help 1  hexType 4  input 1 powerInput 3  join  1 split 2
spltJOIN load locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix
2  macro  merge 2  modify  3  move 2 msg  next 1 overlay 1 parse
preserve 4 purge 3 put putD query 1 quit  read recover 3 refresh
renum 3 repeat 3 replace 1 Creplace  2 reset 3 restore 4 rgtLEFT
right 2 left 2  save  set  shift 2  si  sort sos  stack 3 status
4 top  transfer 3  type 1  up 1
END
parse-commands
]

: valid-abbrevs ( assoc seq -- assoc )
    dup '[ [ _ head? ] [ _ length <= ] bi* and ] assoc-filter ;

: find-command ( seq -- seq )
    >upper [ commands ] dip valid-abbrevs
    [ "*error*" ] [ first first ] if-empty ;

: (find-commands) ( seq -- seq )
    " " split-harvest [ find-command ] map " " join ;

: find-commands ( seq -- seq )
    dup empty? not [ (find-commands) ] when ;

: show-commands ( seq -- )
    dup find-commands " Input: \"%s\"\nOutput: \"%s\"\n" printf
    ;

: main ( -- ) input "" [ show-commands ] [email protected] ;

MAIN: main


include FMS-SI.f
include FMS-SILib.f

${ add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3
   compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate
   3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2
   forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load
   locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2
   msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3
   refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left
   2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1 }
   value list  ' upper: list map:

: compare' { adr len $obj -- f }
  len $obj size: > if false exit then
  adr len $obj @: drop len compare 0= ;

: <= ( n1 n2 = f) 1+ swap > ;

: abbrev 0 0 { adr len obj1 obj2 -- }
  list uneach:
  list each: drop to obj1
  begin
   list each:
  while
   to obj2
   obj2 @: >integer
     if  \ word followed by a number
         len <= if adr len obj1 compare'
                   if obj1 p: exit then
                then list each: if to obj1  else ." *error* " exit then
     else \ word not followed by a number
          adr len obj1 @: compare 0=
          if obj1 p: exit then
          obj2 to obj1
     then
  repeat ;

${ riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin }
  value input-list  ' upper: input-list map:

: valid-input ( adr len -- f)
  over + swap do i [email protected] isalpha 0= if ." *error* " unloop false exit then loop true ;

: run
  begin
    input-list each:
  while
    dup @: valid-input
    if @: abbrev space else drop then
  repeat ;

run RIGHT REPEAT *error*  PUT MOVE RESTORE *error*  *error* *error* POWERINPUT ok


package main

import (
	"io"
	"os"
	"strconv"
	"strings"
	"text/tabwriter"
)

func readTable(table string) ([]string, []int) {
	fields := strings.Fields(table)
	var commands []string
	var minLens []int

	for i, max := 0, len(fields); i < max; {
		cmd := fields[i]
		cmdLen := len(cmd)
		i++

		if i < max {
			num, err := strconv.Atoi(fields[i])
			if err == nil && 1 <= num && num < cmdLen {
				cmdLen = num
				i++
			}
		}

		commands = append(commands, cmd)
		minLens = append(minLens, cmdLen)
	}

	return commands, minLens
}

func validateCommands(commands []string, minLens []int, words []string) []string {
	var results []string
	for _, word := range words {
		matchFound := false
		wlen := len(word)
		for i, command := range commands {
			if minLens[i] == 0 || wlen < minLens[i] || wlen > len(command) {
				continue
			}
			c := strings.ToUpper(command)
			w := strings.ToUpper(word)
			if strings.HasPrefix(c, w) {
				results = append(results, c)
				matchFound = true
				break
			}
		}
		if !matchFound {
			results = append(results, "*error*")
		}
	}
	return results
}

func printResults(words []string, results []string) {
	wr := tabwriter.NewWriter(os.Stdout, 0, 1, 1, ' ', 0)
	io.WriteString(wr, "user words:")
	for _, word := range words {
		io.WriteString(wr, "\t"+word)
	}
	io.WriteString(wr, "\n")
	io.WriteString(wr, "full words:\t"+strings.Join(results, "\t")+"\n")
	wr.Flush()
}

func main() {
	const table = "" +
		"add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3 " +
		"compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate " +
		"3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2 " +
		"forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load " +
		"locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2 " +
		"msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3 " +
		"refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left " +
		"2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1 "

	const sentence = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"

	commands, minLens := readTable(table)
	words := strings.Fields(sentence)

	results := validateCommands(commands, minLens, words)

	printResults(words, results)
}


ackermann = method(m,n,
  cond(
    m zero?, n succ,
    n zero?, ackermann(m pred, 1),
    ackermann(m pred, ackermann(m, n pred)))
)


program AbundantOddNumbers;
{$IFDEF FPC}
   {$MODE DELPHI}{$OPTIMIZATION ON,ALL}{$CODEALIGN proc=16}{$ALIGN 16}
{$ELSE}
  {$APPTYPE CONSOLE}
{$ENDIF}
{geeksforgeeks
*    1100 = 2^2*5^2*11^1
    (2^0 + 2^1 + 2^2) * (5^0 + 5^1 + 5^2) * (11^0 + 11^1)
    (upto the power of factor in factorization i.e. power of 2 and 5 is 2 and 11 is 1.)
    = (1 + 2 + 2^2) * (1 + 5 + 5^2) * (1 + 11)
    = 7 * 31 * 12
    = 2604
    So, sum of all factors of 1100 = 2604 }
uses
  SysUtils;
var
  //all primes < 2^16=65536
  primes : array[0..6541] of Word;

procedure InitPrimes;
//sieve of erathotenes
var
  p : array[word] of byte;
  i,j : NativeInt;
Begin
  fillchar(p,SizeOf(p),#0);
  p[0] := 1;
  p[1] := 1;
  For i := 2 to high(p) do
    if p[i] = 0 then
    begin
      j := i*i;
      IF j>high(p) then
        BREAK;
      while j <= High(p) do
      begin
        p[j] := 1;
        inc(j,i);
      end;
    end;
  j := 0;
  For i := 2 to high(p) do
    IF p[i] = 0 then
    Begin
      primes[j] := i;
      inc(j);
    end;
end;

function PotToString(N: NativeUint):String;
var
  pN,pr,PowerPr,rest : NativeUint;
begin
  pN := 0; //starting at 2;
  Result := '';
  repeat
    pr := primes[pN];
    rest := N div pr;
    if rest < pr then
      BREAK;
    //same as N MOD PR = 0
    if rest*pr = N then
    begin
      result := result+IntToStr(pr);
      N := rest;
      rest := N div pr;
      PowerPr := 1;
      while rest*pr = N do
      begin
        inc(PowerPr);
        N := rest;
        rest := N div pr;
      end;
      if PowerPr > 1 then
        result := result+'^'+IntToStr(PowerPr);
      if N > 1 then
        result := result +'*';
    end;
    inc(pN);
  until pN > High(Primes);
  //is there a last prime factor of N
  if N <> 1 then
    result := result+IntToStr(N);
end;

function OutNum(N: NativeUint):string;
Begin
  result := Format('%10u= %s', [N,PotToString(N)]);
end;

function SumProperDivisors(N: NativeUint): NativeUint;
var
  pN,pr,PowerPr,SumOfPower,rest,N0 : NativeUint;
begin
  N0 := N;
  pN := 0; //starting at 2;
  Result := 1;
  repeat
    pr := primes[pN];
    rest := N div pr;
    if rest < pr then
      BREAK;
    //same as N MOD PR = 0
    if rest*pr = N then
    begin
//      IF pr=5 then break;
//      IF pr=7 then break;
      PowerPr := 1;
      SumOfPower:= 1;
      repeat
        PowerPr := PowerPr*pr;
        inc(SumOfPower,PowerPr);
        N := rest;
        rest := N div pr;
      until N <> rest*pr;
      result := result*SumOfPower;
    end;
    inc(pN);
  until pN > High(Primes);
  //is there a last prime factor of N
  if N <> 1 then
    result := result*(N+1);
  result := result-N0;
end;

var
  C, N,N0,k: Cardinal;
begin
  InitPrimes;

  k := High(k);
  N := 1;
  N0 := N;
  C := 0;
  while C < 25 do begin
    inc(N, 2);
    if N < SumProperDivisors(N) then begin
      Inc(C);
      WriteLn(Format('%5u: %s', [C,OutNum(N)]));
      IF k > N-N0 then
        k := N-N0;
      N0 := N;
    end;
  end;
  Writeln(' Min Delta ',k);
  writeln;

  while C < 1000 do begin
    Inc(N, 2);
    if N < SumProperDivisors(N) then
    Begin
      Inc(C);
      IF k > N-N0 then
        k := N-N0;
      N0 := N;
    end;
  end;
  WriteLn(' 1000: ',OutNum(N));
  Writeln(' Min Delta ',k);
  writeln;

  while C < 10000 do begin
    Inc(N, 2);
    if N < SumProperDivisors(N) then
    Begin
      Inc(C);
      IF k > N-N0 then
        k := N-N0;
      N0 := N;
    end;
  end;
  WriteLn('10000: ',OutNum(N));
  Writeln(' Min Delta ',k);

  N := 1000000001;
  while N >= SumProperDivisors(N) do
    Inc(N, 2);
  WriteLn('The first abundant odd number above one billion is: ',OutNum(N));
end.


import Data.List (find, isPrefixOf)
import Data.Char (isDigit, toUpper)
import Data.Maybe (maybe)

withExpansions :: [(String, Int)] -> String -> String
withExpansions tbl s = unwords $ expanded tbl <$> words s

expanded :: [(String, Int)] -> String -> String
expanded tbl k = maybe "*error" fst (expand k)
  where
    expand [] = Just ([], 0)
    expand s =
      let u = toUpper <$> s
          lng = length s
      in find (\(w, n) -> lng >= n && isPrefixOf u w) tbl

cmdsFromString :: String -> [(String, Int)]
cmdsFromString s =
  let go w@(x:_) (xs, n)
        | isDigit x = (xs, read w :: Int)
        | otherwise = ((toUpper <$> w, n) : xs, 0)
  in fst $ foldr go ([], 0) (words s)

-- TESTS --------------------------------------------------
table :: [(String, Int)]
table =
  cmdsFromString
    "add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1 \
    \Schange Cinsert 2  Clast 3 compress 4 copy 2 count 3 Coverlay 3 \
    \cursor 3  delete 3 Cdelete 2  down 1  duplicate 3 xEdit 1 expand 3 \
    \extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2 \
    \forward 2  get  help 1 hexType 4 input 1 powerInput 3  join 1 \
    \split 2 spltJOIN load locate 1 Clocate 2 lowerCase 3 upperCase 3 \
    \Lprefix 2  macro  merge 2 modify 3 move 2 msg  next 1 overlay 1 \
    \parse preserve 4 purge 3 put putD query 1 quit read recover 3 \
    \refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 \
    \rgtLEFT right 2 left 2  save  set  shift 2  si  sort  sos stack 3 \
    \status 4 top  transfer 3  type 1  up 1"

main :: IO ()
main = do
  let unAbbrev = withExpansions table
  print $
    unAbbrev
      "riG   rePEAT copies  put mo   rest    types   fup.    6      poweRin"
  print $ unAbbrev ""


use strict;
use warnings;
use feature 'say';
use ntheory qw/divisor_sum divisors/;

sub odd_abundants {
    my($start,$count) = @_;
    my $n = int(( $start + 2 ) / 3);
    $n   += 1 if 0 == $n % 2;
    $n   *= 3;
    my @out;
    while (@out < $count) {
        $n += 6;
        next unless (my $ds = divisor_sum($n)) > 2*$n;
        my @d = divisors($n);
        push @out, sprintf "%6d: divisor sum: %s = %d", $n, join(' + ', @d[0..@d-2]), $ds-$n;
    }
    @out;
}

say 'First 25 abundant odd numbers:';
say for odd_abundants(1, 25);
say "\nOne thousandth abundant odd number:\n", (odd_abundants(1, 1000))[999];
say "\nFirst abundant odd number above one billion:\n", odd_abundants(999_999_999, 1);


function abundantOdd(integer n, done, lim, bool printAll)
    while done<lim do
        atom tot = sum(factors(n,-1))
        if tot>n then
            done += 1
            if printAll or done=lim then
                string ln = iff(printAll?sprintf("%2d. ",done):"")
                printf(1,"%s%,6d (proper sum:%,d)\n",{ln,n,tot})
            end if
        end if
        n += 2
    end while
    printf(1,"\n")
    return n
end function
printf(1,"The first 25 abundant odd numbers are:\n")
integer n = abundantOdd(1, 0, 25, true)
printf(1,"The one thousandth abundant odd number is:")
{} = abundantOdd(n, 25, 1000, false)
printf(1,"The first abundant odd number above one billion is:")
{} = abundantOdd(1e9+1, 0, 1, false)


range=:<.+[:i.>.-<.
assert 2 3 4 -: 2 range 5
assert (i.0) -: 3 range 3

abbreviate =: 3 :0
 NB. input is the abbreviation table
 NB. output are the valid abbreviations
 y =. toupper CRLF -.~ y
 y =. ;: y
 y =. (([: (,3":#)L:_1 {)`[`]}~ ([: I. [: -. {[email protected]&Num_j_&>)) y
 y =. [&.:(;:inv) y
 y =. _2 ({. , <./@:".&.>@:{:)\ y
 y =. (<@] , ((range #) <@{."0 _ ]))&.>~/"1 y
 ambiguities =. ;#~1<[:+/e.
 (([: ~. {[email protected]:[ , -.)L:_1 <@:ambiguities) y
)
assert ('ABC A AB' ,&(<@;:) 'ABCDE ABCD') -: abbreviate 'abc 1 abcde 3'
assert ('ABC A AB' ,&(<@;:) 'ABCDE') -: abbreviate 'abc 1 abcde'

expand =: dyad define
 a =. abbreviate x
 words =. <;._2 ' ' ,~ deb toupper y
 interval_index =. <: +/\ #&> a
 a =. a , <,<'*error*'
 ;:inv {.&> (interval_index I.(; a )i."_ 0 words){ a
)


import java.util.*;

public class Abbreviations {
    public static void main(String[] args) {
        CommandList commands = new CommandList(commandTable);
        String input = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin";
        System.out.println(" input: " + input);
        System.out.println("output: " + test(commands, input));
    }

    private static String test(CommandList commands, String input) {
        StringBuilder output = new StringBuilder();
        Scanner scanner = new Scanner(input);
        while (scanner.hasNext()) {
            String word = scanner.next();
            if (output.length() > 0)
                output.append(' ');
            Command cmd = commands.findCommand(word);
            if (cmd != null)
                output.append(cmd.cmd);
            else
                output.append("*error*");
        }
        return output.toString();
    }

    private static String commandTable =
        "add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3 " +
        "compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate " +
        "3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2 " +
        "forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load " +
        "locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2 " +
        "msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3 " +
        "refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left " +
        "2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1";

    private static class Command {
        private Command(String cmd, int minLength) {
             this.cmd = cmd;
             this.minLength = minLength;
        }
        private boolean match(String str) {
            int olen = str.length();
            return olen >= minLength && olen <= cmd.length()
                && cmd.regionMatches(true, 0, str, 0, olen);
        }
        private String cmd;
        private int minLength;
    }

    private static Integer parseInteger(String word) {
        try {
            return Integer.valueOf(word);
        } catch (NumberFormatException ex) {
            return null;
        }
    }

    private static class CommandList {
        private CommandList(String table) {
            Scanner scanner = new Scanner(table);
            List<String> words = new ArrayList<>();
            while (scanner.hasNext()) {
                String word = scanner.next();
                words.add(word.toUpperCase());
            }
            for (int i = 0, n = words.size(); i < n; ++i) {
                String word = words.get(i);
                // if there's an integer following this word, it specifies the minimum
                // length for the command, otherwise the minimum length is the length
                // of the command string
                int len = word.length();
                if (i + 1 < n) {
                    Integer number = parseInteger(words.get(i + 1));
                    if (number != null) {
                        len = number.intValue();
                        ++i;
                    }
                }
                commands.add(new Command(word, len));
            }
        }
        private Command findCommand(String word) {
            for (Command command : commands) {
                if (command.match(word))
                    return command;
            }
            return null;
        }
        private List<Command> commands = new ArrayList<>();
    }
}


V command_table_text =
|‘Add ALTer  BAckup Bottom  CAppend Change SCHANGE  CInsert CLAst COMPress COpy
  COUnt COVerlay CURsor DELete CDelete Down DUPlicate Xedit EXPand EXTract Find
  NFind NFINDUp NFUp CFind FINdup FUp FOrward GET Help HEXType Input POWerinput
  Join SPlit SPLTJOIN  LOAD  Locate CLocate  LOWercase UPPercase  LPrefix MACRO
  MErge MODify MOve MSG Next Overlay PARSE PREServe PURge PUT PUTD  Query  QUIT
  READ  RECover REFRESH RENum REPeat  Replace CReplace  RESet  RESTore  RGTLEFT
  RIght LEft  SAVE  SET SHift SI  SORT  SOS  STAck STATus  TOP TRAnsfer Type Up’

V user_words = ‘riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin’

F find_abbreviations_length(command_table_text)
   ‘ find the minimal abbreviation length for each word by counting capital letters.
        a word that does not have capital letters gets it's full length as the minimum.
   ’
   [String = Int] command_table
   L(word) command_table_text.split((‘ ’, "\n"), group_delimiters' 1B)
      V abbr_len = sum(word.filter(c -> c.is_uppercase()).map(c -> 1))
      I abbr_len == 0
         abbr_len = word.len
      command_table[word] = abbr_len
   R command_table

F find_abbreviations(command_table)
   ‘ for each command insert all possible abbreviations’
   [String = String] abbreviations
   L(command, min_abbr_len) command_table
      L(l) min_abbr_len .. command.len
         V abbr = command[0 .< l].lowercase()
         abbreviations[abbr] = command.uppercase()
   R abbreviations

F parse_user_string(user_string, abbreviations)
   V user_words = user_string.split(‘ ’, group_delimiters' 1B).map(word -> word.lowercase())
   V commands = user_words.map(user_word -> @abbreviations.get(user_word, ‘*error*’))
   R commands.join(‘ ’)

V command_table = find_abbreviations_length(command_table_text)
V abbreviations_table = find_abbreviations(command_table)

V full_words = parse_user_string(user_words, abbreviations_table)

print(‘user words: ’user_words)
print(‘full words: ’full_words)


import java.math.BigInteger;

public static BigInteger ack(BigInteger m, BigInteger n) {
    return m.equals(BigInteger.ZERO)
            ? n.add(BigInteger.ONE)
            : ack(m.subtract(BigInteger.ONE),
                        n.equals(BigInteger.ZERO) ? BigInteger.ONE : ack(m, n.subtract(BigInteger.ONE)));
}


(de accud (Var Key)
   (if (assoc Key (val Var))
      (con @ (inc (cdr @)))
      (push Var (cons Key 1)) )
   Key )
(de **sum (L)
   (let S 1
      (for I (cdr L)
         (inc 'S (** (car L) I)) )
      S ) )
(de factor-sum (N)
   (if (=1 N)
      0
      (let
         (R NIL
            D 2
            L (1 2 2 . (4 2 4 2 4 6 2 6 .))
            M (sqrt N)
            N1 N
            S 1 )
         (while (>= M D)
            (if (=0 (% N1 D))
               (setq M
                  (sqrt (setq N1 (/ N1 (accud 'R D)))) )
               (inc 'D (pop 'L)) ) )
         (accud 'R N1)
         (for I R
            (setq S (* S (**sum I))) )
         (- S N) ) ) )
(de factor-list NIL
   (let (N 1  C 0)
      (make
         (loop
            (when (> (setq @@ (factor-sum N)) N)
               (link (cons N @@))
               (inc 'C) )
            (inc 'N 2)
            (T (= C 1000)) ) ) ) )
(let L (factor-list)
   (for N 25
      (println N (++ L)) )
   (println 1000 (last L))
   (println
      '****
      1000000575
      (factor-sum 1000000575) ) )


void setup() {
  println("First 25 abundant odd numbers: ");
  int abundant = 0;
  int i = 1;
  while (abundant < 25) {
    int sigma_sum = sigma(i);
    if (sigma_sum > 2 * i) {
      abundant++;
      println(i + "  Sigma sum: " + sigma_sum);
    }
    i += 2;
  }
  println("Thousandth abundant odd number: ");
  while (abundant < 1000) {
    int sigma_sum = sigma(i);
    if (sigma_sum > 2 * i) {
      abundant++;
      if (abundant == 1000) {
        println(i + "  Sigma sum: " + sigma_sum);
      }
    }
    i += 2;
  }
  println("First abundant odd number greater than 10^9: ");
  i = int(pow(10, 9)) + 1;
  while (!(sigma(i) > 2 * i)) {
    i += 2;
  }
  println(i + "  Sigma sum: " + sigma(i));
}

int sigma(int n) {
  int sum = 0;
  for (int i = 1; i < sqrt(n); i++) {
    if (n % i == 0) {
      sum += i + n / i;
    }
  }
  if (sqrt(n) % 1 == 0) {
    sum += sqrt(n);
  }
  return sum;
}


NewList l_sum.i()

Procedure.i sum_proper_divisors(n.i)
  Define.i sum, i=3, j
  Shared l_sum()
  AddElement(l_sum())
  l_sum()=1
  While i<Sqr(n)+1
    If n%i=0
      sum+i
      AddElement(l_sum())
      l_sum()=i
      j=n/i
      If i<>j
        sum+j
        AddElement(l_sum())
        l_sum()=j
      EndIf
    EndIf
    i+2
  Wend
  ProcedureReturn sum+1
EndProcedure

If OpenConsole("Abundant_odd_numbers")
  Define.i n, c, s

  n=1
  c=0
  While c<25
    ClearList(l_sum())
    s=sum_proper_divisors(n)
    If n<s
      SortList(l_sum(),#PB_Sort_Ascending)
      c+1
      Print(RSet(Str(c),3)+": "+RSet(Str(n),6)+" -> "+RSet(Str(s),6))
      ForEach l_sum()
        If ListIndex(l_sum())=0
          Print(" = ")
        Else
          Print("+")
        EndIf
        Print(Str(l_sum()))
      Next
      PrintN("")
    EndIf
    n+2
  Wend

  n-2
  While c<1000
    s=sum_proper_divisors(n+2)
    c+Bool(n<s)
    n+2
  Wend
  PrintN(~"\nThe one thousandth abundant odd number is: "+Str(n)+
         ~"\n\tand the proper divisor sum is: "+Str(s))

  n=1000000001-2
  Repeat
    n+2
    s=sum_proper_divisors(n)
  Until n<s
  PrintN("The first abundant odd number above one billion is: "+Str(n)+
         ~"\n\tand the proper divisor sum is: "+Str(s))

  Input()
EndIf


(() => {
    'use strict';

    // withExpansions :: [(String, Int)] -> String -> String
    const withExpansions = tbl => s =>
        unwords(map(expanded(tbl), words(s)));

    // expanded :: [(String, Int)] -> String -> String
    const expanded = tbl => s => {
        const
            lng = s.length,
            u = toUpper(s),
            p = wn => {
                const [w, n] = Array.from(wn);
                return lng >= n && isPrefixOf(u, w);
            }
        return maybe(
            '*error*',
            fst,
            0 < lng ? (
                find(p, tbl)
            ) : Just(Tuple([], 0))
        );
    };

    // cmdsFromString :: String -> [(String, Int)]
    const cmdsFromString = s =>
        fst(foldr(
            (w, a) => {
                const [xs, n] = Array.from(a);
                return isDigit(head(w)) ? (
                    Tuple(xs, parseInt(w, 10))
                ) : Tuple(
                    [Tuple(toUpper(w), n)].concat(xs),
                    0
                );
            },
            Tuple([], 0),
            words(s)
        ));

    // TEST -----------------------------------------------
    const main = () => {

        // table :: [(String, Int)]
        const table = cmdsFromString(
            `add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1
            Schange Cinsert 2  Clast 3 compress 4 copy 2 count 3 Coverlay 3
            cursor 3  delete 3 Cdelete 2  down 1  duplicate 3 xEdit 1 expand 3
            extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2
            forward 2  get  help 1 hexType 4 input 1 powerInput 3  join 1
            split 2 spltJOIN load locate 1 Clocate 2 lowerCase 3 upperCase 3
            Lprefix 2  macro  merge 2 modify 3 move 2 msg  next 1 overlay 1
            parse preserve 4 purge 3 put putD query 1 quit read recover 3
            refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4
            rgtLEFT right 2 left 2  save  set  shift 2  si  sort  sos stack 3
            status 4 top  transfer 3  type 1  up 1`
        );

        return fTable(
            'Abbreviation tests:\n',
            s => "'" + s + "'",
            s => "\n\t'" + s + "'",
            withExpansions(table),
            [
                'riG   rePEAT copies  put mo   rest    types   fup.    6      poweRin',
                ''
            ]
        );
    };

    // GENERIC FUNCTIONS ----------------------------------

    // Just :: a -> Maybe a
    const Just = x => ({
        type: 'Maybe',
        Nothing: false,
        Just: x
    });

    // Nothing :: Maybe a
    const Nothing = () => ({
        type: 'Maybe',
        Nothing: true,
    });

    // Tuple (,) :: a -> b -> (a, b)
    const Tuple = (a, b) => ({
        type: 'Tuple',
        '0': a,
        '1': b,
        length: 2
    });

    // compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
    const compose = (f, g) => x => f(g(x));

    // find :: (a -> Bool) -> [a] -> Maybe a
    const find = (p, xs) => {
        for (let i = 0, lng = xs.length; i < lng; i++) {
            if (p(xs[i])) return Just(xs[i]);
        }
        return Nothing();
    };

    // flip :: (a -> b -> c) -> b -> a -> c
    const flip = f =>
        1 < f.length ? (
            (a, b) => f(b, a)
        ) : (x => y => f(y)(x));

    // foldl1 :: (a -> a -> a) -> [a] -> a
    const foldl1 = (f, xs) =>
        1 < xs.length ? xs.slice(1)
        .reduce(f, xs[0]) : xs[0];

    // foldr :: (a -> b -> b) -> b -> [a] -> b
    const foldr = (f, a, xs) => xs.reduceRight(flip(f), a);

    // fst :: (a, b) -> a
    const fst = tpl => tpl[0];

    // fTable :: String -> (a -> String) ->
    //                     (b -> String) -> (a -> b) -> [a] -> String
    const fTable = (s, xShow, fxShow, f, xs) => {
        // Heading -> x display function ->
        //           fx display function ->
        //    f -> values -> tabular string
        const
            ys = map(xShow, xs),
            w = maximum(map(length, ys)),
            rows = zipWith(
                (a, b) => justifyRight(w, ' ', a) + ' -> ' + b,
                ys,
                map(compose(fxShow, f), xs)
            );
        return s + '\n' + unlines(rows);
    };

    // head :: [a] -> a
    const head = xs => xs.length ? xs[0] : undefined;

    // isDigit :: Char -> Bool
    const isDigit = c => {
        const n = ord(c);
        return 48 <= n && 57 >= n;
    };

    // isPrefixOf takes two lists or strings and returns
    // true iff the first is a prefix of the second.

    // isPrefixOf :: [a] -> [a] -> Bool
    // isPrefixOf :: String -> String -> Bool
    const isPrefixOf = (xs, ys) => {
        const go = (xs, ys) => {
            const intX = xs.length;
            return 0 < intX ? (
                ys.length >= intX ? xs[0] === ys[0] && go(
                    xs.slice(1), ys.slice(1)
                ) : false
            ) : true;
        };
        return 'string' !== typeof xs ? (
            go(xs, ys)
        ) : ys.startsWith(xs);
    };

    // justifyRight :: Int -> Char -> String -> String
    const justifyRight = (n, cFiller, s) =>
        n > s.length ? (
            s.padStart(n, cFiller)
        ) : s;

    // Returns Infinity over objects without finite length.
    // This enables zip and zipWith to choose the shorter
    // argument when one is non-finite, like cycle, repeat etc

    // length :: [a] -> Int
    const length = xs =>
        (Array.isArray(xs) || 'string' === typeof xs) ? (
            xs.length
        ) : Infinity;

    // map :: (a -> b) -> [a] -> [b]
    const map = (f, xs) =>
        (Array.isArray(xs) ? (
            xs
        ) : xs.split('')).map(f);

    // maximum :: Ord a => [a] -> a
    const maximum = xs =>
        0 < xs.length ? (
            foldl1((a, x) => x > a ? x : a, xs)
        ) : undefined;

    // maybe :: b -> (a -> b) -> Maybe a -> b
    const maybe = (v, f, m) =>
        m.Nothing ? v : f(m.Just);

    // ord :: Char -> Int
    const ord = c => c.codePointAt(0);

    // take :: Int -> [a] -> [a]
    // take :: Int -> String -> String
    const take = (n, xs) =>
        'GeneratorFunction' !== xs.constructor.constructor.name ? (
            xs.slice(0, n)
        ) : [].concat.apply([], Array.from({
            length: n
        }, () => {
            const x = xs.next();
            return x.done ? [] : [x.value];
        }));

    // toUpper :: String -> String
    const toUpper = s => s.toLocaleUpperCase();

    // unlines :: [String] -> String
    const unlines = xs => xs.join('\n');

    // unwords :: [String] -> String
    const unwords = xs => xs.join(' ');

    // words :: String -> [String]
    const words = s => s.split(/\s+/);

    // Use of `take` and `length` here allows zipping with non-finite lists
    // i.e. generators like cycle, repeat, iterate.

    // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
    const zipWith = (f, xs, ys) => {
        const
            lng = Math.min(length(xs), length(ys)),
            as = take(lng, xs),
            bs = take(lng, ys);
        return Array.from({
            length: lng
        }, (_, i) => f(as[i], bs[i], i));
    };

    // MAIN ---
    return main();
})();


/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program abbrEasy64.s   */
/* store list of command in a file */
/* and run the program  abbrEasy64 command.file */

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

.equ BUFFERSIZE,   1000
.equ NBMAXIELEMENTS, 100

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessTitre:            .asciz "Nom du fichier : "
szCarriageReturn:      .asciz "\n"
szMessErreur:          .asciz "Error detected.\n"
szMessErrBuffer:       .asciz "buffer size too less !!"
szMessErrorAbr:        .asciz "*error*"
szMessInput:           .asciz "Enter command (or quit to stop) : "
szCmdQuit:              .asciz "QUIT"
szValTest1:            .asciz "Quit"
szValTest2:            .asciz "Rep"
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
sZoneConv:      .skip 24
qAdrFicName:    .skip 8
iTabAdrCmd:     .skip 8 * NBMAXIELEMENTS
sBufferCmd:     .skip BUFFERSIZE
sBuffer:        .skip BUFFERSIZE
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                            // INFO: main
    mov x0,sp                    // stack address for load parameter
    bl traitFic                  // read file and store value in array
    cmp x0,#-1
    beq 100f                     // error ?
    ldr x0,qAdriTabAdrCmd
    bl controlLoad
1:
    ldr x0,qAdrszMessInput       // display input message
    bl affichageMess
    mov x0,#STDIN                // Linux input console
    ldr x1,qAdrsBuffer           // buffer address
    mov x2,#BUFFERSIZE           // buffer size
    mov x8, #READ                // request to read datas
    svc 0                        // call system
    sub x0,x0,#1
    mov x2,#0
    strb w2,[x1,x0]              // replace character 0xA by zéro final
    ldr x0,qAdrsBuffer
    ldr x1,qAdriTabAdrCmd
    bl controlCommand            // control text command
    mov x2,x0
    bl affichageMess
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    mov x0,x2
    ldr x1,qAdrszCmdQuit         // command quit ?
    bl comparStrings
    cmp x0,#0
    beq 100f                     // yes -> end
    b 1b                         // else loop

99:
    ldr x0,qAdrszMessErrBuffer
    bl affichageMess
100:                             // standard end of the program
    mov x0, #0                   // return code
    mov x8, #EXIT                // request to exit program
    svc #0                       // perform the system call

qAdrszCarriageReturn:      .quad szCarriageReturn
qAdrszMessErrBuffer:       .quad szMessErrBuffer
qAdrsZoneConv:             .quad sZoneConv
qAdrszMessInput:           .quad szMessInput
qAdrszCmdQuit:             .quad szCmdQuit
/******************************************************************/
/*      control abbrevation command                               */
/******************************************************************/
/* x0 contains string input command */
/* x1 contains address table string command */
controlCommand:                   // INFO: controlCommand
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    stp x8,x9,[sp,-16]!          // save  registres
    mov x8,x0
    mov x9,x1
    bl computeLength              // length input command
    mov x4,x0                     // save length input
    mov x2,#0                     // indice
    mov x3,#0                     // find counter
1:                                // loop search command in table
    ldr x1,[x9,x2,lsl #3]         // load a item
    cmp x1,#0                     // end ?
    beq 5f
    mov x0,x8
    bl comparStringSpe            //
    cmp x0,#0                     // no found other search
    beq 4f
    mov x6,#0
    mov x5,#0
2:                                // loop count capital letters
    ldrb w0,[x1,x6]
    cmp x0,#0
    beq 3f
    tst x0,#0x20                  // capital letter ?
    cinc x5,x5,eq
    add x6,x6,#1
    b 2b
3:
    cmp x4,x5                     // input < command capital letters
    blt 4f                        // no correct
    add x3,x3,#1                  // else increment counter
    mov x7,x1                     // and save address command
4:
    add x2,x2,#1                  // increment indice
    b 1b                          // and loop
5:
    cmp x3,#1                     // no find or multiple find ?
    bne 99f                       // error
                                  // one find

    mov x0,x7                     // length command table
    bl computeLength
    cmp x4,x0                     // length input > command ?
    bgt 99f                       // error

    // OK
    mov x4,#0x20                  // 5 bit to 1
    mov x2,#0
6:
    ldrb w3,[x7,x2]
    cmp x3,#0
    beq 7f
    bic x3,x3,x4                  // convert to capital letter
    strb w3,[x8,x2]
    add x2,x2,#1
    b 6b
7:
    strb w3,[x8,x2]               // store zéro final
    mov x0,x8                     // return string input address
    b 100f
99:
    ldr x0,qAdrszMessErrorAbr     // return string "error"
100:
    ldp x8,x9,[sp],16           // restaur des  2 registres
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
qAdrszMessErreur:           .quad szMessErreur
qAdrszMessErrorAbr:         .quad szMessErrorAbr
/******************************************************************/
/*     comparaison first letters String                                          */
/******************************************************************/
/* x0 contains first String   */
/* x1 contains second string */
/* x0 return 0 if not find else returns number letters OK */
comparStringSpe:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    mov x2,#0
1:
    ldrb w3,[x0,x2]           // input
    orr x4,x3,#0x20           // convert capital letter
    ldrb w5,[x1,x2]           // table
    orr x6,x5,#0x20           // convert capital letter
    cmp x4,x6
    bne 2f
    cmp x3,#0
    beq 3f
    add x2,x2,#1
    b 1b
2:
   cmp x3,#0                  // fist letters Ok
   beq 3f
   mov x0,#0                  // no ok
   b 100f
3:
   mov x0,x2
100:
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*     compute length  String                                          */
/******************************************************************/
/* x0 contains  String   */
/* x0 return length */
computeLength:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    mov x1,#0
1:
    ldrb w2,[x0,x1]
    cmp x2,#0                    // end ?
    beq 2f
    add x1,x1,#1
    b 1b
2:
   mov x0,x1                  // return length in x0
100:
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*     read file                                                   */
/******************************************************************/
/* x0 contains address stack begin           */
traitFic:                             // INFO: traitFic
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    stp x8,fp,[sp,-16]!          // save  registres
    mov fp,x0                         //  fp <- start address
    ldr x4,[fp]                       // number of Command line arguments
    cmp x4,#1
    ble 99f
    add x5,fp,#16                      // second parameter address
    ldr x5,[x5]
    ldr x0,qAdrqAdrFicName
    str x5,[x0]
    ldr x0,qAdrszMessTitre
    bl affichageMess                  // display string
    mov x0,x5
    bl affichageMess
    ldr x0,qAdrszCarriageReturn
    bl affichageMess                  // display carriage return

    mov x0,AT_FDCWD
    mov x1,x5                         // file name
    mov x2,#O_RDWR                    // flags
    mov x3,#0                         // mode
    mov x8, #OPEN                     // call system OPEN
    svc 0
    cmp x0,#0                         // error ?
    ble 99f
    mov x7,x0                         // File Descriptor
    ldr x1,qAdrsBufferCmd             // buffer address
    mov x2,#BUFFERSIZE                // buffer size
    mov x8,#READ                      // read file
    svc #0
    cmp x0,#0                         // error ?
    blt 99f
    // extraction datas
    ldr x1,qAdrsBufferCmd             // buffer address
    add x1,x1,x0
    mov x0,#0                         // store zéro final
    strb w0,[x1]
    ldr x0,qAdriTabAdrCmd             // key string command table
    ldr x1,qAdrsBufferCmd             // buffer address
    bl extracDatas
                                      // close file
    mov x0,x7
    mov x8, #CLOSE
    svc 0
    mov x0,#0
    b 100f
99:                                   // error
    ldr x0,qAdrszMessErreur           // error message
    bl   affichageMess
    mov x0,#-1
100:
    ldp x8,fp,[sp],16           // restaur des  2 registres
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
qAdrqAdrFicName:              .quad qAdrFicName
qAdrszMessTitre:              .quad szMessTitre
qAdrsBuffer:                  .quad sBuffer
qAdrsBufferCmd:               .quad sBufferCmd
qAdriTabAdrCmd:               .quad iTabAdrCmd
/******************************************************************/
/*     extrac digit file buffer                                   */
/******************************************************************/
/* x0 contains strings address           */
/* x1 contains buffer address         */
extracDatas:                     // INFO: extracDatas
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    stp x8,fp,[sp,-16]!          // save  registres
    mov x7,x0
    mov x6,x1
    mov x2,#0                    // string buffer indice
    mov x4,x1                    // start string
    mov x5,#0                    // string index
    //vidregtit debextrac
1:
    ldrb w3,[x6,x2]
    cmp x3,#0
    beq 4f                       // end
    cmp x3,#0xA
    beq 2f
    cmp x3,#' '                  // end string
    beq 3f
    add x2,x2,#1
    b 1b
2:
    mov x3,#0
    strb w3,[x6,x2]
    ldrb w3,[x6,x2]
    cmp x3,#0xD
    bne 21f
    add x2,x2,#2
    b 4f
21:
    add x2,x2,#1
    b 4f

3:
    mov x3,#0
    strb w3,[x6,x2]
    add x2,x2,#1
4:
    mov x0,x4
    str x4,[x7,x5,lsl #3]
    add x5,x5,#1
5:
    ldrb w3,[x6,x2]
    cmp x3,#0
    beq 100f
    cmp x3,#' '
    cinc x2,x2,eq
    //addeq x2,x2,#1
    beq 5b

    add x4,x6,x2                 // new start address
    b 1b
100:
    ldp x8,fp,[sp],16           // restaur des  2 registres
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*     control load                                      */
/******************************************************************/
/* x0 contains string table           */
controlLoad:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    mov x2,x0
    mov x1,#0
1:
    ldr x0,[x2,x1,lsl #3]
    cmp x0,#0
    beq 100f
    bl affichageMess
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    add x1,x1,#1
    b 1b

100:
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/************************************/
/* Strings case sensitive comparisons  */
/************************************/
/* x0 et x1 contains the address of strings */
/* return 0 in x0 if equals */
/* return -1 if string x0 < string x1 */
/* return 1  if string x0 > string x1 */
comparStrings:
    stp x1,lr,[sp,-16]!      // save  registres
    stp x2,x3,[sp,-16]!      // save  registres
    stp x4,x5,[sp,-16]!      // save  registres
    mov x2,#0                // counter
1:
    ldrb w3,[x0,x2]          // byte string 1
    ldrb w4,[x1,x2]          // byte string 2
    cmp x3,x4
    blt 2f
    bgt 3f
    cmp x3,#0                // 0 end string
    beq 4f                   // end string
    add x2,x2,#1             // else add 1 in counter
    b 1b                     // and loop
2:
    mov x0,#-1               // small
    b 100f
3:
    mov x0,#1                // greather
    b 100f
4:
    mov x0,#0                // equal
100:
    ldp x4,x5,[sp],16        // restaur des  2 registres
    ldp x2,x3,[sp],16        // restaur des  2 registres
    ldp x1,lr,[sp],16        // restaur des  2 registres
    ret
/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"


with Ada.Characters.Handling;
with Ada.Containers.Indefinite_Vectors;
with Ada.Strings.Fixed;
with Ada.Strings.Maps.Constants;
with Ada.Text_IO;

procedure Abbreviations_Easy is

   package Command_Vectors
   is new Ada.Containers.Indefinite_Vectors (Index_Type   => Positive,
                                             Element_Type => String);
   use Command_Vectors;

   Commands : Vector;

   procedure Append (Word_List : String) is
      use Ada.Strings;
      First : Positive := Word_List'First;
      Last  : Natural;
   begin
      loop
         Fixed.Find_Token (Word_List,
                           Set   => Maps.Constants.Letter_Set,
                           From  => First,
                           Test  => Inside,
                           First => First,
                           Last  => Last);
         exit when Last = 0;
         Commands.Append (Word_List (First .. Last));
         exit when Last = Word_List'Last;
         First := Last + 1;
      end loop;
   end Append;

   function Match (Word : String) return String is
      use Ada.Strings;
      use Ada.Characters.Handling;
      Upper_Word   : constant String := To_Upper (Word);
      Prefix_First : Positive;
      Prefix_Last  : Natural;
   begin
      if Word = "" then
         return "";
      end if;

      for Command of Commands loop
         Fixed.Find_Token (Command, Maps.Constants.Upper_Set, Inside,
                           Prefix_First, Prefix_Last);
         declare
            Upper_Prefix  : constant String  := Command (Prefix_First .. Prefix_Last);
            Upper_Command : constant String  := To_Upper (Command);
            Valid_Length  : constant Boolean := Word'Length >= Upper_Prefix'Length;
            Match_Length  : constant Natural := Natural'Min (Word'Length,
                                                             Command'Length);
            Valid_Match   : constant Boolean
              := Fixed.Head (Upper_Word, Upper_Word'Length)
                = Fixed.Head (Upper_Command, Upper_Word'Length);
         begin
            if Valid_Length and Valid_Match then
               return Upper_Command;
            end if;
         end;
      end loop;
      return "*error*";
   end Match;

   procedure Put_Match (To : String) is
      use Ada.Text_IO;
      M : constant String := Match (To);
   begin
      Put ("Match to '");  Put (To);
      Put ("' is '");      Put (M);
      Put_Line ("'");
   end Put_Match;

   procedure A (Item : String) renames Append;
begin
   A ("Add ALTer  BAckup Bottom  CAppend Change SCHANGE  CInsert CLAst COMPress COpy");
   A ("COUnt COVerlay CURsor DELete CDelete Down DUPlicate Xedit EXPand EXTract Find");
   A ("NFind NFINDUp NFUp CFind FINdup FUp FOrward GET Help HEXType Input POWerinput");
   A ("Join SPlit SPLTJOIN  LOAD  Locate CLocate  LOWercase UPPercase  LPrefix MACRO");
   A ("MErge MODify MOve MSG Next Overlay PARSE PREServe PURge PUT PUTD  Query  QUIT");
   A ("READ  RECover REFRESH RENum REPeat  Replace CReplace  RESet  RESTore  RGTLEFT");
   A ("RIght LEft  SAVE  SET SHift SI  SORT  SOS  STAck STATus  TOP TRAnsfer Type Up");

   Put_Match ("riG");
   Put_Match ("rePEAT");
   Put_Match ("copies");
   Put_Match ("put");
   Put_Match ("mo");
   Put_Match ("rest");
   Put_Match ("types");
   Put_Match ("fup.");
   Put_Match ("6");
   Put_Match ("poweRin");
   Put_Match ("");
   Put_Match ("o");
end Abbreviations_Easy;


function ack(m, n) {
 return m === 0 ? n + 1 : ack(m - 1, n === 0  ? 1 : ack(m, n - 1));
}


#!/usr/bin/python
# Abundant odd numbers - Python

oddNumber  = 1
aCount  = 0
dSum  = 0

from math import sqrt

def divisorSum(n):
    sum = 1
    i = int(sqrt(n)+1)

    for d in range (2, i):
        if n % d == 0:
            sum += d
            otherD = n // d
            if otherD != d:
                sum += otherD
    return sum

print ("The first 25 abundant odd numbers:")
while aCount  < 25:
    dSum  = divisorSum(oddNumber )
    if dSum  > oddNumber :
        aCount  += 1
        print("{0:5} proper divisor sum: {1}". format(oddNumber ,dSum ))
    oddNumber  += 2

while aCount  < 1000:
    dSum  = divisorSum(oddNumber )
    if dSum  > oddNumber :
        aCount  += 1
    oddNumber  += 2
print ("\n1000th abundant odd number:")
print ("    ",(oddNumber - 2)," proper divisor sum: ",dSum)

oddNumber  = 1000000001
found  = False
while not found :
    dSum  = divisorSum(oddNumber )
    if dSum  > oddNumber :
        found  = True
        print ("\nFirst abundant odd number > 1 000 000 000:")
        print ("    ",oddNumber," proper divisor sum: ",dSum)
    oddNumber  += 2


s:{c where 0=x mod c:1+til x div 2}            / proper divisors
sd:sum s@                                      / sum of proper divisors
abundant:{x<sd x}
Filter:{y where x each y}


const commandtable = """
add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3
compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate
3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2
forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load
locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2
msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3
refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left
2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1"""

function makedict(tbl)
    str = split(uppercase(tbl), r"\s+")
    dict = Dict{String, String}()
    for (i, s) in enumerate(str)
        if (n = tryparse(Int, s)) != nothing
            dict[str[i-1][1:n]] = str[i-1]
        else
            dict[s] = s
        end
    end
    dict
end

function okabbrev(dict, abb)
    for i in length(abb):-1:1
        if haskey(dict, abb[1:i])
            com = dict[abb[1:i]]
            if length(abb) <= length(com) && abb == com[1:length(abb)]
                return dict[abb[1:i]]
            end
        end
    end
    return "*error*"
end

formattedprint(arr, n) =  (for s in arr print(rpad(s, n)) end; println())

function teststring(str)
    d = makedict(commandtable)
    commands = split(str, r"\s+")
    formattedprint(commands, 9)
    formattedprint([okabbrev(d, uppercase(s)) for s in commands], 9)
end

teststring("riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin")


import java.util.Locale

private const val table = "" +
        "add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3 " +
        "compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate " +
        "3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2 " +
        "forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load " +
        "locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2 " +
        "msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3 " +
        "refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left " +
        "2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1 "

private data class Command(val name: String, val minLen: Int)

private fun parse(commandList: String): List<Command> {
    val commands = mutableListOf<Command>()
    val fields = commandList.trim().split(" ")
    var i = 0
    while (i < fields.size) {
        val name = fields[i++]
        var minLen = name.length
        if (i < fields.size) {
            val num = fields[i].toIntOrNull()
            if (num != null && num in 1..minLen) {
                minLen = num
                i++
            }
        }
        commands.add(Command(name, minLen))
    }
    return commands
}

private fun get(commands: List<Command>, word: String): String? {
    for ((name, minLen) in commands) {
        if (word.length in minLen..name.length && name.startsWith(word, true)) {
            return name.toUpperCase(Locale.ROOT)
        }
    }
    return null
}

fun main(args: Array<String>) {
    val commands = parse(table)
    val sentence = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"
    val words = sentence.trim().split(" ")

    val results = words.map { word -> get(commands, word) ?: "*error*" }

    val paddedUserWords = words.mapIndexed { i, word -> word.padEnd(results[i].length) }
    println("user words:  ${paddedUserWords.joinToString(" ")}")
    println("full words:  ${results.joinToString(" ")}")
}


abbr = {
  define = function(self, cmdstr)
    local cmd
    self.hash = {}
    for word in cmdstr:upper():gmatch("%S+") do
      if cmd then
        local n = tonumber(word)
        for len = n or #cmd, #cmd do
          self.hash[cmd:sub(1,len)] = cmd
        end
        cmd = n==nil and word or nil
      else
        cmd = word
      end
    end
  end,
  expand = function(self, input)
    local output = {}
    for word in input:upper():gmatch("%S+") do
      table.insert(output, self.hash[word] or "*error*")
    end
    return table.concat(output, " ")
  end
}
abbr:define[[
  add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3
  compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate
  3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2
  forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load
  locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2
  msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3
  refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left
  2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1
]]
local input = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"
print("Input:", input)
print("Output:", abbr:expand(input))


# "Easy" abbreviations                                                 #
# table of "commands" - upper-case indicates the mminimum abbreviation #
STRING command table = "Add ALTer  BAckup Bottom  CAppend Change SCHANGE  CInsert CLAst COMPress COpy "
                     + "COUnt COVerlay CURsor DELete CDelete Down DUPlicate Xedit EXPand EXTract Find "
                     + "NFind NFINDUp NFUp CFind FINdup FUp FOrward GET Help HEXType Input POWerinput "
                     + "Join SPlit SPLTJOIN  LOAD  Locate CLocate  LOWercase UPPercase  LPrefix MACRO "
                     + "MErge MODify MOve MSG Next Overlay PARSE PREServe PURge PUT PUTD  Query  QUIT "
                     + "READ  RECover REFRESH RENum REPeat  Replace CReplace  RESet  RESTore  RGTLEFT "
                     + "RIght LEft  SAVE  SET SHift SI  SORT  SOS  STAck STATus  TOP TRAnsfer Type Up";

# returns the next word from text, updating pos                        #
PRIO NEXTWORD = 1;
OP   NEXTWORD = ( REF INT pos, STRING text )STRING:
     BEGIN
        # skip spaces #
        WHILE IF pos > UPB text THEN FALSE ELSE text[ pos ] = " " FI DO pos +:= 1 OD;
        # get the word #
        STRING word := "";
        WHILE IF pos > UPB text THEN FALSE ELSE text[ pos ] /= " " FI DO
            word +:= text[ pos ];
            pos +:= 1
        OD;
        word
     END # NEXTWORD # ;
# returns text converted to upper case                                 #
OP   TOUPPER  = ( STRING text )STRING:
     BEGIN
        STRING result := text;
        FOR ch pos FROM LWB result TO UPB result DO
            IF is lower( result[ ch pos ] ) THEN result[ ch pos ] := to upper( result[ ch pos ] ) FI
        OD;
        result
     END # TOUPPER # ;
# returns the minimum abbreviation length of command                   #
OP   MINABLENGTH = ( STRING command )INT:
     BEGIN
        INT ab min := LWB command;
        WHILE IF ab min > UPB command THEN FALSE ELSE is upper( command[ ab min ] ) FI DO ab min +:= 1 OD;
        ab min - LWB command
     END # MINABLENGTH # ;
# searches for word in command table and returns the full command      #
# matching the possible abbreviation or *error* if there is no match   #
PRIO EXPAND  = 1;
OP   EXPAND  = ( STRING command table, word )STRING:
     IF word = ""
     THEN # empty word #
        ""
     ELSE # non-empty word #
        INT    word len    = ( UPB word + 1 ) - LWB word;
        STRING upper word := TOUPPER word;
        STRING result     := "*error*";
        INT    pos        := LWB command table;
        WHILE  STRING command := pos NEXTWORD command table;
               IF command = ""
               THEN # end of command table #
                   FALSE
               ELIF word len < MINABLENGTH command OR word len > ( ( UPB command + 1 ) - LWB command )
               THEN # word is too short or too long - try the next command #
                   TRUE
               ELIF upper word = TOUPPER command[ LWB command : ( LWB command - 1 ) + word len ]
               THEN # found the command #
                   result := TOUPPER command;
                   FALSE
               ELSE # word doexn't match - try the next command #
                   TRUE
               FI
        DO SKIP OD;
        result
     FI # EXPAND # ;
# tests the EXPAND operator                                            #
PROC test expand = ( STRING words, command table )VOID:
     BEGIN
        STRING results := "", separator := "";
        INT    pos   := LWB words;
        WHILE STRING word = pos NEXTWORD words; word /= "" DO
            results +:= separator + ( command table EXPAND word );
            separator := " "
        OD;
        print( ( "Input:  ", words, newline ) );
        print( ( "Output: ", results, newline ) )
     END # test expand # ;

# task test cases                                                      #
test expand( "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin", command table );
test expand( "",                                                                      command table )


DEFINE ack == [ [ [pop null]  popd succ ]
                [ [null]  pop pred 1 ack ]
                [ [dup pred swap] dip pred ack ack ] ]
              cond.


 [ 0 swap factors witheach + ] is sigmasum ( n --> n )

  0 -1 [ 2 +
         dup sigmasum
         over 2 * over < iff
           [ over echo sp
             echo cr
             dip 1+ ]
         else drop
         over 25 = until ]
  2drop
  cr
  0 -1
  [ 2 + dup sigmasum
    over 2 * > if [ dip 1+ ]
    over 1000 = until ]
  dup echo sp sigmasum echo cr
  drop
  cr
  999999999
  [ 2 + dup sigmasum
    over 2 * > until ]
  dup echo sp sigmasum echo cr


# Abundant Odd Numbers

find_div_sum <- function(x){
  # Finds sigma: the sum of the divisors (not including the number itself) of an odd number
  if (x < 16) return(0)
  root <- sqrt(x)
  vec <- as.vector(1)
  for (i in seq.int(3, root - 1, by = 2)){
    if(x %% i == 0){
      vec <- c(vec, i, x/i)
    }
  }
  if (root == trunc(root)) vec = c(vec, root)
  return(sum(vec))
}

get_n_abun <- function(index = 1, total = 25, print_all = TRUE){
  # Finds a total of 'total' abundant odds starting with 'index', with print option
  n <- 1
  while(n <= total){
    my_sum <- find_div_sum(index)
    if (my_sum > index){
      if(print_all) cat(index, "..... sigma is", my_sum, "\n")
      n <- n + 1
    }
    index <- index + 2
  }
  if(!print_all) cat(index - 2, "..... sigma is", my_sum, "\n")
}

# Get first 25
cat("The first 25 abundants are")
get_n_abun()

# Get the 1000th
cat("The 1000th odd abundant is")
get_n_abun(total = 1000, print_all = F)

# Get the first after 1e9
cat("First odd abundant after 1e9 is")
get_n_abun(index = 1e9 + 1, total = 1, print_all = F)


#lang racket

(require math/number-theory
         racket/generator)

(define (make-generator start)
  (in-generator
   (for ([n (in-naturals start)] #:when (odd? n))
     (define divisor-sum (- (apply + (divisors n)) n))
     (when (> divisor-sum n) (yield (list n divisor-sum))))))

(for/list ([i (in-range 25)] [x (make-generator 0)]) x) ; Task 1
(for/last ([i (in-range 1000)] [x (make-generator 0)]) x) ; Task 2
(for/first ([x (make-generator (add1 (inexact->exact 1e9)))]) x) ; Task 3


Module Abbreviations_Simple {
	Function Lex {
		a$={add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3
		   compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate
		   3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2
		   forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load
		   locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2
		   msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3
		   refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left
		   2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1
		}
		const crlftab$={
		}+chr$(9)

		Lex=Queue
		Word$=""
		dim part$()
		part$()=piece$(trim$(filter$(a$, crlftab$)), " ")
		for i=0 to len(part$())-1
		if part$(i)<>"" then
			k=val(part$(i))
			if k=0 then
				if Word$<>"" then Append Lex, Word$:=Word$
				Word$=ucase$(part$(i))
			else
				for j=k to len(Word$)
				Append Lex, left$(Word$,j):=Word$
				next j
				word$=""
			end if
		end if
		next i
		if Word$<>"" then Append Lex, Word$:=Word$
		=Lex
	}
	Parse$=Lambda$ Lex=Lex() (a$) -> {
		Dim part$()
		Rep$=""
		part$()=piece$(a$," ")
		if len(part$())=0 then exit
		for i=0 to len(part$())-1
		if part$(i)<>"" then
			if exist(Lex, ucase$(part$(i))) then
				Rep$+=if$(Rep$=""->"", " ")+Eval$(lex)
			else
				Rep$+=if$(Rep$=""->"", " ")+"*error*"
			end if
		end if
		next i
		=Rep$
	}
	Print Parse$("riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin")
	Print Parse$("riG   macro copies macr")
	Print Parse$("")=""
}
Abbreviations_Simple


ClearAll[ct, FunctionMatchQ, ValidFunctionQ, ProcessString]
ct = "add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3
   compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate
   3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2
   forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load
   locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2
   msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3
   refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left
   2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1";
ct = FixedPoint[StringReplace[{"\n" -> "", Longest[" " ..] -> " "}], ct];
ct = StringSplit[ct, " "];
ct = SequenceReplace[ct, {x_, y : (Alternatives @@ (ToString /@ Range[1, 9]))} :> {x, [email protected]}];
ct = If[MatchQ[#, {_, _Integer}], #, {#, 1}] & /@ ct;
FunctionMatchQ[{func_String, min_Integer}, test_String] :=
 Module[{max, l},
  max = StringLength[func];
  l = StringLength[test];
  If[min <= l <= max,
   If[StringStartsQ[func, test, IgnoreCase -> True],
    True
    ,
    False
    ]
   ,
   False
   ]
  ]
ValidFunctionQ[test_String] := Module[{val},
  val = SelectFirst[ct, FunctionMatchQ[#, test] &, Missing[]];
  If[MissingQ[val], "*error*", ToUpperCase[[email protected]]]
  ]
ProcessString[test_String] := Module[{parts},
  parts = StringSplit[test];
  StringRiffle[ValidFunctionQ /@ parts, " "]
  ]
ProcessString["riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"]


c = "add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2 Clast 3" +
 " compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate" +
 " 3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2" +
 " forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load" +
 " locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2" +
 " msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3" +
 " refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left" +
 " 2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1"

minLen = {}
lastItem = ""
for item in c.split
    if item == "" then continue
    item = item.upper
    if lastItem and item[0] >= "0" and item[0] <= "9" then
        minLen[lastItem] = val(item)
        lastItem = ""
    else
        minLen[item] = null
        lastItem = item
    end if
end for

check = function(word)
    word = word.upper
    for key in minLen.indexes
        if key[:word.len] != word then continue
        min = minLen[key]
        if min and word.len < min then continue
        return key
    end for
    return "*error*"
end function

input = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"

output = []
for word in input.split
    if word == "" then continue
    output.push check(word)
end for
print output.join


import parseutils
import strutils
import tables

const Commands =
  "add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3 " &
  "compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate " &
  "3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2 " &
  "forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load " &
  "locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2 " &
  "msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3 " &
  "refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left " &
  "2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1"

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

proc abbrevationLengths(commands: string): Table[string, int] =
  ## Find the minimal abbreviation length for each word.
  ## A word that does not have minimum abbreviation length specified
  ## gets it's full length as the minimum.

  var word = ""
  for item in commands.splitWhitespace():
    var n: int
    if item.parseInt(n) == 0:
      # Not a number.
      if word.len != 0:
        # No minimal length specified for the word.
        result[word] = word.len
      word = item
    else:
      # Got an integer.
      if word.len == 0:
        raise newException(ValueError, "Invalid position for number: " & $n)
      result[word] = n
      word = ""

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

proc abbreviations(commandTable: Table[string, int]): Table[string, string] =
  ## For each command insert all possible abbreviations.
  for command, minlength in commandTable.pairs:
    for length in minLength..command.len:
      let abbr = command[0..<length].toLower
      result[abbr] = command.toUpper

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

proc parse(words: seq[string]; abbrevTable: Table[string, string]): seq[string] =
  ## Parse a list of words and return the list of full words (or *error*).
  for word in words:
    result.add(abbrevTable.getOrDefault(word.toLower, "*error*"))

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

let commandTable = Commands.abbrevationLengths()
let abbrevTable = commandTable.abbreviations()

while true:

  try:
    stdout.write "Input? "
    let userWords = stdin.readline().strip().splitWhitespace()
    let fullWords = userWords.parse(abbrevTable)
    stdout.write("\nUser words: ")
    for i, word in userWords:
      stdout.write(word.alignLeft(fullWords[i].len) & ' ')
    stdout.write("\nFull words: ")
    for word in fullWords:
      stdout.write(word & ' ')
    stdout.write("\n\n")

  except EOFError:
    echo ""
    break


; Setting up command table as one string
str =
(
 Add ALTer  BAckup Bottom  CAppend Change SCHANGE  CInsert CLAst COMPress COpy
 COUnt COVerlay CURsor DELete CDelete Down DUPlicate Xedit EXPand EXTract Find
 NFind NFINDUp NFUp CFind FINdup FUp FOrward GET Help HEXType Input POWerinput
 Join SPlit SPLTJOIN  LOAD  Locate CLocate  LOWercase UPPercase  LPrefix MACRO
 MErge MODify MOve MSG Next Overlay PARSE PREServe PURge PUT PUTD  Query  QUIT
 READ  RECover REFRESH RENum REPeat  Replace CReplace  RESet  RESTore  RGTLEFT
 RIght LEft  SAVE  SET SHift SI  SORT  SOS  STAck STATus  TOP TRAnsfer Type Up
)
str := StrReplace(str,"`n")

; comTable turns the command table string into an array
; comTableCapsCount creates an array with the count of capital values for each word
comTable := StrSplit(RegExReplace(str, "\s+", " "), " ")
comTableCapsCount := []
for cmds in comTable
	comTableCapsCount.push(StrLen(RegExReplace(comTable[cmds], "[a-z]")))

; Take and process user input into an array of abbreviations
InputBox, abbrev, Command, Type in your command(s).`n If you have several commands`, leave spaces between them.
abbrev := Trim(abbrev)
StringLower, lowerCaseAbbrev, abbrev
abbrev := StrSplit(RegExReplace(abbrev, "\s+", " "), " ")

; Double loop compares abbreviations to commands in command table
Loop % abbrev.MaxIndex() {
	count := A_Index
	found := false
	for cmds in comTable {
		command := SubStr(comTable[cmds], 1, StrLen(abbrev[count]))
		StringLower, lowerCaseCommand, command
		if (lowerCaseCommand = abbrev[count]) and (StrLen(abbrev[count]) >= comTableCapsCount[cmds]) {
			StringUpper, foundCmd, % comTable[cmds]
			found := true
		}
	}
	if (found)
		result .= " " foundCmd
	else
		result .= " *error*"
}
MsgBox % Trim(result)


# input: [m,n]
def ack:
  .[0] as $m | .[1] as $n
  | if $m == 0 then $n + 1
    elif $n == 0 then [$m-1, 1] | ack
    else [$m-1, ([$m, $n-1 ] | ack)] | ack
    end ;


sub odd-abundant (\x) {
    my @l = x.is-prime ?? 1 !! flat
    1, (3 .. x.sqrt.floor).map: -> \d {
         next unless d +& 1;
         my \y = x div d;
         next if y * d !== x;
         d !== y ?? (d, y) !! d
    };
    @l.sum > x ?? @l.sort !! Empty;
}

sub odd-abundants (Int :$start-at is copy) {
    $start-at = ( $start-at + 2 ) div 3;
    $start-at += $start-at %% 2;
    $start-at *= 3;
    ($start-at, *+6 ... *).hyper.map: {
        next unless my $oa = cache .&odd-abundant;
        sprintf "%6d: divisor sum: {$oa.join: ' + '} = {$oa.sum}", $_
    }
}

put 'First 25 abundant odd numbers:';
.put for odd-abundants( :start-at(1) )[^25];

put "\nOne thousandth abundant odd number:\n" ~ odd-abundants( :start-at(1) )[999] ~

"\n\nFirst abundant odd number above one billion:\n" ~ odd-abundants( :start-at(1_000_000_000) ).head;


open String

let table_as_string =
  "add 1 alter 3  backup 2  bottom 1  Cappend 2  change 1 \
   Schange  Cinsert 2  Clast 3 compress 4 copy 2 count 3 \
   Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate 3 \
   xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 \
   Cfind 2 findUP 3 fUP 2 forward 2  get  help 1 hexType 4 \
   input 1 powerInput 3  join 1 split 2 spltJOIN load locate 1 \
   Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 \
   modify 3 move 2 msg  next 1 overlay 1 parse preserve 4 purge 3 \
   put putD query 1 quit  read recover 3 refresh renum 3 repeat 3 \
   replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left 2 \
   save  set  shift 2  si  sort  sos  stack 3 status 4 top \
   transfer 3  type 1  up 1"


@c = (uc join ' ', qw<
add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3
compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate
3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2
forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load
locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2
msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3
refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left
2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1
>) =~ /([a-zA-Z]+(?:\s+\d+)?)(?=\s+[a-zA-Z]|$)/g;

my %abr = ('' => '', ' ' => '');
for (@c) {
    ($w,$sl) = split ' ', $_;
    $ll = length($w);
    $sl = $ll unless $sl;
    $abr{substr($w,0,$sl)} = $w;
    map { $abr{substr($w, 0, $_)} = $w } $sl .. $ll;
}

$fmt = "%-10s";
$inp = sprintf $fmt, 'Input:';
$out = sprintf $fmt, 'Output:';
for $str ('', qw<riG rePEAT copies put mo rest types fup. 6 poweRin>) {
    $inp .= sprintf $fmt, $str;
    $out .= sprintf $fmt, $abr{uc $str} // '*error*';
}

print "$inp\n$out\n";


#!/usr/bin/awk -f
BEGIN {
FS=" ";
split("   Add ALTer  BAckup Bottom  CAppend Change SCHANGE  CInsert CLAst COMPress COpy" \
      "   COUnt COVerlay CURsor DELete CDelete Down DUPlicate Xedit EXPand EXTract Find" \
      "   NFind NFINDUp NFUp CFind FINdup FUp FOrward GET Help HEXType Input POWerinput" \
      "   Join SPlit SPLTJOIN  LOAD  Locate CLocate  LOWercase UPPercase  LPrefix MACRO" \
      "   MErge MODify MOve MSG Next Overlay PARSE PREServe PURge PUT PUTD  Query  QUIT" \
      "   READ  RECover REFRESH RENum REPeat  Replace CReplace  RESet  RESTore  RGTLEFT" \
      "   RIght LEft  SAVE  SET SHift SI  SORT  SOS  STAck STATus  TOP TRAnsfer Type Up" \
      , CMD);

	for (k=1; k <= length(CMD); k++) {
		cmd[k] = CMD[k];
		sub(/[a-z]*$/,"",cmd[k]);
		# print "0: ",CMD[k],"\t",cmd[k];
	}
}

function GET_ABBR(input) {
	for (k2=1; k2<=length(CMD); k2++) {
		if (index(toupper(CMD[k2]),input)==1) {
			if (index(input,toupper(cmd[k2]))==1) {
				return toupper(CMD[k2]);
			}
		}
	}
	return "*error*";
}

{
	R="";
	for (k1=1; k1 <= NF; k1++) {
		R=R" "GET_ABBR(toupper($k1))
	}
	print R;
}


#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char* command_table =
  "Add ALTer  BAckup Bottom  CAppend Change SCHANGE  CInsert CLAst COMPress COpy "
  "COUnt COVerlay CURsor DELete CDelete Down DUPlicate Xedit EXPand EXTract Find "
  "NFind NFINDUp NFUp CFind FINdup FUp FOrward GET Help HEXType Input POWerinput "
  "Join SPlit SPLTJOIN  LOAD  Locate CLocate  LOWercase UPPercase  LPrefix MACRO "
  "MErge MODify MOve MSG Next Overlay PARSE PREServe PURge PUT PUTD  Query  QUIT "
  "READ  RECover REFRESH RENum REPeat  Replace CReplace  RESet  RESTore  RGTLEFT "
  "RIght LEft  SAVE  SET SHift SI  SORT  SOS  STAck STATus  TOP TRAnsfer Type Up";

typedef struct command_tag {
    char* cmd;
    size_t length;
    size_t min_len;
    struct command_tag* next;
} command_t;

// str is assumed to be all uppercase
bool command_match(const command_t* command, const char* str) {
    size_t olen = strlen(str);
    return olen >= command->min_len && olen <= command->length
        && strncmp(str, command->cmd, olen) == 0;
}

// convert string to uppercase
char* uppercase(char* str, size_t n) {
    for (size_t i = 0; i < n; ++i)
        str[i] = toupper((unsigned char)str[i]);
    return str;
}

size_t get_min_length(const char* str, size_t n) {
    size_t len = 0;
    while (len < n && isupper((unsigned char)str[len]))
        ++len;
    return len;
}

void fatal(const char* message) {
    fprintf(stderr, "%s\n", message);
    exit(1);
}

void* xmalloc(size_t n) {
    void* ptr = malloc(n);
    if (ptr == NULL)
        fatal("Out of memory");
    return ptr;
}

void* xrealloc(void* p, size_t n) {
    void* ptr = realloc(p, n);
    if (ptr == NULL)
        fatal("Out of memory");
    return ptr;
}

char** split_into_words(const char* str, size_t* count) {
    size_t size = 0;
    size_t capacity = 16;
    char** words = xmalloc(capacity * sizeof(char*));
    size_t len = strlen(str);
    for (size_t begin = 0; begin < len; ) {
        size_t i = begin;
        for (; i < len && isspace((unsigned char)str[i]); ++i) {}
        begin = i;
        for (; i < len && !isspace((unsigned char)str[i]); ++i) {}
        size_t word_len = i - begin;
        if (word_len == 0)
            break;
        char* word = xmalloc(word_len + 1);
        memcpy(word, str + begin, word_len);
        word[word_len] = 0;
        begin += word_len;
        if (capacity == size) {
            capacity *= 2;
            words = xrealloc(words, capacity * sizeof(char*));
        }
        words[size++] = word;
    }
    *count = size;
    return words;
}

command_t* make_command_list(const char* table) {
    command_t* cmd = NULL;
    size_t count = 0;
    char** words = split_into_words(table, &count);
    for (size_t i = 0; i < count; ++i) {
        char* word = words[i];
        command_t* new_cmd = xmalloc(sizeof(command_t));
        size_t word_len = strlen(word);
        new_cmd->length = word_len;
        new_cmd->min_len = get_min_length(word, word_len);
        new_cmd->cmd = uppercase(word, word_len);
        new_cmd->next = cmd;
        cmd = new_cmd;
    }
    free(words);
    return cmd;
}

void free_command_list(command_t* cmd) {
    while (cmd != NULL) {
        command_t* next = cmd->next;
        free(cmd->cmd);
        free(cmd);
        cmd = next;
    }
}

const command_t* find_command(const command_t* commands, const char* word) {
    for (const command_t* cmd = commands; cmd != NULL; cmd = cmd->next) {
        if (command_match(cmd, word))
            return cmd;
    }
    return NULL;
}

void test(const command_t* commands, const char* input) {
    printf(" input: %s\n", input);
    printf("output:");
    size_t count = 0;
    char** words = split_into_words(input, &count);
    for (size_t i = 0; i < count; ++i) {
        char* word = words[i];
        uppercase(word, strlen(word));
        const command_t* cmd_ptr = find_command(commands, word);
        printf(" %s", cmd_ptr ? cmd_ptr->cmd : "*error*");
        free(word);
    }
    free(words);
    printf("\n");
}

int main() {
    command_t* commands = make_command_list(command_table);
    const char* input = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin";
    test(commands, input);
    free_command_list(commands);
    return 0;
}