/*REXX pgm displays abundant odd numbers:  1st 25,  one─thousandth,  first > 1 billion. */
parse arg Nlow Nuno Novr .                       /*obtain optional arguments from the CL*/
if Nlow=='' | Nlow==","  then Nlow=          25  /*Not specified?  Then use the default.*/
if Nuno=='' | Nuno==","  then Nuno=        1000  /* "      "         "   "   "     "    */
if Novr=='' | Novr==","  then Novr=  1000000000  /* "      "         "   "   "     "    */
numeric digits max(9, length(Novr) )             /*ensure enough decimal digits for  // */
@= 'odd abundant number'                         /*variable for annotating the output.  */
#= 0                                             /*count of odd abundant numbers so far.*/
      do j=3  by 2  until #>=Nlow;   $= sigO(j)  /*get the  sigma  for an odd integer.  */
      if $<=j  then iterate                      /*sigma  ≤  J ?    Then ignore it.     */
      #= # + 1                                   /*bump the counter for abundant odd #'s*/
      say rt(th(#))     @      'is:'rt(commas(j), 8)     rt("sigma=")     rt(commas($), 9)
      end  /*j*/
say
#= 0                                             /*count of odd abundant numbers so far.*/
      do j=3  by 2;                  $= sigO(j)  /*get the  sigma  for an odd integer.  */
      if $<=j    then iterate                    /*sigma  ≤  J ?    Then ignore it.     */
      #= # + 1                                   /*bump the counter for abundant odd #'s*/
      if #<Nuno  then iterate                    /*Odd abundant# count<Nuno?  Then skip.*/
      say rt(th(#))     @      'is:'rt(commas(j), 8)     rt("sigma=")     rt(commas($), 9)
      leave                                      /*we're finished displaying NUNOth num.*/
      end  /*j*/
say
      do j=1+Novr%2*2  by 2;         $= sigO(j)  /*get sigma for an odd integer > Novr. */
      if $<=j    then iterate                    /*sigma  ≤  J ?    Then ignore it.     */
      say rt(th(1))   @  'over'  commas(Novr)  "is: "   commas(j)  rt('sigma=')  commas($)
      leave                                      /*we're finished displaying NOVRth num.*/
      end  /*j*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas:parse arg _;  do c_=length(_)-3  to 1  by -3; _=insert(',', _, c_);  end;  return _
rt:    procedure;  parse arg #,len;     if len==''  then len= 20;     return right(#, len)
th:    parse arg th; return th||word('th st nd rd',1+(th//10)*(th//100%10\==1)*(th//10<4))
/*──────────────────────────────────────────────────────────────────────────────────────*/
sigO:  parse arg x;            s= 1              /*sigma for odd integers.           ___*/
             do k=3  by 2  while k*k<x           /*divide by all odd integers up to √ x */
             if x//k==0  then  s= s + k + x%k    /*add the two divisors to (sigma) sum. */
             end   /*k*/                         /*                                  ___*/
       if k*k==x  then  return s + k             /*Was  X  a square?    If so, add  √ x */
                        return s                 /*return (sigma) sum of the divisors.  */


constant abbrtxt = """
   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
""",
input = "riG   rePEAT copies  put mo   rest    types   fup.    6   poweRin"

function set_min_lengths(sequence a)
--
-- set default lengths and apply min lengths if present, eg ..."macro","merge","2",...
--  ==> {.."macro",5}} ==> {.."macro",5},{"merge",5}} ==> {.."macro",5},{"merge",2}}
-- ie both macro and merge get a default min length of 5, but the min length of merge
--    is overwritten when the "2" is processed.
--
    sequence res = {}
    for i=1 to length(a) do
        string ai = a[i]
        if length(ai)=1 and ai>="1" and ai<="9" then
            res[$][2] = ai[1]-'0'
        else
            res = append(res,{ai,length(ai)})
        end if
    end for
    return res
end function

constant abbrevs = set_min_lengths(split(substitute(abbrtxt,"\n"," "),no_empty:=true))
constant inputs = split(input,no_empty:=true)

for i=1 to length(inputs) do
    string ii = inputs[i],
           res = "*error*"
    for j=1 to length(abbrevs) do
        {string aj, integer l} = abbrevs[j]
        if length(ii)>=l
        and match(ii,aj,case_insensitive:=true)==1 then
            res = upper(aj)
            exit
        end if
    end for
    puts(1,res&" ")
end for
puts(1,"\n")


#include <algorithm>
#include <cctype>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

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";

class command {
public:
    command(const std::string&, size_t);
    const std::string& cmd() const { return cmd_; }
    size_t min_length() const { return min_len_; }
    bool match(const std::string&) const;
private:
    std::string cmd_;
    size_t min_len_;
};

// cmd is assumed to be all uppercase
command::command(const std::string& cmd, size_t min_len)
    : cmd_(cmd), min_len_(min_len) {}

// str is assumed to be all uppercase
bool command::match(const std::string& str) const {
    size_t olen = str.length();
    return olen >= min_len_ && olen <= cmd_.length()
        && cmd_.compare(0, olen, str) == 0;
}

// convert string to uppercase
void uppercase(std::string& str) {
    std::transform(str.begin(), str.end(), str.begin(),
        [](unsigned char c) -> unsigned char { return std::toupper(c); });
}

size_t get_min_length(const std::string& str) {
    size_t len = 0, n = str.length();
    while (len < n && std::isupper(static_cast<unsigned char>(str[len])))
        ++len;
    return len;
}

class command_list {
public:
    explicit command_list(const char*);
    const command* find_command(const std::string&) const;
private:
    std::vector<command> commands_;
};

command_list::command_list(const char* table) {
    std::vector<command> commands;
    std::istringstream is(table);
    std::string word;
    while (is >> word) {
        // count leading uppercase characters
        size_t len = get_min_length(word);
        // then convert to uppercase
        uppercase(word);
        commands_.push_back(command(word, len));
    }
}

const command* command_list::find_command(const std::string& word) const {
    auto iter = std::find_if(commands_.begin(), commands_.end(),
        [&word](const command& cmd) { return cmd.match(word); });
    return (iter != commands_.end()) ? &*iter : nullptr;
}

std::string test(const command_list& commands, const std::string& input) {
    std::string output;
    std::istringstream is(input);
    std::string word;
    while (is >> word) {
        if (!output.empty())
            output += ' ';
        uppercase(word);
        const command* cmd_ptr = commands.find_command(word);
        if (cmd_ptr)
            output += cmd_ptr->cmd();
        else
            output += "*error*";
    }
    return output;
}

int main() {
    command_list commands(command_table);
    std::string input("riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin");
    std::string output(test(commands, input));
    std::cout << " input: " << input << '\n';
    std::cout << "output: " << output << '\n';
    return 0;
}


function ack(m,n)
    if m == 0
        return n + 1
    elseif n == 0
        return ack(m-1,1)
    else
        return ack(m-1,ack(m,n-1))
    end
end


#Project: Anbundant odd numbers

max = 100000000
limit = 25
nr = 0
m = 1
check = 0
index = 0
see "working..." + nl
see "wait for done..." + nl
while true
      check = 0
      if m%2 = 1
         nice(m)
      ok
      if check = 1
         nr = nr + 1
      ok
      if nr = max
         exit
      ok
      m = m + 1
end
see "done..." + nl

func nice(n)
     check = 0
     nArray = []
     for i = 1 to n - 1
         if n % i = 0
            add(nArray,i)
         ok
     next
     sum = 0
     for p = 1 to len(nArray)
         sum = sum + nArray[p]
     next
     if sum > n
        check = 1
        index = index + 1
        if index < limit + 1
           showArray(n,nArray,sum,index)
        ok
        if index = 100
           see "One thousandth abundant odd number:" + nl
           showArray2(n,nArray,sum,index)
        ok
        if index = 100000000
           see "First abundant odd number above one billion:" + nl
           showArray2(n,nArray,sum,index)
        ok
     ok

func showArray(n,nArray,sum,index)
        see "" + index + ". " + string(n) + ": divisor sum: "
        for m = 1 to len(nArray)
            if m < len(nArray)
               see string(nArray[m]) + " + "
            else
               see string(nArray[m]) + " = " + string(sum) + nl + nl
            ok
        next

func showArray2(n,nArray,sum,index)
        see "" + index + ". " + string(n) + ": divisor sum: " +
        see string(nArray[m]) + " = " + string(sum) + nl + nl


require "prime"

class Integer
  def proper_divisors
    return [] if self == 1
    primes = prime_division.flat_map{|prime, freq| [prime] * freq}
    (1...primes.size).each_with_object([1]) do |n, res|
      primes.combination(n).map{|combi| res << combi.inject(:*)}
    end.flatten.uniq
  end
end

def generator_odd_abundants(from=1)
  from += 1 if from.even?
  Enumerator.new do |y|
    from.step(nil, 2) do |n|
      sum = n.proper_divisors.sum
      y << [n, sum] if sum > n
    end
  end
end

generator_odd_abundants.take(25).each{|n, sum| puts "#{n} with sum #{sum}" }
puts "\n%d with sum %#d" % generator_odd_abundants.take(1000).last
puts "\n%d with sum %#d" % generator_odd_abundants(1_000_000_000).next


command_table_text = """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"""

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

def find_abbreviations_length(command_table_text):
    """ find the minimal abbreviation length for each word.
        a word that does not have minimum abbreviation length specified
        gets it's full lengths as the minimum.
    """
    command_table = dict()
    input_iter = iter(command_table_text.split())

    word = None
    try:
        while True:
            if word is None:
                word = next(input_iter)
            abbr_len = next(input_iter, len(word))
            try:
                command_table[word] = int(abbr_len)
                word = None
            except ValueError:
                command_table[word] = len(word)
                word = abbr_len
    except StopIteration:
        pass
    return command_table

def find_abbreviations(command_table):
    """ for each command insert all possible abbreviations"""
    abbreviations = dict()
    for command, min_abbr_len in command_table.items():
        for l in range(min_abbr_len, len(command)+1):
            abbr = command[:l].lower()
            abbreviations[abbr] = command.upper()
    return abbreviations

def parse_user_string(user_string, abbreviations):
    user_words = [word.lower() for word in user_string.split()]
    commands = [abbreviations.get(user_word, "*error*") for user_word in user_words]
    return " ".join(commands)

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

full_words = parse_user_string(user_words, abbreviations_table)

print("user words:", user_words)
print("full words:", full_words)


#lang racket
(require srfi/13)

(define command-table #<<EOS
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
EOS
  )

(define command/abbr-length-pairs
  (let loop ((cmd-len-list (string-split command-table)) (acc (list)))
    (match cmd-len-list
      ((list) (sort acc < #:key cdr))
      ((list-rest a (app string->number (and ad (not #f))) dd) (loop dd (cons (cons a ad) acc)))
      ((list-rest a d) (loop d (cons (cons a (string-length a)) acc))))))

(define (validate-word w)
  (or (let ((w-len (string-length w)))
        (for/first ((candidate command/abbr-length-pairs)
                    #:when (and (>= w-len (cdr candidate)) (string-prefix-ci? w (car candidate))))
          (string-upcase (car candidate))))
      "*error*"))

(define (validate-string s) (string-join (map validate-word (string-split s))))

(module+ main
  (define (debug-i/o s) (printf "input:  ~s~%output: ~s~%" s (validate-string s)))
  (debug-i/o "")
  (debug-i/o "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"))

(module+ test
  (require rackunit)
  (check-equal?
   (validate-string "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin")
   "RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT")
  (check-equal? (validate-string "") ""))


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

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

(def cmd-table
  "Command Table - List of words to match against"
  (words
   "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"))

; TODO - cache word properties
(defn abbr-valid?
  "Is abbr abbreviation of word?"
  [abbr word]
  (and (.startsWith (.toLowerCase word) (.toLowerCase abbr))
       (<= (count (filter #(Character/isUpperCase %) word))
           (count abbr)
           (count word))))

(defn find-word-for-abbr
  "Find first word matching abbreviation, or nil if not found"
  [abbr]
  (first (filter #(abbr-valid? abbr %) cmd-table)))

(defn solution
  "Find word matching each abbreviation in input (or *error* if not found),
   and join results into a string"
  [str]
  (join-words (for [abbr (words str)]
                (if-let [word (find-word-for-abbr abbr)]
                  (.toUpperCase word)
                  "*error*"))))

;; Example Input
(print (solution "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"))


program Abbreviations_Easy;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

const
  _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 ';

function validate(commands, words: TArray<string>; minLens: TArray<Integer>):
  TArray<string>;
begin
  SetLength(result, 0);
  if Length(words) = 0 then
    exit;
  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 (minLens[i] = 0) or (wlen < minLens[i]) or (wlen > length(command)) then
        continue;

      var c := command.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;

begin
  var table := _TABLE_.Trim;
  var commands := table.Split([' '], TStringSplitOptions.ExcludeEmpty);
  var clen := Length(commands);
  var minLens: TArray<integer>;
  SetLength(minLens, clen);
  for var i := 0 to clen - 1 do
  begin
    var count := 0;
    for var c in commands[i] do
    begin
      if (c >= 'A') and (c <= 'Z') then
        inc(count);
    end;
    minLens[i] := count;
  end;

  var sentence := 'riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin';
  var words := sentence.Split([' '], TStringSplitOptions.ExcludeEmpty);
  var results := validate(commands, words, minLens);
  Write('user words: ');
  for var j := 0 to Length(words) - 1 do
    Write(words[j].PadRight(1 + length(results[j])));
  Write(#10, 'full words: ');
  Writeln(string.Join(' ', results));
  Readln;
end.


fn divisors(n: u64) -> Vec<u64> {
    let mut divs = vec![1];
    let mut divs2 = Vec::new();

    for i in (2..).take_while(|x| x * x <= n).filter(|x| n % x == 0) {
        divs.push(i);
        let j = n / i;
        if i != j {
            divs2.push(j);
        }
    }
    divs.extend(divs2.iter().rev());

    divs
}

fn sum_string(v: Vec<u64>) -> String {
    v[1..]
        .iter()
        .fold(format!("{}", v[0]), |s, i| format!("{} + {}", s, i))
}

fn abundant_odd(search_from: u64, count_from: u64, count_to: u64, print_one: bool) -> u64 {
    let mut count = count_from;
    for n in (search_from..).step_by(2) {
        let divs = divisors(n);
        let total: u64 = divs.iter().sum();
        if total > n {
            count += 1;
            let s = sum_string(divs);
            if !print_one {
                println!("{}. {} < {} = {}", count, n, s, total);
            } else if count == count_to {
                println!("{} < {} = {}", n, s, total);
            }
        }
        if count == count_to {
            break;
        }
    }
    count_to
}

fn main() {
    let max = 25;
    println!("The first {} abundant odd numbers are:", max);
    let n = abundant_odd(1, 0, max, false);

    println!("The one thousandth abundant odd number is:");
    abundant_odd(n, 25, 1000, true);

    println!("The first abundant odd number above one billion is:");
    abundant_odd(1e9 as u64 + 1, 0, 1, true);
}


import scala.collection.mutable.ListBuffer

object Abundant {
  def divisors(n: Int): ListBuffer[Int] = {
    val divs = new ListBuffer[Int]
    divs.append(1)

    val divs2 = new ListBuffer[Int]
    var i = 2

    while (i * i <= n) {
      if (n % i == 0) {
        val j = n / i
        divs.append(i)
        if (i != j) {
          divs2.append(j)
        }
      }
      i += 1
    }

    divs.appendAll(divs2.reverse)
    divs
  }

  def abundantOdd(searchFrom: Int, countFrom: Int, countTo: Int, printOne: Boolean): Int = {
    var count = countFrom
    var n = searchFrom
    while (count < countTo) {
      val divs = divisors(n)
      val tot = divs.sum
      if (tot > n) {
        count += 1
        if (!printOne || !(count < countTo)) {
          val s = divs.map(a => a.toString).mkString(" + ")
          if (printOne) {
            printf("%d < %s = %d\n", n, s, tot)
          } else {
            printf("%2d. %5d < %s = %d\n", count, n, s, tot)
          }
        }
      }
      n += 2
    }

    n
  }

  def main(args: Array[String]): Unit = {
    val max = 25
    printf("The first %d abundant odd numbers are:\n", max)
    val n = abundantOdd(1, 0, max, printOne = false)

    printf("\nThe one thousandth abundant odd number is:\n")
    abundantOdd(n, 25, 1000, printOne = true)

    printf("\nThe first abundant odd number above one billion is:\n")
    abundantOdd((1e9 + 1).intValue(), 0, 1, printOne = true)
  }
}


<
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
> ~~ m:g/ (<.alpha>+) \s* (\d*) /;

my %abr = '' => '', |$/.map: {
    my $abbrv = .[0].Str.fc;
    |map { $abbrv.substr( 0, $_ ) => $abbrv.uc },
    +(.[1].Str || .[0].Str.chars) .. .[0].Str.chars;
};

sub abbr-simple ( $str ) { %abr{$str.trim.fc} // '*error*' }

# Testing
for 'riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin', '' -> $str {
    put ' Input: ', $str;
    put 'Output: ', join ' ', $str.words.map: &abbr-simple;
}


include std/text.e  -- for upper conversion
include std/console.e -- for display
include std/sequence.e

sequence ct = """
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
"""
ct = upper(split(join(split(ct,"\n")," ")," "))

object input = remove_all("\n",upper(remove_all("",split(gets(0)))))
display(validate(input))

-------------------------------
function validate(object words)
-------------------------------
object results = repeat("*error*",length(words)) -- build an output list;
integer x
for i = 1 to length(words) do
    words[i] = remove_all('\n',words[i]) -- final word in input line (may) have \n, get rid of it;
    for j = 1 to length(ct) do
        x = match(words[i],ct[j])
        if x = 1 then
            results[i] = ct[j] -- replace this slot in the output list with the "found" word;
            exit -- and don't look further into the list;
        end if
    end for
end for
return flatten(join(results," ")) -- convert sequence of strings into one string, words separated by a single space;
end function


USING: arrays ascii assocs combinators.short-circuit io kernel
literals math qw sequences sequences.extras splitting.extras ;
IN: rosetta-code.abbreviations-easy

CONSTANT: commands qw{
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 }

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

: starts-with? ( cand com -- ? ) [ >upper ] [email protected] start 0 = ;
: capitals ( str -- n ) [ LETTER? ] count ;
: min-len? ( candidate command -- ? ) capitals swap length <= ;
: not-longer? ( candidate command -- ? ) [ length ] [email protected] <= ;
: permitted? ( candidate command -- ? ) dup [ letter? ] count 0
    > [ [ >upper ] [email protected] = ] dip or ;

: valid-abbr? ( candidate command -- ? )
    {
        [ permitted?   ]
        [ starts-with? ]
        [ min-len?     ]
        [ not-longer?  ]
    } 2&& ;

: find-command ( candidate -- command/f )
    commands swap [ swap valid-abbr? ] curry find nip ;

: process-candidate ( candidate -- abbr/error )
    find-command [ >upper ] [ "*error*" ] if* ;

: process-user-string ( str -- seq ) dup "" = [ drop "" ]
    [ " " split-harvest [ process-candidate ] map ] if ;

: .abbr ( input -- )
    [ " " split-harvest ] [ process-user-string ] bi zip
    [ first2 32 pad-longest 2array ] map
    [ keys ] [ values ] bi
    [ " " join ] [email protected]
    [ "User words: " write print ]
    [ "Full words: " write print ] bi* ;

: main ( -- ) user-input "" [ .abbr ] [email protected] ;

MAIN: main


V6; W0;
YS26000;
RESTART; J999; J999;
PROGRAM;                   (main program);
   V1 = B1212121212121212; (radix 10 for FRB);
   V2 = B2020202020202020; (high bits for decimal digits);
   V3 = B0741062107230637; ("A[3,"  in Flexowriter code);
   V4 = B0727062200250007; ("7] = " in Flexowriter code);
   V5 = B7777777777777777;

      ZERO; NOT; =M1;      (Q1 := 0/0/-1);
      SETAYS0; =M2; I2=2;  (Q2 := 0/2/AYS0: M2 is the stack pointer);
      SET 3; =RC7;         (Q7 := 3/1/0: C7 = m);
      SET 7; =RC8;         (Q8 := 7/1/0: C8 = n);
   JSP1;                   (call Ackermann function);
      V1; REV; FRB;        (convert result to base 10);
      V2; OR;              (convert decimal digits to characters);
      V5; REV;
      SHLD+24; =V5; ERASE; (eliminate leading zeros);
      SETAV5; =RM9;
      SETAV3; =I9;
      POAQ9;               (write result to Flexowriter);

999;  ZERO; OUT;           (terminate run);

P1; (To compute A[m, n]);

   99;
      J1C7NZ;           (to 1 if m ± 0);
         I8; =+C8;      (n := n + 1);
         C8;            (result to NEST);
      EXIT 1;           (return);
   *1;
      J2C8NZ;           (to 2 if n ± 0);
         I8; =C8;       (n := 1);
         DC7;           (m := m - 1);
      J99;              (tail recursion for A[m-1, 1]);
   *2;
         LINK; =M0M2;   (push return address);
         C7; =M0M2QN;   (push m);
         DC8;           (n := n - 1);
      JSP1;             (full recursion for A[m, n-1]);
         =C8;           (n := A[m, n-1]);
         M1M2; =C7;     (m := top of stack);
         DC7;           (m := m - 1);
         M-I2;          (pop stack);
         M0M2; =LINK;   (return address := top of stack);
      J99;              (tail recursion for A[m-1, A[m, n-1]]);

FINISH;


func is_abundant(n) {
    n.sigma > 2*n
}

func odd_abundants (from = 1) {
     from =  (from + 2)//3
     from += (from%2 - 1)
     3*from .. Inf `by` 6 -> lazy.grep(is_abundant)
}

say         " Index |      Number | proper divisor sum"
const sep = "-------+-------------+-------------------\n"
const fstr = "%6s | %11s | %11s\n"

print sep

odd_abundants().first(25).each_kv {|k,n|
    printf(fstr, k+1, n, n.sigma-n)
}

with (odd_abundants().nth(1000)) {|n|
    printf(sep + fstr, 1000, n, n.sigma-n)
}

with(odd_abundants(1e9).first) {|n|
    printf(sep + fstr, '***', n, n.sigma-n)
}


divisors :=
    [:nr |
        |divs|

        divs := Set with:1.
        "no need to check even factors; we are only looking for odd nrs"
        3 to:(nr integerSqrt) by:2 do:[:d | nr % d = 0 ifTrue:[divs add:d; add:(nr / d)]].
        divs.
    ].

isAbundant := [:nr | (divisors value:nr) sum > nr].

"from set of abdundant numbers >= minNr, print nMinPrint-th to nMaxPrint-th"
printNAbundant :=
    [:minNr :nMinPrint :nMaxPrint |
        |count divs|

        count := 0.
        minNr to:Infinity positive doWithExit:[:nr :exit |
            (nr odd and:[isAbundant value:nr]) ifTrue:[
                count := count + 1.
                count >= nMinPrint ifTrue:[
                    divs := divisors value:nr.
                    Transcript
                        show:nr; show:' -> '; show:divs asArray sorted;
                        show:' sum = '; showCR:divs sum.
                ].
                count >= nMaxPrint ifTrue: exit
            ]
        ]
    ].

Transcript showCR:'first 25 odd abundant numbers:'.
"from set of abdundant numbers >= 3, print 1st to 25th"
printNAbundant value:3 value:1 value:25.

Transcript cr; showCR:'first odd abundant number above 1000000000:'.
"from set of abdundant numbers >= 1000000000, print 1st to 1st"
printNAbundant value:1000000000 value:1 value:1.

Transcript cr; showCR:'first odd abundant number above 1000000000000:'.
"from set of abdundant numbers >= 1000000000, print 1st to 1st"
printNAbundant value:1000000000000 value:1 value:1.

Transcript cr; showCR:'the 1000th odd abundant number is:'.
"from set of abdundant numbers>= 3, print 1000th to 1000th"
printNAbundant value:3 value:1000 value:1000.


/*REXX program validates a user  "word"  against a  "command table"  with abbreviations.*/
parse arg uw                                     /*obtain optional arguments from the CL*/
if uw=''  then uw= 'riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin'
say 'user words: '   uw

@= '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'

say 'full words: '   validate(uw)                /*display the result(s) to the terminal*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
validate: procedure expose @;  arg x;  upper @   /*ARG   capitalizes all the  X  words. */
          $=                                     /*initialize the return string to null.*/
             do j=1  to words(x);   _=word(x, j) /*obtain a word from the     X  list.  */
               do k=1  to words(@); a=word(@, k) /*get a legitmate command name from  @.*/
               L=word(@, k+1)                    /*··· and maybe get it's abbrev length.*/
               if datatype(L, 'W')  then k=k + 1       /*yuppers, it's an abbrev length.*/
                                    else L=length(a)   /*nope,  it can't be abbreviated.*/
               if abbrev(a, _, L)   then do; $=$ a;  iterate j;  end  /*is valid abbrev?*/
               end   /*k*/
             $=$ '*error*'                       /*processed the whole list, not valid. */
             end     /*j*/
          return strip($)                        /*elide the superfluous leading blank. */


str = "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"

RE = /(?<word1>[a-zA-Z]+)\s+(?<word2>[a-zA-Z]+)/
str = str.upcase
# add missing wordsizes
2.times{ str.gsub!(RE){ [  $~[:word1], $~[:word1].size, $~[:word2] ].join(" ")} }

table = Hash[*str.split].transform_values(&:to_i)

test =  "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"
ar = test.split.map do |w|
  (res = table.detect{|k,v| k.start_with?(w.upcase) && w.size >= v}) ? res[0] : "*error*"
end

puts ar.join(" ")


package main

import (
    "fmt"
    "strings"
)

var 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 "

func validate(commands, words []string, minLens []int) []string {
    results := make([]string, 0)
    if len(words) == 0 {
        return results
    }
    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 main() {
    table = strings.TrimSpace(table)
    commands := strings.Fields(table)
    clen := len(commands)
    minLens := make([]int, clen)
    for i := 0; i < clen; i++ {
        count := 0
        for _, c := range commands[i] {
            if c >= 'A' && c <= 'Z' {
                count++
            }
        }
        minLens[i] = count
    }
    sentence :=  "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"
    words := strings.Fields(sentence)
    results := validate(commands, words, minLens)
    fmt.Print("user words:  ")
    for j := 0; j < len(words); j++ {
        fmt.Printf("%-*s ", len(results[j]), words[j])
    }
    fmt.Print("\nfull words:  ")
    fmt.Println(strings.Join(results, " "))
}


:ack
    %n !n %m !m

    $m 0 ==
    ( [$n 1 +]
      [$n 0 ==
        ( [$m 1 - 1 ack]
          [$m 1 - $m $n 1 - ack ack]
        ) if
      ]
    ) if
;

3 6 ack print nl
msec print

" " input


extension BinaryInteger {
  @inlinable
  public func factors(sorted: Bool = true) -> [Self] {
    let maxN = Self(Double(self).squareRoot())
    var res = Set<Self>()

    for factor in stride(from: 1, through: maxN, by: 1) where self % factor == 0 {
      res.insert(factor)
      res.insert(self / factor)
    }

    return sorted ? res.sorted() : Array(res)
  }
}

@inlinable
public func isAbundant<T: BinaryInteger>(n: T) -> (Bool, [T]) {
  let divs = n.factors().dropLast()

  return (divs.reduce(0, +) > n, Array(divs))
}

let oddAbundant = (0...).lazy.filter({ $0 & 1 == 1 }).map({ ($0, isAbundant(n: $0)) }).filter({ $1.0 })

for (n, (_, factors)) in oddAbundant.prefix(25) {
  print("n: \(n); sigma: \(factors.reduce(0, +))")
}

let (bigA, (_, bigFactors)) =
  (1_000_000_000...)
    .lazy
    .filter({ $0 & 1 == 1 })
    .map({ ($0, isAbundant(n: $0)) })
    .first(where: { $1.0 })!

print("first odd abundant number over 1 billion: \(bigA), sigma: \(bigFactors.reduce(0, +))")


Module AbundantOddNumbers
    ' find some abundant odd numbers - numbers where the sum of the proper
    '                                  divisors is bigger than the number
    '                                  itself

    ' returns the sum of the proper divisors of n
    Private Function divisorSum(n As Integer) As Integer
        Dim sum As Integer = 1
        For d As Integer = 2 To Math.Round(Math.Sqrt(n))
            If n Mod d = 0 Then
                sum += d
                Dim otherD As Integer = n \ d
                IF otherD <> d Then
                    sum += otherD
                End If
            End If
        Next d
        Return sum
    End Function

    ' find numbers required by the task
    Public Sub Main(args() As String)
        ' first 25 odd abundant numbers
        Dim oddNumber As Integer = 1
        Dim aCount As Integer = 0
        Dim dSum As Integer = 0
        Console.Out.WriteLine("The first 25 abundant odd numbers:")
        Do While aCount < 25
            dSum = divisorSum(oddNumber)
            If dSum > oddNumber Then
                aCount += 1
                Console.Out.WriteLine(oddNumber.ToString.PadLeft(6) & " proper divisor sum: " & dSum)
            End If
            oddNumber += 2
        Loop
        ' 1000th odd abundant number
        Do While aCount < 1000
            dSum = divisorSum(oddNumber)
            If dSum > oddNumber Then
                aCount += 1
            End If
            oddNumber += 2
        Loop
        Console.Out.WriteLine("1000th abundant odd number:")
        Console.Out.WriteLine("    " & (oddNumber - 2) & " proper divisor sum: " & dSum)
        ' first odd abundant number > one billion
        oddNumber = 1000000001
        Dim found As Boolean = False
        Do While Not found
            dSum = divisorSum(oddNumber)
            If dSum > oddNumber Then
                found = True
                Console.Out.WriteLine("First abundant odd number > 1 000 000 000:")
                Console.Out.WriteLine("    " & oddNumber & " proper divisor sum: " & dSum)
            End If
            oddNumber += 2
        Loop
    End Sub
End Module


use std::collections::HashMap;

// The plan here is to build a hashmap of all the commands keyed on the minimum number of
// letters than can be provided in the input to match. For each known command it will appear
// in a list of possible commands for a given string lengths. A command can therefore appear a
// number of times. For example, the command 'recover' has a minimum abbreviation length of 3.
// In the hashmap 'recover' will be stored behind keys for 3, 4, 5, 6 & 7 as any abbreviation of
// 'recover' from 3 until 7 letters inclusive can match. This way, once the length of the input
// string is known a subset of possible matches can be retrieved immediately and then checked.
//
fn main() {
    let command_table_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_command 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";

    // Split up the command table string using the whitespace and set up an iterator
    // to run through it. We need the iterator to be peekable so that we can look ahead at
    // the next item.
    let mut iter = command_table_string.split_whitespace().peekable();

    let mut command_table = HashMap::new();

    // Attempt to take two items at a time from the command table string. These two items will be
    // the command string and the minimum length of the abbreviation. If there is no abbreviation length
    // then there is no number provided. As the second item might not be a number, so we need to peek at
    // it first. If it is a number we can use it as a key for the hashmap. If it is not a number then
    // we use the length of the first item instead because no abbreviations are available for the
    // word i.e. the whole word must be used. A while loop is used because we need to control iteration
    // and look ahead.
    //
    while let Some(command_string) = iter.next() {
        let command_string_length = command_string.len() as i32;

        let min_letter_match = match iter.peek() {
            Some(potential_number) => match potential_number.parse::<i32>() {
                Ok(number) => {
                    iter.next();
                    number
                }
                Err(_) => command_string_length,
            },
            None => break,
        };

        // The word must be stored for every valid abbreviation length.
        //
        for i in min_letter_match..=command_string_length {
            let cmd_list = command_table.entry(i).or_insert_with(Vec::new);
            cmd_list.push(command_string.to_uppercase());
        }
    }

    const ERROR_TEXT: &str = "*error*";

    let test_input_text = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin";

    let mut output_text = String::new();

    let mut iter = test_input_text.split_whitespace().peekable();

    // Run through each item in the input string, find the length of it
    // and then use this to fetch a list of possible matches.
    // A while loop is used because we need to look ahead in order to indentify
    // the last item and avoid adding an unnecessary space.
    //
    while let Some(input_command) = iter.next() {
        let input_command_length = input_command.len() as i32;

        let command_list = match command_table.get(&input_command_length) {
            Some(list) => list,
            None => {
                output_text.push_str(ERROR_TEXT);
                continue;
            }
        };

        let input_command_caps = input_command.to_uppercase();
        let matched_commands: Vec<&String> = command_list
            .iter()
            .filter(|command| command.starts_with(&input_command_caps))
            .collect();

        // Should either be 0 or 1 command found
        assert!(
            matched_commands.len() < 2,
            "Strange.. {:?}",
            matched_commands
        );

        match matched_commands.first() {
            Some(cmd) => output_text.push_str(cmd),
            None => output_text.push_str(ERROR_TEXT),
        }

        if iter.peek().is_some() {
            output_text.push(' ');
        }
    }

    println!("Input was: {}", test_input_text);
    println!("Output is: {}", output_text);

    let correct_output = "RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT";
    assert_eq!(output_text, correct_output)
}


object Main extends App {
    implicit class StrOps(i: String) {
        def isAbbreviationOf(target: String, targetMinLength: Int): Boolean = {
            @scala.annotation.tailrec
            def checkPAsPrefixOfM(p: List[Char], m: List[Char]): Boolean = (p, m) match {
                case (Nil, _) => true //prefix empty
                case (_, Nil) => false //main string empty
                case (ph :: pt, mh :: mt) if ph.toUpper == mh.toUpper => checkPAsPrefixOfM(pt, mt) //case insensitive match of head characters
                case _ => false
            }
            i.length >= targetMinLength && checkPAsPrefixOfM(i.toList, target.toList)
        }
    }

    val 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
      """.stripMargin.replace("\n", " ").trim.split(" ")

    val commandWithMinLengths = commands.sliding(2, 1)
                                       .filter{ window =>
                                           window.length > 1 && Try(window(0).toInt).toOption.isEmpty
                                       }
                                       .map{ w =>
                                           (
                                               w(0),
                                               Try(w(1).toInt).toOption.getOrElse(0)
                                           )
                                       }
                                       .toList

    val input = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin".split(" ").filter(!_.isEmpty)

    val resultLine = input.map{ i =>
        commandWithMinLengths.find{case (c, l) => i.isAbbreviationOf(c, l)}.map(_._1.toUpperCase).getOrElse("*error*")
    }.mkString(" ")

    println(resultLine)
}


import Data.Maybe (fromMaybe)
import Data.List (find, isPrefixOf)
import Data.Char (toUpper, isUpper)

isAbbreviationOf :: String -> String -> Bool
isAbbreviationOf abbreviation command =
  minimumPrefix `isPrefixOf` normalizedAbbreviation
  && normalizedAbbreviation `isPrefixOf` normalizedCommand
  where
    normalizedAbbreviation = map toUpper abbreviation
    normalizedCommand = map toUpper command
    minimumPrefix = takeWhile isUpper command

expandAbbreviation :: String -> String -> Maybe String
expandAbbreviation commandTable abbreviation = do
  command <- find (isAbbreviationOf abbreviation) (words commandTable)
  return $ map toUpper command

commandTable = unwords [
  "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"]

main :: IO ()
main = do
  input <- getLine
  let abbreviations = words input
  let commands = map (fromMaybe "*error*" . expandAbbreviation commandTable) abbreviations
  putStrLn $ unwords results


   COMMAND_TABLE=: noun define
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
 )

   'CAPA CAPZ'=:a.i.'AZ'
   CT =: (, 3 ": [: +/ (CAPA&<: *. <:&CAPZ)@:(a.&i.))&.>&.:;: CRLF -.~ COMMAND_TABLE
   user_words =: 'riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin'
   CT expand user_words
RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT


fn divisors(n i64) []i64 {
    mut divs := [i64(1)]
    mut divs2 := []i64{}
    for i := 2; i*i <= n; i++ {
        if n%i == 0 {
            j := n / i
            divs << i
            if i != j {
                divs2 << j
            }
        }
    }
    for i := divs2.len - 1; i >= 0; i-- {
        divs << divs2[i]
    }
    return divs
}

fn sum(divs []i64) i64 {
    mut tot := i64(0)
    for div in divs {
        tot += div
    }
    return tot
}

fn sum_str(divs []i64) string {
    mut s := ""
    for div in divs {
        s += "${u8(div)} + "
    }
    return s[0..s.len-3]
}

fn abundant_odd(search_from i64, count_from int, count_to int, print_one bool) i64 {
    mut count := count_from
    mut n := search_from
    for ; count < count_to; n += 2 {
        divs := divisors(n)
        tot := sum(divs)
        if tot > n {
            count++
            if print_one && count < count_to {
                continue
            }
            s := sum_str(divs)
            if !print_one {
                println("${count:2}. ${n:5} < $s = $tot")
            } else {
                println("$n < $s = $tot")
            }
        }
    }
    return n
}

const max = 25

fn main() {
    println("The first $max abundant odd numbers are:")
    n := abundant_odd(1, 0, 25, false)

    println("\nThe one thousandth abundant odd number is:")
    abundant_odd(n, 25, 1000, true)

    println("\nThe first abundant odd number above one billion is:")
    abundant_odd(1_000_000_001, 0, 1, true)
}


import "/fmt" for Fmt
import "/math" for Int, Nums

var sumStr = Fn.new { |divs| divs.reduce("") { |acc, div| acc + "%(div) + " }[0...-3] }

var abundantOdd = Fn.new { |searchFrom, countFrom, countTo, printOne|
    var count = countFrom
    var n = searchFrom
    while (count < countTo) {
        var divs = Int.properDivisors(n)
        var tot = Nums.sum(divs)
        if (tot > n) {
            count = count + 1
            if (!printOne || count >= countTo) {
                var s = sumStr.call(divs)
                if (!printOne) {
                    System.print("%(Fmt.d(2, count)). %(Fmt.d(5, n)) < %(s) = %(tot)")
                } else {
                    System.print("%(n) < %(s) = %(tot)")
                }
            }
        }
        n = n + 2
    }
    return n
}

var MAX = 25
System.print("The first %(MAX) abundant odd numbers are:")
var n = abundantOdd.call(1, 0, 25, false)

System.print("\nThe one thousandth abundant odd number is:")
abundantOdd.call(n, 25, 1000, true)

System.print("\nThe first abundant odd number above one billion is:")
abundantOdd.call(1e9+1, 0, 1, true)


* Program: abbr_simple.sbl
* To run: sbl abbr_simple.sbl
* Description: Abbreviations, simple
* Comment: Tested using the Spitbol for Linux version of SNOBOL4

	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 "

	commands = replace(commands,&lcase,&ucase)
	numerals = '0123456789'

* Function filltable will fill the command abbreviations table
	define("filltable(s,n)slen,i")
		ct = table(300, ,"*error*") :f(errr);* command abbreviations table
	:(filltable_end)
filltable
	slen = size(s)
	ct[s] = s
	eq(n,slen) :s(filltable3)
	i = n - 1
filltable2
	i = lt(i,slen - 1) i + 1 :f(filltable3)
	ct[substr(s,1,i)] = s
	:(filltable2)
filltable3
	filltable = ""
	:(return)
filltable_end

x0
* Populate command abbreviations table
	commands ? (span(' ') | "") breakx(&ucase) span(&ucase) . c
+		span(' ') (span(numerals) | "") . ablen = "" :f(x1)
	ablen = ident(ablen) size(c)
	ret = filltable(c,ablen)
    :(x0)
x1
* Process user string
	userstring = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"
	output = "Original user string:"
	output = userstring
	userstring = replace(userstring,&lcase,&ucase)
x2
	userstring ? (span(' ') | "") (break(' ') | (len(1) rem)) . c = "" :f(x3)
	user_commands = (gt(size(user_commands),0) user_commands ' ' ct[c], ct[c])
	:(x2)
x3
	output = ""
	output = "User string with abbreviations expanded:"
	output = user_commands

END


proc appendCmd {word} {
  # Procedure to append the correct command from the global list ::cmds
  # for the word given as parameter to the global list ::result.
  # If a matching word has been found and appended to ::result, this procedure
  # behaves like a "continue" statement, causing the loop containing it to
  # jump over the rest of the body.
  set candidates [lsearch -inline -all -nocase -glob $::cmds "${word}*"]
  foreach cand $candidates {
    if {[string length $word] >= $::minLen($cand)} {
      lappend ::result [string toupper $cand]
      return -code continue
    }
  }
}

set cmds {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}

# Find the minimum lengths necessary for each command.
foreach c $cmds {
  regexp {^[A-Z]+} $c match
  set minLen($c) [string length $match]
}

set words {riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin}
set result {}

foreach w $words {
  appendCmd $w
  lappend result *error*
}

puts "user words: $words"
puts $result


Private Function ValidateUserWords(userstring As String) As String
    Dim s As String
    Dim user_words() As String
    Dim command_table As Scripting.Dictionary
    Set command_table = New Scripting.Dictionary
    Dim abbreviations As Scripting.Dictionary
    Set abbreviations = New Scripting.Dictionary
    abbreviations.CompareMode = TextCompare
    Dim commandtable() As String
    Dim commands As String
    s = s & "add 1  alter 3  backup 2  bottom 1  Cappend 2  change 1  Schange  Cinsert 2  Clast 3 "
    s = s & "compress 4 copy 2 count 3 Coverlay 3 cursor 3  delete 3 Cdelete 2  down 1  duplicate "
    s = s & "3 xEdit 1 expand 3 extract 3  find 1 Nfind 2 Nfindup 6 NfUP 3 Cfind 2 findUP 3 fUP 2 "
    s = s & "forward 2  get  help 1 hexType 4  input 1 powerInput 3  join 1 split 2 spltJOIN load "
    s = s & "locate 1 Clocate 2 lowerCase 3 upperCase 3 Lprefix 2  macro  merge 2 modify 3 move 2 "
    s = s & "msg  next 1 overlay 1 parse preserve 4 purge 3 put putD query 1 quit  read recover 3 "
    s = s & "refresh renum 3 repeat 3 replace 1 Creplace 2 reset 3 restore 4 rgtLEFT right 2 left "
    s = s & "2  save  set  shift 2  si  sort  sos  stack 3 status 4 top  transfer 3  type 1  up 1 "
    commandtable = Split(s, " ")
    Dim i As Integer, word As Variant, number As Integer
    For i = LBound(commandtable) To UBound(commandtable)
        word = commandtable(i)
        If Len(word) > 0 Then
            i = i + 1
            Do While Len(commandtable(i)) = 0: i = i + 1: Loop
            number = Val(commandtable(i))
            If number > 0 Then
                command_table.Add Key:=word, Item:=number
            Else
                command_table.Add Key:=word, Item:=Len(word)
                i = i - 1
            End If
        End If
    Next i
    For Each word In command_table
        For i = command_table(word) To Len(word)
            On Error Resume Next
            abbreviations.Add Key:=Left(word, i), Item:=UCase(word)
        Next i
    Next word
    user_words() = Split(userstring, " ")
    For Each word In user_words
        If Len(word) > 0 Then
            If abbreviations.exists(word) Then
                commands = commands & abbreviations(word) & " "
            Else
                commands = commands & "*error* "
            End If
        End If
    Next word
    ValidateUserWords = commands
End Function
Public Sub program()
    Dim guserstring As String
    guserstring = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"
    Debug.Print "user words:", guserstring
    Debug.Print "full words:", ValidateUserWords(guserstring)
End Sub


import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class AbbreviationsEasy {
    private static final Scanner input = new Scanner(System.in);
    private static final String  COMMAND_TABLE
            =       "  Add ALTer  BAckup Bottom  CAppend Change SCHANGE  CInsert CLAst COMPress COpy\n" +
                    " COUnt COVerlay CURsor DELete CDelete Down DUPlicate Xedit EXPand EXTract Find\n" +
                    " NFind NFINDUp NFUp CFind FINdup FUp FOrward GET Help HEXType Input POWerinput\n" +
                    " Join SPlit SPLTJOIN  LOAD  Locate CLocate  LOWercase UPPercase  LPrefix MACRO\n" +
                    " MErge MODify MOve MSG Next Overlay PARSE PREServe PURge PUT PUTD  Query  QUIT\n" +
                    " READ  RECover REFRESH RENum REPeat  Replace CReplace  RESet  RESTore  RGTLEFT\n" +
                    " RIght LEft  SAVE  SET SHift SI  SORT  SOS  STAck STATus TOP TRAnsfer Type Up";

    public static void main(String[] args) {
        String[]             cmdTableArr = COMMAND_TABLE.split("\\s+");
        Map<String, Integer> cmd_table   = new HashMap<String, Integer>();

        for (String word : cmdTableArr) {  //Populate words and number of caps
            cmd_table.put(word, countCaps(word));
        }

        System.out.print("Please enter your command to verify: ");
        String   userInput  = input.nextLine();
        String[] user_input = userInput.split("\\s+");

        for (String s : user_input) {
            boolean match = false; //resets each outer loop
            for (String cmd : cmd_table.keySet()) {
                if (s.length() >= cmd_table.get(cmd) && s.length() <= cmd.length()) {
                    String temp = cmd.toUpperCase();
                    if (temp.startsWith(s.toUpperCase())) {
                        System.out.print(temp + " ");
                        match = true;
                    }
                }
            }
            if (!match) { //no match, print error msg
                System.out.print("*error* ");
            }
        }
    }

    private static int countCaps(String word) {
        int numCaps = 0;
        for (int i = 0; i < word.length(); i++) {
            if (Character.isUpperCase(word.charAt(i))) {
                numCaps++;
            }
        }
        return numCaps;
    }
}


tailrec fun A(m: Long, n: Long): Long {
    require(m >= 0L) { "m must not be negative" }
    require(n >= 0L) { "n must not be negative" }
    if (m == 0L) {
        return n + 1L
    }
    if (n == 0L) {
        return A(m - 1L, 1L)
    }
    return A(m - 1L, A(m, n - 1L))
}

inline fun<T> tryOrNull(block: () -> T): T? = try { block() } catch (e: Throwable) { null }

const val N = 10L
const val M = 4L

fun main() {
    (0..M)
        .map { it to 0..N }
        .map { (m, Ns) -> (m to Ns) to Ns.map { n -> tryOrNull { A(m, n) } } }
        .map { (input, output) -> "A(${input.first}, ${input.second})" to output.map { it?.toString() ?: "?" } }
        .map { (input, output) -> "$input = $output" }
        .forEach(::println)
}


        .model  tiny
        .code
        .486
        org     100h
;ebp=counter, edi=Num, ebx=Div, esi=Sum
start:  xor     ebp, ebp        ;odd abundant number counter:= 0
        mov     edi, 3          ;Num:= 3
ab10:   mov     ebx, 3          ;Div:= 3
        mov     esi, 1          ;Sum:= 1
ab20:   mov     eax, edi        ;Quot:= Num/Div
        cdq                     ;edx:= 0
        div     ebx             ;eax(q):edx(r):= edx:eax/ebx
        cmp     ebx, eax        ;if Div > Quot then quit loop
        jge     ab50
         test   edx, edx        ;if remainder = 0 then
         jne    ab30
          add   esi, ebx        ;  Sum:= Sum + Div
          cmp   ebx, eax        ;  if Div # Quot then
          je    ab30
          add   esi, eax        ;    Sum:= Sum + Quot
ab30:    add    ebx, 2          ;Div:= Div+2 (only check odd Nums)
         jmp    ab20            ;loop
ab50:
        cmp     esi, edi        ;if Sum > Num then
        jle     ab80
        inc     ebp             ;  counter:= counter+1
        cmp     ebp, 25         ;  if counter<=25 or counter>=1000 then
        jle     ab60
         cmp    ebp, 1000
         jl     ab80
ab60:   mov     eax, edi        ;    print Num
        call    numout
        mov     al, ' '         ;    print spaces
        int     29h
        int     29h
        mov     eax, esi        ;    print Sum
        call    numout
        mov     al, 0Dh         ;    carriage return
        int     29h
        mov     al, 0Ah         ;    line feed
        int     29h
        cmp     ebp, 1000       ;    if counter = 1000 then
        jne     ab65
         mov    edi, 1000000001-2 ;    Num:= 1,000,000,001 - 2
ab65:   cmp     edi, 1000000000 ;      if Num > 1,000,000,000 then exit
        jg      ab90
ab80:   add     edi, 2          ;Num:= Num+2 (only check odd Nums)
        jmp     ab10            ;loop
ab90:   ret

;Print signed integer in eax with commas, e.g: 12,345,010
numout: xor     ecx, ecx        ;digit counter:= 0
no00:   cdq                     ;edx:= 0
        mov     ebx, 10         ;Num:= Num/10
        div     ebx             ;eax(q):edx(r):= edx:eax/ebx
        push    edx             ;remainder = least significant digit
        inc     ecx             ;count digit
        test    eax, eax        ;if Num # 0 then NumOut(Num)
        je      no20
         call   no00
no20:   pop     eax             ;print digit + '0'
        add     al, '0'
        int     29h
        dec     ecx             ;un-count digit
        je      no30            ;if counter # 0 and
         mov    al, cl          ;  if remainder(counter/3) = 0 then
         aam    3
         jne    no30
          mov   al, ','         ;    print ','
          int   29h
no30:   ret
        end     start


import encoding.utf8
import strconv
fn read_table(table string) ([]string, []int) {
    fields := table.fields()
    mut commands := []string{}
    mut min_lens := []int{}

    for i, max := 0, fields.len; i < max; {
        cmd := fields[i]
        mut cmd_len := cmd.len
        i++

        if i < max {
            num := strconv.atoi(fields[i]) or {-1}
            if 1 <= num && num < cmd_len {
                cmd_len = num
                i++
            }
        }
        commands << cmd
        min_lens << cmd_len
    }
    return commands, min_lens
}

fn validate_commands(commands []string, min_lens []int, words []string) []string {
    mut results := []string{}
    for word in words {
        mut match_found := false
        wlen := word.len
        for i, command in commands {
            if min_lens[i] == 0 || wlen < min_lens[i] || wlen > command.len {
                continue
            }
            c := utf8.to_upper(command)
            w := utf8.to_upper(word)
            if c.index(w) or {-1} == 0 {
                results << c
                match_found = true
                break
            }
        }
        if !match_found {
            results << "*error*"
        }
    }
    return results
}

fn print_results(words []string, results []string) {
    println("user words:\t${words.join("\t")}")
    println("full words:\t${results.join("\t")}")
}

fn main() {
    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 "

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

    commands, min_lens := read_table(table)
    words := sentence.fields()

    results := validate_commands(commands, min_lens, words)

    print_results(words, results)
}


import "/fmt" for Fmt
import "/str" for Str

var 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"

var validate = Fn.new { |commands, words, minLens|
    var results = []
    if (words.count == 0) return results
    for (word in words) {
        var matchFound = false
        var wlen = word.count
        for (i in 0...commands.count) {
            var command = commands[i]
            if (minLens[i] != 0 && wlen >= minLens[i] && wlen <= command.count) {
                var c = Str.upper(command)
                var w = Str.upper(word)
                if (c.startsWith(w)) {
                    results.add(c)
                    matchFound = true
                    break
                }
            }
        }
        if (!matchFound) results.add("*error*")
    }
    return results
}

var splits = table.split(" ")
// get rid of empty entries
for (i in splits.count-1..0) if (splits[i] == "") splits.removeAt(i)
var slen = splits.count
var commands = []
var minLens = []
var i = 0
while (true) {
    commands.add(splits[i])
    var len = splits[i].count
    if (i == slen - 1) {
        minLens.add(len)
        break
    }
    i = i + 1
    var num = Num.fromString(splits[i])
    if (num != null) {
        minLens.add( (num < len) ? num : len )
        i = i + 1
        if (i == slen) break
    } else minLens.add(len)
}
var sentence = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"
var words = sentence.split(" ")
// get rid of empty entries
for (i in words.count-1..0) if (words[i] == "") words.removeAt(i)
var results = validate.call(commands, words, minLens)
System.write("user words:  ")
for (j in 0...words.count) {
    System.write("%(Fmt.s(-results[j].count, words[j])) ")
}
System.write("\nfull words:  ")
System.print(results.join(" "))


var abr=`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`
   .split(/\W+/).map(_=>_.trim())
function escapeRegex(string) {
    return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
var input = prompt();
console.log(input.length==0?null:input.trim().split(/\s+/)
            .map(
              (s=>abr.filter(
                a=>(new RegExp('^'+escapeRegex(s),'i'))
                  .test(a)&&s.length>=a.match(/^[A-Z]+/)[0].length
				  )[0])
				)
            .map(_=>typeof _=="undefined"?"*error*":_).join(' ')
			)


def commands:
 "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 ";

# produce a "dictionary" in the form of an array of {prefix, word} objects
def dictionary:
  reduce (splits(" +") | select(length>0)) as $w ([];
    . + [$w | {prefix: sub("[a-z]+";""), word: ascii_upcase} ]);

def translate($dict):
  # input: a string; $command: a {prefix, word} object
  def match($command):
     . as $uc
     | startswith($command.prefix) and ($command.word | startswith($uc));

  if length==0 then ""
  else ascii_upcase
  | first($dict[] as $command | select( match($command) ) | $command | .word)
    // "*error*"
  end;

# Emit the translation of an entire "sentence"
def translation:
  (commands|dictionary) as $dict
  | reduce splits(" +") as $w (""; . + ($w|translate($dict)) + " ")
  | sub(" $";"");

# Example:
"riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"
| translation


int Cnt, Num, Div, Sum, Quot;
[Cnt:= 0;
Num:= 3;        \find odd abundant numbers
loop    [Div:= 1;
        Sum:= 0;
        loop    [Quot:= Num/Div;
                if Div > Quot then quit;
                if rem(0) = 0 then
                    [Sum:= Sum + Div;
                    if Div # Quot then Sum:= Sum + Quot;
                    ];
                Div:= Div+2;
                ];
        if Sum > 2*Num then
                [Cnt:= Cnt+1;
                if Cnt<=25 or Cnt>=1000 then
                    [IntOut(0, Num);  ChOut(0, 9);
                    IntOut(0, Sum);  CrLf(0);
                    if Cnt = 1000 then Num:= 1_000_000_001 - 2;
                    if Num > 1_000_000_000 then quit;
                    ];
                ];
        Num:= Num+2;
        ];
]


fcn oddAbundants(startAt=3){  //--> iterator
   Walker.zero().tweak(fcn(rn){
      n:=rn.value;
      while(True){
	 sum:=0;
	 foreach d in ([3.. n.toFloat().sqrt().toInt(), 2]){
	    if( (y:=n/d) *d != n) continue;
	    sum += ((y==d) and y or y+d)
	 }
	 if(sum>n){ rn.set(n+2); return(n) }
	 n+=2;
      }
   }.fp(Ref(startAt.isOdd and startAt or startAt+1)))
}


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

c$ = upper$(c$)

dim chunk$(1)

n = token(c$, chunk$())

dim lonc(n)

for i = 1 to n - 1
    v = val(chunk$(i + 1))
    if v then
        lonc(i) = v
        chunk$(i + 1) = ""
    else
        lonc(i) = len(chunk$(i))
    end if
next

inp$ = "riG   rePEAT copies   put mo   rest    types   fup.    6       poweRin"
inp$ = upper$(inp$)

dim w$(1)

x = token(inp$, w$())

dim lonw(x)

for i = 1 to x : lonw(i) = len(w$(i)) : next

for j = 1 to x
    p$ = ""
    for i = 1 to n
        lc$ = left$(chunk$(i), lonw(j)) : lw$ = w$(j)
        if (lw$ = lc$) and (lonc(i) <= lonw(j))  p$ = chunk$(i) : break
    next
    if p$ = "" p$ = "*error*"
    r$ = r$ + " " + p$
next

print r$


commands:=Data(0,String,	// "add\01\0alter\0..."
#<<<
"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"
.toUpper().split());
#<<<

var szs=Dictionary(); // [<index>:<length> ...]
n:=0; while(n<commands.len()){
   cmd,nc := commands.readString(n), n + cmd.len() + 1;
   len:=commands.readString(nc);
   if(len.matches("[0-9]*")){ szs[n]=len.toInt(); n=nc+len.len()+1 }
   else			    { szs[n]=cmd.len();   n=nc; }
}

testText:="riG   rePEAT copies  put mo   rest    types "
          "   fup.    6       poweRin";

testText.split().apply('wrap(w){
   w=w.toUpper(); n:=0;
   while(True){  // check for length requirement and, if there, verify
      n=commands.find(w,n);
      if(Void==n) return("*error*");	// end of loop if no match
      c:=commands.readString(n);
      if(w.len()>=szs.find(n,99999)) return(c);
      n+=c.len();
   }
}).concat(" ").println();


const 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 "

function validate(commands::AbstractVector{<:AbstractString},
        minlens::AbstractVector{<:Integer}, words::AbstractVector{<:AbstractString})
    r = String[]
    for word in words
        matchfound = false
        for (i, command) in enumerate(commands)
            if iszero(minlens[i]) || length(word) ∉ minlens[i]:length(command)
                continue
            end
            if startswith(lowercase(command), lowercase(word))
                push!(r, uppercase(command))
                matchfound = true
                break
            end
        end
        !matchfound && push!(r, "*error*")
    end
    return r
end

commands = split(strip(table))
minlens  = count.(isupper, commands)
sentence = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"
words    = split(sentence)
result   = validate(commands, minlens, words)
println("User words: ", join(lpad.(words,  11)))
println("Full words: ", join(lpad.(result, 11)))


// version 1.1.4-3

val r = Regex("[ ]+")

val 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 "

fun validate(commands: List<String>, minLens: List<Int>, words: List<String>): List<String> {
    if (words.isEmpty()) return emptyList<String>()
    val results = mutableListOf<String>()
    for (word in words) {
        var matchFound = false
        for ((i, command) in commands.withIndex()) {
            if (minLens[i] == 0 || word.length !in minLens[i] .. command.length) continue
            if (command.startsWith(word, true)) {
                results.add(command.toUpperCase())
                matchFound = true
                break
            }
        }
        if (!matchFound) results.add("*error*")
    }
    return results
}

fun main(args: Array<String>) {
    val commands = table.trimEnd().split(r)
    val minLens = MutableList(commands.size) { commands[it].count { c -> c.isUpperCase() } }
    val sentence = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"
    val words = sentence.trim().split(r)
    val results = validate(commands, minLens, words)
    print("user words:  ")
    for (j in 0 until words.size) print("${words[j].padEnd(results[j].length)} ")
    print("\nfull words:  ")
    for (j in 0 until results.size) print("${results[j]} ")
    println()
}


#!/usr/bin/lasso9

define ackermann(m::integer, n::integer) => {
  if(#m == 0) => {
    return ++#n
  else(#n == 0)
    return ackermann(--#m, 1)
  else
    return ackermann(#m-1, ackermann(#m, --#n))
  }
}

with x in generateSeries(1,3),
     y in generateSeries(0,8,2)
do stdoutnl(#x+', '#y+': ' + ackermann(#x, #y))


#!/usr/bin/lua

local list1 = [[
   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 ]]

local indata1 = [[riG  rePEAT copies  put mo   rest    types
   fup.    6       poweRin]]

local indata2 = [[ALT  aLt  ALTE  ALTER  AL  ALF ALTERS TER A]]
local indata3 = [[o  ov  oVe  over  overL  overla]]

local function split(text)
   local result = {}
   for w in string.gmatch(text, "%g+") do
      result[#result+1]=w
      -- print(#result,w,#w)
   end
   return result
end

local function print_line( t )
   for i = 1,#t do
      io.write( string.format("%s ", t[i] ) )
   end
   print()
end

local function is_valid(cmd,abbrev)
   --print(abbrev,cmd,"##")

   local sm = string.match( cmd:lower(), abbrev:lower() )
   if sm == nil then return -1 end

   -- test if any lowercase in "cmd"
   if false then do -- NOTE!: requirement spec error .. put not equal PUT
	 local lowcase = string.match(cmd,"%l+")
	 if lowcase == nil then return -2 end
	 if #lowcase < 1 then return -3 end
		 end
   end

   -- test if abbrev is too long
   if #abbrev > #cmd then return -4 end

   --- num caps in "cmd" is minimum length of abbrev
   local caps = string.match(cmd,"%u+")
   if #abbrev < #caps then return -5 end

   local s1 = abbrev:sub(1,#caps)
   local s2 = cmd:sub(1,#caps)
   if s1:lower() ~= s2:lower() then return -6 end

   return 1
end

local function start()
   local t1 = {}
   local t2 = {}
   local result = {}
   t1 = split(list1)
   t2 = split(indata1)
   print_line(t2);

   for i = 1,#t2 do
      good = 0
      for j = 1,#t1 do
	 local abbrev = t2[i]
	 local cmd = t1[j]
	 good = is_valid(cmd,abbrev)
	 if good==1 then do
	       result[#result+1] = t1[j]:upper()
	       break end
	 end  --if
      end --for j
      if good < 1 then result[#result+1] = "*error*" end
   end --for i
   print_line(result)
end

start() -- run the program


(defun ackermann
  ((0 n) (+ n 1))
  ((m 0) (ackermann (- m 1) 1))
  ((m n) (ackermann (- m 1) (ackermann m (- n 1)))))


ClearAll[ct, FunctionMatchQ, ValidFunctionQ, ProcessString]
ct = "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";
ct = FixedPoint[StringReplace[{"\n" -> "", Longest[" " ..] -> " "}], ct];
ct = StringSplit[ct, " "];
FunctionMatchQ[func_String, test_String] := Module[{min, max, l},
  min = StringCount[func, Alternatives @@ CharacterRange["A", "Z"]];
  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[val]]
  ]
ProcessString[test_String] := Module[{parts},
  parts = StringSplit[test];
  StringRiffle[ValidFunctionQ /@ parts, " "]
  ]
ProcessString["riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin"]


function R = abbreviations_easy(input)

CMD=strsplit(['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' ],' ');

for k=1:length(CMD)
	cmd{k} = CMD{k}(CMD{k}<'a');
	CMD{k} = upper(CMD{k});
end

ilist = strsplit(input,' ');
R = '';
for k=1:length(ilist)
	input = upper(ilist{k});

	ix = find(strncmp(CMD, input, length(input)));
	result= '*error*';
	for k = ix(:)',
		if strncmp(input, cmd{k}, length(cmd{k}));
			result = CMD{k};
		end
	end
	R = [R,' ',result];
end


Print Ackermann(1, 2)

    Function Ackermann(m, n)
        Select Case
            Case (m < 0) Or (n < 0)
                Exit Function
            Case (m = 0)
                Ackermann = (n + 1)
            Case (m > 0) And (n = 0)
                Ackermann = Ackermann((m - 1), 1)
            Case (m > 0) And (n > 0)
                Ackermann = Ackermann((m - 1), Ackermann(m, (n - 1)))
        End Select
    End Function


import map

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

def countCaps(word)
        if len(word) < 1
                return 0
        end

        numCaps = 0
        for i in range(0, len(word) - 1)
                if word[i] = upper(word[i])
                        numCaps += 1
                end
        end
        return numCaps
end

cmdTableArr = COMMAND_TABLE.split("\\s+")
cmd_table = new(map)

for word in cmdTableArr
        cmd_table.put(word, countCaps(word))
end

print "Please enter your command to verify: "
user_input = input().split("\\s+")

for s in user_input
        match = false
        for i in range(0, len(cmd_table.keys) - 1)
                if (len(s) >= cmd_table.get(cmd_table.keys[i])) and (len(s) <= len(cmd_table.keys[i]))
                        temp = upper(cmd_table.keys[i])
                        if temp .startswith. upper(s)
                                print temp + " "
                                match = true
                        end
                end
        end

        if !match
                print "*error* "
        end
end


import sequtils
import strutils

const Commands = "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"

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

proc validate(words, commands: seq[string]; minLens: seq[int]): seq[string] =

  if words.len == 0:
    return

  for word in words:
    var matchFound = false
    for i, command in commands:
      if word.len notin minLens[i]..command.len:
        continue
      if command.toUpper.startsWith(word.toUpper):
        result.add(command.toUpper)
        matchFound = true
        break
    if not matchFound:
      result.add("*error*")

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

var commands = Commands.splitWhitespace()
var minLens = newSeq[int](commands.len)     # Count of uppercase characters.
for idx, command in commands:
  minLens[idx] = command.countIt(it.isUpperAscii)

while true:

  try:
    stdout.write "Input? "
    let words = stdin.readline().strip().splitWhitespace()
    let results = words.validate(commands, minLens)
    stdout.write("\nUser words: ")
    for i, word in words:
      stdout.write(word.alignLeft(results[i].len) & ' ')
    stdout.write("\nFull words: ")
    for result in results:
      stdout.write(result & ' ')
    stdout.write("\n\n")

  except EOFError:
    echo ""
    break


let cmds = "\
  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"

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

let char_is_uppercase c =
  match c with
  | 'A'..'Z' -> true
  | _ -> false

let get_abbr s =
  let seq = String.to_seq s in
  let seq = Seq.filter char_is_uppercase seq in
  (String.of_seq seq)

let () =
  let cmds = Str.split (Str.regexp "[ \r\n]+") cmds in
  let cmds =
    List.map (fun s ->
      get_abbr s,
      String.uppercase_ascii s
    ) cmds
  in
  let user = Str.split (Str.regexp "[ \r\n]+") user in
  let r =
    List.map (fun ucmd ->
      let n = String.length ucmd in
      let find_abbr (abbr, cmd) =
        let na = String.length abbr in
        let nc = String.length cmd in
        if n < na || nc < n then false else
          let sub = String.sub cmd 0 n in
          (sub = String.uppercase_ascii ucmd)
      in
      match List.find_opt find_abbr cmds with
      | Some (_, found) -> found
      | None -> "*error*"
    ) user
  in
  print_endline (String.concat " " r)


function ackermann m,n
    switch
        Case m = 0
            return n + 1
        Case (m > 0 And n = 0)
            return ackermann((m - 1), 1)
        Case (m > 0 And n > 0)
            return ackermann((m - 1), ackermann(m, (n - 1)))
    end switch
end ackermann


program Abbreviations_Easy;
{$IFDEF WINDOWS}
  {$APPTYPE CONSOLE}
{$ENDIF}
{$IFDEF FPC}
  {$MODE DELPHI}
  uses
    SysUtils;
{$ELSE}
 uses
    System.SysUtils;
{$ENDIF}

const
  _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 ';

function validate(commands, words: TArray<string>; minLens: TArray<Integer>):
  TArray<string>;
var
  wd,c,command,w : String;
  wdIdx,wlen,i : integer;
  matchFound : boolean;

begin
  SetLength(result, 0);
  if Length(words) = 0 then
    exit;
  for wdIdx := Low(words) to High(words) do
  begin
    wd := words[wdIdx];
    matchFound := false;
    wlen := wd.Length;
    for i := 0 to High(commands) do
    begin
      command := commands[i];
      if (minLens[i] = 0) or (wlen < minLens[i]) or (wlen > length(command)) then
        continue;

      c := command.ToUpper;
      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;
var
  results,commands,words :TArray<string>;
  table,sentence :String;
  minLens: TArray<integer>;
  cLen,i,j,count : integer;
  c:char;
begin
  table := _TABLE_.Trim;
  commands := table.Split([' '], TStringSplitOptions.ExcludeEmpty);
  clen := Length(commands);
  SetLength(minLens, clen);
  for i := 0 to clen - 1 do
  begin
    count := 0;
    For j := length(commands[i]) downto 1 do
    begin
      c := commands[i][j];
      if (c >= 'A') and (c <= 'Z') then
        inc(count);
    end;
    minLens[i] := count;
  end;

  sentence := 'riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin';
  words := sentence.Split([' '], TStringSplitOptions.ExcludeEmpty);
  results := validate(commands, words, minLens);
  Write('user words: ');
  for j := 0 to Length(words) - 1 do
    Write(words[j].PadRight(1 + length(results[j])));
  Write(#10, 'full words: ');
// FOr fpc 3.0.4 on TIO.RUN
  for j := 0 to Length(words) - 1 do
    Write(results[j],' ');
// fpc 3.2.2 will do
//  Writeln(string.Join(' ', results));
  {$IFDEF WINDOWS}
  Readln;
  {$ENDIF}
end.


to ack :i :j
  if :i = 0 [output :j+1]
  if :j = 0 [output ack :i-1 1]
  output ack :i-1 ack :i :j-1
end


@c = (join ' ', qw<
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 Replace REPeat  CReplace  RESet  RESTore  RGTLEFT
RIght LEft  SAVE  SET SHift SI  SORT  SOS  STAck STATus  TOP TRAnsfer Type Up
>) =~ /([A-Z]+)([a-z]*)(?:\s+|$)/g;

my %abr = ('' => '', ' ' => '');
for ($i = 0; $i < @c; $i += 2) {
    $sl = length($s =    $c[$i]  );
    $ll = length($l = uc $c[$i+1]);
    $abr{$s} = $w = $s.$l;
    map { $abr{substr($w, 0, $_)} = $w } $sl .. $ll;
    $abr{$w} = $w; # full command should always work
}

$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"


constant abbrtxt = """
   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
""",
input = "riG   rePEAT copies  put mo   rest    types   fup.    6   poweRin"

function set_min_lengths(sequence a)
    sequence res = {}
    for i=1 to length(a) do
        string ai = a[i], uai = upper(ai)
        for j=-length(ai) to 0 do
            if j=0 or ai[j]!=uai[j] then
                res = append(res,{ai,length(ai)+j})
                exit
            end if
        end for
    end for
    return res
end function

constant abbrevs = set_min_lengths(split(substitute(abbrtxt,"\n"," "),no_empty:=true))
constant inputs = split(input,no_empty:=true)

for i=1 to length(inputs) do
    string ii = inputs[i],
           res = "*error*"
    for j=1 to length(abbrevs) do
        {string aj, integer l} = abbrevs[j]
        if length(ii)>=l
        and match(ii,aj,case_insensitive:=true)==1 then
            res = upper(aj)
            exit
        end if
    end for
    puts(1,res&" ")
end for
puts(1,"\n")


HAI 1.3

HOW IZ I ackermann YR m AN YR n
    NOT m, O RLY?
        YA RLY, FOUND YR SUM OF n AN 1
    OIC

    NOT n, O RLY?
        YA RLY, FOUND YR I IZ ackermann YR DIFF OF m AN 1 AN YR 1 MKAY
    OIC

    FOUND YR I IZ ackermann YR DIFF OF m AN 1 AN YR...
     I IZ ackermann YR m AN YR DIFF OF n AN 1 MKAY MKAY
IF U SAY SO

IM IN YR outer UPPIN YR m TIL BOTH SAEM m AN 5
    IM IN YR inner UPPIN YR n TIL BOTH SAEM n AN DIFF OF 6 AN m
        VISIBLE "A(" m ", " n ") = " I IZ ackermann YR m AN YR n MKAY
    IM OUTTA YR inner
IM OUTTA YR outer

KTHXBYE


// note this is php 7.x
$commands = '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';

$input = 'riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin';
$expect = 'RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT';
$table = makeCommandTable($commands);
$table_keys = array_keys($table);

$inputTable = processInput($input);

foreach ($inputTable as $word) {
    $rs = searchCommandTable($word, $table);
    if ($rs) {
        $output[] = $rs;
    } else {
        $output[] = '*error*';
    }

}
echo 'Input: '. $input. PHP_EOL;
echo 'Output: '. implode(' ', $output). PHP_EOL;

function searchCommandTable($search, $table) {
    foreach ($table as $key => $value) {
        if ((strtoupper(substr($value['word'], 0, strlen($search))) === strtoupper($search)) && (strlen($search) >= $value['min_length'])) {
            return $key;
        }
    }
    return false;
}

function processInput($input) {
    $input = preg_replace('!\s+!', ' ', $input);
    $pieces = explode(' ', trim($input));
    return $pieces;
}

function makeCommandTable($commands) {
    $commands = preg_replace('!\s+!', ' ', $commands);
    $pieces = explode(' ', trim($commands));
    foreach ($pieces as $word) {
        $rs[strtoupper($word)] = ['word'=>$word, 'min_length' => preg_match_all("/[A-Z]/", $word)];
    }
    return $rs;
}


function ack(M,N)
    if M == 0 then return N + 1 end
    if N == 0 then return ack(M-1,1) end
    return ack(M-1,ack(M, N-1))
end


import util.

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").

validate("", _, Result) ?=>
    Result = "".

validate(Word, Commands, Result), Word \= "" ?=>
    member(Command, Commands),
    append(Prefix, Suffix, Command),
    Prefix == to_uppercase(Prefix),
    Suffix == to_lowercase(Suffix),
    LowWord = to_lowercase(Word),
    LowPrefix = to_lowercase(Prefix),
    append(LowPrefix, Other, LowWord),
    LowCommand = to_lowercase(Command),
    append(LowWord, _, LowCommand),
    Result = to_uppercase(Command).

validate(Word, _, Result), Word \= "" =>
    Result = "*error*".

main(Args) =>
    command_table(Table),
    Commands = split(Table),
    foreach (Word in Args)
        validate(Word, Commands, Result),
        printf("%w ", Result)
    end,
    nl.