Quante volte devo premere questo?


24

Siamo tutti abituati alla tastiera del telefono della vecchia scuola, giusto? Per riferimento, ecco come appare:

Telefono Keybad


Data una stringa composta solo da lettere ASCII minuscole e singoli spazi , il tuo compito è quello di restituire il numero di tocchi che uno dovrebbe fare per digitare l'intera stringa con una tastiera del telefono come quella sopra.

Per coloro che non hanno familiarità con questo, ecco come funziona:

  • La chiave con la cifra 2, ad esempio, ha anche la stringa abcscritta su di essa. Per digitare a, è necessario premere questo tasto una volta, poiché bè necessario premere due volte e per ctre volte.

  • Per le lettere consecutive che si trovano sullo stesso tasto, è necessario attendere 1 secondo prima di premere nuovamente. Quindi, se si desidera digitare cb, è necessario premere 3 volte per c, attendere un secondo e quindi premere due volte per b, quindi ancora 5 tocchi.

  • Lo stesso vale per tutti gli altri tasti, tranne uno spazio singolo , che richiede solo 1 pressione. Si noti inoltre che i tasti 7e 9hanno quattro lettere su di essi. Viene applicato lo stesso algoritmo, l'unica differenza è il numero di lettere. Le stringhe corrispondenti a ciascun tasto si trovano nell'immagine sopra (ma in minuscolo), o nel seguente elenco, che contiene tutti i caratteri che potresti ricevere:

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

Casi test

Ingresso -> Uscita (spiegazione)

"" -> 0 (nulla deve essere toccato)
"water" -> 8 ("w, a, t" richiedono ciascuno 1 tap (sui tasti 9, 2 e 8), "e" richiede 2 tap (sul tasto 3), "r" richiede 3 tap (sul tasto 7 ), 1 + 1 + 1 + 2 + 3 = 8)
"sapone" -> 9 (4 + 3 + 1 + 1)
"candela" -> 13 (3 + 1 + 2 + 1 + 2 + 3 + 1)
"code golf" -> 20 (3 + 3 + 1 + 2 + 1 (per lo spazio) + 1 + 3 + 3 + 3)
"re della collina" -> 33 (2 + 3 + 2 + 1 + 1 + 3 + 3 + 1 + 1 + 2 + 2 + 1 + 2 + 3 + 3 + 3)

Specifiche

  • Si applicano le regole I / O standard e le lacune predefinite.

  • Puoi inserire solo input nel tipo di stringa nativo della tua lingua. L'output può essere un numero intero o una rappresentazione di stringa di quel numero intero.

  • Questo è , la risposta più breve in ogni lingua vince.




2
Penso che questa sarebbe una domanda più interessante se tu facessi 1 tap al secondo, e dovessi aspettare 1 secondo e contare i secondi invece dei tap.
Yakk,

@Yakk Sarebbe troppo complicato
Mr. Xcoder,

@ Mr.Xcoder Ne sei sicuro? Ho visto i maghi del codice qui fare cose impossibili in meno spazio di un tweet.
J_F_B_M,

Risposte:


11

JavaScript (ES6) 77 66 64 60 byte

(Salvati alcuni byte grazie a @Johan Karlsson e @Arnauld).

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


(s,t=0)=>[...s].map(l=>t+=(1+'behknquxcfilorvysz'.indexOf(l)/8|0)+1)&&tper 71 byte
Johan Karlsson,

Grazie, @JohanKarlsson, ho pensato la stessa cosa mentre ero sotto la doccia! Abbiamo trovato un'altra ottimizzazione per eliminare altri 5 byte.
Rick Hitchcock,

6
Ho trovato una soluzione puramente aritmetica per 71 byte: 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, anche se potrebbe non essere più breve, è sicuramente più intelligente.
Rick Hitchcock,

1
@Neil Dovresti pubblicarlo.
Mr. Xcoder,

7

05AB1E , 29 26 25 byte

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

Provalo online!

Spiegazione

ð¢                         # 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

Ci dispiace, ma per un input vuoto questo dà 10. Va bene altrove
Mr. Xcoder,

@ Mr.Xcoder: la stringa vuota non fornisce output, ma è ancora errata. Grazie per averlo avvisato, lo aggiusterò.
Emigna,

2
Dà 10 su TIO.
Mr. Xcoder,

@ Mr.Xcoder: Sì, devi dare esplicitamente la stringa vuota. Nessun input non è uguale a una stringa vuota. Lo so, è un po 'confuso. Risolto ora però :)
Emigna il

