Ortografía multitáctil del teléfono

21

Inspirado por el Google Code Challenge :

El alfabeto latino contiene 26 caracteres y los teléfonos solo tienen diez dígitos en el teclado. Nos gustaría que sea más fácil escribir un mensaje a su amigo usando una secuencia de pulsaciones de teclas para indicar los caracteres deseados. Las letras se asignan a los dígitos como se muestra a continuación. Para insertar el carácter B, por ejemplo, el programa presionaría 22. Para insertar dos caracteres en secuencia desde la misma tecla, el usuario debe hacer una pausa antes de presionar la tecla por segunda vez. El carácter de espacio '' debe imprimirse para indicar una pausa. Por ejemplo, 2 2 indica AA mientras que 22 indica B.

Cada mensaje constará solo de caracteres en minúscula az y de espacio ''. Al presionar cero se emite un espacio.

ingrese la descripción de la imagen aquí

Su desafío es escribir la función más pequeña que toma la cadena de entrada y devuelve la secuencia de pulsaciones de teclas necesarias para producir la entrada como cadena o salida a stdout. La función que es la menor cantidad de bytes gana.

Ejemplo de entrada / salida

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

Otras aclaraciones

  • Pausas debe solamente ser añadido cuando sea necesario y debe ser un espacio ''.
  • Cada mensaje constará solo de caracteres en minúscula az y de espacio ''. Imprimir 0para significar espacios.
  • No hay bibliotecas externas.
  • Solo se puede pasar la cadena de entrada a su función.
  • Para que otros idiomas sean competitivos, la declaración de la función principal no cuenta y tampoco importa otras bibliotecas estándar. #includes, imports y usings no cuentan. Todo lo demás lo hace. Esto incluye #definesy funciones auxiliares. Vea la regla 2 en esta pregunta si está confundido.
  • Múltiples espacios se pueden denotar como 00o 0 0ya que realmente no tiene que hacer una pausa entre un espacio
Danny
fuente
1
Relacionado con esto: codegolf.stackexchange.com/questions/21327/…
Victor Stafusa
¿Podemos suponer que la entrada es minúscula / mayúscula?
Phil H
@PhilH " caracteres en minúscula az y caracteres espaciales ''"
Danny
¿Considera que los corchetes son {}parte de la firma de la función? Por ejemplo, si mi código es function f(){alert('hi');}, ¿debo contar los caracteres de alert('hi');o {alert('hi');}?
ProgramFOX
2
Hasta donde recuerdo t9funciona de manera diferente: tienes que hacer clic en cada tecla una vez para obtener una palabra.
VisioN

Respuestas:

8

Rubí, 129 129 122 115 111 108 107 105

Hecho con el golf ...

¡Vaya! Olvidé por completo eliminar espacios innecesarios. Se corrigió ...

Ahorró 2 caracteres gracias a Peter Taylor.

Versión en línea

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

Explicación:

el espacio se traduce al char con el ordinal 96

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

los caracteres se asignan primero a series de números: - a a 2 - b a 22 - d a 3222 - ha 444333222

una expresión regex luego coincide con el primer grupo de dígitos iguales

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

la matriz está unida

*' ')

todos los espacios en las ocurrencias de "digit space different_digit" se eliminan

gsub /(\d) (?!\1)/,'\1'
David Herrmann
fuente
1
No parece funcionar al 100% correcto. Veo que 66666 no debería necesitar presionarse 4 veces seguidas.
Danny
Debería arreglarse, gracias;)
David Herrmann
1
¿Cuál es el punto de \2esa expresión regular final? ¿Seguramente el segundo grupo es una afirmación de ancho cero?
Peter Taylor
¡Estás absolutamente en lo correcto!
David Herrmann
6

REBELDE - 154 110 103

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

Esta 'función' acepta la entrada de stdin y envía resultados a stdout.

Pruebas de ejecución (para que no tenga que instalar el intérprete):

hi
44 444

hello world
4433555 555666096667775553

yes
999337777

