¿Cuántas veces debo presionar esto?

24

Todos estamos acostumbrados al teclado del teléfono de la vieja escuela, ¿verdad? Como referencia, así es como se ve:

Phone Keybad


Dada una Cadena que consiste solo en letras minúsculas ASCII y espacios individuales , su tarea es devolver el número de toques que uno debe hacer para escribir la Cadena completa con un teclado de teléfono como el de arriba.

Para aquellos que no están familiarizados con esto, así es como funciona:

  • La clave con el dígito 2, por ejemplo, también tiene la cadena abcescrita en ella. Para escribir a, debe presionar esta tecla una vez, para bpresionar dos veces y para cpresionar tres veces.

  • Para letras consecutivas que están en la misma tecla, debe esperar 1 segundo antes de presionar nuevamente. Por lo tanto, si desea escribir cb, debe presionar 3 veces para c, esperar un segundo y luego presionar dos veces para b, así que todavía 5 toques.

  • Lo mismo se aplica para todas las demás teclas, excepto para un solo espacio, que solo requiere 1 pulsación. También tenga en cuenta que las teclas 7y 9tienen cuatro letras en ellas. Se aplica el mismo algoritmo, la única diferencia es el número de letras. Las cadenas correspondientes a cada tecla se pueden encontrar en la imagen de arriba (pero en minúsculas), o en la siguiente lista, que contiene todos los caracteres que puede recibir:

    "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz", " "
    

Casos de prueba

Entrada -> Salida (Explicación)

"" -> 0 (no se debe tocar nada)
"agua" -> 8 ("w, a, t" cada uno requiere 1 toque (en las teclas 9, 2 y 8), "e" requiere 2 toques (en la tecla 3), "r" requiere 3 toques (en la tecla 7 ), 1 + 1 + 1 + 2 + 3 = 8)
"jabón" -> 9 (4 + 3 + 1 + 1)
"candela" -> 13 (3 + 1 + 2 + 1 + 2 + 3 + 1)
"código golf" -> 20 (3 + 3 + 1 + 2 + 1 (para el espacio) + 1 + 3 + 3 + 3)
"rey de la colina" -> 33 (2 + 3 + 2 + 1 + 1 + 3 + 3 + 1 + 1 + 2 + 2 + 1 + 2 + 3 + 3 + 3)

Especificaciones

  • Se aplican las reglas estándar de E / S y las lagunas predeterminadas.

  • Solo puede ingresar datos en el tipo de cadena nativo de su idioma. La salida puede ser un entero o una representación de cadena de ese entero.

  • Este es el , gana la respuesta más corta en todos los idiomas .

Sr. Xcoder
fuente
2
Creo que esta sería una pregunta más interesante si hicieras 1 pulsación por segundo, y tuvieras que esperar 1 segundo, y contaras segundos en lugar de pulsaciones.
Yakk
@Yakk Eso sería demasiado complicado
Sr. Xcoder
@ Mr.Xcoder ¿Estás seguro? He visto a los asistentes de código aquí hacer cosas imposibles en menos espacio que un tweet.
J_F_B_M

Respuestas:

11

JavaScript (ES6) 77 66 64 60 bytes

(Ahorré algunos bytes gracias a @Johan Karlsson y @Arnauld).

s=>[...s].map(l=>s=~~s+2+'behknquxcfilorvysz'.search(l)/8)|s

Rick Hitchcock
fuente
(s,t=0)=>[...s].map(l=>t+=(1+'behknquxcfilorvysz'.indexOf(l)/8|0)+1)&&tpor 71 bytes
Johan Karlsson
Gracias, @JohanKarlsson, ¡pensé lo mismo mientras estaba en la ducha! Encontró otra optimización para reducir 5 bytes más.
Rick Hitchcock
66
He encontrado una solución puramente aritmética para 71 bytes: f=s=>[...s].map(c=>t+=((c=parseInt(0+c,36))>23?c+3:c&&~-c%3)%7%4+1,t=0)|t.
Neil
1
@Neil, aunque puede que no sea más corto, sin duda es más inteligente.
Rick Hitchcock
1
@Neil Deberías publicarlo.
Sr. Xcoder
7

05AB1E , 29 26 25 bytes

ð¢svA•22ā₂•S£ð«øðδKy.åƶOO

Pruébalo en línea!

Explicación

ð¢                         # count spaces in input
  sv                       # for each char y in input
    A                      # push the lowercase alphabet
     •22ā₂•S               # push the base-10 digit list [3,3,3,3,3,4,3,4]
            £              # split the alphabet into pieces of these sizes
             ð«            # append a space to each
               ø           # transpose
                ðδK        # deep remove spaces
                   y.å     # check y for membership of each
                      ƶ    # lift each by their index in the list
                       O   # sum the list
                        O  # sum the stack
