Quantas vezes devo pressionar isso?

24

Estamos todos acostumados com o teclado do telefone da velha escola, certo? Para referência, aqui está o que parece:

Telefone Keybad


Dada uma String que consiste apenas em letras ASCII minúsculas e espaços únicos , sua tarefa é retornar o número de toques que você deve fazer para digitar a String completa com um teclado de telefone como o descrito acima.

Para aqueles que não estão familiarizados com isso, veja como funciona:

  • A tecla com o dígito 2, por exemplo, também possui a string abcescrita nela. Para digitar a, você deve pressionar essa tecla uma vez, pois bdeve pressionar duas vezes e cpressionar três vezes.

  • Para letras consecutivas que estão na mesma tecla, você deve esperar 1 segundo antes de pressionar novamente. Portanto, se você quiser digitar cb, pressione 3 vezes c, aguarde um segundo e depois pressione duas vezes b, para continuar com 5 toques.

  • O mesmo se aplica a todas as outras teclas, exceto um espaço único , que requer apenas 1 toque. Observe também as teclas 7e 9tem quatro letras nelas. O mesmo algoritmo é aplicado, a única diferença é o número de letras. As seqüências correspondentes a cada chave podem ser encontradas na imagem acima (mas em minúsculas) ou na lista a seguir, que contém todos os caracteres que você pode receber:

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

Casos de teste

Entrada -> Saída (Explicação)

"" -> 0 (nada deve ser tocado)
"água" -> 8 ("w, a, t" exige 1 torneira (nas teclas 9, 2 e 8), "e" requer 2 torneiras (na tecla 3), "r" requer 3 torneiras (na tecla 7 ), 1 + 1 + 1 + 2 + 3 = 8)
"sabão" -> 9 (4 + 3 + 1 + 1)
"candela" -> 13 (3 + 1 + 2 + 1 + 2 + 3 + 1)
"código de golfe" -> 20 (3 + 3 + 1 + 2 + 1 (para o espaço) + 1 + 3 + 3 + 3)
"rei da colina" -> 33 (2 + 3 + 2 + 1 + 1 + 3 + 3 + 1 + 1 + 2 + 2 + 1 + 2 + 3 + 3 + 3)

Especificações

  • Aplicam-se as regras de E / S padrão e as brechas padrão.

  • Você pode receber apenas entradas no tipo String nativo do seu idioma. A saída pode ser um número inteiro ou uma representação de sequência desse número inteiro.

  • Este é o , a resposta mais curta em todos os idiomas vence.

Mr. Xcoder
fonte
2
Acho que essa seria uma pergunta mais interessante se você desse 1 toque por segundo e tivesse que esperar 1 segundo e contar segundos em vez de toques.
Yakk
@Yakk Isso seria muito complicado
Mr. Xcoder
@ Mr.Xcoder Você tem certeza? Vi os assistentes de código aqui fazer coisas impossíveis em menos espaço do que um tweet.
J_F_B_M

Respostas:

11

JavaScript (ES6) 77 66 64 60 bytes

(Economizou alguns bytes graças a @Johan Karlsson e @Arnauld).

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

Rick Hitchcock
fonte
(s,t=0)=>[...s].map(l=>t+=(1+'behknquxcfilorvysz'.indexOf(l)/8|0)+1)&&tpara 71 bytes
Johan Karlsson
Obrigado, @JohanKarlsson, achei a mesma coisa enquanto estava no chuveiro! Encontrei outra otimização para eliminar mais 5 bytes.
Rick Hitchcock
6
I encontrada uma solução 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, embora isso possa não ser mais curto, é certamente mais inteligente.
Rick Hitchcock
1
@ Neil Você deve publicá-lo.
Mr. Xcoder
7

05AB1E , 29 26 25 bytes

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

Experimente online!

Explicação

ð¢                         # 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
fonte
Desculpe, mas para uma entrada vazia isto dá 10. É bom em outro lugar
Mr. Xcoder
@ Mr.Xcoder: A string vazia não dá saída, mas ainda está errada. Obrigado por notificar, eu vou consertar.
Emigna
2
Dá 10 no TIO.
Mr. Xcoder
@ Mr.Xcoder: Sim, você deve dar explicitamente a string vazia. Nenhuma entrada é igual a uma sequência vazia. É um pouco confuso, eu sei. Corrigido agora :)
Emigna 28/0617
@ Mr.Xcoder: entrada para a cadeia vazia é dada como este
Emigna
7

