When entering text on a phone's digital pad it is possible that a particular combination of digits corresponds to more than one word. Such are called textonyms.

Assuming the digit keys are mapped to letters as follows:

    2 -> ABC
    3 -> DEF
    4 -> GHI
    5 -> JKL
    6 -> MNO
    7 -> PQRS
    8 -> TUV
    9 -> WXYZ  



Task

Write a program that finds textonyms in a list of words such as  
Textonyms/wordlist   or  
unixdict.txt.

The task should produce a report:

There are #{0} words in #{1} which can be represented by the digit key mapping.
They require #{2} digit combinations to represent them.
#{3} digit combinations represent Textonyms.

Where:

#{0} is the number of words in the list which can be represented by the digit key mapping.
#{1} is the URL of the wordlist being used.
#{2} is the number of digit combinations required to represent the words in #{0}.
#{3} is the number of #{2} which represent more than one word.

At your discretion show a couple of examples of your solution displaying Textonyms.

E.G.:

 2748424767 -> "Briticisms", "criticisms"



Extra credit

Use a word list and keypad mapping other than English.




Other tasks related to string operations:

Metrics
 Array length
 String length
 Copy a string
 Empty string  (assignment)
Counting
 Word frequency
 Letter frequency
 Jewels and stones
 I before E except after C
 Bioinformatics/base count
 Count occurrences of a substring
 Count how many vowels and consonants occur in a string
Remove/replace
 XXXX redacted
 Conjugate a Latin verb
 Remove vowels from a string
 String interpolation (included)
 Strip block comments
 Strip comments from a string
 Strip a set of characters from a string
 Strip whitespace from a string -- top and tail
 Strip control codes and extended characters from a string
Anagrams/Derangements/shuffling
 Word wheel
 ABC problem
 Sattolo cycle
 Knuth shuffle
 Ordered words
 Superpermutation minimisation
 Textonyms (using a phone text pad)
 Anagrams
 Anagrams/Deranged anagrams
 Permutations/Derangements
Find/Search/Determine
 ABC words
 Odd words
 Word ladder
 Semordnilap
 Word search
 Wordiff  (game)
 String matching
 Tea cup rim text
 Alternade words
 Changeable words
 State name puzzle
 String comparison
 Unique characters
 Unique characters in each string
 Extract file extension
 Levenshtein distance
 Palindrome detection
 Common list elements
 Longest common suffix
 Longest common prefix
 Compare a list of strings 
 Longest common substring
 Find common directory path
 Words from neighbour ones
 Change e letters to i in words
 Non-continuous subsequences
 Longest common subsequence
 Longest palindromic substrings
 Longest increasing subsequence
 Words containing "the" substring
 Sum of the digits of n is substring of n
 Determine if a string is numeric
 Determine if a string is collapsible
 Determine if a string is squeezable
 Determine if a string has all unique characters
 Determine if a string has all the same characters
 Longest substrings without repeating characters
 Find words which contains all the vowels
 Find words which contains most consonants
 Find words which contains more than 3 vowels
 Find words which first and last three letters are equals
 Find words which odd letters are consonants and even letters are vowels or vice_versa
Formatting
 Substring
 Rep-string
 Word wrap
 String case
 Align columns
 Literals/String
 Repeat a string
 Brace expansion
 Brace expansion using ranges
 Reverse a string
 Phrase reversals
 Comma quibbling
 Special characters
 String concatenation
 Substring/Top and tail
 Commatizing numbers
 Reverse words in a string
 Suffixation of decimal numbers
 Long literals, with continuations 
 Numerical and alphabetical suffixes
 Abbreviations, easy
 Abbreviations, simple
 Abbreviations, automatic
Song lyrics/poems/Mad Libs/phrases
 Mad Libs
 Magic 8-ball
 99 Bottles of Beer
 The Name Game (a song)
 The Old lady swallowed a fly
 The Twelve Days of Christmas
Tokenize
 Text between
 Tokenize a string
 Word break problem
 Tokenize a string with escaping
 Split a character string based on change of character
Sequences
 Show ASCII table
 De Bruijn sequences
 Self-referential sequences
 Generate lower case ASCII alphabet




# find textonyms in a list of words #
# use the associative array in the Associate array/iteration task     #
PR read "aArray.a68" PR
 
# returns the number of occurances of ch in text #
PROC count = ( STRING text, CHAR ch )INT:
     BEGIN
         INT result := 0;
         FOR c FROM LWB text TO UPB text DO IF text[ c ] = ch THEN result +:= 1 FI OD;
         result
     END # count # ;
 
CHAR invalid char = "*";
 
