Huruf dalam nomor telepon


23

Masalah:

Anda membuat telepon baru di mana orang dapat mengetikkan nomor telepon khusus, misalnya 1-800-program, dan mereka akan dikonversi secara otomatis ke nomor telepon yang dapat digunakan, seperti 1-800-7764726(untuk contoh sebelumnya).

Program Anda akan menerima string jika panjangnya dengan angka, huruf dan garis, dan mengonversi semua huruf menjadi angka yang sesuai.

Ini adalah keypad, untuk referensi:

papan tombol

Aturan:

  • Program Anda akan menerima string
  • Ini akan memprosesnya dan mengembalikan / mencetak string lain
  • Bahasa apa pun diterima
  • Karena , kode terpendek menang

Haruskah program menangani huruf besar dan kecil pada input?
mattnewport

3
@mattnewport - tidak, anggap variabel sudah berubah menjadi huruf kecil
TheDoctor

Jawaban:


8

GolfScript, 24 karakter

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

Input tes:

0123456789-abcdefghijklmnopqrstuvwxyz

Output tes:

0123456789-22233344455566677778889999

Penjelasan:

  • { }% menerapkan kode antara kawat gigi ke setiap karakter input.

  • .96>{ }* mengeksekusi kode antara kawat gigi bagian dalam jika dan hanya jika kode ASCII dari karakter lebih besar dari 96 (yaitu itu adalah huruf kecil).

  • Yang pertama ,mengubah karakter menjadi daftar semua karakter dengan kode ASCII yang lebih rendah, dan 91,'qx'+-menyaring semua karakter dengan kode ASCII kurang dari 91, serta huruf qdan x, dari daftar. Jadi, misalnya, karakter adiubah menjadi daftar 6 karakter [\]^_`, sementara zdiubah menjadi daftar 29 karakter [\]^_`abcdefghijklmnoprstuvwy.

  • Yang kedua ,menghitung elemen yang tersisa dalam daftar, dan 3/membagi jumlah ini dengan tiga (pembulatan ke bawah). Akhirnya, `mengubah angka yang dihasilkan (dalam kisaran 2 - 9) menjadi string.

Jadi, sesuai spek, tanda hubung dan angka dibiarkan tidak berubah, sedangkan huruf kecil dipetakan ke dalam angka sesuai dengan diagram papan tombol referensi. Kode ini benar-benar akan dengan bersih melewati semua karakter ASCII yang dapat dicetak kecuali untuk huruf kecil (yang dipetakan seperti yang dijelaskan) dan karakter {, |dan }(yang dipetakan ke string dua karakter 10). Input 8-bit Non-ASCII akan menghasilkan segala macam output numerik yang aneh.

Setelah semua ini, agak mengecewakan bahwa ini hanya mengalahkan solusi bash sepele hanya dengan enam karakter.


50

Bash, 30

Sunting: Terima kasih Gagang Pintu untuk menghilangkan 3 karakter

tr a-z 22233344455566677778889

Contoh:


10
Tidak bisakah Anda menghapus 3 9detik terakhir ?
Gagang Pintu

16

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


3
Matematika yang bagus. Hanya ingin mengatakan bahwa Anda dapat mengurangi 1 char dengan mengasumsikan EOF adalah -1 dan lakukan~(c=getchar())
user12205

Tidak bisakah Anda menggunakan getch()bukan getchar()?
starsplusplus

Sebenarnya, getch()bukan standar C, karena itu saya kira itu tidak terhubung di ideone. Namun saya mengujinya di MSVC dan itu tidak benar-benar bekerja dengan sedih - karena secara langsung mengkonsumsi input keyboard tidak ada cara untuk keluar dari program, meskipun itu menerjemahkan apa yang Anda ketik dengan cepat yang agak rapi.
mattnewport

4

Javascript - 103 karakter

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)}))

1
Saya tidak tahu Anda bisa melakukannya dengan .replace. Beri suara untuk Anda!
SuperJedi224

Anda dapat mengganti charCodeAt(0)dengan charCodeAt()dan Anda dapat menggunakan fungsi panah untuk function(y)...menyimpan beberapa byte dan untuk ~~(y/3)Anda dapat menggunakany/3|0
chau giang

3

Ruby, 75 karakter

gets.chars{|c|$><<"22233344455566677778889999#{c}"[[*?a..?z].index(c)||-1]}

Menggunakan charsblok yang sudah usang , dan mencetak setiap huruf satu per satu $><<. Saya juga suka [[*?a..?z].index(c)||-1]; itu mengambil karakter yang sesuai dengan huruf alfabet jika huruf, dan karakter terakhir (yang merupakan karakter uji tidak berubah) jika tidak.

Ruby, 43 (atau 35) karakter

Mencuri dari @ace;)

puts gets.tr'a-z','22233344455566677778889'

Shave off 8 chars jika saya bisa berjalan di IRB dengan variabel ssebagai string:

s.tr'a-z','22233344455566677778889'

3

C ++ - 222 karakter

Solusi terlama sejauh ini:

#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;}}

1
Lol, saya tidak berpikir solusi terpanjang adalah tujuannya di sini ...
Danny

@Danny C ++ tidak cocok dengan kode-golf . Java dan C # adalah satu-satunya bahasa yang lebih buruk, yang saya tahu (semua kelas, pembuatan objek, dan nama panjang untuk keluaran ...).
Hosch250

Saya tahu, saya pikir itu lucu bahwa Anda menyebut "solusi terpanjang".
Danny

3

Frink, 92

Bahasa yang agak verbose, saya tahu. Ini memeriksa 8 nilai alih-alih 26 tanpa harus mengetikkan perbandingan. Bisakah solusi "222333444 .." di atas dapat dikurangi dengan cara yang sama?

Menggunakan struktur bawaan, 107

co=new OrderedList
co.insertAll[charList["cfilosv{"]]
println[input[""]=~%s/([a-z])/co.binarySearch[$1]+2/eg]

Menggunakan fungsi rekursif khusus, 92

fn[x,a]:=x<=(charList["cfilosv{"])@a?a+2:fn[x,a+1]
println[input[""]=~%s/([a-z])/fn[$1,0]/eg]

+1 untuk mengurangi metode terjemahan string menjadi pencarian 8 karakter. Sentuhan yang bagus.
Jonathan Van Matre

2

Smalltalk, 79 70

input adalah s:

s collect:[:c|' 22233344455566677778889999'at:1put:c;at:(($ato:$z)indexOf:c)+1]

mungkin bukan kandidat untuk tersingkat - tetapi mungkin menarik untuk trik lama untuk menghindari tes untuk kondisi yang tidak ditemukan (indexOf: mengembalikan 0 dalam kasus ini). Jadi tidak diperlukan tes khusus untuk surat. Namun beberapa Smalltalks memiliki string yang tidak dapat diubah, dan kita membutuhkan 4 karakter tambahan ("copy").

Oh, versi yang lebih baik, yang bahkan berurusan dengan string yang tidak dapat diubah dalam 70 karakter:

s collect:[:c|c,'22233344455566677778889999'at:(($ato:$z)indexOf:c)+1]

2

Mathematica 90

Ini mengikuti logika solusi @ ace:

StringReplace[#,Thread[CharacterRange["A","Z"]->Characters@"22233344455566677778889999"]]&

Contoh

StringReplace[#1,Thread[CharacterRange["A","Z"]-> 
Characters@"22233344455566677778889999"]]&["VI37889"]

8437889


Representasi karakter panah Anda tidak diterima oleh Mma dalam salinan / tempel
Dr. belisarius

Juga, Anda tidak perlu 1masuk #1:)
Dr. belisarius

Belisarius, saya mengubah panah kembali dan menghapus 1. Masih 90 char tapi potong dan tempel akan bekerja. Anda tentu saja memahami motivasi untuk menggunakan panah char tunggal.
DavidC

Pernah ke sana, melakukan itu :)
Dr. belisarius

2

Perl, 50

Salinan jawaban bash Ace yang jelas

($_)=@ARGV;y/a-z/22233344455566677778889999/;print

1
Kode ini berfungsi dengan benar tetapi ada ruang untuk perbaikan. Mari kita singkirkan $ ARGV [0] dan gunakan -pswitch sebagai gantinya yang memungkinkan Anda dengan baik melalui setiap baris stdin. Sementara kita berada di sana, rentang dalam y /// tidak perlu diletakkan dalam tanda kurung. Kami juga dapat menyingkirkan tiga angka 9 yang tersisa hanya satu dan menghapus titik koma terakhir: -p y/a-z/22233344455566677778889/ Begini, 30 +1 untuk -p. Terima kasih telah menggunakan Enterprise Chinese Perl Golfing dan Layanan Optimasi dan selamat bersenang-senang.
Chinese perl goth

2

R, sangat panjang tapi menyenangkan

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)] ))

2

k [32 Karakter]

{(.Q.a!|,/(4 3 4,5#3)#'|$2+!8)x}

Pemakaian

{(.Q.a!|,/(4 3 4,5#3)#'|$2+!8)x}"stack exchange"
"78225 39242643"

2

JavaScript, 85

JavaScript tidak akan pernah memenangkan perang golf, tetapi saya menyukainya dan saya ingin melakukan sesuatu yang berbeda dari melompat pada kereta musik @ace.

alert(prompt().replace(/[a-z]/g,function(a){for(i=7;a<"dgjmptw{"[i--];);return i+4}))

2

PHP, 141

Bukan yang terpendek, tetapi lebih menyenangkan:

<?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;}}

Lebih mudah dibaca:

<?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;}
}

OP mengatakan bahwa input sudah dalam huruf kecil, sehingga Anda dapat menghapusstrtolower
Einacio

2

Python 2.7, 80

for c in raw_input():print'\b'+(`(ord(c)-97)/3+2-(c in('svyz'))`if c>'`'else c),

