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.
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)
@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); })A solution in bash.