Crea un teclado T9

12

Esta pregunta solicita una funcionalidad de coincidencia de diccionario T9 que es un problema muy interesante. Pero T9 tiene otra forma de escribir y es escribir caracteres por caracteres. NO necesitaría un diccionario para implementar este teclado.

Aquí está el mapa de teclas de un teclado T9 si lo olvidó:

+-------+-------+-------+
|   1   |   2   |   3   |
|  .?!  |  ABC  |  DEF  |
+-------+-------+-------+
|   4   |   5   |   6   |
|  GHI  |  JKL  |  MNO  |
+-------+-------+-------+
|   7   |   8   |   9   |
| PQRS  |  TUV  |  WXYZ |
+-------+-------+-------+
|   *   |   0   |   #   |
|   ←   | SPACE |   →   |
+-------+-------+-------+

Cómo funciona T9

Para escribir un carácter con T9, debe presionar la tecla numérica que representa los ntiempos de ese carácter . nes el orden de ese personaje escrito en esa tecla. Los números son el último carácter que puede escribir para cada tecla. Por ejemplo, para escribir Bpresiono 2dos veces, o para escribir 5presiono 5cuatro veces. Para terminar de escribir este personaje, presiono #. *es simplemente retroceso. En nuestra versión de teclado no hay mayúsculas.

Ejemplos de entrada y salida:

8#99999#055#33#999#22#666#2#777#3# → T9 KEYBOARD

Explicación:

  • 8selecciona Ty #pasa al siguiente personaje
  • 99999selecciona el último carácter de la 9clave que es 9y #pasa al siguiente personaje
  • 0 inserta un espacio
  • 33selecciona el segundo carácter de la 3clave que es Ky se #mueve al siguiente carácter
  • Y así...

Reglas

Su función o programa debe aceptar una cadena que represente las pulsaciones de teclas T9. La salida es el texto resultante de esas pulsaciones de teclas, como se describe anteriormente.

Este es un código básico de golf, por lo que el ganador es el más corto en bytes, y se aplican reglas / lagunas estándar.

Mohsen
fuente
¿La bonificación no tiene ningún efecto en la puntuación? ¿Por qué iría por eso?
Optimizador
2
Además, su ejemplo T9 KEYBOARDes completamente incorrecto. Eso se leeT9 JEYBARD
Optimizer
1
@Mohsen generalmente, las bonificaciones en el código de golf restarán una cantidad fija de la puntuación. Tendrás que averiguar cuánto es razonable. para el primer bono, probablemente no más de 10 o 20 bytes. El segundo bono, ni siquiera lo entiendo. si doy la secuencia de pulsaciones de teclas como una cadena a la función, ¿cómo habría algún tipo de tiempo entre pulsaciones de teclas? Creo que una ventaja más razonable sería permitir la omisión #si los botones consecutivos son diferentes de todos modos. Dicho esto: sin ese bono, ¿qué pasaría si #se omite?
Martin Ender
1
Debe agregar un posible beneficio de conteo de bytes para estos bonos. Los bonos son opcionales, pero parece que pide todas las respuestas para implementar los bonos como si fueran obligatorios. Por favor, borre el tono, si son obligatorios, muévalos a las reglas, si no lo son, no solicite todas las respuestas para implementar los bonos. Esperaré por un par de horas su respuesta antes de votar para cerrar como no está claro.
Optimizador
2
No hay respuesta incluso después de 18 horas. Votación para cerrar como poco claro.
Optimizador

Respuestas:

5

CJam, 109 94 bytes ( bono)

Una solución muy ingenua y larga.

q'#/);{__'*-:A-,_g{){;}*A_}*;'0/{_,g{)~".?~1"a'[,65>292994 5b{/(X):X+\s}%+1:Xm>=\,=}*}%S*1/~}%

Este es un programa completo, aunque una función tendrá la misma duración.

La entrada entra en STDIN

Ejemplo:

8#99999#055#33#999#***22#666#2#777#3#

Salida:

T9 BOARD

Pruébalo en línea aquí

Optimizador
fuente
¿Puedes hacer que funcione para el primer bono?
Mohsen
3
@Mohsen ¡No hasta que haya un beneficio real de obtener bonificación! Digamos, una reducción del 25% en la longitud del código en la puntuación final.
Optimizador
2

JavaScript ES6, 220-10 = 210 178 bytes

Como parte del CMC de Helka , superé mi primer desafío.

n=>(g=n=>n==(k=n.replace(/.\*/,""))?n:g(k))(n.match(/(\d)\1*|\*/g).map(e=>e<"0"?e:(a=" |.?!|ABC|DEF|GHI|JKL|MNO|PQRS|TUV|WXYZ".split`|`[+e[0]]+e[0])[~-e.length%a.length]).join``)

