[Question]
  [
**Problem:**
You are making a new phone where people can type in specialized phone numbers, for example, `1-800-program`, and they would be converted automatically to a usable phone number, like `1-800-7764726` (for the previous example). 
Your program will recieve a string if any length with numbers, letters and dashes, and convert all the letters to their corresponding numbers.
Here is a keypad, for reference:
![keypad](https://i.stack.imgur.com/7TKsb.png)
**Rules:**
* Your program will receive a string
* It will process it and return/print another string
* Any language is accepted
* Since it is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), the shortest code wins
  
[Answer]
## Bash, 30
Edit: Thank you Doorknob for eliminating 3 chars
```
tr a-z 22233344455566677778889
```
Example:  
![](https://i.stack.imgur.com/RmNe7.png)
[Answer]
# 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>
[Answer]
# 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](https://codegolf.stackexchange.com/a/21331) by just six chars.
[Answer]
# Javascript - 103 characters
```
alert(prompt().replace(/[a-z]/g,function(y){y=y.charCodeAt(0)-91;return y>27?9:y>24?8:y>20?7:~~(y/3)}))
```
[Answer]
# Ruby, 75 chars
```
gets.chars{|c|$><<"22233344455566677778889999#{c}"[[*?a..?z].index(c)||-1]}
```
Uses the deprecated `chars` with block, and prints each letter individually with `$><<`. I also like `[[*?a..?z].index(c)||-1]`; it grabs the character corresponding to that letter of the alphabet if it's a letter, and the last character (which happens to be the test character unchanged) if not.
# Ruby, 43 (or 35) chars
Blatantly stealing from @ace ;)
```
puts gets.tr'a-z','22233344455566677778889'
```
Shave off 8 chars if I can run in IRB with the variable `s` as the string:
```
s.tr'a-z','22233344455566677778889'
```
[Answer]
# C++ - 222 chars
Longest solution so far:
```
#include<iostream>
#include<string>
#define o std::cout<<
int main(){std::string s;std::cin>>s;for(int i=0;i<s.size();i++){int j=s[i]-97;if(j<0)o s[i];if(0<=j&j<15)o 2+j/3;if(14<j&j<19)o 7;if(18<j&j<22)o 8;if(21<j&j<26)o 9;}}
```
[Answer]
# Frink, 92
A rather verbose language, I know. This checks 8 values instead of 26 without having to type out the compares. Can any of the above "222333444.." solutions be reduced in a similar way?
Using built in structures, 107
```
co=new OrderedList
co.insertAll[charList["cfilosv{"]]
println[input[""]=~%s/([a-z])/co.binarySearch[$1]+2/eg]
```
Using a custom recursive function, 92
```
fn[x,a]:=x<=(charList["cfilosv{"])@a?a+2:fn[x,a+1]
println[input[""]=~%s/([a-z])/fn[$1,0]/eg]
```
[Answer]
# Python 2.7, 66 65
  
### Anakata's Original
```
for c in raw_input():print'\b'+(`(ord(c)-97)/3+2-(c in('svyz'))`if c>'`'else c),
```
  
### Further golfed
```
for c in input():print(ord(c)-91)/3-(c in('svyz'))if c>'`'else c,
```
  
I don't have enough reputation to comment on @anakata's answer, so I made a separate post here. I had the same idea (taking the ordinance modulus 3) but couldn't figure out how to print the right numbers for *s - z*. 
Anyways, the golf improvements I made:
* changed `raw_input` to `input`
* removed the extraneous `'\b'` and parentheses and single quotes
* removed the `+2` offset and placed that in the original subtraction (97 - (3 \* 2) = 91)
*Tested with the Python 2.7.6 interpreter. Assumes, per the rules, a string input.*
[Answer]
# [Scala](http://www.scala-lang.org/), 49 48 bytes
```
_.map(c=>if(c>96)(c/3.2+20).toChar min'9'else c)
```
[Try it online!](https://tio.run/##VczPasJAEMfxu08xeHGXMnEb658IBkpPQilCH6Bs1omJJps1u1Zb8dnj5CJ4m4Hv5@eNrnTXZHsyAT4pBGr92m6KxtLXqc74A7oEslsP787BdQCwpRzyJXyHtrQ7WKWPq/uJau2EWaVlLkyazKQw40kUv8RKRqH5KHQLdWlHyYgqT2BkB@CYhsqKXAx1Znh6V5T7Q1Xbxh1bH06/58vf/1DKwVOqlELOkXtkgCyQCfYGGWGvUCWL@Wz6Nolf@4Fbdwc "Scala – Try It Online")
Maps `abcdefghijklmnopqrstuvwxyz` to `22233344455566677778889999` via `(c/3.2+20).toChar min'9'`
(saved 1 byte thanks to Kevin Cruijssen)
[Answer]
# Smalltalk, 79 70
input is s:
```
s collect:[:c|' 22233344455566677778889999'at:1put:c;at:(($ato:$z)indexOf:c)+1]
```
probably not a candidate for being shortest - but may be of interest for an old trick to avoid a test for a not-found condition (indexOf: returns 0 in this case). So no special test for letters is needed. Some Smalltalks however, have immutable strings, and we need 4 more chars ("copy").
Oh, a better version, which even deals with immutable strings in 70 chars:
```
s collect:[:c|c,'22233344455566677778889999'at:(($ato:$z)indexOf:c)+1]
```
[Answer]
# Mathematica 90
This follows the logic of @ace's solution:
```
StringReplace[#,Thread[CharacterRange["A","Z"]->Characters@"22233344455566677778889999"]]&
```
Example
```
StringReplace[#1,Thread[CharacterRange["A","Z"]-> 
Characters@"22233344455566677778889999"]]&["VI37889"]
```
> 
> 8437889
> 
> 
> 
[Answer]
## Perl, 50
Another obvious copy of Ace's bash answer
```
($_)=@ARGV;y/a-z/22233344455566677778889999/;print
```
[Answer]
## R, very long but fun
```
foo <- '1-800-splurghazquieaobuer57'
oof <- unlist(strsplit(foo,''))
#don't count that part - it's input formatting :-) 
digout <- unlist(strsplit('22233344455566677778889999','')) 
oof[oof%in%letters[1:26]] <- unlist(sapply(oof[oof%in%letters[1:26]], function(j) digout[which(letters[1:26]==j)] ))
```
[Answer]
# k [32 Chars]
```
{(.Q.a!|,/(4 3 4,5#3)#'|$2+!8)x}
```
### Usage
```
{(.Q.a!|,/(4 3 4,5#3)#'|$2+!8)x}"stack exchange"
"78225 39242643"
```
[Answer]
# JavaScript, 85
JavaScript is never going to win the golf wars, but I like it and I wanted to do something different than jump on the @ace bandwagon.
```
alert(prompt().replace(/[a-z]/g,function(a){for(i=7;a<"dgjmptw{"[i--];);return i+4}))
```
[Answer]
## PHP, 141
Not the shortest, but more fun:
```
<?php foreach(str_split($argv[1])as$c){$v=ord($c);if($v>114){$v--;}if($v==121){$v--;}if($v<123&$v>96){echo chr(ceil($v/3+17));}else{echo$c;}}
```
More readable:
```
<?php 
foreach (str_split($argv[1]) as $c) {
  $v=ord($c);
  if ($v>114) {$v--;}
  if ($v==121){$v--;}
  if ($v<123 & $v>96){
    echo chr(ceil($v/3+17));
    } else {echo $c;}
}
```
[Answer]
**Python 2.7, 80** 
```
for c in raw_input():print'\b'+(`(ord(c)-97)/3+2-(c in('svyz'))`if c>'`'else c),
```
I am new to python, so **I'm sure there must be a way to golf this even further**, it's a different aproach, hope you guys like it, ***my god, is python pretty!***
Run example:
* input: 01-800-abcdefghijklmnopqrstuvwxyz
* output: 01-800-22233344455566677778889999
[Answer]
# T-SQL, 216 bytes
I spent quite some time over the past couple of nights painstakingly creating a mathematical sequence function that would round correctly to generate the proper ASCII codes for the numbers from the alphabetical ASCII codes. It had a ridiculous number of decimal places in the coefficients, but it worked.
However, mattnewport's rational approach works in SQL as well, at a much lower cost of bytes, so I am shamelessly scrapping my own math in favor of his. Go up-vote him, it's an elegant solution!
Here's mine:
```
DECLARE @p VARCHAR(MAX)='';WITH t AS(SELECT ASCII(LEFT(@s,1))c,2 i UNION ALL SELECT ASCII(SUBSTRING(@s,i,1)),i+1FROM t WHERE i<=LEN(@s))SELECT @p=@p+CHAR(CASE WHEN c>96THEN 20-c/122+5*c/16 ELSE c END)FROM t;SELECT @p
```
This uses a recursive CTE to make an impromptu stack of the characters in the phone number and translate the letters on the fly, then a bit of SQL trickery (SELECT @p=@p+columnValue) to recompose the string from the CTE without requiring another recursion construct.
Output:
```
DECLARE @s VARCHAR(MAX)='1-800-abcdefghijklmnopqrstuvwxyz'
--above code runs here
1-800-22233344455566677778889999
```
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E), 11 bytes
```
Aā6+žq÷T9:‡
```
[Try it online!](https://tio.run/##yy9OTMpM/f/f8UijmfbRfYWHt4dYWj1qWPj/v4GhkbGJqZm5haVuYlJySmpaekZmVnZObl5@QWFRcUlpWXlFZRUA "05AB1E – Try It Online")
```
A                 # alphabet: "abcdefghijklmnoqrstuvwxyz"
 ā                # length range: [1..26]
  6+              # add 6 to each: [7..32]
    žq÷           # divide by pi: [2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,10]
       T9:        # replace 10 with 9
          ‡       # transliterate the input (a => 2, ..., z => 9)
```
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal), 14 bytes
```
ka:ż6+kiḭṪ9JṅĿ
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyIiLCIiLCJrYTrFvDYra2nhuK3huao5SuG5hcS/IiwiIiwiMDEyMzQ1Njc4OS1hYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiJd)
```
ka:ż6+kiḭṪ9JṅĿ
ka:            # Push the alphabet twice
   ż           # Length range: [1..26]
    6+         # Add 6: [7..32]
      kiḭ      # Floor divide by pi: [2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,10]
         Ṫ9J   # Remove the last item and append 10
            ṅ  # Join by nothing to make a string
             Ŀ # Transliterate the input from the alphabet to this
```
[Answer]
## PHP, 87
```
echo str_ireplace(range('a','z'),str_split('22233344455566677778889999'),fgets(STDIN));
```
[Answer]
# q [38 Chars]
```
{(.Q.a!"22233344455566677778889999")x}
```
Inspired by @ace's solution
Example
```
{(.Q.a!"22233344455566677778889999")x}"stack exchange"
"78225 39242643"
```
[Answer]
### XQuery, 71
[BaseX](http://basex.org) was used as XQuery processor. `$i` is input.
```
translate($i,"abcdefghijklmnopqrstuvwxyz","22233344455566677778889999")
```
Not the shortest answer, but quite short and very readable.
[Answer]
## Python, very ungolfed
Since everyone is copying ace, i decided to post the code i made up before i submitted the question:
```
def phonekeypad(text):
    c = ['','','abc','def','ghi','jkl','mno','pqrs','tuv','wxyz']
    st = ""
    for i in list(text):
        a = False
        for t in range(len(c)):
            if i in c[t]:
                st += str(t)
                a=True
        if a == False:
            st += str(i)
    return st
```
[Answer]
# EcmaScript 6 (103 bytes):
```
i.replace(/[a-z]/g,x=>keys(a='00abc0def0ghi0jkl0mno0pqrs0tuv0wxyz'.split(0)).find(X=>a[X].contains(x)))
```
*Expects `i` to contain the string.*
Try it in any recent version of Firefox. I've not tried Google Chrome.
[Answer]
## Python 3, 121
```
print("".join((lambda x:"22233344455566677778889999"[ord(x)-97] if ord(x)>96 and ord(x)<123 else x)(i) for i in input()))
```
[Answer]
# Haskell, 93C
```
t[]_ a=a
t(b:c)(d:e)a
 |a==b=d
 |True=t c e a
y=map(t['a'..'z']"22233344455566677778889999")
```
Usage
```
y "1-800-program"
```
[Answer]
# C# 140
```
using System.Linq;class P{static void Main(string[]a){System.Console.Write(string.Concat(a[0].Select(d=>(char)(d>96?20-d/122+5*d/16:d))));}}
```
[Answer]
# Perl, 54
```
print map{/[a-y]/?int(5/16*ord)-28:/z/?9:$_}<>=~/./gs
```
Shoot, @RobHoare still beat me by 4 characters. :)
[Answer]
# [C++ (clang)](http://clang.llvm.org/), 50 bytes
```
[](auto&s){for(auto&c:s)c=c>96?20-c/122+5*c/16:c;}
```
this is a port of [mattnewport's C solution](https://codegolf.stackexchange.com/a/21349/112488).
[Try it online!](https://tio.run/##TY7dCoJAFISvPU@xEIQWkgpJqW0P4WV0sRw3WXB/2D0GET27KUJ0NTMMwzfoXIqDMP1EUrtBkGzo5aQRWrKWQ8tIBopbFhJ4T7d7LEay25C8H9avHquQ4AX5ubwWWYqHvCj2x92sZYX1Z4rikNQQeUmjNyzU8AHYKIPD2EnWKBvIS6E5gDIEWigTP63qZhhEgbqqmntl@mW4ZlSGcf6X7UisadabC@rHymbWlKenLEudt70X@gs "C++ (clang) – Try It Online")
]