Saya baru mengenal python, jadi saya yakin pasti ada cara untuk bermain golf ini lebih jauh , ini adalah pendekatan yang berbeda, harap kalian menyukainya, ya Tuhan, python cantik!

Jalankan contoh:

  • input: 01-800-abcdefghijklmnopqrstuvwxyz
  • output: 01-800-22233344455566677778889999

2

T-SQL, 216 byte

Saya menghabiskan beberapa waktu selama beberapa malam dengan susah payah menciptakan fungsi urutan matematis yang akan dibulatkan dengan benar untuk menghasilkan kode ASCII yang tepat untuk angka-angka dari kode ASCII alfabet. Itu memiliki jumlah tempat desimal dalam koefisien yang konyol, tetapi berhasil.

Namun, pendekatan rasional mattnewport bekerja di SQL juga, dengan biaya byte yang jauh lebih rendah, jadi saya tanpa malu-malu menggesek matematika saya sendiri untuk mendukungnya. Pilih dia, ini solusi yang elegan!

Ini milik saya:

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

Ini menggunakan CTE rekursif untuk membuat tumpukan karakter dadakan di nomor telepon dan menerjemahkan huruf-huruf dengan cepat, kemudian sedikit tipuan SQL (SELECT @ p = @ p ​​+ columnValue) untuk mengomposisi ulang string dari CTE tanpa memerlukan konstruksi rekursi lainnya.