Emigna
fuente
Lo siento, pero para una entrada vacía, esto da 10. Está bien en otro lugar
Sr. Xcoder
@ Mr.Xcoder: la cadena vacía no da salida, pero sigue siendo incorrecta. Gracias por avisar, lo arreglaré.
Emigna
2
Da 10 en TIO.
Sr. Xcoder
@ Mr.Xcoder: Sí, tienes que dar explícitamente la cadena vacía. Ninguna entrada no es lo mismo que una cadena vacía. Es un poco confuso, lo sé. Solucionado ahora :)
Emigna
@ Mr.Xcoder: entrada de cadena vacía se da como este
Emigna
7

Python 2 , 56 bytes

Utiliza el mismo algoritmo que la solución Javascript de @ RickHitchcock

lambda x:sum('behknquxcfilorvysz'.find(c)/8+2for c in x)

Pruébalo en línea!

ovs
fuente
Solución interesante ¿Cómo funciona para espacios, no lo entiendo>. <?
Sr. Xcoder
@ Mr.Xcoder para cualquier cosa que no esté en la cadena '...'.find(c)devuelve -1. Al sumar 2 obtenemos una pulsación de tecla.
ovs
Sabía que había regresado -1, pero no me di cuenta de que tenías una +2placa posterior ... De todos modos, la solución Python más corta con diferencia.
Sr. Xcoder
Oml, resultó que hice exactamente la misma solución después de jugar lentamente mi programa, hasta que me di cuenta de que lo publicaste :( Buen trabajo para encontrar esta solución también :)
Mario Ishac
5

Python 3 , 69 67 65 64 bytes

1 byte gracias al Sr. Xcoder.

1 byte gracias a Felipe Nardi Batista.

lambda x:sum((ord(i)+~(i>"s"))%3+3*(i in"sz")+(i>" ")for i in x)

Pruébalo en línea!

Monja permeable
fuente
Ahorre un byte reemplazándolo i==" "con i<"a", porque solo recibe letras y espacios
Sr. Xcoder
44
61 minutos ... demasiado tarde!
Erik the Outgolfer
5

Dyalog APL, 37 bytes

+/⌈9÷⍨'adgjmptw behknqux~cfilorvy~'⍳⍞

Pruébalo en línea!

¿Cómo?

Obtenga el ndex de cada carácter de la entrada en la cadena 'adgjmptw behknqux~cfilorvy~'( sy el zvalor predeterminado será 28), divida por 9, redondee y sume.

Uriel
fuente
Puede usar 'adgjmptw ' 'behknqux' 'cfilorvy' 'sz'para guardar algunos bytes
Kritixi Lithos
49 bytes
Leaky Nun
@LeakyNun onice
Uriel
Puede soltar el espacio en la cadena
Kritixi Lithos
@Uriel espera, no necesitas contar, f←por lo que son 47 bytes
Leaky Nun
4

JavaScript (ES6), 71 bytes

f=
s=>[...s].map(c=>t+=((c=parseInt(0+c,36))>23?c+3:c&&~-c%3)%7%4+1,t=0)|t
<input oninput=o.textContent=f(this.value)><pre id=o>

¡No busques tablas de cartas! No entendía bien la fórmula de @ LeakyNun, así que se me ocurrió la mía.

Neil
fuente
Aritmética pura :)
Sr. Xcoder
¿Qué hace s=>[...s]por qué no solo?s=>s.map()...
Evan Carroll
1
@EvanCarroll ses una cadena, por lo que no puede maphacerlo directamente. ...sitera sobre s, mientras [...s]convierte la iteración en una matriz, dividiéndose efectivamente sen una matriz de caracteres.
Neil
4

DO, 211 196 bytes

La primera presentación aquí ... parece bastante larga y veo que este no es un enfoque eficiente, pero al menos funciona :)

f(char*n){char*k=" abcdefghijklmnopqrstuvwxyz";int t[]={0,3,3,3,3,3,4,3,4};int l=0,s,j,i;while(*n){i=0;while(k[i]){if(k[i]==*n){s=0;for(j=0;s<i-t[j];s+=t[j++]);*n++;l+=(!i?1:i-s);}i++;}}return l;}

Versión sin golf:

