Abbreviations, easy

From Rosetta Code
Task
Abbreviations, easy
You are encouraged to solve this task according to the task description, using any language you may know.

This task is an easier (to code) variant of the Rosetta Code task:   Abbreviations, simple.


For this task, the following   command table   will be used:

   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


Notes concerning the above   command table:

  •   it can be thought of as one long literal string   (with blanks at end-of-lines)
  •   it may have superfluous blanks
  •   it may be in any case (lower/upper/mixed)
  •   the order of the words in the   command table   must be preserved as shown
  •   the user input(s) may be in any case (upper/lower/mixed)
  •   commands will be restricted to the Latin alphabet   (A ──► Z,   a ──► z)
  •   A valid abbreviation is a word that has:
  •   at least the minimum length of the number of capital letters of the word in the command table
  •   compares equal (regardless of case) to the leading characters of the word in the command table
  •   a length not longer than the word in the command table
  •   ALT,   aLt,   ALTE,   and   ALTER   are all abbreviations of   ALTer
  •   AL,   ALF,   ALTERS,   TER,   and   A   aren't valid abbreviations of   ALTer
  •   The number of capital letters in   ALTer   indicates that any abbreviation for   ALTer   must be at least three letters
  •   Any word longer than five characters can't be an abbreviation for   ALTer
  •   o,   ov,   oVe,   over,   overL,   overla   are all acceptable abbreviations for   Overlay
  •   if there isn't any lowercase letters in the word in the command table,   then there isn't an abbreviation permitted


Task
  •   The command table needn't be verified/validated.
  •   Write a function to validate if the user "words"   (given as input)   are valid   (in the command table).
  •   If the word   is   valid,   then return the full uppercase version of that "word".
  •   If the word isn't valid,   then return the lowercase string:   *error*       (7 characters).
  •   A blank input   (or a null input)   should return a null string.
  •   Show all output here.


An example test case to be used for this task

For a user string of:

 riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin

the computer program should return the string:

 RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT
Other tasks related to string operations:
Metrics
Counting
Remove/replace
Anagrams/Derangements/shuffling
Find/Search/Determine
Formatting
Song lyrics/poems/Mad Libs/phrases
Tokenize
Sequences



ALGOL 68

Works with: ALGOL 68G version Any - tested with release 2.8.3.win32

Uses Algol 68G specific is lower and to upper procedures. Does not use a hash table. <lang algol68># "Easy" abbreviations #

  1. table of "commands" - upper-case indicates the mminimum abbreviation #

STRING command table = "Add ALTer BAckup Bottom CAppend Change SCHANGE CInsert CLAst COMPress COpy "

                    + "COUnt COVerlay CURsor DELete CDelete Down DUPlicate Xedit EXPand EXTract Find "
                    + "NFind NFINDUp NFUp CFind FINdup FUp FOrward GET Help HEXType Input POWerinput "
                    + "Join SPlit SPLTJOIN  LOAD  Locate CLocate  LOWercase UPPercase  LPrefix MACRO "
                    + "MErge MODify MOve MSG Next Overlay PARSE PREServe PURge PUT PUTD  Query  QUIT "
                    + "READ  RECover REFRESH RENum REPeat  Replace CReplace  RESet  RESTore  RGTLEFT "
                    + "RIght LEft  SAVE  SET SHift SI  SORT  SOS  STAck STATus  TOP TRAnsfer Type Up";
  1. returns the next word from text, updating pos #

PRIO NEXTWORD = 1; OP NEXTWORD = ( REF INT pos, STRING text )STRING:

    BEGIN
       # skip spaces #
       WHILE IF pos > UPB text THEN FALSE ELSE text[ pos ] = " " FI DO pos +:= 1 OD;
       # get the word #
       STRING word := "";
       WHILE IF pos > UPB text THEN FALSE ELSE text[ pos ] /= " " FI DO
           word +:= text[ pos ];
           pos +:= 1
       OD;
       word
    END # NEXTWORD # ;
  1. returns text converted to upper case #

OP TOUPPER = ( STRING text )STRING:

    BEGIN
       STRING result := text;
       FOR ch pos FROM LWB result TO UPB result DO
           IF is lower( result[ ch pos ] ) THEN result[ ch pos ] := to upper( result[ ch pos ] ) FI
       OD;
       result
    END # TOUPPER # ;
  1. returns the minimum abbreviation length of command #

OP MINABLENGTH = ( STRING command )INT:

    BEGIN
       INT ab min := LWB command;
       WHILE IF ab min > UPB command THEN FALSE ELSE is upper( command[ ab min ] ) FI DO ab min +:= 1 OD;
       ab min - LWB command
    END # MINABLENGTH # ;
  1. searches for word in command table and returns the full command #
  2. matching the possible abbreviation or *error* if there is no match #

PRIO EXPAND = 1; OP EXPAND = ( STRING command table, word )STRING:

    IF word = ""
    THEN # empty word #
       ""
    ELSE # non-empty word #
       INT    word len    = ( UPB word + 1 ) - LWB word;
       STRING upper word := TOUPPER word;
       STRING result     := "*error*";
       INT    pos        := LWB command table;
       WHILE  STRING command := pos NEXTWORD command table;
              IF command = ""
              THEN # end of command table #
                  FALSE
              ELIF word len < MINABLENGTH command OR word len > ( ( UPB command + 1 ) - LWB command )
              THEN # word is too short or too long - try the next command #
                  TRUE
              ELIF upper word = TOUPPER command[ LWB command : ( LWB command - 1 ) + word len ]
              THEN # found the command #
                  result := TOUPPER command;
                  FALSE
              ELSE # word doexn't match - try the next command #
                  TRUE
              FI
       DO SKIP OD;
       result
    FI # EXPAND # ;
  1. tests the EXPAND operator #

PROC test expand = ( STRING words, command table )VOID:

    BEGIN
       STRING results := "", separator := "";
       INT    pos   := LWB words;
       WHILE STRING word = pos NEXTWORD words; word /= "" DO
           results +:= separator + ( command table EXPAND word );
           separator := " "
       OD;
       print( ( "Input:  ", words, newline ) );
       print( ( "Output: ", results, newline ) )
    END # test expand # ;
  1. task test cases #

test expand( "riG rePEAT copies put mo rest types fup. 6 poweRin", command table ); test expand( "", command table )</lang>

Output:
Input:  riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin
Output: RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT
Input:
Output:

ARM Assembly

This example is in need of improvement:



Please include the required/mandatory test cases mentioned in the task's requirements:

riG   rePEAT   copies   put   mo   rest   types   fup.   6   poweRin

Note that the test cases are in mixed case.

Also note that the program should return the uppercase string (as per the requirements):

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

Also note that an   error   is noted by:     *error*


Works with: as version Raspberry Pi

<lang ARM Assembly> /* ARM assembly Raspberry PI */ /* program abbrEasy.s */ /* store list of command in a file */ /* and run the program abbrEasy command.file */

/* REMARK 1 : this program use routines in a include file

  see task Include a file language arm assembly 
  for the routine affichageMess conversion10 
  see at end of this program the instruction include */

/* for constantes see task include a file in arm assembly */ /************************************/ /* Constantes */ /************************************/ .include "../constantes.inc"

.equ STDIN, 0 @ Linux input console .equ STDOUT, 1 @ Linux output console .equ EXIT, 1 @ Linux syscall .equ READ, 3 @ Linux syscall .equ WRITE, 4 @ Linux syscall .equ OPEN, 5 @ Linux syscall .equ CLOSE, 6 @ Linux syscall

.equ O_RDWR, 0x0002 @ open for reading and writing

.equ SIZE, 4 .equ NBBOX, SIZE * SIZE .equ BUFFERSIZE, 1000 .equ NBMAXIELEMENTS, 100

/*********************************/ /* Initialized data */ /*********************************/ .data szMessTitre: .asciz "Nom du fichier : " szCarriageReturn: .asciz "\n" szMessErreur: .asciz "Error detected.\n" szMessErrBuffer: .asciz "buffer size too less !!" szMessErrorAbr: .asciz "error" szMessInput: .asciz "Enter command (or quit to stop) : " szCmdQuit: .asciz "QUIT" /*********************************/ /* UnInitialized data */ /*********************************/ .bss .align 4 sZoneConv: .skip 24 iAdrFicName: .skip 4 iTabAdrCmd: .skip 4 * NBMAXIELEMENTS sBufferCmd: .skip BUFFERSIZE sBuffer: .skip BUFFERSIZE /*********************************/ /* code section */ /*********************************/ .text .global main main: @ INFO: main

   mov r0,sp                    @ stack address for load parameter
   bl traitFic                  @ read file and store value in array
   cmp r0,#-1
   beq 100f                     @ error ?
   ldr r0,iAdriTabAdrCmd
   bl controlLoad

1:

   ldr r0,iAdrszMessInput       @ display input message
   bl affichageMess
   mov r0,#STDIN                @ Linux input console
   ldr r1,iAdrsBuffer           @ buffer address 
   mov r2,#BUFFERSIZE           @ buffer size 
   mov r7, #READ                @ request to read datas
   svc 0                        @ call system
   sub r0,r0,#1
   mov r2,#0
   strb r2,[r1,r0]              @ replace character 0xA by zéro final
   ldr r0,iAdrsBuffer   
   ldr r1,iAdriTabAdrCmd
   bl controlCommand            @ control text command
   mov r2,r0
   bl affichageMess
   ldr r0,iAdrszCarriageReturn
   bl affichageMess
   mov r0,r2
   ldr r1,iAdrszCmdQuit         @ command quit ?
   bl comparStrings
   cmp r0,#0
   beq 100f                     @ yes -> end
   b 1b                         @ else loop