# returns text with the characters replaced by their text digits      #
PROC to text = ( STRING text )STRING:
     BEGIN
         STRING result := text;
         FOR pos FROM LWB result TO UPB result DO
             CHAR c = to upper( result[ pos ] );
             IF   c = "A" OR c = "B" OR c = "C"            THEN result[ pos ] := "2"
             ELIF c = "D" OR c = "E" OR c = "F"            THEN result[ pos ] := "3"
             ELIF c = "G" OR c = "H" OR c = "I"            THEN result[ pos ] := "4"
             ELIF c = "J" OR c = "K" OR c = "L"            THEN result[ pos ] := "5"
             ELIF c = "M" OR c = "N" OR c = "O"            THEN result[ pos ] := "6"
             ELIF c = "P" OR c = "Q" OR c = "R" OR c = "S" THEN result[ pos ] := "7"
             ELIF c = "T" OR c = "U" OR c = "V"            THEN result[ pos ] := "8"
             ELIF c = "W" OR c = "X" OR c = "Y" OR c = "Z" THEN result[ pos ] := "9"
             ELSE # not a character that can be encoded #       result[ pos ] := invalid char
             FI
         OD;
         result
     END # to text # ;
 
# read the list of words and store in an associative array           #
 
CHAR separator = "/"; # character that will separate the textonyms   #
 
IF  FILE input file;
    STRING file name = "unixdict.txt";
    open( input file, file name, stand in channel ) /= 0
THEN
    # failed to open the file #
    print( (  "Unable to open """ + file name + """", newline ) )
ELSE
    # file opened OK #
    BOOL at eof := FALSE;
    # set the EOF handler for the file #
    on logical file end( input file, ( REF FILE f )BOOL:
                                     BEGIN
                                         # note that we reached EOF on the #
                                         # latest read #
                                         at eof := TRUE;
                                         # return TRUE so processing can continue #
                                         TRUE
                                     END
                       );
    REF AARRAY words   := INIT LOC AARRAY;
    INT word count     := 0;
    INT combinations   := 0;
    INT multiple count := 0;
    INT max length     := 0;
    WHILE STRING word;
          get( input file, ( word, newline ) );
          NOT at eof
    DO
        STRING text word = to text( word );
        IF count( text word, invalid char ) = 0 THEN
            # the word can be fully encoded #
            word count +:= 1;
            INT length := ( UPB word - LWB word ) + 1;
            IF length > max length THEN
                # this word is longer than the maximum length found so far #
                max length := length
            FI; 
            IF ( words // text word ) = "" THEN
                # first occurance of this encoding #
                combinations +:= 1;
                words // text word := word
            ELSE
                # this encoding has already been used #
                IF count( words // text word, separator ) = 0
                THEN
                    # this is the second time this encoding is used #
                    multiple count +:= 1
                FI;
                words // text word +:= separator + word
            FI
        FI
    OD;
    # close the file #
    close( input file );
 
    # find the maximum number of textonyms #
 
    INT max textonyms := 0;
 
    REF AAELEMENT e := FIRST words;
    WHILE e ISNT nil element DO
        INT textonyms := count( value OF e, separator );
        IF  textonyms > max textonyms 
        THEN
            max textonyms := textonyms
        FI;
        e := NEXT words
    OD;
 
    print( ( "There are ", whole( word count, 0 ), " words in ", file name, " which can be represented by the digit key mapping.", newline ) );
    print( ( "They require ", whole( combinations, 0 ), " digit combinations to represent them.", newline ) );
    print( ( whole( multiple count, 0 ), " combinations represent Textonyms.", newline ) );
 
    # show the textonyms with the maximum number #
    print( ( "The maximum number of textonyms for a particular digit key mapping is ", whole( max textonyms + 1, 0 ), " as follows:", newline ) ); 
    e := FIRST words;
    WHILE e ISNT nil element DO
        IF  INT textonyms := count( value OF e, separator );
            textonyms = max textonyms 
        THEN
            print( ( "    ", key OF e, " encodes ", value OF e, newline ) )
        FI;
        e := NEXT words
    OD;
 
    # show the textonyms with the maximum length #
    print( ( "The longest words are ", whole( max length, 0 ), " chracters long", newline ) );
    print( ( "Encodings with this length are:", newline ) );
    e := FIRST words;
    WHILE e ISNT nil element DO
        IF max length = ( UPB key OF e - LWB key OF e ) + 1
        THEN
            print( ( "    ", key OF e, " encodes ", value OF e, newline ) )
        FI;
        e := NEXT words
    OD;
 
FI
 