kthxbai
558449922 2444
Kendall Frey
fuente
¡Nunca puedo cargar tus enlaces! :(
luser droog
4

JavaScript (124)

Ejecutar en Firefox

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

GolfScript, 46 caracteres

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

Como de costumbre, lee la entrada de stdin, imprime en stdout. Ver demostración en línea (con entrada enlatada).

Tenga en cuenta que este código se basa en una interpretación muy estricta de la especificación de entrada (solo letras minúsculas y espacios): en particular, cualquier nueva línea en la entrada lo bloqueará. Este problema se puede solucionar, a costa de dos caracteres adicionales, anteponiendo n-al código para filtrar cualquier nueva línea.

Ilmari Karonen
fuente
3

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

Utiliza el mismo razonamiento que mi respuesta aquí , solo usando forbucles para generar cada letra el número apropiado de veces.

Hosch250
fuente
Puedes usar en s[i]==32lugar de s[i]==' '. El valor ASCII del espacio es 32.
user12205
@ace Claro que sí.
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

Aquí está mi solución anterior en 120128130155 :

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

Pruebas:

hi
 44 444

hello world
 4433555 555666096667775553

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

VBA 220 253/258/219

Sin contar Functionlíneas aquí:

Con 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

Con un Forbucle 258 :

Se agregaron correcciones para la clave 7/9 (gracias, Danny), que agregó muchos caracteres.

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

Usando Choose 219 :

No quería correr con este, ya que es más básico en funcionalidad, pero es el código más corto ...

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
fuente
yesdebería ser 999337777. Me pongo a 10338usar tu función.
Danny
3

C, 165 163 153 149 138 caracteres

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

Mi primer intento de golf de código, cualquier sugerencia es apreciada.

usuario18204
fuente
2

C ++ - 170 168 160

Golfizado:

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

Sin golf

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
fuente
2

C: 136 caracteres

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

Y un poco descuidado (sí, así es como se escribió):

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

Podría reducirlo un poco aplicando algo de recursión, magia negra y una buena cantidad de chile en polvo.

Fors
fuente
2

Java - 243

Solución bastante ingenua de Java. Gracias a los comentaristas por sus sugerencias.

Se corrigió un error que a veces insertaba espacios innecesarios, por ejemplo, para la entrada "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;
    }
comodín
fuente
44
Bastante bien, pero necesitas jugar golf y proporcionar la puntuación.
Hosch250
1
Supongo que esto es java. ¿Puedes poner eso en tu título, como hacen las otras respuestas?
Digital Trauma
1
Un golf: reemplazar t.lengthcon10
Justin
Además, teniendo en cuenta que isolo se usa para iterar String, eliminarlo y hacer un ciclo foreach:for(char c:s.toCharArray())
Justin
Además, el cambio if(c==' '){o+='0';continue;}de if(c==' ')o+='0';else{y añadir la adecuada }.
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
fuente
1

APL, 77 caracteres

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

Explicación

  • 2+⌊y←7.99,⍨.315×⍳25o, sin golf, y←(0.315×⍳25),7.99 ◇ 2+⌊ymuestrea una línea inclinada adecuadamente (y = 0.315 x) en los puntos del 1 al 25; la línea está inclinada de tal manera que el piso de estos valores y sigue el patrón repetitivo 000111 ... 777, excepto el sexto grupo de dígitos 5555; se agrega un número al final para obtener el cuarto 7, de modo que la matriz final más 2 es 22233344455566677778889999;
  • ⌈3.1×y-⌊y amplifica la diferencia entre esos valores y y sus pisos, de modo que los límites máximos de las diferencias dan el patrón 123123 ... con un 4 en los últimos dígitos de los dos grupos de 4 dígitos;
  • '0',⍨( ... )/¨⍕¨ ...o (( ... ) /¨ ⍕¨ ...),'0' utiliza el último resultado para duplicar dígitos del primero, de modo que la salida es la matriz de cadenas "2" "22" "222" "3" "33" "333" ... con el "7777" correcto y " 9999 "en su lugar y un" 0 "agregado al final;
  • ⍵⍳⍨⎕UCS 96+⍳26o (⎕UCS 96+⍳26)⍳⍵calcula el índice de cada carácter de entrada, donde "a" es 1, "z" es 26 y el espacio (y todos los demás caracteres) es 27;
  • { ... }/( ... )[ ... ] toma el último resultado, el índice de cada carácter de entrada, para traducir cada carácter a la cadena de dígitos correspondiente, luego concatena las cadenas utilizando la función entre llaves;
  • {⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}o {(⍺,(=/↑¨⍺,⍵)↑''),⍵}agrega cada nueva cadena ⍺ al acumulador ⍵, interponiendo un solo espacio solo si ambos argumentos comienzan con el mismo carácter.

Ejemplos

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

Python 155 150

Desearía ser mejor en este XD. Definición de función no contada. El primer nivel de sangría es un espacio, el segundo es una pestaña y el tercero 2 pestañas.

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
fuente
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
fuente
0

R 224

Estoy seguro de que hay una mejor manera de hacerlo, así que seguiré trabajando en ello.

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
fuente