Resultados de muestra:

> f=n=>(g=n=>n==(k=n.replace(/.\*/,""))?n:g(k))(n.match(/(\d)\1*|\*/g).map(e=>e<"0"?e:(a=" |.?!|ABC|DEF|GHI|JKL|MNO|PQRS|TUV|WXYZ".split`|`[+e[0]]+e[0])[~-e.length%a.length]).join``)
[Function]
> f("8#99999#055#33#999#***22#666#2#777#3#")
'T9 BOARD'
> f("8#44#33#0#999#*77#88#444#222#55#0#22#777#666#9#66#0#333#666#99#0#5#88#6#7#7777#0#666#888#33#777#0#8#44#33#0#555#2#99#*9999#999#0#3#666#4#111#")
'THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG!'
> f("8#99999#055#33#999#***22#666#2#777#3#")
'T9 BOARD'

Explicación

(g=n=>n==(k=n.replace(/.\*/,""))?n:g(k))

Esto implementa el reemplazo recursivo, reemplazando todos los caracteres seguidos por *hasta que no queden *s.

n.match(/(\d)\1*|\*/g)

Esto coincide con todas las ejecuciones de dígitos consecutivos, o *s.

a=" |.?!|ABC|DEF|GHI|JKL|MNO|PQRS|TUV|WXYZ".split`|`[+e[0]]+e[0]

Esto crea el diccionario deseado, obtiene la parte codificada de la cadena grande y luego le agrega el dígito deseado.

a[~-e.length%a.length]

Esto obtiene el carácter, ala longitud del módulo .

.join``

Esto prepara la cadena para el procesamiento y eliminación de *s.

Conor O'Brien
fuente
1
¿Puedes hacer que funcione con el primer bono?
Mohsen
@Mohsen Sí, y eso realmente podría ayudarlo. Trabajaré en ello hoy y mañana.
Conor O'Brien
Al menos, no anuncie una puntuación incorrecta ya que la respuesta ni siquiera cumple con las especificaciones.
Optimizador
@Mohsen Ahora está trabajando con el primer bono.
Conor O'Brien
t("2#2");da en Blugar de AA. Intenta combinar cualquiera en #lugar de eliminarlos.
Titus
1

Pitón, 167 157 151 bytes

(no admite '*')

Nada especial. Uso regex para convertir la entrada en una lista, luego hago un bucle de las entradas. Utilizo el primer carácter y la longitud de cada entrada para buscarlo en una lista de búsqueda:

def f(i):
  import re
  t9 = [" 0",".?!1","ABC2","DEF3","GHI4","JKL5","MNO6","PQRS7","TUV9","WXYZ9"]
  i = re.findall(r'[1-9]+|0+',i)
  answer = []
  for j in i:
    answer = answer + [t9[int(j[0])][len(j)-1]]
  return ''.join(answer)

Después de jugar al golf se ve así:

import re;m=lambda i:"".join([" 0,.?!1,ABC2,DEF3,GHI4,JKL5,MNO6,PQRS7,TUV9,WXYZ9".split(",")[int(j[0])][len(j)-1] for j in re.findall(r'[1-9]+|0+',i)])

Sin bonificaciones (todavía). No sé cómo implementaría el primer bono en regex. El segundo bono agregaría muchos bytes ya que los elementos de búsqueda no son del mismo tamaño. Realmente no entiendo el tercer bono.

Def
fuente
1

Perl 5: 106 (código 104 + 2 banderas)

Modificado para manejar eliminaciones.

#!perl -lp
s/((\d)\2*)#?|./chr$2*5+length$1/ge;y//d 0-3.?!1 ABC2 DEF3 GHI4 JKL5 MNO6 P-S7TUV8 W-Z9/c;1while s/.?d//

Uso:

perl t9.pl <<<'8#99999#055#33#999#22#666#2#777#3#'
perl t9.pl <<<'899999055339992266627773'

Perl 5: 88 (código 86 + 2 banderas)

Versión anterior sin eliminación de estrellas.

#!perl -lp
s/(\d)(\1*)#?/chr$1*5+length$2/ge;y// 0-3.?!1 ABC2 DEF3 GHI4 JKL5 MNO6 P-S7TUV8 W-Z9/c
nutki
fuente
@Optimizer lo intentó, y de hecho no funciona con *. Sin embargo, ¿es realmente necesario? Dice: "Tenga en cuenta que puede incluir * para retroceso ..."
Def
Ya que no es parte de la bonificación. Es una regla obligatoria.
Optimizador
Habiendo dicho eso. la pregunta no está clara sobre qué es una regla y qué es un bono. Pedí aclaraciones a OP hace varias horas. Si no hay respuesta, votaré para cerrar esta pregunta como poco clara.
Optimizador
Lo siento, me engañaron porque las respuestas actuales en los idiomas que puedo leer tampoco son compatibles *.
nutki
Si te refieres a mi respuesta de Python, tienes razón. Interpreté mal la pregunta.
Def
1