int f(char *n){
  char *k=" abcdefghijklmnopqrstuvwxyz";
  int t[]={0,3,3,3,3,3,4,3,4};
  int l=0,s,j,i;
  while(*n){                          // loop through input characters
    i=0;
    while(k[i]){
      if(k[i]==*n){                   // find matching char in k
        s=0;
        for(j=0;s<i-t[j];s+=t[j++]);  // sum up the "key sizes" up to the key found
        *n++;
        l+=(!i?1:i-s);                // key presses are i-s except for space (1)
      }
      i++;
    }
  }
  return l;
}
dbuchmann
fuente
*(k+i)puede ser k[i].
CalculatorFeline
Puede cortar el espacio después de un *(p char*n. Ej. ), Y agregar sus declaraciones a su fordeclaración vacía (en lugar de int s=0,j=0;(for(;lo que tendría for(int s=0,k=0;) y en lugar de i==0usar!i
Tas
Gracias por esos consejos. No pude poner sen el bucle for porque lo uso más adelante, pero puse las intdeclaraciones juntas y usé asignaciones donde las necesitaba.
dbuchmann
¡Yay un compañero golfista C! De todos modos, algunos punteros: los bucles for son estrictamente mejores que los bucles while en casi todas las situaciones: aproveche los puntos y comas libres, especialmente en la expresión de iteración. Use comas en lugar de punto y coma en la mayoría de los lugares, esto le permite evitar no tener llaves en la mayoría de los lugares. Existen otras optimizaciones, pero dependen más de la versión de C con la que compila.
dj0wns
4

Haskell - 74 71 62 bytes

Editar: eliminó 3 bytes usando una lista de comprensión en lugar de filtro

Editar: ¡Ahorre 9 bytes gracias a Siracusa, Laikoni y Zgarb!

f=sum.(>>= \x->1:[1|y<-"bcceffhiikllnooqrrsssuvvxyyzzz",y==x])

Uso

λ> f "candela"
13
λ>

Pruébalo en línea!

Enrique
fuente
¿Cuál es el propósito de las letras duplicadas?
Sr. Xcoder
@ Mr.Xcoder Se utiliza para contar los grifos, agregaré una explicación.
Henry
Puede guardar un byte reescribiendo fen f=length.(=<<)(\x->x:[y|y<-l,y==x]), donde (=<<)está concatMapaquí.
siracusa
Y otro con volver a filter:f=length.(=<<)(\x->x:filter(==x)l)
siracusa
1
Como lo usa lsolo una vez, puede estar en línea.
Laikoni
3

Clojure, 82 76 bytes

#(apply +(for[c %](+(count(filter #{c}"bcceffhiikllnooqrrsssuvvxyyzzz"))1)))

Oh, es más simple de usar filtery countde usar frequencies. Original:

#(apply +(count %)(for[c %](get(frequencies"bcceffhiikllnooqrrsssuvvxyyzzz")c 0)))

La cadena codifica cuántas veces más que solo una vez necesita presionar la tecla para un carácter dado :)

NikoNyrh
fuente
2

Python 3 , 60 bytes

Probablemente subóptimo, ya que este es mi primer golf en Python.

lambda x:sum((ord(i)-8)%3.15//1+3*(i>'y')+(i>' ')for i in x)

Pruébalo en línea!

Arnauld
fuente
2

Java, 95 73 bytes

a->a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum()

Gracias a Kevin Cruijssen por hacer de la función una expresión lambda (donde aes de tipo String). ¡95 bytes se convirtieron en 73 bytes!

Una expresión lambda resume el recuento de prensa de cada carácter usando map(). map()convierte cada carácter (ASCII en el rango caso inferior es 97-122) en la corriente en el valor adecuado (se parece a la onda de sierra simple, pero teniendo en cuenta tanto 4 ciclos es molesto) usando este matemáticas: 1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112). Aquí hay un gráfico desmos de ese modelo.

Adam Mendenhall
fuente
La lista de lagunas legales dice que no se publiquen fragmentos de código, aunque parece que hasta ahora todos lo han hecho. De cualquier manera, mi programa completo es de 130 bytes . Aquí está:interface Z{static void main(String a){System.out.print(a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum());}}
Adam Mendenhall
1
Bienvenido a PPCG! De hecho, tiene razón en que los fragmentos no están permitidos, pero el valor predeterminado es programa o función . Y con Java 8 puedes usar lambdas. Entonces en este caso a->{return a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum();}está permitido. Y dado que es una declaración de devolución única, a->a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum()( 73 bytes ) sería su respuesta. Además, aquí hay un enlace TryItOnline de su respuesta que quizás desee agregar a su respuesta. Nuevamente: bienvenido y buena respuesta. +1 de mi parte
Kevin Cruijssen
2
Algunas cosas a tener en cuenta sobre lambdas. No tiene que contar f=ni el punto y coma principal ;. Y tampoco tiene que agregar el tipo de parámetro siempre que mencione cuál es el tipo (por lo que en lugar de (String a)->usarlo a->y mencionar que la entrada aes un Stringen su respuesta). Ah, y Consejos para jugar al golf en Java y Consejos para jugar al golf en <todos los idiomas> pueden ser interesantes de leer, en caso de que aún no lo haya hecho.
Kevin Cruijssen
1

Mathematica, 83 bytes

c=Characters;Tr[Tr@Mod[c@"bc1def1ghi1jkl1mno1pqrstuv1wxyz "~Position~#,4]+1&/@c@#]&
J42161217
fuente
Parece generalmente aceptado que las respuestas de Mathematica pueden usar listas de caracteres para variables de cadena, como la entrada a esta función. (¿También hay una afalta al comienzo de "bc1..."?)
Greg Martin
este es el código golf.Este da el resultado correcto sin un "Tr" hace el trabajo
J42161217
1

QBIC , 94 bytes

[_l;||_SA,a,1|p=p-(instr(@sz`,B)>0)-(instr(@cfilorvy`+C,B)>0)-(instr(@behknqux`+C+D,B)>0)+1}?p

Explicación

[    |      FOR a = 1 TO
 _l |         the length of
   ;            the input string (A$)
_SA,a,1|    Take the a'th char of A$ and assign it to B$
p=p         p is our tap-counter, and in each iteration it gets increased by the code below
            which consist of this pattern:
                instr(@xyz`,B)>0    where 
                - instr tests if arg 2 is in arg 1 (it either returns 0 or X where X is the index of a2 in a1)
                - @...` defines the letters we want to test as arg1
                - B is the current letter to count the taps for
            Each of these blocks adds 1 tap to the counter, and each block has the letters of its level
            (4-taps, 3-taps or 2-taps) and the level 'above' it.
    -(instr(@sz`,B)>0)              <-- letters that require 4 taps
    -(instr(@cfilorvy`+C,B)>0)      <-- 3 or 4 taps
    -(instr(@behknqux`+C+D,B)>0)    <-- 2, 3,or 4 taps
    +1                              <-- and always a 1-tap
}           NEXT
?p          PRINT the number of taps
Steenbergh
fuente
1

Bash ,69 68 bytes

bc<<<`fold -1|tr "\n "adgjmptwbehknquxcfilorvysz +[1*9][2*8][3*8]44`

Pruébalo en línea!

Dobla un carácter por línea, translitera cada nueva línea con +, cada espacio con 1y cada letra con el número correspondiente de pulsaciones. bc hace la suma.

marcom
fuente
en su máquina que pueda necesitarbc <(fold -1|tr "\n "adgjmptwbehknquxcfilorvysz +[1*9][2*8][3*8]44;echo 0)
marcosm
1

C, 92 88 bytes

c,n;f(char*s){n=0;while(c=*s++)n+=(c=='s')+3*(c>'y')+1+(c+1+(c<'s'))%3-(c<33);return n;}
Rayo
fuente
puede usar s=npara reemplazar return ny combinar s++;con c=*s. Podría ser 9 bytes más corto.
Keyu Gan
@KeyuGan s=nno funcionaría, ya que ses un local. Y *s=nno funcionaría ya que solo hay CHAR_BITbits *s, lo que no sería suficiente para algunos mensajes. Pero tienes razón sobre el s++. Gracias.
Ray
1

APL (Dyalog) , 36 bytes

{+/(3×⍵∊'sz'),1+31+⍵⍳⍨819⌶⎕A~'SZ'}

Pruébalo en línea!

Encuentra el mod 3-índices en el alfabeto sin S y Z . Como el espacio, S y Z no se encuentran, "tienen" el índice 25 (uno más que el índice máximo), lo cual es bueno para el espacio. A continuación, sólo tenemos que añadir 3 para cada S o Z .

{ función anónima donde el argumento está representado por :

⎕A~'SZ' el alfabeto en mayúscula A , excepto S y Z

819⌶ minúsculas

⍵⍳⍨ los ɩ nices del argumento en ese

¯1+ agregar uno negativo

3| mod-3

1+ agregue uno (esto convierte todos los 0-mods a 3)

(... ), anteponer:

  ⍵∊'sz' Booleano donde el argumento es o s o z

   multiplicar por 3

+/ suma

Adán
fuente
1

C (gcc) , 7577 bytes

n,b;f(char*a){for(n=0;b=*a++;)n+=b<'s'?--b%3+(b>31):""[b-'s'];a=n;}

La cadena no imprimible ""es una tabla de 04 01 02 03 01 02 03 04.

Pruébalo en línea!

Keyu Gan
fuente
@ceilingcat gracias!
Keyu Gan
1

Pip , 100 90 bytes

a:qb:["abc""def""ghi""jkl""mno""pqrs""tuv""wxyz"s]Fc,#a{Fd,#b{e:((bd)@?(ac))e<4?i+:e+1x}}i

Verifique cada carácter de la entrada para una coincidencia en cada elemento de b. El índice de esa coincidencia más 1 se agrega al total.

Pruébalo en línea!

Kenneth Taylor
fuente