Task: Abbreviations, simple

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

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

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


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


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

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 = word_len;
        new_cmd->cmd = uppercase(word, word_len);
        if (i + 1 < count) {
            char* eptr = 0;
            unsigned long min_len = strtoul(words[i + 1], &eptr, 10);
            if (min_len > 0 && *eptr == 0) {
                free(words[i + 1]);
                new_cmd->min_len = min_len;
                ++i;
            }
        }
        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;
}




Go: package main

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

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

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

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

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

	return commands, minLens
}

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

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

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

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

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

	results := validateCommands(commands, minLens, words)

	printResults(words, results)
}