AWK 211 bytes (con las bonificaciones)

{split(".?!1-ABC2-DEF3-GHI4-JKL5-MNO6-PQRS7-TUV8-WXYZ9- 0",k,"-");split($0"#",a,"");while(1+(b=a[++i])){if(b==p)++c;else{for(g in k)if(p==substr(k[g],l=length(k[g])))printf(substr(k[g],1+((c-1)%l),1));c=1;p=b}}}

Este es un programa completo que lee la entrada de stdin. Sería más eficiente no volver a dividir el teclado para cada línea, pero alargaría el guión.

Además, si la tecla "0" fuera algo más que 0, el script sería 4 bytes más corto, pero eso es parte del juego: o)

LeFauve
fuente
1

C (245 bytes)

#define M "8#44#33#0#999#*77#88#444#222#55#0#22#777#666#9#66#0#333#666#99#0#5#88#6#7#7777#0#666#888#33#777#0#8#44#33#0#555#2#99#*9999#999#0#3#666#4#111#"

#include<stdio.h>
char K[][4]={" ",".?!","ABC","DEF","GHI","JKL","MNO","PQRS","TUV","WXYZ"},I[]=M;int       
i,j,k,r;main(){for(;I[i];++i){if(I[i]=='#')I[j++]=K[k][--r],r=k=0;else               
if(I[i]=='*')j?--j:0;else if(!r++)k=I[i]-'0';}I[j]=0;printf("%s\n",I);}

Salida

THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG!

Explicación

El recuento de bytes no incluye la cadena de entrada dada en el primero #define.

Utilizo una matriz bidimensional como la tabla de búsqueda de qué personaje imprimir. El programa lee en caracteres delimitados por '#'.

Para cada grupo, el número de entrada determina el índice de matriz de primera dimensión, y el número de repeticiones del número de entrada determina el índice de matriz de segunda dimensión. Los '*'mueve hacia atrás el índice de la matriz de la cadena de salida a fin de sobrescribir la letra anterior.

Entonces la cadena de entrada 44#(1 repetición de '4') se traduce a la tabla de búsqueda K[4][1], que es el carácter H.


Versión sin golf

#define INPUT "8#44#33#0#999#*77#88#444#222#55#0#22#777#666#9#66#0#333#666#99#0#5#88#6#7#7777#0#666#888#33#777#0#8#44#33#0#555#2#99#*9999#999#0#3#666#4#"

#include<stdio.h>

