Letters in phone numbers

Bash, 30

Edit: Thank you Doorknob for eliminating 3 chars

tr a-z 22233344455566677778889

Example:


C, 83 78 77 65 63 62

main(c){for(;~(c=getchar());putchar(c>96?20-c/122+5*c/16:c));}

http://ideone.com/qMsIFQ


GolfScript, 24 chars

{.96>{,91,'qx'+-,3/`}*}%

Test input:

0123456789-abcdefghijklmnopqrstuvwxyz

Test output:

0123456789-22233344455566677778889999

Explanation:

  • { }% applies the code between the braces to each character of the input.

  • .96>{ }* executes the code between the inner braces if and only if the ASCII code of the character is greater than 96 (i.e. it is a lowercase letter).

  • The first , turns the character into a list of all characters with lower ASCII codes, and 91,'qx'+- filters out all characters with ASCII codes less than 91, as well as the letters q and x, from the list. Thus, for example, the character a gets turned into the 6-character list [\]^_`, while z gets turned into the 29-character list [\]^_`abcdefghijklmnoprstuvwy.

  • The second , counts the elements remaining in the list, and 3/ divides this count by three (rounding down). Finally, the ` turns the resulting number (in the range 2 – 9) into a string.

Thus, as per spec, hyphens and numbers are left unchanged, while lowercase letters are mapped into numbers according to the reference keypad diagram. The code will actually cleanly pass through all printable ASCII characters except for lowercase letters (which as mapped as described) and the characters {, | and } (which are mapped to the two-character string 10). Non-ASCII 8-bit input will produce all sorts of weird numeric output.

After all this, it's a bit disappointing that this only beats the trivial bash solution by just six chars.