99:

   ldr r0,iAdrszMessErrBuffer
   bl affichageMess

100: @ standard end of the program

   mov r0, #0                       @ return code
   mov r7, #EXIT                    @ request to exit program
   svc #0                           @ perform the system call

iAdrszCarriageReturn: .int szCarriageReturn iAdrszMessErrBuffer: .int szMessErrBuffer iAdrsZoneConv: .int sZoneConv iAdrszMessInput: .int szMessInput iAdrszCmdQuit: .int szCmdQuit /******************************************************************/ /* control abbrevation command */ /******************************************************************/ /* r0 contains string input command */ /* r1 contains address table string command */ controlCommand: @ INFO: controlCommand

   push {r1-r8,lr}               @ save  registers
   mov r8,r0
   mov r9,r1
   mov r2,#0                     @ indice
   mov r3,#0                     @ find counter

1:

   mov r0,r8
   ldr r1,[r9,r2,lsl #2]         @ load a item
   cmp r1,#0                     @ end ?
   beq 3f
   bl comparStringSpe            @ 
   cmp r0,#0                     @ no found other search
   beq 2f
   add r3,r3,#1                  @ else increment counter
   mov r5,r1                     @ and save address command

2:

   add r2,r2,#1                  @ increment indice
   b 1b                          @ and loop

3:

   cmp r3,#1                     @ no find or multiple find ?
   bne 99f                       @ error 
                                 @ one find
   mov r0,r8                     @ length input command
   bl computeLength
   mov r4,r0                     @ length input
   mov r0,r5                     @ length command table
   bl computeLength
   cmp r4,r0                     @ length input > command ?
   bgt 99f                       @ error
   mov r2,#0
   mov r1,#0

4: @ loop count capital letters

   ldrb r3,[r5,r2]
   cmp r3,#0
   beq 5f
   tst r3,#0x20                  @ capital letter ?
   addeq r1,r1,#1
   add r2,r2,#1
   b 4b

5:

   cmp r4,r1                     @ input < command capital letters
   blt 99f                       @ error
   mov r4,#0x20                  @ 5 bit to 1
   mov r2,#0

6:

   ldrb r3,[r5,r2]
   cmp r3,#0
   beq 7f
   bic r3,r3,r4                  @ convert to capital letter
   str r3,[r8,r2]
   add r2,r2,#1
   b 6b

7:

   mov r0,r8                     @ return string input address
   b 100f

99:

   ldr r0,iAdrszMessErrorAbr     @ return string "error"

100:

   pop {r1-r8,lr}                @ restaur registers 
   bx lr                         @return

iAdrszMessErreur: .int szMessErreur iAdrszMessErrorAbr: .int szMessErrorAbr /******************************************************************/ /* comparaison first letters String */ /******************************************************************/ /* r0 contains first String */ /* r1 contains second string */ /* r0 return 0 if not find else returns number letters OK */ comparStringSpe:

   push {r1-r6,lr}           @ save  register
   mov r2,#0

1:

   ldrb r3,[r0,r2]           @ input
   orr r4,r3,#0x20           @ convert capital letter
   ldrb r5,[r1,r2]           @ table
   orr r6,r5,#0x20           @ convert capital letter
   cmp r4,r6
   bne 2f
   cmp r3,#0
   beq 3f
   add r2,r2,#1
   b 1b 

2:

  cmp r3,#0                  @ fist letters Ok
  beq 3f
  mov r0,#0                  @ no ok
  b 100f

3:

  mov r0,r2

100:

   pop {r1-r6,lr}                     @ restaur registers 
   bx lr                        @return

/******************************************************************/ /* compute length String */ /******************************************************************/ /* r0 contains String */ /* r0 return length */ computeLength: @ INFO: functionFN

   push {r1-r2,lr}              @ save  register
   mov r1,#0

1:

   ldrb r2,[r0,r1]
   cmp r2,#0                    @ end ?
   moveq r0,r1                  @ return length in r0
   beq 100f
   add r1,r1,#1
   b 1b

100:

   pop {r1-r2,lr}               @ restaur registers 
   bx lr                        @return 

/******************************************************************/ /* read file */ /******************************************************************/ /* r0 contains address stack begin */ traitFic: @ INFO: traitFic

   push {r1-r8,fp,lr}                @ save  registers
   mov fp,r0                         @  fp <- start address
   ldr r4,[fp]                       @ number of Command line arguments
   cmp r4,#1
   movle r0,#-1
   ble 99f
   add r5,fp,#8                      @ second parameter address 
   ldr r5,[r5]
   ldr r0,iAdriAdrFicName
   str r5,[r0]
   ldr r0,iAdrszMessTitre
   bl affichageMess                  @ display string
   mov r0,r5
   bl affichageMess 
   ldr r0,iAdrszCarriageReturn
   bl affichageMess                  @ display carriage return
   mov r0,r5                         @ file name
   mov r1,#O_RDWR                    @ flags    
   mov r2,#0                         @ mode 
   mov r7, #OPEN                     @ call system OPEN 
   svc 0 
   cmp r0,#0                         @ error ?
   ble 99f
   mov r8,r0                         @ File Descriptor
   ldr r1,iAdrsBufferCmd             @ buffer address
   mov r2,#BUFFERSIZE                @ buffer size
   mov r7,#READ                      @ read file
   svc #0
   cmp r0,#0                         @ error ?
   blt 99f
   @ extraction datas
   ldr r1,iAdrsBufferCmd             @ buffer address
   add r1,r0
   mov r0,#0                         @ store zéro final
   strb r0,[r1] 
   ldr r0,iAdriTabAdrCmd             @ key string command table
   ldr r1,iAdrsBufferCmd             @ buffer address
   bl extracDatas
                                     @ close file
   mov r0,r8
   mov r7, #CLOSE 
   svc 0 
   mov r0,#0
   b 100f

99: @ error

   ldr r1,iAdrszMessErreur           @ error message
   bl   displayError
   mov r0,#-1

100:

   pop {r1-r8,fp,lr}                 @ restaur registers 
   bx lr                             @return

iAdriAdrFicName: .int iAdrFicName iAdrszMessTitre: .int szMessTitre iAdrsBuffer: .int sBuffer iAdrsBufferCmd: .int sBufferCmd iAdriTabAdrCmd: .int iTabAdrCmd /******************************************************************/ /* extrac digit file buffer */ /******************************************************************/ /* r0 contains strings address */ /* r1 contains buffer address */ extracDatas: @ INFO: extracDatas

   push {r1-r8,lr}              @ save  registers
   mov r7,r0
   mov r6,r1
   mov r2,#0                    @ string buffer indice
   mov r4,r1                    @ start string
   mov r5,#0                    @ string index
   //vidregtit debextrac

1:

   ldrb r3,[r6,r2]
   cmp r3,#0
   beq 4f                       @ end
   cmp r3,#0xA
   beq 2f
   cmp r3,#' '                  @ end string
   beq 3f
   add r2,#1
   b 1b

2:

   mov r3,#0
   strb r3,[r6,r2]
   ldrb r3,[r6,r2]
   cmp r3,#0xD
   addeq r2,#2
   addne r2,#1
   b 4f

3:

   mov r3,#0
   strb r3,[r6,r2]
   add r2,#1

4:

   mov r0,r4
   str r4,[r7,r5,lsl #2]
   add r5,#1

5:

   ldrb r3,[r6,r2]
   cmp r3,#0
   beq 100f
   cmp r3,#' '
   addeq r2,r2,#1
   beq 5b
   
   add r4,r6,r2                 @ new start address
   b 1b

100:

   pop {r1-r8,lr}               @ restaur registers 
   bx lr                        @return

/******************************************************************/ /* control load */ /******************************************************************/ /* r0 contains string table */ controlLoad:

   push {r1-r8,lr}              @ save  registers
   mov r5,r0
   mov r1,#0

1:

   ldr r0,[r5,r1,lsl #2]
   cmp r0,#0
   beq 100f
   bl affichageMess
   ldr r0,iAdrszCarriageReturn
   bl affichageMess
   add r1,r1,#1
   b 1b
   

100:

   pop {r1-r8,lr}               @ restaur registers 
   bx lr                        @return

/************************************/ /* Strings case sensitive comparisons */ /************************************/ /* r0 et r1 contains the address of strings */ /* return 0 in r0 if equals */ /* return -1 if string r0 < string r1 */ /* return 1 if string r0 > string r1 */ comparStrings:

   push {r1-r4}             @ save des registres
   mov r2,#0                @ counter

1:

   ldrb r3,[r0,r2]          @ byte string 1
   ldrb r4,[r1,r2]          @ byte string 2
   cmp r3,r4
   movlt r0,#-1             @ small
   movgt r0,#1              @ greather
   bne 100f                 @ not equals
   cmp r3,#0                @ 0 end string
   moveq r0,#0              @ equal 
   beq 100f                 @ end string
   add r2,r2,#1             @ else add 1 in counter
   b 1b                     @ and loop

100:

   pop {r1-r4}
   bx lr   

/***************************************************/ /* ROUTINES INCLUDE */ /***************************************************/ .include "../affichage.inc" </lang>

Enter command (or quit to stop) : test
error
Enter command (or quit to stop) : so
error
Enter command (or quit to stop) : sos
SOS
Enter command (or quit to stop) : rgt
error
Enter command (or quit to stop) : rgtleft
RGTLEFT
Enter command (or quit to stop) : quit
QUIT

AutoHotkey

<lang AutoHotKey>; Setting up command table as one string str = (

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

) str := StrReplace(str,"`n")

comTable turns the command table string into an array
comTableCapsCount creates an array with the count of capital values for each word

comTable := StrSplit(RegExReplace(str, "\s+", " "), " ") comTableCapsCount := [] for cmds in comTable comTableCapsCount.push(StrLen(RegExReplace(comTable[cmds], "[a-z]")))

Take and process user input into an array of abbreviations

InputBox, abbrev, Command, Type in your command(s).`n If you have several commands`, leave spaces between them. abbrev := Trim(abbrev) StringLower, lowerCaseAbbrev, abbrev abbrev := StrSplit(RegExReplace(abbrev, "\s+", " "), " ")

Double loop compares abbreviations to commands in command table

Loop % abbrev.MaxIndex() { count := A_Index found := false for cmds in comTable { command := SubStr(comTable[cmds], 1, StrLen(abbrev[count])) StringLower, lowerCaseCommand, command if (lowerCaseCommand = abbrev[count]) and (StrLen(abbrev[count]) >= comTableCapsCount[cmds]) { StringUpper, foundCmd, % comTable[cmds] found := true } } if (found) result .= " " foundCmd else result .= " *error*" } MsgBox % Trim(result) </lang>

Output:
 input: riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin
output: RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

AWK

<lang AWK>#!/usr/bin/awk -f BEGIN { FS=" "; split(" Add ALTer BAckup Bottom CAppend Change SCHANGE CInsert CLAst COMPress COpy" \

     "   COUnt COVerlay CURsor DELete CDelete Down DUPlicate Xedit EXPand EXTract Find" \
     "   NFind NFINDUp NFUp CFind FINdup FUp FOrward GET Help HEXType Input POWerinput" \
     "   Join SPlit SPLTJOIN  LOAD  Locate CLocate  LOWercase UPPercase  LPrefix MACRO" \
     "   MErge MODify MOve MSG Next Overlay PARSE PREServe PURge PUT PUTD  Query  QUIT" \
     "   READ  RECover REFRESH RENum REPeat  Replace CReplace  RESet  RESTore  RGTLEFT" \
     "   RIght LEft  SAVE  SET SHift SI  SORT  SOS  STAck STATus  TOP TRAnsfer Type Up" \
     , CMD);

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

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

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


</lang>

Output:
echo 'riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin'|./abbreviations_easy.awk 
 RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

C

<lang c>#include <ctype.h>

  1. include <stdbool.h>
  2. include <stdio.h>
  3. include <stdlib.h>
  4. include <string.h>

const char* command_table =

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

typedef struct command_tag {

   char* cmd;
   size_t length;
   size_t min_len;
   struct command_tag* next;

} command_t;

// str is assumed to be all uppercase bool command_match(const command_t* command, const char* str) {

   size_t olen = strlen(str);
   return olen >= command->min_len && olen <= command->length
       && strncmp(str, command->cmd, olen) == 0;

}

// convert string to uppercase char* uppercase(char* str, size_t n) {

   for (size_t i = 0; i < n; ++i)
       str[i] = toupper((unsigned char)str[i]);
   return str;

}