static const char keyboard[10][4] = {" ", ".?!", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ"};

int main(void)
{
  char input[] = INPUT;
  char output[256];
  int i, j;
  int key = 0;
  int reps = 0;

  for (i = j = 0; input[i] != '\0'; ++i) {
    switch (input[i]) {
    case '#':
      output[j] = keyboard[key][reps - 1];
      ++j;
      reps = key = 0;
      break;
    case '*':
      if (j > 0) --j;
      break;
    default:
      if (reps == 0)  {
        key = (int)input[i] - '0';
      }
      ++reps;
      break;
    }
  }

  output[j] = '\0';
  printf("%s\n", output);

  return(0);
}
musaritmia
fuente
1

Ruby 254 , 248 , 229 bytes

Golfizado:

n=->(t){r,m,b=[]," _.?!1_ABC2_DEF3_GHI4_JKL5_MNO6_PQRS7_TUV8_WXYZ9_*_0_#".split("_"),nil;t.scan(/((.)\2*)/){|l,_|(!(l=~/\#/)?(l=~/\*/?(r.pop l.size):(l=="00"?r<<(b ? "0 ":" 0"):(c=m[l[0].to_i];r<<c[l.size%c.size-1]))):b=l)};r*""}

Sin golf:

def t9totext(t)
  bonq = nil
  numpad = [" ",".?!1","ABC2","DEF3","GHI4","JKL5","MNO6","PQRS7","TUV8","WXYZ9","*","0","#"]

  r = []
  t.scan(/((.)\2*)/) do |l, _|
    if !(l =~ /\#/)
      if l =~ /\*/
        r.pop(l.size)
      elsif l == "00"
        r << (bonq ? "0 " : " 0")
      else
        c = numpad[l[0].to_i]
        r << c[l.size % c.size - 1]
      end
    else
      bonq = l
    end
  end
  r.join
end

Todas estas especificaciones deberían tener éxito:

  it "outputs the correct word" do
    expect(n.call('8#99999#055#33#999#22#666#2#777#3#1')).to eq("T9 KEYBOARD.")
    expect(n.call('4433555#55566609666666677755533*3111')).to eq("HELLO WORLD!")
    expect(n.call('7##222#222**7#222#4')).to eq('PPCG')
    expect(n.call('00#0#00')).to eq(' 0 0 ')
  end

La 0 0respuesta se parece un poco a una solución hacky. Lo investigaré cuando tenga tiempo.

Biketire
fuente
0

PHP, 183-10 = 173 bytes

Todas las versiones toman datos del argumento de la línea de comando; llamar con php -r '<code>' <string>.

Nota : Todas las versiones lanzan una advertencia si la entrada comienza con *.
Anteponga $o=[];al código para eliminar esa falla.

preg_match_all("%(\d)\1*|\*%",$argv[1],$m);foreach($m[0]as$w)if("*"==$w)array_pop($o);else$o[]="- 0   .?!1 ABC2 DEF3 GHI4 JKL5 MNO6 PQRS7TUV8 WXYZ9"[$w[0]*5+strlen($w)];echo join($o);
  • no necesita etiquetas hash
  • falla si se presiona una tecla con demasiada frecuencia

210-10 - ?? = ??? bytes

$a=[" 0",".?!1",ABC2,DEF3,GHI4,JKL5,MNO6,PQRS7,TUV8,WXYZ9];preg_match_all("%(\d)\1*|\*%",$argv[1],$m);foreach($m[0]as$w)if("*"==$w)array_pop($o);else$o[]=$a[$w[0]][strlen($w)%strlen($a[$w[0]])-1];echo join($o);
  • no necesita etiquetas hash
  • gira si se presiona una tecla con demasiada frecuencia

181 bytes, sin bonificación

preg_match_all("%\d+#|\*%",$argv[1],$m);foreach($m[0]as$w)if("*"==$w)array_pop($o);else$o[]=" 0   .?!1 ABC2 DEF3 GHI4 JKL5 MNO6 PQRS7TUV8 WXYZ9"[$w[0]*5+strlen($w)-2];echo join($o);

Descompostura

Las versiones "sin etiquetas hash" dividen la cadena en (racha de números iguales) y (asterisco) y olvidan todo lo demás. La versión sin bonificación toma (racha de números seguidos de #) y (asterisco).

Luego recorra las coincidencias: si se encuentra un '*', elimine el último elemento de la matriz de resultados.

La diferencia entre las versiones está en la elseparte:

  • sin versión de bonificación: desplace la cadena del mapa a (clave * 5), luego agregue (pulsaciones de teclas = longitud de palabra-1) -1, agregue caracteres de esa posición al resultado.
  • versión simple sin etiqueta: casi lo mismo, pero: (pulsaciones de tecla = longitud de palabra); agregó un carácter a la cadena del mapa para deshacerse del otro -1.
  • versión giratoria: tome el elemento (clave) de la matriz del mapa, agregue el carácter (pulsaciones de teclas% longitud del elemento-1) de ese elemento para obtener el resultado.
Titus
fuente
0

JavaScript, 147 bytes

La respuesta de Conor se arregló con la expresión regular de mi respuesta de PHP y bajó el nivel.

t=i=>i.match(/(\d)\1*|\*/g).map(w=>(" 0~.?!1~ABC2~DEF3~GHI4~JKL5~MNO6~PQRS7~TUV8~WXYZ9".split`~`[w[0]]||"*")[w.length-1]).join``.replace(/.\*/g,"")

Descompostura

t=i=>i
    .match(/(\d)\1*|\*/g)   // split input to streaks of equal numbers and single `*`
    .map(w=>                // replace each item with ...
                            // .. take string depending on the digit
        (" 0~.?!1~ABC2~DEF3~GHI4~JKL5~MNO6~PQRS7~TUV8~WXYZ9".split`~`[w[0]]
        ||"*")              // .. ("*" for not a digit)
        [w.length-1]        // -> the (item length)th character of that string
    )
    .join``                 // join without delimiter
    .replace(/.\*/g,"")     // and recursively remove every (letter,asterisk) combination

versión giratoria, 158 bytes

agregado s=para recordar la cadena y %s.lengthrotar.

t=i=>i.match(/(\d)\1*|\*/g).map(w=>(s=" 0~.?!1~ABC2~DEF3~GHI4~JKL5~MNO6~PQRS7~TUV8~WXYZ9".split`~`[w[0]]||"*")[w.length%s.length-1]).join``.replace(/.\*/g,"")
Titus
fuente