Telefon Çoklu Dokunma Yazımı


21

Google Code Challenge'dan ilham alındı :

Latin alfabesi 26 karakterden oluşur ve telefonlarda tuş takımında yalnızca on rakam bulunur. İstediğiniz karakterleri belirtmek için bir dizi tuşa basarak arkadaşınıza bir mesaj yazmayı kolaylaştırmak istiyoruz. Harfler, aşağıda gösterildiği gibi rakamlarla eşleştirilir. Örneğin B karakterini eklemek için, program 22'ye basacaktır. Aynı tuşa iki sırayla iki karakter eklemek için, kullanıcının tuşa ikinci kez basmadan önce duraklatması gerekir. Bir duraklama belirtmek için boşluk karakteri '' yazdırılmalıdır. Örneğin, 2 2 AA'yı gösterirken, 22 B'yi gösterir.

Her mesaj sadece küçük harf ve az karakterlerinden ve '' boşluk karakterlerinden oluşacaktır. Sıfıra basmak boşluk yayar.

görüntü tanımını buraya girin

Buradaki zorluk, giriş dizesini alan en küçük işlevi yazmak ve girdiyi dizge olarak üretmek veya stdout'a çıkarmak için gereken tuşa basma sırasını döndürmektir. En az bayt olan işlev kazanır.

Örnek Giriş / Çıkış

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

Diğer açıklamalar

  • Duraklatmalar gerekir sadece gerektiğinde eklenebilir ve bir boşluk '' olmalıdır.
  • Her mesaj sadece küçük harf ve az karakterlerinden ve '' boşluk karakterlerinden oluşacaktır . 0Boşlukları belirtmek için yazdırın .
  • Harici kütüphaneler yok.
  • İşlevinize yalnızca giriş dizesi geçirilebilir.
  • Diğer dilleri rekabetçi hale getirmek için, birincil işlev bildirimi sayılmaz ve diğer standart kitaplıkları içe aktarmaz. #includes, imports ve usings sayılmaz. Her şey yapar. Bu #defines ve yardımcı fonksiyonları içerir. Kafanız karışıksa , bu sorudaki 2. kurala bakınız .
  • Birden çok boşluk, bir boşluk arasında gerçekten duraklatmanız gerekmediğinden 00veya olduğu gibi belirtilebilir.0 0


Girişin küçük / büyük harf olduğunu varsayabilir miyiz?
Phil H

@PhilH " küçük harf az karakterleri ve boşluk karakterleri ''"
Danny

Parantezleri {}fonksiyon imzasının bir parçası olarak mı düşünüyorsunuz ? Örneğin, eğer kodum buysa function f(){alert('hi');}, alert('hi');veya karakterlerini saymalı mıyım {alert('hi');}?
ProgramFOX

2
Hatırladığım kadarıyla t9farklı işler: bir kelime almak için her tuşa bir kez tıklamanız gerekir.
18'de

Yanıtlar:


8

Yakut, 129 122 115 111 108 107 105

Golf ile bitti ...

Hata! Tamamen gereksiz yerleri kaldırmayı unuttum - düzeltildi ...

Peter Taylor sayesinde 2 karakter kurtardı.

Çevrimiçi sürüm

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

Açıklama:

alan sıra 96 ​​ile karaktere çevrilir

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

karakterler ilk önce bir dizi sayıyla eşleştirilir: - a - 2 - b - 22 - d - 3222 - s - 444333222

Bir regex ifadesi daha sonra ilk eşit haneler grubuyla eşleşir

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

dizi katıldı

*' ')

"digit space different_digit" oluşumundaki tüm boşluklar kaldırıldı

gsub /(\d) (?!\1)/,'\1'

1
% 100 doğru çalışmak için görünmüyor. Görüyorum ki 66666 üst üste 4 kez basmaya gerek kalmamalı.
Danny

Sabit olmalı, teşekkürler;)
David Herrmann

1
\2Bu son regex'in amacı ne ? Elbette ikinci grup sıfır genişlikte bir iddia mı?
Peter Taylor

Kesinlikle haklısın!
David Herrmann

6

REBEL - 154 110 103

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

Bu 'fonksiyon' stdin'den girdiyi kabul eder ve sonuçları stdout'a gönderir.

Test çalışır (tercümanı kurmanıza gerek kalmaz):

hi
44 444

hello world
4433555 555666096667775553

yes
999337777

kthxbai
558449922 2444

Bağlantılarınızın yüklenmesini asla bulamıyorum! :(
luser droog

4

JavaScript (124)

Firefox'ta çalıştırın.

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

4

GolfScript, 46 karakter

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

Her zamanki gibi, stdin'den girdi okur, stdout'a yazdırır. Çevrimiçi demoya bakın (konserve girişli).

Bu kodun girdi spesifikasyonunun (sadece küçük harfler ve boşluklar) çok katı bir şekilde yorumlanmasına dayandığını unutmayın: özellikle girdideki tüm yeni satırlar onu çökertir! Bu sorun, n-herhangi bir yeni satırı filtrelemek için koda hazırlanarak , iki ekstra ücret karşılığında düzeltilebilir .


3

C ++ - 365 karakter 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;}}}