size_t get_min_length(const char* str, size_t n) {

   size_t len = 0;
   while (len < n && isupper((unsigned char)str[len]))
       ++len;
   return len;

}

void fatal(const char* message) {

   fprintf(stderr, "%s\n", message);
   exit(1);

}

void* xmalloc(size_t n) {

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

}

void* xrealloc(void* p, size_t n) {

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

}

char** split_into_words(const char* str, size_t* count) {

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

}

command_t* make_command_list(const char* table) {

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

}

void free_command_list(command_t* cmd) {

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

}

const command_t* find_command(const command_t* commands, const char* word) {

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

}

void test(const command_t* commands, const char* input) {

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

}

int main() {

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

}</lang>

Output:
 input: riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin
output: RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

C++

<lang cpp>#include <algorithm>

  1. include <cctype>
  2. include <iostream>
  3. include <sstream>
  4. include <string>
  5. 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;

}</lang>

Output:
 input: riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin
output: RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT


Euphoria

<lang Euphoria> 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 </lang>

Output:
 riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin
 RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

Factor

<lang factor>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 ] bi@ start 0 = ;
capitals ( str -- n ) [ LETTER? ] count ;
min-len? ( candidate command -- ? ) capitals swap length <= ;
not-longer? ( candidate command -- ? ) [ length ] bi@ <= ;
permitted? ( candidate command -- ? ) dup [ letter? ] count 0
   > [ [ >upper ] bi@ = ] 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 ] bi@
   [ "User words: " write print ]
   [ "Full words: " write print ] bi* ;
   