Keluaran:

DECLARE @s VARCHAR(MAX)='1-800-abcdefghijklmnopqrstuvwxyz'
--above code runs here
1-800-22233344455566677778889999

2

Python 2.7, 66 65


Asli Anakata

for c in raw_input():print'\b'+(`(ord(c)-97)/3+2-(c in('svyz'))`if c>'`'else c),


Selanjutnya bermain golf

for c in input():print(ord(c)-91)/3-(c in('svyz'))if c>'`'else c,


Saya tidak memiliki reputasi yang cukup untuk mengomentari jawaban @ anakata, jadi saya membuat posting terpisah di sini. Saya memiliki ide yang sama (mengambil modulus tata cara 3) tetapi tidak tahu bagaimana cara mencetak angka yang tepat untuk s - z .

Bagaimanapun, peningkatan golf yang saya buat:

  • diubah raw_inputmenjadiinput

  • menghapus '\b'tanda kurung dan tanda kurung serta tanda kutip tunggal

  • menghapus +2offset dan menempatkannya dalam pengurangan asli (97 - (3 * 2) = 91)

Diuji dengan juru bahasa Python 2.7.6. Asumsikan, sesuai aturan, input string.


Anda juga dapat menghapus ruang antara) dan if
Willem

Kamu benar. good catch willem
zheshishei