@ Mr.Xcoder: l'immissione di stringhe vuote è data in questo modo
Emigna,

7

Python 2 , 56 byte

Utilizza lo stesso algoritmo della soluzione Javascript di @ RickHitchcock

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

Provalo online!


Soluzione interessante. Come funziona per gli spazi, non capisco>. <?
Mr. Xcoder,

@ Mr.Xcoder per qualsiasi cosa non nella stringa '...'.find(c)ritorna-1 . Aggiungendo 2 otteniamo un tasto premuto.
Ovs,

Sapevo che sarebbe tornato -1, ma non mi ero reso conto che tu avessi un+2 dopo la piastra della caldaia ... Comunque, la soluzione Python più corta di gran lunga.
Mr. Xcoder,

Oml, mi è capitato di fare la stessa identica soluzione dopo aver pianificato lentamente il mio programma, fino a quando ho capito che l'hai pubblicato :( Bel lavoro anche per trovare questa soluzione :)
Mario Ishac,


5

Dyalog APL, 37 byte

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

Provalo online!

Come?

Ottieni il ndex di ogni carattere dell'input nella stringa 'adgjmptw behknqux~cfilorvy~'( se zper impostazione predefinita sarà 28), dividi per 9, arrotonda per eccesso e somma.


È possibile utilizzare 'adgjmptw ' 'behknqux' 'cfilorvy' 'sz'per salvare alcuni byte
Kritixi Lithos,


@LeakyNun onice
Uriel,

Puoi rilasciare lo spazio nella stringa
Kritixi Lithos,

@Uriel aspetta, non devi contare f←quindi è 47 byte
Leaky Nun,

4

JavaScript (ES6), 71 byte

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>

Non cercare tabelle di lettere! Non ho capito bene la formula di @ LeakyNun, quindi ho pensato alla mia.


Pure arithmetic :)
Mr. Xcoder,

Cosa fa s=>[...s]perché non solos=>s.map()...
Evan Carroll,

1
@EvanCarroll sè una stringa, quindi non puoi mapdirettamente. ...sesegue l'iterazione s, mentre [...s]converte l'iterazione in un array, dividendosi efficacemente sin un array di caratteri.
Neil,

4

C, 211 196 byte

La prima presentazione qui ... sembra piuttosto lunga e vedo che questo non è un approccio efficiente, ma almeno funziona :)

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

Versione non golfata:

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

*(k+i)può essere k[i].
CalculatorFeline