main ( -- ) user-input "" [ .abbr ] bi@ ;

MAIN: main</lang>

Output:
User words: riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin
Full words: RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT
User words:
Full words:

Go

Translation of: Kotlin

<lang go>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, " "))

}</lang>

Output:
user words:  riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin    
full words:  RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

Haskell

<lang haskell> 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

</lang>

J

Using the expand definition as well as its dependencies from Abbreviations, simple#J we convert this command table into the form with the abbreviation length given as a number. <lang J>

  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

  </lang>

Java

<lang Java>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;
   }

} </lang>

Output:
Please enter your command to verify:  
riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin

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

Julia

Works with: Julia version 0.6
Translation of: Kotlin

<lang julia>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)))</lang>

Output:
User words:         riG     rePEAT     copies        put         mo       rest      types       fup.          6    poweRin
Full words:       RIGHT     REPEAT    *error*        PUT       MOVE    RESTORE    *error*    *error*    *error* POWERINPUT

Kotlin

<lang scala>// 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()

}</lang>

Output:
user words:  riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin    
full words:  RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT 

Lua

<lang Lua>#!/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 </lang>

Output:
Please enter your command to verify:  
riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin

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

MATLAB / Octave

<lang Matlab> 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 </lang>

Output:
abbreviations_easy('riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin')
ans =  RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