Python 2 , 56 bytes

Usa o mesmo algoritmo da solução Javascript de @ RickHitchcock

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

Experimente online!

ovs
fonte
Solução interessante. Como funciona para espaços, não entendo>. <?
Mr. Xcoder
@ Mr.Xcoder para qualquer coisa que não esteja na string '...'.find(c)retorna -1. Ao adicionar 2, obtemos um pressionamento de tecla.
ovs 28/06
Eu sabia que ele retornou -1, mas não percebi que você tinha um +2clichê posterior ... Enfim, a solução Python mais curta de longe.
Sr. Xcoder
OML, aconteceu de eu fazer exatamente a mesma solução após golfe lentamente meu programa para baixo, até que eu percebi que você postou :( Bom trabalho para encontrar esta solução também :)
Mario Ishac
5

Python 3 , 69 67 65 64 bytes

1 byte graças ao Sr. Xcoder.

1 byte graças a Felipe Nardi Batista.

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

Experimente online!

Freira Furada
fonte
Salvar um byte, substituindo i==" "com i<"a", porque você só recebe letras e espaços
Mr. Xcoder
4
61 minutos ... tarde demais!
Erik the Outgolfer
5

Dyalog APL, 37 bytes

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

Experimente online!

Quão?

Obtenha o ndex de cada caractere de entrada na string 'adgjmptw behknqux~cfilorvy~'( se zo padrão será 28), divida por 9, arredonde e some.

Uriel
fonte
Você pode usar 'adgjmptw ' 'behknqux' 'cfilorvy' 'sz'para salvar alguns bytes
Kritixi Lithos
49 bytes
Freira vazada
@LeakyNun onice
Uriel
Você pode soltar o espaço na cadeia de caracteres
Kritixi Lithos
@Uriel espera, você não precisa contar, f←portanto são 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>

Não procure tabelas de letras! Eu não entendi direito a fórmula do @ LeakyNun, então criei a minha.

Neil
fonte
:) aritmética pura
Mr. Xcoder
O que s=>[...s]faz porque não apenass=>s.map()...
Evan Carroll
1
@EvanCarroll sé uma string, então você não pode mapdiretamente. ...sitera s, enquanto [...s]converte a iteração em uma matriz, dividindo-se efetivamente sem uma matriz de caracteres.
28417 Neil
4

C, 211 196 bytes

A primeira submissão aqui ... parece bastante longa e vejo que essa não é uma abordagem eficiente, mas pelo 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;}