Puoi tagliare lo spazio dopo un *(ad es. char*n) E aggiungere le tue dichiarazioni alla tua fordichiarazione vuota (invece int s=0,j=0;(for(;che avresti avuto for(int s=0,k=0;) e invece di i==0usare!i
Tas

Grazie per questi suggerimenti. Non ho potuto inserirmi snel ciclo for perché lo uso in seguito, ma ho messo intinsieme le dichiarazioni e ho usato gli assegnatori dove ne avevo bisogno.
dbuchmann,

Yay un compagno di golf C! Comunque, alcuni suggerimenti: per i loop sono strettamente migliori di mentre i loop in quasi tutte le situazioni - sfruttano i punti e virgola gratuiti, in particolare nell'espressione di iterazione. Usa le virgole anziché i punti e virgola nella maggior parte dei luoghi, questo ti consente di cavartela senza avere parentesi graffe nella maggior parte dei luoghi. Esistono altre ottimizzazioni, ma sono più dipendenti da quale versione di C viene compilata.
dj0wns

4

Haskell - 74 71 62 byte

Modifica: rimosso 3 byte utilizzando una comprensione dell'elenco anziché il filtro

Modifica: risparmia 9 byte grazie a Siracusa, Laikoni e Zgarb!

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

uso

λ> f "candela"
13
λ>

Provalo online!


Qual è lo scopo delle lettere duplicate?
Mr. Xcoder,

@ Mr.Xcoder Serve per contare i tocchi, aggiungerò una spiegazione.
Henry,

È possibile salvare un byte riscrivendolo fin f=length.(=<<)(\x->x:[y|y<-l,y==x]), dove si (=<<)trova concatMap.
siracusa,

E un altro con il ritorno a filter:f=length.(=<<)(\x->x:filter(==x)l)
siracusa,

1
Come si usa lsolo una volta, può essere integrato.
Laikoni,


3

Clojure, 82 76 byte

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

Oh, è più semplice da usare filtere countda usare frequencies. Originale:

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

La stringa codifica quante volte più di una volta è necessario premere il tasto per un dato carattere :)



2

Python 3 , 60 byte

Probabilmente non ottimale, poiché questo è il mio primo golf in assoluto a Python.

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

Provalo online!



2

Java, 95 73 byte

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

Grazie a Kevin Cruijssen per aver reso la funzione un'espressione lambda (dove aè di tipo String). 95 byte sono diventati 73 byte!

Un'espressione lambda riassume il conteggio della stampa di ciascun carattere usando map(). map()converte ogni carattere (ASCII nella gamma minuscolo è 97-122) nel flusso al valore appropriato (sembra semplice onda sega, ma tenendo conto sia 4 cicli è fastidioso) utilizzando questo matematica: 1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112). Ecco un grafico desmos di quel modello.


L'elenco delle scappatoie dice di non pubblicare frammenti di codice anche se sembra che finora tutti lo abbiano fatto. Ad ogni modo, il mio programma completo è di 130 byte . Eccolo: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
Benvenuti in PPCG! Hai davvero ragione sul fatto che i frammenti non sono ammessi, ma il valore predefinito è programma o funzione . E con Java 8 puoi usare lambdas. Quindi in questo caso a->{return a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum();}è permesso. E poiché è una singola dichiarazione di ritorno, a->a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum()( 73 byte ) sarebbe la tua risposta. Inoltre, ecco un link TryItOnline della tua risposta che potresti voler aggiungere alla tua risposta. Ancora: benvenuta e bella risposta. +1 da me.
Kevin Cruijssen,

2
Alcune cose da notare sugli lambda. Non devi contare f=né il punto e virgola principale ;. Inoltre, non è necessario aggiungere il tipo di parametro fintanto che si menziona il tipo (quindi invece di (String a)->utilizzare a->e menzionare che l'input aè un Stringnella risposta). Oh, e Suggerimenti per giocare a golf in Java e Suggerimenti per giocare a golf in <tutte le lingue> potrebbero essere interessanti da leggere, nel caso in cui non l'avessi ancora fatto.
Kevin Cruijssen,

1

Mathematica, 83 byte

c=Characters;Tr[Tr@Mod[c@"bc1def1ghi1jkl1mno1pqrstuv1wxyz "~Position~#,4]+1&/@c@#]&

Sembra generalmente accettato che le risposte di Mathematica possano utilizzare elenchi di caratteri per variabili stringa, come l'input per questa funzione. (C'è anche una amancanza all'inizio "bc1..."?)
Greg Martin,

questo è il codice golf.questo dà il risultato giusto senza un "Tr" fa il lavoro
J42161217

1

QBIC , 94 byte

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

Spiegazione

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

1

Bash ,69 68 byte

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

Provalo online!

Piega un carattere per riga, traslittera ogni nuova riga +, ogni spazio con 1e ogni lettera con il corrispondente numero di spinte. bc fa la somma.


sulla tua macchina potresti aver bisognobc <(fold -1|tr "\n "adgjmptwbehknquxcfilorvysz +[1*9][2*8][3*8]44;echo 0)
marcosm,

1

C, 92 88 byte

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

è possibile utilizzare s=nper sostituire return ne combinare s++;con c=*s. Potrebbe essere più breve di 9 byte.
Keyu Gan,

@KeyuGan s=nnon funzionerebbe, poiché sè un locale. E *s=nnon funzionerebbe poiché ci sono solo CHAR_BITbit *s, che non sarebbero sufficienti per alcuni messaggi. Ma hai ragione riguardo al s++. Grazie.
Ray

1

APL (Dyalog) , 36 byte

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

Provalo online!

Trova i mod-3 indici in alfabeto senza S e Z . Poiché spazio, S e Z non vengono trovati, "hanno" un indice 25 (uno in più dell'indice massimo), che è buono per lo spazio. Poi abbiamo solo bisogno di aggiungere 3 per ogni S o Z .

{ funzione anonima in cui l'argomento è rappresentato da :

⎕A~'SZ' l' alfabeto A maiuscolo , ad eccezione di S e Z

819⌶ minuscolo

⍵⍳⍨ le of ndice dell'argomento in questo

¯1+ aggiungi uno negativo

3| mod-3

1+ aggiungi uno (questo converte tutte le mod 0 in 3)

(... ), anteporre:

  ⍵∊'sz' Booleano in cui l'argomento è s o z

   moltiplicare per 3

+/ somma



1

Pip , 100 90 byte

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

Controllare ogni carattere dell'input per una corrispondenza in ciascun elemento di b. L'indice di quella corrispondenza più 1 viene aggiunto al totale.

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.