1-800-PPRAXIS
September 18, 2018
I guess this is probably the textbook solution:
(define (telemap c)
(case (char-upcase c)
((#\A #\B #\C) #\2)
((#\D #\E #\F) #\3)
((#\G #\H #\I) #\4)
((#\J #\K #\L) #\5)
((#\M #\N #\O) #\6)
((#\P #\Q #\R #\S) #\7)
((#\T #\U #\V) #\8)
((#\W #\X #\Y #\Z) #\9)
(else c)))
(define (telemapper str)
(list->string
(filter char-numeric?
(map telemap
(string->list str)))))
> (telemapper "1-800-PPRAXIS") "18007772947"
But here’s the solution I wrote while I was on hold:
$ echo "1-800-PPRAXIS" |
tr a-z A-Z |
tr A-Z 22233344455566677778889999 |
tr -cd [0-9]
18007772947
You can run the program at https://ideone.com/IMU1lA.
Here’s a Haskell version. We keep any non-letters.
import Data.Char (toUpper) import qualified Data.Map.Strict as M import Data.Maybe (fromMaybe) letterMap :: M.Map Char Char letterMap = M.fromList $ concatMap (\(cs, d) -> map (\c -> (c, d)) cs) letsDig where letsDig = [("ABC", '2'), ("DEF", '3'), ("GHI", '4'), ("JKL", '5'), ("MNO", '6'), ("PQRS", '7'), ("TUV", '8'), ("WXYZ", '9')] unPhoneword :: String -> String unPhoneword = map (\c -> fromMaybe c (M.lookup (toUpper c) letterMap)) test :: String -> IO () test pw = putStrLn $ pw ++ " -> " ++ unPhoneword pw main :: IO () main = do test "1-800-PPRAXIS" -- These are from https://en.wikipedia.org/wiki/Phoneword. test "+1-514-AUTOBUS" test "13TAXI" test "1800-THRIFTY" test "1-US-RENT-A-WRECK"Python version. As with Globules, I kept any non-letters.
import string def telemapper(phone_num): src = string.ascii_uppercase tgt = '22233344455566677778889999' mapping = dict(zip(src, tgt)) phone_num = phone_num.upper() return ''.join(mapping[c] if c in src else c for c in phone_num)Outputs as follows:
>>> telemapper('1-800-PPRAXIS') '1-800-7772947' >>> telemapper('1-800-ppraxis') '1-800-7772947' >>> telemapper('+1-514-AUTOBUS') '+1-514-2886287' >>> telemapper('1-US-RENT-A-WRECK') '1-87-7368-2-97325' >>> telemapper('1-888-Wait-Wait') '1-888-9248-9248' >>>Here’s a solution in C.
#include <stdio.h> #include <stdlib.h> int main(int argc, char* argv[]) { if (argc != 2) { fprintf(stderr, "Usage: %s <PHONE_NUMBER>\n", argv[0]); return EXIT_FAILURE; } for (int i = 0;; ++i) { char c = argv[1][i]; if (c == '\0') break; if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; static char lookup[] = "22233344455566677778889999"; if (c >= 'a' && c <= 'z') c = lookup[c - 'a']; printf("%c", c); } printf("\n"); return EXIT_SUCCESS; }Example:
Here’s a code golf solution in Python.
from string import ascii_letters as l def convert(s): return "".join("22233344455566677778889999"[l.index(c) % 26] if c in l else c for c in s) s = "1-800-PPRAXIS" print(convert(s))Output:
Solution in ruby.
# Simple obvious solution: direct key/value mapping using a hash. def translate(text) text.chars.map do |c| { a: 2, b: 2, c: 2, d: 3, e: 3, f: 3, g: 4, h: 4, i: 4, j: 5, k: 5, l: 5, m: 6, n: 6, o: 6, p: 7, q: 7, r: 7, s: 7, t: 8, u: 8, v: 8, w: 9, x: 9, y: 9, z: 9 }[c.downcase.to_sym] or c end.join end # Still mapping key to values using a hash. # This time the keys contains all letters of a number. def translate(text) text.chars.map do |c| match = { "abc" => 2, "def" => 3, "ghi" => 4, "jkl" => 5, "mno" => 6, "pqrs" => 7, "tuv" => 8, "wxyz" => 9 }.detect { |k,v| k.include?(c.downcase) } match ? match.last : c end.join end # And this one does the mapping with an array infering the value from the index. def translate(text) mapping = ["abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"] text.chars.map do |c| match = mapping.find_index { |s| s.include?(c.downcase) } match ? (match + 2) : c end.join end def test_translate(input, target) output = translate(input) puts puts "input: #{input}" puts "output: #{output}" puts "pass: #{output == target ? '✅' : '❌'}" end test_translate "1-800-PPRAXIS", "1-800-7772947" test_translate "+1-514-AUTOBUS", "+1-514-2886287" test_translate "13TAXI", "138294" test_translate "1800-THRIFTY", "1800-8474389" test_translate "1-US-RENT-A-WRECK", "1-87-7368-2-97325"All three version output:
input: 1-800-PPRAXIS
output: 1-800-7772947
pass: ✅
input: +1-514-AUTOBUS
output: +1-514-2886287
pass: ✅
input: 13TAXI
output: 138294
pass: ✅
input: 1800-THRIFTY
output: 1800-8474389
pass: ✅
input: 1-US-RENT-A-WRECK
output: 1-87-7368-2-97325
pass: ✅
Tests from @Globules
A small improvement to Alex B’s solution is to make use of the Python dict’s ability to return a default when it can’t find a key:
import string def telemapper(phone_num): src = string.ascii_uppercase tgt = '22233344455566677778889999' mapping = dict(zip(src, tgt)) return ''.join(mapping.get(c, c) for c in phone_num.upper())