Cevabımdakiyle aynı akıl yürütmeyi burada kullanır, sadece forher harfi uygun sayıda yazdırmak için döngüler kullanır .


Sen kullanabilirsiniz s[i]==32yerine s[i]==' '.
Alanın

@ ace Emin bir şey.
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

İşte 120 128 130 155'deki önceki çözümüm :

$_=<>;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

Testler:

hi
 44 444

hello world
 4433555 555666096667775553

jackdaws loves my big sphinx
 52 222553297777055566688833777706999022444 407777 744 4446699

3

VBA 220 253/258/219

FunctionBuradaki satır saymıyor :

İle 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

258 bir Fordöngü ile :

7/9 anahtar için düzeltmeler eklendi (teşekkürler, Danny).

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

kullanma Choose 219 :

İşlevselliği daha basit beri bu biriyle çalıştırmak istemediğini, ancak bir kısa kod ...

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

yesolmalı 999337777. Elde 10338senin işlevini kullanarak.
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++;}}

Kod golf oynamadaki ilk girişimim, önerileriniz için teşekkür ederim.


2

C ++ - 170 168 160

golfed:

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

Ungolfed

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

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

Ve biraz ağzı kapalı (evet, işte böyle yazıldı):

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

Biraz özyineleme, kara büyü ve adil miktarda biber tozu uygulayarak biraz kesebilirim.


2

Java - 243

Oldukça saf java çözümü. Önerileriniz için yorum yapanlara teşekkür ederiz.

Gereksiz boşluklar ekleyen bir hata düzeltildi, örneğin "merhaba dünyalar sup" girişi gibi.

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

4
Oldukça iyi, ama golf oynamak ve puan vermek gerekir.
Hosch250,

1
Bunun olduğunu varsayıyorum java. Bunu, diğer cevapların yaptığı gibi başınıza koyabilir misiniz?
Dijital Travma,

1
Bir golf: değiştirmek t.lengthile10
Justin

Ayrıca, isadece yineleme için kullanıldığını göz önünde bulundurarak , Stringonu kaldırın ve bir foreach döngüsü yapın:for(char c:s.toCharArray())
Justin

Ayrıca, değişim if(c==' '){o+='0';continue;}için if(c==' ')o+='0';else{ve uygun düzgün ekleyin }.
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

1

APL, 77 karakter

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

açıklama

  • 2+⌊y←7.99,⍨.315×⍳25veya, kurtulan, y←(0.315×⍳25),7.99 ◇ 2+⌊y1 ila 25 arasındaki noktalar üzerinde uygun bir şekilde eğilmiş bir çizgiyi (y = 0.315 x) örnekler; çizgi, bu y değerlerinin tabanının, 5555. basamakların altıncı grubu hariç, yinelenen modeli 000111 ... 777 izleyeceği şekilde eğilir; dördüncü 7'yi elde etmek için sonuna bir sayı eklenir, böylece son dizi artı 2 22233344455566677778889999;
  • ⌈3.1×y-⌊y bu y değerleri ve katları arasındaki farkı yükseltir, böylece farklılıkların tavanları 123123 ... modelini verir, böylece 4 basamaklı iki grubun son hanesinde 4 bulunur;
  • '0',⍨( ... )/¨⍕¨ ...veya (( ... ) /¨ ⍕¨ ...),'0' sonuncu sonucu, sonuçtan önceki haneleri çoğaltmak için kullanır, böylece çıktı "2" "22" "222" "3" "33" "333" ... doğru "7777" ve "ile dizelerin dizisidir. 9999 "yerinde ve sonuna eklenmiş" 0 ";
  • ⍵⍳⍨⎕UCS 96+⍳26veya (⎕UCS 96+⍳26)⍳⍵"a" 1, "z" nin 26 ve boşluk (ve diğer tüm karakterlerin) 27 olduğu her girdi karakterinin dizinini hesaplar;
  • { ... }/( ... )[ ... ] ikinci sonucu alır, her bir karakterin dizini, her karakterin ilgili sayı dizisine çevrilmesi için, daha sonra karakterleri parantez içindeki işleviyle birleştirir;
  • {⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}veya {(⍺,(=/↑¨⍺,⍵)↑''),⍵}her yeni dizgiyi ⍺ akümülatöre ⍵ ekler, sadece her iki argüman aynı karakter ile başlarsa, tek bir alana müdahale eder.

Örnekler

      {{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('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 

1

Python 155 150

Keşke bu XD'de daha iyi olsaydım. İşlev tanımı sayılmaz. İlk girinti seviyesi boşluk, ikincisi bir sekme ve üçüncü 2 sekmedir.

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

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)


0

R 224

Eminim bunu yapmanın daha iyi bir yolu vardır, bu yüzden üzerinde çalışmaya devam edeceğim.

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='')
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.