Pisownia na telefonie z wieloma opcjami

21

Inspirowany Google Code Challenge :

Alfabet łaciński zawiera 26 znaków, a telefony mają tylko dziesięć cyfr na klawiaturze. Chcemy ułatwić pisanie wiadomości do znajomego za pomocą sekwencji naciśnięć klawiszy w celu wskazania pożądanych znaków. Litery są odwzorowane na cyfry, jak pokazano poniżej. Na przykład, aby wstawić znak B, program nacisnąłby 22. Aby wstawić dwa znaki w sekwencji z tego samego klawisza, użytkownik musi przerwać przed ponownym naciśnięciem klawisza. Znak spacji „” powinien zostać wydrukowany, aby wskazać pauzę. Na przykład 2 2 oznacza AA, a 22 oznacza B.

Każda wiadomość będzie się składać tylko z małych liter az i spacji ''. Naciśnięcie zera powoduje emisję spacji.

wprowadź opis zdjęcia tutaj

Wyzwanie polega na napisaniu najmniejszej funkcji, która pobiera ciąg wejściowy i zwraca sekwencję naciśnięć klawiszy niezbędnych do wygenerowania wejścia jako ciągu lub wysłania go na standardowe wyjście. Funkcja, która jest najmniejszą liczbą bajtów, wygrywa.

Przykład wejścia / wyjścia

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

Inne wyjaśnienia

  • Przerwy należy dodawać tylko w razie potrzeby i muszą być spacją ''.
  • Każda wiadomość będzie się składać tylko z małych liter az i spacji ''. Drukuj, 0aby zaznaczyć spacje.
  • Brak bibliotek zewnętrznych.
  • Do funkcji można przekazać tylko ciąg wejściowy.
  • Aby inne języki były konkurencyjne, deklaracja funkcji podstawowej nie ma znaczenia, podobnie jak import innych standardowych bibliotek. #includes, imports i usings nie liczą się. Wszystko inne robi. Obejmuje to #definefunkcje pomocnicze i pomocnicze. Jeśli jesteś zdezorientowany, zobacz zasadę 2 w tym pytaniu.
  • Wiele spacji można oznaczyć jako 00lub, 0 0ponieważ tak naprawdę nie trzeba przerywać między spacjami
Danny
źródło
1
Powiązane z tym: codegolf.stackexchange.com/questions/21327/…
Victor Stafusa
Czy możemy założyć, że dane wejściowe są małe / duże?
Phil H
@PhilH „ małe litery az i spacje” ”
Danny
Czy uważasz, że nawiasy {}są częścią podpisu funkcji? Na przykład, jeśli mój kod to function f(){alert('hi');}, czy powinienem liczyć znaki alert('hi');lub {alert('hi');}?
ProgramFOX
2
O ile pamiętam t9działa inaczej: musisz kliknąć każdy klawisz raz, aby uzyskać słowo.
VisioN

Odpowiedzi:

8

Rubin, 129 122 115 111 108 107 105

Z golfem ...

Ups, całkowicie zapomniałem usunąć niepotrzebne spacje - naprawiono ...

Zaoszczędziłem 2 znaki dzięki Peterowi Taylorowi.

Wersja online

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

Wyjaśnienie:

spacja jest tłumaczona na znak za pomocą liczby porządkowej 96

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

znaki są najpierw mapowane na ciąg liczb: - od a do 2 - od b do 22 - od d do 3222 - od h do 444333222

wyrażenie regularne dopasowuje następnie pierwszą grupę równych cyfr

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

tablica jest połączona

*' ')

wszystkie spacje występujące w miejscu „cyfra spacja inny_cyfr” są usuwane

gsub /(\d) (?!\1)/,'\1'
David Herrmann
źródło
1
Nie działa poprawnie w 100%. Widzę, że 66666 nie powinno nigdy wymagać naciskania 4 razy z rzędu.
Danny
Należy naprawić, dzięki;)
David Herrmann
1
Jaki jest sens \2tego końcowego wyrażenia regularnego? Z pewnością druga grupa to twierdzenie o zerowej szerokości?
Peter Taylor
Masz całkowitą rację!
David Herrmann
6

REBEL - 154 110 103

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

Ta „funkcja” akceptuje dane wejściowe ze standardowego wejścia i wysyła wyniki do standardowego wejścia.

Testy działają (więc nie musisz instalować interpretera):

hi
44 444

hello world
4433555 555666096667775553

yes
999337777

kthxbai
558449922 2444
Kendall Frey
źródło
Nigdy nie mogę załadować twoich linków! :(
luser droog
4

JavaScript (124)

Uruchom w przeglądarce Firefox.

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

GolfScript, 46 znaków

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

Jak zwykle odczytuje dane wejściowe ze standardowego wejścia, drukuje na standardowe wyjście. Zobacz demo online (z wejściem w puszce).

Zauważ, że ten kod opiera się na bardzo ścisłej interpretacji specyfikacji wejściowej (tylko małe litery i spacje): w szczególności wszelkie znaki nowej linii na wejściu spowodują awarię! Ten problem można rozwiązać kosztem dwóch dodatkowych znaków, przygotowując n-kod, aby odfiltrować wszelkie znaki nowej linii.

Ilmari Karonen
źródło
3

C ++ - 365 znaków bez 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;}}}

Używa tego samego rozumowania, co moja odpowiedź tutaj , tylko używając forpętli, aby wypisać każdą literę odpowiednią liczbę razy.

Hosch250
źródło
Możesz użyć s[i]==32zamiast s[i]==' '. Wartość ASCII miejsca wynosi 32.
12205
@ace Pewna rzecz.
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

Oto moje poprzednie rozwiązanie w 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

Testy:

hi
 44 444

hello world
 4433555 555666096667775553

jackdaws loves my big sphinx
 52 222553297777055566688833777706999022444 407777 744 4446699
mniip
źródło
3

VBA 220 253/258/219

Nie licząc Functionlinii tutaj:

Z 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

Z Forpętlą 258 :

Dodano poprawki dla klucza 7/9 (dzięki, Danny), które dodały wiele znaków.

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

Za pomocą Choose 219 :

Nie chciałem uruchamiać tego, ponieważ ma on bardziej podstawową funkcjonalność, ale jest to krótszy 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
Gaffi
źródło
yespowinno być 999337777. Uzyskać 10338za pomocą funkcji.
Danny
3

C, 165 163 153 149 138 znaków

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

Moja pierwsza próba gry w golfa kodu, wszelkie sugestie są mile widziane.

użytkownik18204
źródło
2

C ++ - 170 168 160

Gra w golfa:

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

Nie golfił

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
źródło
2

C: 136 znaków

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

I nieco nie golfisty (tak, tak to zostało napisane):

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

Może uda mi się to trochę zmniejszyć, stosując rekursję, czarną magię i spore ilości chili w proszku.

Fors
źródło
2

Java - 243

Dość naiwne rozwiązanie Java. Dzięki komentatorom za sugestie.

Naprawiono błąd, który czasami wstawiał niepotrzebne spacje, np. Dla wpisu „cześć światu 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;
    }
dzika karta
źródło
4
Całkiem dobrze, ale musisz zagrać w golfa i podać wynik.
Hosch250
1
Zakładam, że tak jest java. Czy umiesz to umieścić w swoim nagłówku, tak jak inne odpowiedzi?
Digital Trauma
1
Jeden golf zamienić t.lengthz10
Justin
Ponadto, biorąc pod uwagę, że ijest używany tylko do iteracji przez String, usuń go i wykonaj pętlę foreach:for(char c:s.toCharArray())
Justin
Zmień if(c==' '){o+='0';continue;}także if(c==' ')o+='0';else{i dodaj odpowiedni }.
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
źródło
1

APL, 77 znaków

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

Wyjaśnienie

  • 2+⌊y←7.99,⍨.315×⍳25lub, bez golfa, y←(0.315×⍳25),7.99 ◇ 2+⌊ypobiera próbki odpowiednio nachylonej linii (y = 0,315 x) w punktach od 1 do 25; linia jest przechylona w taki sposób, że dolna część tych wartości y jest zgodna z powtarzającym się wzorem 000111 ... 777, z wyjątkiem szóstej grupy cyfr 5555; na końcu dołączana jest liczba, aby uzyskać czwartą 7, tak że końcowa tablica plus 2 to 22233344455566677778889999;
  • ⌈3.1×y-⌊y zwiększa różnicę między tymi wartościami y a ich podłogami, tak że sufity różnic dają wzór 123123 ... z 4 na ostatnich cyfrach z dwóch grup 4 cyfr;
  • '0',⍨( ... )/¨⍕¨ ...lub (( ... ) /¨ ⍕¨ ...),'0' wykorzystuje ten drugi wynik do duplikowania cyfr z pierwszego, tak aby wynik był tablicą ciągów „2” „22” „222” „3” „33” „333” ... z poprawnymi „7777” i „ 9999 ”na miejscu, a na końcu dołączone jest„ 0 ”;
  • ⍵⍳⍨⎕UCS 96+⍳26lub (⎕UCS 96+⍳26)⍳⍵oblicza indeks każdego wejściowego znaku, gdzie „a” wynosi 1, „z” wynosi 26, a spacja (i każdy inny znak) wynosi 27;
  • { ... }/( ... )[ ... ] bierze ten ostatni wynik, indeks dla każdego wejściowego znaku, w celu przetłumaczenia każdego znaku na odpowiedni ciąg cyfr, a następnie konkatenuje ciągi znaków za pomocą funkcji w nawiasach klamrowych;
  • {⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}lub {(⍺,(=/↑¨⍺,⍵)↑''),⍵}dołącza każdy nowy ciąg ⍺ do akumulatora ⍵, wstawiając pojedynczą spację tylko wtedy, gdy oba argumenty zaczynają się od tego samego znaku.

Przykłady

      {{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('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
źródło
1

Python 155 150

Chciałbym być lepszy na tym XD. Definicja funkcji nie jest liczona. Pierwszy poziom wcięcia to spacja, drugi to tabulator, a trzeci 2 tabulatory.

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
źródło
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
źródło
0

R 224

Jestem pewien, że jest lepszy sposób, aby to zrobić, więc będę dalej nad tym pracował.

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
źródło