Versão não destruída:

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
fonte
*(k+i)pode ser k[i].
CalculatorFeline
Você pode cortar o espaço depois de uma *(por exemplo char*n), e adicionar as suas declarações para o seu vazio fordeclaração (em vez de int s=0,j=0;(for(;você teria for(int s=0,k=0;) e em vez de i==0uso!i
Tas
Obrigado por essas dicas. Não pude colocar sno loop for porque o uso mais tarde, mas juntei as intdeclarações e usei atribuições onde precisava delas.
dbuchmann
Yay um companheiro golfista C! De qualquer forma, algumas dicas: para loops são estritamente melhores do que para loops em quase todas as situações - aproveite os pontos e vírgulas livres, principalmente na expressão da iteração. Use vírgulas em vez de ponto-e-vírgula na maioria dos lugares, para evitar que você não tenha chaves na maioria dos lugares. Existem outras otimizações, mas elas dependem mais de qual versão do C você compila.
dj0wns
4

Haskell - 74 71 62 bytes

Editar: removido 3 bytes usando uma compreensão de lista em vez de filtro

Edit: Economize 9 bytes graças a Siracusa, Laikoni e Zgarb!

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

Uso

λ> f "candela"
13
λ>

Experimente online!

Henry
fonte
Qual é o objetivo das cartas duplicadas?
Mr. Xcoder
@ Mr.Xcoder É usado para contar as torneiras, vou adicionar uma explicação.
Henry
Você pode salvar um byte reescrevendo fpara f=length.(=<<)(\x->x:[y|y<-l,y==x]), onde (=<<)está concatMapaqui.
Siracusa
E outro com voltar a filter:f=length.(=<<)(\x->x:filter(==x)l)
siracusa 28/06
1
Como você usa lapenas uma vez, ele pode ser incorporado.
Laikoni
3

Clojure, 82 76 bytes

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

Oh, é mais simples de usar filtere countde usar frequencies. Original:

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

A string codifica quantas vezes mais do que apenas uma vez você precisa pressionar a tecla para um determinado caractere :)

NikoNyrh
fonte
2

Python 3 , 60 bytes

Provavelmente abaixo do ideal, pois este é o meu primeiro golfe em Python.

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

Experimente online!

Arnauld
fonte
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()

Obrigado a Kevin Cruijssen por tornar a função uma expressão lambda (onde aé do tipoString ). 95 bytes se tornaram 73 bytes!

Uma expressão lambda resume a contagem de imprensa de cada caractere usando map(). map()converte cada caractere (ASCII em baixa gama caso é 97-122) no fluxo para o valor apropriado (parece onda serra simples, mas tendo em conta ambos os 4 ciclos é irritante) usando essa matemática: 1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112). Aqui está um gráfico de desmos desse modelo.

Adam Mendenhall
fonte
A lista de brechas diz para não publicar trechos de código, embora pareça que todo mundo já fez isso. De qualquer forma, meu programa completo é de 130 bytes . Aqui 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
Bem-vindo ao PPCG! Você está certo de que trechos não são permitidos, mas o padrão é programa ou função . E com o Java 8 você pode usar lambdas. Então, neste caso, a->{return a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum();}é permitido. E como é uma única declaração de retorno, a->a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum()( 73 bytes ) seria sua resposta. Além disso, aqui está um link TryItOnline da sua resposta que você pode adicionar à sua resposta. Mais uma vez: bem-vinda e boa resposta. +1 de mim.
Kevin Cruijssen 29/06
2
Algumas coisas a serem observadas sobre as lambdas. Você não precisa contar f=nem o ponto e vírgula principal ;. E você também não precisa adicionar o tipo do parâmetro, desde que mencione qual é o tipo (portanto, em vez de (String a)->poder usar a->e mencionar que a entrada aé um Stringna sua resposta). Ah, e Dicas para jogar golfe em Java e Dicas para jogar golfe em <todos os idiomas> podem ser interessantes para ler, caso você ainda não o tenha feito.
Kevin Cruijssen
1

Mathematica, 83 bytes

c=Characters;Tr[Tr@Mod[c@"bc1def1ghi1jkl1mno1pqrstuv1wxyz "~Position~#,4]+1&/@c@#]&
J42161217
fonte
Parece ser geralmente aceito que as respostas do Mathematica podem usar listas de caracteres para variáveis ​​de string, como a entrada para esta função. (Também há uma afalta no início da "bc1..."?)
Greg Martin
. este é golf.this código dá o resultado certo sem um "Tr" faz o trabalho
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

Explicação

[    |      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
fonte
1

Bash ,69 68 bytes

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

Experimente online!

Dobra um caracter por linha, translitera cada nova linha com +, cada espaço com 1e cada letra com o número correspondente de toques. bc faz a soma.

marcosm
fonte
em sua máquina você pode precisarbc <(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;}
Raio
fonte
você pode usar s=npara substituir return ne combinar s++;com c=*s. Pode ser 9 bytes mais curto.
usar o seguinte
@KeyuGan s=nnão funcionaria, já que sé local. E *s=nnão funcionaria, pois existem apenas CHAR_BITbits *s, o que não seria suficiente para algumas mensagens. Mas você está certo sobre o s++. Obrigado.
Raio
1

APL (Dyalog) , 36 bytes

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

Experimente online!

Encontrados os mod 3-índices no alfabeto sem S e Z . Como espaço, S e Z não são encontrados, eles "têm" o índice 25 (um a mais que o índice máximo), o que é bom para o espaço. Então nós só precisa adicionar 3 para cada S ou Z .

{ função anônima em que o argumento é representado por :

⎕A~'SZ' o alfabeto A maiúsculo , exceto S e Z

819⌶ minúsculas

⍵⍳⍨ os índices do argumento em que

¯1+ adicione um negativo

3| mod-3

1+ adicione um (isso converte todos os 0-mods em 3)

(), Prepend:

  ⍵∊'sz' Booleano em que o argumento é s ou z

   multiplicar por 3

+/ soma

Adám
fonte
1

C (gcc), 75 77 bytes

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

The unprintable string "" is a table of 04 01 02 03 01 02 03 04.

Try it online!

Keyu Gan
fonte
@ceilingcat thanks!
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

Check each character of the input for a match in each element of b. The index of that match plus 1 gets added to the total.

Try it online!

Kenneth Taylor
fonte