1

PHP, 87

echo str_ireplace(range('a','z'),str_split('22233344455566677778889999'),fgets(STDIN));

1

q [38 Karakter]

{(.Q.a!"22233344455566677778889999")x}

Terinspirasi oleh solusi ace

Contoh

{(.Q.a!"22233344455566677778889999")x}"stack exchange"
"78225 39242643"

1

XQuery, 71

BaseX digunakan sebagai prosesor XQuery. $iadalah input.

translate($i,"abcdefghijklmnopqrstuvwxyz","22233344455566677778889999")

Bukan jawaban terpendek, tetapi cukup singkat dan sangat mudah dibaca.


1

Python, sangat ungolfed

Karena semua orang menyalin ace, saya memutuskan untuk mengirim kode yang saya buat sebelum saya mengajukan pertanyaan:

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

1

EcmaScript 6 (103 bytes):

i.replace(/[a-z]/g,x=>keys(a='00abc0def0ghi0jkl0mno0pqrs0tuv0wxyz'.split(0)).find(X=>a[X].contains(x)))

Berharap imengandung string.

Cobalah di semua versi Firefox terbaru. Saya belum mencoba Google Chrome.


1

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

1

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")

Pemakaian

y "1-800-program"

1

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))));}}

0

Python

import string          
trans = str.maketrans(string.ascii_lowercase,
                      '22233344455566677778889999')                                                                                         
print("1-800-ask-usps".translate(trans))

0

ECMASCRIPT, 101 (dengan input)

"1-800-PROGRAM".replace(/./g,function(c){
return "22233344455566677778889999"[c.charCodeAt(0)-65]||c})

Newline ditambahkan untuk kejelasan. 85 karakter jika input dalam variabel.


0

Perl, 54

print map{/[a-y]/?int(5/16*ord)-28:/z/?9:$_}<>=~/./gs

Tembak, @RobHoare masih mengalahkan saya dengan 4 karakter. :)


0

QBasic, 155

Ah, kenangan itu ...

INPUT n$
FOR i=1 TO LEN(n$)
c$=MID$(n$,i,1)
a=ASC(c$)
IF 97>a THEN
PRINT c$;
ELSE IF 122>a THEN
PRINT STR$(a\3.2-28);
ELSE
PRINT 9;
END IF
NEXT i

Seharusnya ini lebih pendek, tapi saya menguji dengan repl.it , yang tidak memungkinkan IFpernyataan baris tunggal dan berperilaku aneh jika Anda membiarkan variabel off NEXT i. Ini juga tidak mengenali ASCfungsinya, jadi untuk menjalankan kode Anda harus menambahkan solusi ini di awal:

DECLARE FUNCTION ASC(s$)
FUNCTION ASC(s$)
FOR j=1 TO 255
IF CHR$(j)=LEFT$(s$,1) THEN
ASC=j
END IF
NEXT j
END FUNCTION

(Kali kedua Anda menjalankannya, penerjemah akan mengeluh kecuali jika Anda menghapus DECLARE FUNCTIONgaris, pergi angka.)


0

R, 110

s=strsplit(scan(,""),"")[[1]];i=grep("[a-z]",s);s[i]=sort(c(1:24%%8+2,7,9))[match(s[i],letters)];cat(s,sep="")

Contoh:

> s=strsplit(scan(,""),"")[[1]];i=grep("[a-z]",s);s[i]=sort(c(1:24%%8+2,7,9))[match(s[i],letters)];cat(s,sep="")
1: 1-800-program
2: 
Read 1 item
1-800-7764726
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.