Task: Abbreviations, easy


C++: #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_;
};


command::command(const std::string& cmd, size_t min_len)
    : cmd_(cmd), min_len_(min_len) {}


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


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) {
        
        size_t len = get_min_length(word);
        
        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;
}



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