Nanoquery

Translation of: Java

<lang nanoquery>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</lang>

Output:
Please enter your command to verify: riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin           RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

Nim

Translation of: Kotlin

This is a translation of Kotlin solution with some modifications. <lang Nim> 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"
  1. ---------------------------------------------------------------------------------------------------

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

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

</lang>

Output:
Input?  riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin

User words: riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin    
Full words: RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT 

Input? 

User words: 
Full words: 

Input? 

OCaml

<lang ocaml>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)</lang>
Output:
$ ocaml str.cma abbr.ml
RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

Perl

Translation of: Raku

<lang perl>@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"</lang>

Output:
Input:              riG       rePEAT    copies    put       mo        rest      types     fup.      6         poweRin
Output:             RIGHT     REPEAT    *error*   PUT       MOVE      RESTORE   *error*   *error*   *error*   POWERINPUT

Phix

<lang Phix>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")</lang>

Output:
RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

PowerShell

<lang powershell> <#Start with a string of the commands#> $cmdTableStr = "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"

<#String of inputs#> $userWordStr = "riG rePEAT copies put mo rest types fup. 6 poweRin"

$outputStr = $null <#Set this string to null only so all variables are intialized#>

$cmdTabArray = @() <#Arrays for the commands and the inputs#> $userWordArray = @()

<#Split the strings into arrays using a space as the delimiter. This also removes "blank" entries, which fits the requirement "A blank input (or a null input) should return a null string."#> $cmdTabArray = $cmdTableStr.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries) $userWordArray = $userWordStr.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)

<#Begins a loop to iterate through the inputs#> foreach($word in $userWordArray) {

   $match = $false #Variable set to false so that if a match is never found, the "*error*" string can be appended
   foreach($cmd in $cmdTabArray)
   {
       if($cmd -like "$word*" -and ($word.Length -ge ($cmd -creplace '[a-z]').Length)) <#This test: 1) ensures inputs match the leading characters of the command 2) are abbreviations of the command 3) the abbreviations is at least the number of capital characters in the command#>
       {
           $outputStr += $cmd.ToUpper() + " " #Adds the command in all caps to the output string
           $match = $true #sets the variable so that "*error*" is not appended
           break #break keep the loop from continuing and wasting time once a match was found
       }   
   }
   if($match -eq $false){$outputStr += "*error* "} #appends error if no match was found

}

  1. below lines display the input and output

$userWordStr "" $outputStr </lang>

Python

This example does not show the output mentioned in the task description on this page (or a page linked to from here). Please ensure that it meets all task requirements and remove this message.
Note that phrases in task descriptions such as "print and display" and "print and show" for example, indicate that (reasonable length) output be a part of a language's solution.


Works with: Python version 3.6

<lang python>

command_table_text = """Add ALTer BAckup Bottom CAppend Change SCHANGE CInsert CLAst COMPress COpy

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

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 by counting capital letters.
       a word that does not have capital letters
       gets it's full lengths as the minimum.
   """
   command_table = dict()
   for word in command_table_text.split():
       abbr_len = sum(1 for c in word if c.isupper())
       if abbr_len == 0:
           abbr_len = len(word)
       command_table[word] = abbr_len
   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

<lang racket>#lang racket

