Words On A Telephone Keypad

January 13, 2017

The digits on a telephone keypad are associated with letters; for instance, the digit 2 is associated with the letters A, B and C, and the digit 7 is associated with the letters P, Q, R and S. Thus, a word can be converted to its numeric equivalent; for instance, PRAXIS can be converted to the number 772947. The conversion is not necessarily unique, so ACT, BAT and CAT all convert to 228.

Your task is to write a program that takes a number, such as 228, and returns a list of all the words in a dictionary that are represented by that number. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Advertisement

Pages: 1 2

3 Responses to “Words On A Telephone Keypad”

  1. Jamie Hope said

    Here’s one that goes the other way, turning the provided number into a string regex, and then using grep to search /usr/share/dict/words (via a Kawa process quasi-literal).

    (import (srfi 13))                      ; for string-join
    (require 'regex)                        ; for regex-split
    
    (define letters
      ["[+]" "1" "[abc]" "[def]" "[ghi]" "[jkl]" "[mno]" "[pqrs]" "[tuv]" "[wxyz]"])
    
    (define (digits n::integer)
      (let loop ((ds '()) (n n))
        (if (< n 10)
            (cons n ds)
            (loop (cons (remainder n 10) ds) (div n 10)))))
    
    (define (num->regex n::integer)
      (string-join (map letters (digits n)) ""))
    
    (define (paragraph->lines s::String)
      (regex-split #/\n/ (*:trim s)))
    
    (define (lookup n::integer)
      (paragraph->lines
       &`{grep -i "^&[(num->regex n)]$" /usr/share/dict/words}))
    
    (for-each
     (lambda (arg)
       (format #t "~a: ~a~%" arg (lookup (string->number arg))))
     (cdr (command-line)))
    

    $ kawa /tmp/words.scm 772947 228
    772947: (praxis)
    228: (Abu abu act Bat bat Cat cat)

  2. matthew said

    @Jamie: Great idea! Here’s a node.js version:

    const readline = require('readline');
    const s = process.argv[2] || "43556";
    const map = ['[+]','1','[abc]','[def]','[ghi]','[jkl]','[mno]','[pqrs]','[tuv]','[wxyz]'];
    let restr = "";
    for (const c of s.split('')) {
        restr += map[Number(c)] || "";
    }
    restr = "^" + restr + "$"; // Match whole line
    
    const re = new RegExp(restr,"i"); // Case insensitive
    
    const rl = readline.createInterface({
      input: process.stdin;
    });
    
    rl.on('line', function(line){
        if (re.test(line)) console.log(line);
    })
    
    $ cat /usr/share/dict/words | nodejs --harmony phone.js
    hello
    $ cat /usr/share/dict/words | nodejs --harmony phone.js 666
    Mon
    Ono
    mom
    moo
    non
    
  3. r. clayton said

    A solution in bash.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: