Ejaan Multi-ketuk Ponsel

21

Terinspirasi oleh Tantangan Kode Google :

Alfabet Latin berisi 26 karakter dan telepon hanya memiliki sepuluh digit pada tombol. Kami ingin membuatnya lebih mudah untuk menulis pesan kepada teman Anda menggunakan urutan penekanan tombol untuk menunjukkan karakter yang diinginkan. Huruf-huruf dipetakan ke digit seperti yang ditunjukkan di bawah ini. Misalnya, untuk memasukkan karakter B, program akan menekan 22. Untuk memasukkan dua karakter secara berurutan dari tombol yang sama, pengguna harus berhenti sebelum menekan tombol untuk kedua kalinya. Karakter spasi '' harus dicetak untuk menunjukkan jeda. Sebagai contoh, 2 2 menunjukkan AA sedangkan 22 menunjukkan B.

Setiap pesan hanya akan terdiri dari huruf kecil az dan karakter spasi ''. Menekan nol memancarkan spasi.

masukkan deskripsi gambar di sini

Tantangan Anda adalah menulis fungsi terkecil yang mengambil string input, dan mengembalikan urutan penekanan tombol yang diperlukan untuk menghasilkan input sebagai string atau output ke stdout. Fungsi yang merupakan jumlah byte terkecil yang menang.

Contoh Input / Output

phone("hi")
44 444
phone("hello world")
4433555 555666096667775553

Klarifikasi lainnya

  • Jeda harus hanya ditambahkan bila perlu dan harus menjadi ruang ''.
  • Setiap pesan hanya akan terdiri dari huruf kecil az dan karakter spasi ''. Cetak 0untuk menandakan ruang.
  • Tidak ada perpustakaan eksternal.
  • Hanya string input yang dapat diteruskan ke fungsi Anda.
  • Untuk membuat bahasa lain menjadi kompetitif, deklarasi fungsi utama tidak masuk hitungan, dan juga tidak mengimpor perpustakaan standar lainnya. #includes, imports, dan usings tidak masuk hitungan. Yang lainnya tidak. Ini termasuk #definefungsi s dan helper. Lihat aturan 2 dalam pertanyaan ini jika Anda bingung.
  • Beberapa spasi dapat dilambangkan sebagai 00atau 0 0karena Anda tidak benar-benar harus berhenti di antara spasi
Danny
sumber
1
Terkait dengan ini: codegolf.stackexchange.com/questions/21327/…
Victor Stafusa
Bisakah kita menganggap inputnya huruf kecil / besar?
Phil H
@PhilH " huruf kecil az dan karakter luar angkasa ''"
Danny
Apakah Anda menganggap tanda kurung {}bagian dari tanda tangan fungsi? Misalnya, jika kode saya adalah function f(){alert('hi');}, apakah saya harus menghitung karakter alert('hi');atau {alert('hi');}?
ProgramFOX
2
Sejauh yang saya ingat t9bekerja berbeda: Anda harus mengklik setiap tombol sekali untuk mendapatkan kata.
VisioN

Jawaban:

8

Rubi, 129 122 115 111 108 107 105

Selesai dengan bermain golf ...

Ups, benar-benar lupa menghapus spasi yang tidak perlu - diperbaiki ...

Menyimpan 2 karakter berkat Peter Taylor.

Versi online

def t9(t)
(t.tr(" ",?`).bytes.map{|c|"09998887777666555444333222"[96-c..-1][/(.)\1*/]}*' ').gsub /(\d) (?!\1)/,'\1'
end

Penjelasan:

ruang diterjemahkan ke char dengan ordinal 96

(t.tr(" ",?`).bytes

karakter pertama kali dipetakan ke serangkaian angka: - a ke 2 - b ke 22 - d ke 3222 - h ke 444333222

ekspresi regex kemudian cocok dengan grup pertama dengan angka yang sama

map{|c|"09998887777666555444333222"[96-c..-1][/(.)\1*/]}

array bergabung

*' ')

semua spasi dalam kejadian "digit space different_digit" dihapus

gsub /(\d) (?!\1)/,'\1'
David Herrmann
sumber
1
Tidak terlihat berfungsi 100% benar. Saya melihat 66666 seharusnya tidak perlu ditekan 4 kali berturut-turut.
Danny
Harus diperbaiki, terima kasih;)
David Herrmann
1
Apa gunanya \2regex terakhir itu? Tentunya kelompok kedua adalah pernyataan nol-lebar?
Peter Taylor
Anda benar sekali!
David Herrmann
6

REBEL - 154 110 103

;0 2abc3def4ghi5jkl6mno7pqrs8tuv9wxyz/^;/$<;/([^\d-])(?=\D.*(\d)(\w)*\1)/$2$3-/(\d)-+\1/$1 $1/-//;/$>$`

'Fungsi' ini menerima input dari stdin dan mengirimkan hasilnya ke stdout.

Tes berjalan (jadi Anda tidak harus menginstal penerjemah):

hi
44 444

hello world
4433555 555666096667775553

yes
999337777

kthxbai
558449922 2444
Kendall Frey
sumber
Saya tidak pernah dapat memuat tautan Anda! :(
luser droog
4

JavaScript (124)

Jalankan di Firefox.

t9=s=>s.replace(/./g,c=>'099998887777666555444333222'.slice(36-parseInt(c,36)).match(/(.)\1*/)[0]+' ').replace(/(.) (?!\1)/g,'$1')
FizzyTea
sumber
4

GolfScript, 46 karakter

{).," adgjmptw"&.,.1>*`@@)\;-*}/]{.2$^!" "*\}*

Seperti biasa, membaca input dari stdin, mencetak ke stdout. Lihat demo online (dengan input kalengan).

Perhatikan bahwa kode ini bergantung pada interpretasi spesifikasi input yang sangat ketat (hanya huruf dan spasi huruf kecil): khususnya, setiap baris baru dalam input akan menabraknya! Masalah ini dapat diperbaiki, dengan biaya dua karakter tambahan, dengan menambahkan n-kode ke filter untuk menyaring baris baru.

Ilmari Karonen
sumber
3

C ++ - 365 karakter tanpa int main(){}

#include<iostream>
#include<string>
#include<cmath>
#define o std::cout<<
int main(){std::string s;getline(std::cin,s);for(int i=0;i<s.size();i++){if(s[i]==32)o 0;int j=s[i]-97;if(i>0&&j/3==(s[i-1]-97)/3)o ' ';if(-1<j&j<15){for(int k=j-j%3-1;k<j;k++)o 2+j/3;}if(14<j&j<19){for(int k=14;k<j;k++)o 7;}if(18<j&j<22){for(int k=18;k<j;k++)o 8;}if(21<j&j<26){for(int k=21;k<j;k++)o 9;}}}

Menggunakan alasan yang sama dengan jawaban saya di sini , hanya menggunakan forloop untuk menampilkan setiap huruf beberapa kali sesuai.

Hosch250
sumber
Anda bisa menggunakan s[i]==32bukan s[i]==' '. Nilai ASCII ruang adalah 32.
user12205
@ Ya tentu saja.
Hosch250
3

Perl - 107 110

$_=<>;y/ /0/;$z='a';$==2;for$l((3)x5,4,3,4){for$q(1..$l){s/$z/$=x$q.$"/ge,$z++}$=++}s/(.) (?!\1)/\1/g;print

Inilah solusi saya sebelumnya di 120 128 130 155 :

$_=<>;s//_/g;y/sz/79/;for$x(cfilorvy,behknqux,adgjmptw){s/(\d)_/\1\1_/g,eval"y/$x/2-9/"}y/ _/0 /;s/(.) (?!\1)/\1/g;print

Tes:

hi
 44 444

hello world
 4433555 555666096667775553

jackdaws loves my big sphinx
 52 222553297777055566688833777706999022444 407777 744 4446699
mniip
sumber
3

VBA 220 253/258/219

Tidak menghitung Functiongaris di sini:

Dengan String, 253 :

Function t(s)
For Each c In Split(StrConv(s,64),Chr(0))
If c<>""Then If c=" "Then t=t & 0 Else b=Asc(c)-91:n=String(IIf(b>27,(b-4)Mod 4+1,IIf(b>23,(b-1)Mod 4+1,b Mod 3+1)),Trim(Str(Int(b/3)-IIf(b=24Or b=27Or b>29,1,0)))):t=t &IIf(Right(t,1)=Left(n,1)," " &n,n)
Next
End Function

Dengan Forloop 258 :

Menambahkan koreksi untuk kunci 7/9 (terima kasih, Danny), yang menambahkan banyak karakter.

Function t(s)
For Each c In Split(StrConv(s,64),Chr(0))
If c<>""Then
n=""
b=Asc(c)-91
For i=1To IIf(b>27,(b-4)Mod 4+1,IIf(b>23,(b-1)Mod 4+1,b Mod 3+1))
n=n &Int(b/3)-IIf(b=24Or b=27Or b>29,1,0)
Next
t=t &IIf(c=" ",0,IIf(Right(t,1)=Left(n,1)," " &n,n))
End If
Next
End Function

Menggunakan Choose 219 :

Saya tidak ingin menjalankan yang ini, karena fungsionalitasnya lebih mendasar, tetapi ini adalah kode yang lebih pendek ...

Function t(s)
For Each c In Split(StrConv(s,64),Chr(0))
If c<>"" Then:b=Asc(c)-96:n=Choose(b,2,22,222,3,33,333,4,44,444,5,55,555,6,66,666,7,77,777,7777,8,88,888,9,99,999,9999):t=t &IIf(c=" ",0,IIf(Right(t,1)=Left(n,1)," " &n,n))
Next
End Function
Gaffi
sumber
yesseharusnya 999337777. Saya bisa 10338menggunakan fungsi Anda.
Danny
3

C, 165 163 153 149 138 karakter

k(char*s){char*m="`cfilosvz",l=0,i,c;while(*s^0){for(i=0;*s>m[i];i++);c=*s-m[i-1];i==0?i=-1,c=1:i==l?putchar(32):1;while(c--)putchar(i+49);l=i;s++;}}

Upaya pertama saya di golf kode, ada saran yang dihargai.

pengguna18204
sumber
2

C ++ - 170 168 160

Golf:

#define t std::cout<< 
void g(char*s){char v,p,b,l=1;while(*s){v=*s++-97;p=(v==18)+(v==25)+(v-=v/18+v/25)%3;b=v<0?48:v/3+50;if(l==b)t' ';while(p--+1){t(l=b);}}}

Tidak disatukan

void numpresses(char* s)
{
char lastbutton = 1;
const char asciiOffset = 97;

while(*s)
{
    char val = *s++ - asciiOffset;

    char presses = 
        (val == 18) + (val == 25)           //Z and S are special cases. Check for their ascii codes.
        + (val -= val / 18 + val / 25) % 3; //Simple mod 3 for number of presses. Also apply offset for characters above s and z.

    char button =
        val < 0                             //If the character is a space...
        ? '0'                               //The button character needs to be 0
        : val / 3 + '2';                    //Buttons are offset by the ascii code for the number 2


    if (lastbutton == button)               //Add a space if we need to pause
    {
        std::cout << ' ';
    }

    while (presses-- + 1)                   //Print the button once for each press required
    {
        std::cout << button;
        lastbutton = button;            
    }
}
}
Tharwen
sumber
2

C: 136 karakter

p(char*s){int i,c,l=1;while(c=*s%32,*s++)for(i=l!=(l=(c+149-c/18-c/25)/3-!c);i++<(c-!!c-c/18-c/25)%3+(c==19)+c/26+2;putchar(i^1?l:32));}

Dan sedikit ungolfed (ya, begitulah ditulisnya):

p(char*s){
        int i,c,l=1;
        while(c=*s%32,*s++)for(
                i=l!=(l=(c+149-c/18-c/25)/3-!c);
                i++<(c-!!c-c/18-c/25)%3+(c==19)+c/26+2;
                putchar(i^1?l:32)
        );
}

Saya mungkin bisa mengurangi sedikit dengan menerapkan rekursi, ilmu hitam dan bubuk cabai yang cukup banyak.

Untuk S
sumber
2

Jawa - 243

Solusi java yang cukup naif. Terima kasih kepada komentator untuk saran.

Memperbaiki bug yang terkadang memasukkan spasi yang tidak perlu, misalnya untuk input "hello worlds sup".

    private static void t9(String s) {
        String[]t=",,abc,def,ghi,jkl,mno,pqrs,tuv,wxyz".split(",");String o="";int i,j,k,l=0;for(char c:s.toCharArray()){if(c==32){o+='0';l=0;}else for(j=0;j<10;j++){int n=t[j].indexOf(c);if(n>=0){if(j==l)o+=' ';for(k=0;k<n+1;k++)o+=j;l=j;}}}return o;
    }
wildcard
sumber
4
Cukup bagus, tetapi Anda perlu golf dan memberikan skor.
Hosch250
1
Saya berasumsi ini java. Bisakah Anda memasukkannya ke dalam pos Anda, seperti jawaban lainnya?
Digital Trauma
1
Satu golf: ganti t.lengthdengan10
Justin
Juga, mengingat yang idigunakan hanya untuk iterasi melalui String, hapus dan lakukan loop foreach:for(char c:s.toCharArray())
Justin
Juga, perubahan if(c==' '){o+='0';continue;}ke if(c==' ')o+='0';else{dan menambahkan sesuai dengan }.
Justin
1

CoffeeScript - 202 (210 - 8)

t9=(s)->
    t=[3,3,3,3,3,4,3,4];l=-1;r=""
    for c in s
        n="";d=c.charCodeAt(0)-96
        if c is ' '
            n=0
        else((n+=k+2 for x in[0...d];break)if d<=v;d-=v)for v,k in t
        r+=if n[0]is l[0] then " "+n else n
        l=n
    r
TimWolla
sumber
1

APL, 77 karakter

{{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('0',⍨(⌈3.1×y-⌊y)/¨⍕¨2+⌊y←7.99,⍨.315×⍳25)[⍵⍳⍨⎕UCS 96+⍳26]}

Penjelasan

  • 2+⌊y←7.99,⍨.315×⍳25atau, ungolfed, y←(0.315×⍳25),7.99 ◇ 2+⌊ysampel garis miring yang sesuai (y = 0,315 x) pada titik 1 hingga 25; garis dimiringkan sedemikian rupa sehingga lantai dari nilai-nilai y ini mengikuti pola berulang 000111 ... 777 kecuali untuk kelompok angka keenam 5555; angka ditambahkan pada akhir untuk mendapatkan 7 keempat, sehingga susunan akhir ditambah 2 adalah 22233344455566677778889999;
  • ⌈3.1×y-⌊y memperkuat perbedaan antara nilai-nilai y dan lantai mereka, sehingga langit-langit perbedaan memberikan pola 123123 ... dengan 4 pada digit terakhir dari dua grup dengan 4 digit;
  • '0',⍨( ... )/¨⍕¨ ...atau (( ... ) /¨ ⍕¨ ...),'0' menggunakan hasil terakhir untuk menggandakan digit dari yang sebelumnya, sehingga outputnya adalah deretan string "2" "22" "222" "3" "33" "333" ... dengan "7777" dan "yang benar" 9999 "pada tempatnya, dan" 0 "ditambahkan sampai akhir;
  • ⍵⍳⍨⎕UCS 96+⍳26atau (⎕UCS 96+⍳26)⍳⍵menghitung indeks dari setiap input char, di mana "a" adalah 1, "z" adalah 26, dan ruang (dan setiap char lainnya) adalah 27;
  • { ... }/( ... )[ ... ] mengambil hasil yang terakhir, indeks untuk masing-masing char input, untuk menerjemahkan masing-masing char ke dalam string masing-masing digit, kemudian menggabungkan string menggunakan fungsi dalam kurung kurawal;
  • {⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}atau {(⍺,(=/↑¨⍺,⍵)↑''),⍵}menambahkan setiap string baru ⍺ ke akumulator ⍵, menempatkan satu spasi hanya jika kedua argumen dimulai dengan karakter yang sama.

Contohnya

      {{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('0',⍨(⌈3.1×y-⌊y)/¨⍕¨2+⌊y←7.99,⍨.315×⍳25)[⍵⍳⍨⎕UCS 96+⍳26]} 'hello world'
 4433555 555666096667775553 
      {{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('0',⍨(⌈3.1×y-⌊y)/¨⍕¨2+⌊y←7.99,⍨.315×⍳25)[⍵⍳⍨⎕UCS 96+⍳26]} 'the quick brown fox jumped over the lazy dog'
 84433077884442225502277766696603336669905886733 3066688833777084433055529999 999036664 
Tobia
sumber
1

Python 155 150

Saya berharap saya lebih baik di XD ini. Definisi fungsi tidak dihitung. Level indentasi pertama adalah spasi, kedua adalah tab, dan 2 tab lainnya.

def p(s,l=None):
 for c in s:
    for i,g in enumerate(" ,,abc,def,ghi,jkl,mno,pqrs,tuv,wxyz".split(",")):
        if c in g:print"\b"+[""," "][l==i]+str(i)*(g.index(c)+1),;l=i
gcq
sumber
0

JavaScript 234

for(l=-1,r="",I=0,y=(s=prompt()).length;I<y;I++){c=s[I];n="";d=c.charCodeAt(0)-96;if(0>d)n=0;else for(k=J=0;J<8;k=++J){v="33333434"[k];if(d<=v){for(x=K=0;0<=d?K<d:K>d;x=0<=d?++K:--K)n+=k+2;break}d-=v}r+=n[0]==l[0]?" "+n:n;l=n}alert(r)

WallyWest
sumber
0

R 224

Saya yakin ada cara yang lebih baik untuk melakukan ini, jadi saya akan terus mengusahakannya.

a=strtoi(charToRaw(scan(,'',sep='\n')),16L)-95;a[a<0]=1;b=c(0,2,22,222,3,33,333,4,44,444,5,55,555,6,66,666,7,77,777,7777,8,88,888,9,99,999,9999)[a];c=append(b[-1],0)%%10;d=b%%10;b[c==d]=paste(b[c==d],'');paste(b,collapse='')
Gaffi
sumber