(define command-string

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

(define input-string

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

(define (make-command command)

 (cons (string-upcase command)
       (list->string (takef (string->list command) char-upper-case?))))

(define commands (map make-command (string-split command-string)))

(string-join

(for/list ([s (in-list (string-split input-string))])
  (define up (string-upcase s))
  (or (for/or ([command (in-list commands)])
        (match-define (cons full-command abbrev) command)
        (and (string-prefix? up abbrev)
             (string-prefix? full-command up)
             full-command))
      "*error*"))
" ")</lang>
Output:
"RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT"

Raku

(formerly Perl 6)

Works with: Rakudo version 2017.08

Demonstrate that inputting an empty string returns an empty string in addition to the required test input.

<lang perl6>< 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 > ~~ m:g/ ((<.:Lu>+) <.:Ll>*) /;

my %abr = => , |$/.map: {

   my $abbrv = .[0].Str.fc;
   |map { $abbrv.substr( 0, $_ ) => $abbrv.uc },
   .[0][0].Str.chars .. $abbrv.chars

};

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

  1. Testing

for 'riG rePEAT copies put mo rest types fup. 6 poweRin', -> $str {

   put ' Input: ', $str;
   put 'Output: ', join ' ', $str.words.map: &abbr-easy;

}</lang>

Output:
 Input: riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin
Output: RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT
 Input: 
Output: 

REXX

<lang REXX>/*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 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 MOve MODify 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'

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 legitimate command name from @.*/
              L=verify(_, 'abcdefghijklmnopqrstuvwxyz', "M")  /*maybe get abbrev's len.*/
              if L==0  then L=length(_)         /*0?  Command name 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. */</lang>
output   when using the default input:
user words:  riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin
full words:  RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

Ruby

<lang ruby>#!/usr/bin/env ruby

cmd_table = File.read(ARGV[0]).split user_str = File.read(ARGV[1]).split

user_str.each do |abbr|

 candidate = cmd_table.find do |cmd|
   cmd.count('A-Z') <= abbr.length && abbr.casecmp(cmd[0...abbr.length]).zero?
 end
 print candidate.nil? ? '*error*' : candidate.upcase
 print ' '

end

puts </lang>

Output:
$ ./abbreviations_easy.rb cmd_table user_str
RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

Rust

<lang rust>use std::collections::HashMap;

fn main() {

   let 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 \
   ";
   let split = commands.split_ascii_whitespace();
   let count_hashtable: HashMap<&str, usize> = split.map(|word| {
       (word, word.chars().take_while(|c| c.is_ascii_uppercase()).count())
   }).collect();
   let line = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin";
   let mut words_vec: Vec<String> = vec![];
   for word in line.split_ascii_whitespace() {
       let split = commands.split_ascii_whitespace();
       let abbr = split.filter(|x| {
           x.to_ascii_lowercase().starts_with(&word.to_ascii_lowercase()) &&
           word.len() >= *count_hashtable.get(x).unwrap()
       }).next();
       words_vec.push(match abbr {
           Some(word) => word.to_ascii_uppercase(),
           None => String::from("*error*"),
       });
   }
   let corrected_line = words_vec.join(" ");
   println!("{}", corrected_line);

} </lang>

Output:
RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

Scala

<lang Scala> object Main extends App {

   implicit class StrOps(i: String) {
       def isAbbreviationOf(target: String): 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 >= target.count(_.isUpper) && checkPAsPrefixOfM(i.toList, target.toList)
       }
   }
   val 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
     """.stripMargin.replace("\n", " ").trim.split(" ")
   val input = "riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin".split(" ").filter(!_.isEmpty)
   val resultLine = input.map{ i =>
       commands.find(c => i.isAbbreviationOf(c)).map(_.toUpperCase).getOrElse("*error*")
   }.mkString(" ")
   println(resultLine)

} </lang>

Output:
RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

Tcl

<lang tcl> 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}
  1. 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 $result </lang>

Output:
RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

VBA

<lang vb>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 ALTer  BAckup Bottom  CAppend Change SCHANGE  CInsert CLAst COMPress COpy "
   s = s & "COUnt COVerlay CURsor DELete CDelete Down DUPlicate Xedit EXPand EXTract Find "
   s = s & "NFind NFINDUp NFUp CFind FINdup FUp FOrward GET Help HEXType Input POWerinput "
   s = s & "Join SPlit SPLTJOIN  LOAD  Locate CLocate  LOWercase UPPercase  LPrefix MACRO "
   s = s & "MErge MODify MOve MSG Next Overlay PARSE PREServe PURge PUT PUTD  Query  QUIT "
   s = s & "READ  RECover REFRESH RENum REPeat  Replace CReplace  RESet  RESTore  RGTLEFT "
   s = s & "RIght LEft  SAVE  SET SHift SI  SORT  SOS  STAck STATus  TOP TRAnsfer Type Up "
   commandtable = Split(s, " ")
   Dim i As Integer
   For Each word In commandtable
       If Len(word) > 0 Then
           i = 1
           Do While Mid(word, i, 1) >= "A" And Mid(word, i, 1) <= "Z"
               i = i + 1
           Loop
           command_table.Add Key:=word, Item:=i - 1
       End If
   Next word
   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</lang>

Output:
user words:   riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin
full words:   RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT 

Vedit macro language

<lang vedit>// Command table: Buf_Switch(#10=Buf_Free) Ins_Text("

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

")

// Example input: Buf_Switch(#11=Buf_Free) Ins_Text("riG rePEAT copies put mo rest types fup. 6 poweRin ") BOF

// Main program

  1. 20 = Reg_Free() // Text register for the word to be converted

Repeat(ALL) {

   Buf_Switch(#11)			// Buffer for example input
   Search("|!|X", ERRBREAK)		// Find next non-space character
   #30 = Cur_Pos			// #30 = begin of a word
   Search("|X", NOERR+NORESTORE)	// Find whitespace (end of the word)
   Reg_Copy_Block(#20, #30, Cur_Pos)	// Get the word to text register #20
   Call("acronym_to_word")		// Convert acronym to full word
   Reg_Type(#20)			// Display the full word
   Type_Char(' ')			// Display a space character

} Buf_Switch(#10) Buf_Quit(OK) // Clean-up Buf_Switch(#11) Buf_Quit(OK) Reg_Empty(#20) Return

// Convert an acronym to full word in uppercase // Input: @(#20) = the acronym // Return: @(#20) = the full word //

acronym_to_word:

if (Reg_Size(#20) == 0) { // If zero length input,

   return				// return zero length string

} Buf_Switch(#10) // Switch to command table BOF While (!At_EOF) {

   if (Search("|S|@(#20)", NOERR)) {		// Find (the first part of) the word

Char // Skip the separator #31 = Cur_Pos // #31 = Begin of the acronym Char(Reg_Size(#20)) // Check if the acronym is log enough if (Cur_Char < 'A' || Cur_Char > 'Z') { // Not a capital letter, verified Search("|X") // Find the end of the word Reg_Copy_Block(#20, #31, Cur_Pos) // Get the word into text register #20 Buf_Switch(Buf_Free) // Convert to upper case using tmp buffer Reg_Ins(#20) Case_Upper_Block(0, Cur_Pos) Reg_Copy_Block(#20, 0, Cur_Pos) Buf_Quit(OK) break // Word found, exit loop }

   } else {					// Not found

Reg_Set(#20, "*error*") break

   }

} Return</lang>

Output:
RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT 

Wren

Translation of: Go
Library: Wren-fmt
Library: Wren-str

<lang ecmascript>import "/fmt" for Fmt import "/str" for Str

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"

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 commands = table.split(" ") // get rid of empty entries for (i in commands.count-1..0) if (commands[i] == "") commands.removeAt(i) var clen = commands.count var minLens = [0] * clen for (i in 0...clen) {

   var count = 0
   for (c in commands[i].codePoints) {
       if (c >= 65 && c <= 90) count = count + 1 // A to Z
   }
   minLens[i] = count

} 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(" "))</lang>

Output:
user words:  riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin    
full words:  RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT

Yabasic

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

dim abrev$(1)

do

   read a$
   if a$ = "" break
   s$ = s$ + " " + a$

loop

size = token(s$, abrev$())

do

   input "Input abbreviation: " a$
   l1 = len(a$)
   
   if l1 = 0 break
   test = false
   for i = 1 to size
       l2 = uppers(abrev$(i))
       if lower$(left$(abrev$(i), l1)) = lower$(left$(a$, l1)) and l1 >= l2 then
           print upper$(abrev$(i))
           test = true
       end if
   next
   if not test print "*error*"

loop

sub uppers(s$)

   local l, i, c$, n
   
   l = len(s$)
   for i = 1 to l
       c$ = mid$(s$, i, 1)
       if c$ >= "A" and c$ <= "Z" n = n + 1
   next
   return n

end sub </lang>

zkl

Rather more brute force than I'd like but hashing the command table is just too much code. And the table is so small... <lang zkl>commands:=Data(0,String, // "Add\0ALTer\0..."

  1. <<<

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

  1. <<<

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

testText.split().apply('wrap(word){

  sz,w := word.len(),word + "*";
  foreach c in (commands){	// rather inelegant but gotta ignore case
     // check for length requirement and, if there, verify
     if(c.matches(w) and sz>=(c-"abcdefghijklmnopqrstuvwxyz").len())

return(c.toUpper());

  }
  "*error*"

.concat(" ").println();</lang>

Output:
RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT