1-800-PPRAXIS

September 18, 2018

I hate businesses with telephone numbers that spell words; it’s awkward to type letters at a telephone, and often the words are abbreviated or spelled wrong so they are no longer mnemonic, which defeats the purpose. So this morning when I had to call one of those businesses, I wrote a program to translate letters to numbers after I had been waiting on hold long enough to get really annoyed.

Your task is to write a program to translate telephone numbers specified as words. 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

6 Responses to “1-800-PPRAXIS”

  1. Globules said

    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"
    
    $ ./unphoneword
    1-800-PPRAXIS -> 1-800-7772947
    +1-514-AUTOBUS -> +1-514-2886287
    13TAXI -> 138294
    1800-THRIFTY -> 1800-8474389
    1-US-RENT-A-WRECK -> 1-87-7368-2-97325
    
  2. Alex B said

    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'
    >>> 
    
  3. Daniel said

    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:

    $ ./a.out 1-800-PPRAXIS
    1-800-7772947
    
  4. Daniel said

    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:

    1-800-7772947
    
  5. V said

    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

  6. 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())
    

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: