Combien de fois dois-je appuyer dessus?

24

Nous sommes tous habitués au clavier téléphonique de la vieille école, non? Pour référence, voici à quoi ça ressemble:

Téléphone Keybad


Étant donné une chaîne composée uniquement de lettres ASCII minuscules et d'espaces simples , votre tâche consiste à renvoyer le nombre d'appuis que vous devez effectuer afin de taper la chaîne complète avec un clavier téléphonique comme celui ci-dessus.

Pour ceux qui ne connaissent pas cela, voici comment cela fonctionne:

  • La clé avec le chiffre 2, par exemple, a également la chaîne abcécrite dessus. Pour taper a, vous devez appuyer une fois sur cette touche, car bvous devez appuyer deux fois et cvous devez appuyer trois fois.

  • Pour les lettres consécutives qui sont sur la même touche, vous devez attendre 1 seconde avant d'appuyer à nouveau. Donc, si vous voulez taper cb, vous devez appuyer 3 fois sur c, attendre une seconde puis appuyer deux fois sur b, donc toujours 5 taps.

  • Il en va de même pour toutes les autres touches, à l'exception d'un seul espace, qui ne nécessite qu'une seule pression. Notez également que les clés 7et 9ont quatre lettres sur eux. Le même algorithme est appliqué, la seule différence étant le nombre de lettres. Les chaînes correspondant à chaque clé se trouvent dans l'image ci-dessus (mais en minuscules), ou dans la liste suivante, qui contient tous les caractères que vous pourriez recevoir:

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

Cas de test

Entrée -> Sortie (explication)

"" -> 0 (rien ne doit être tapé)
"eau" -> 8 ("w, a, t" nécessitent chacun 1 robinet (sur les touches 9, 2 et 8), "e" nécessite 2 robinets (sur la touche 3), "r" nécessite 3 robinets (sur la touche 7 ), 1 + 1 + 1 + 2 + 3 = 8)
"savon" -> 9 (4 + 3 + 1 + 1)
"candela" -> 13 (3 + 1 + 2 + 1 + 2 + 3 + 1)
"code golf" -> 20 (3 + 3 + 1 + 2 + 1 (pour l'espace) + 1 + 3 + 3 + 3)
"roi de la colline" -> 33 (2 + 3 + 2 + 1 + 1 + 3 + 3 + 1 + 1 + 2 + 2 + 1 + 2 + 3 + 3 + 3)

Spécifications

  • Les règles d'E / S standard et les failles par défaut s'appliquent.

  • Vous ne pouvez prendre en entrée que le type de chaîne natif de votre langue. La sortie peut être soit un entier, soit une représentation sous forme de chaîne de cet entier.

  • C'est le , la réponse la plus courte dans toutes les langues l' emporte.

M. Xcoder
la source
Connexes . Connexes .
Shaggy
2
Je pense que ce serait une question plus intéressante si vous faisiez 1 tap par seconde, et deviez attendre 1 seconde, et compter les secondes au lieu des taps.
Yakk
@Yakk Ce serait beaucoup trop compliqué
M. Xcoder
@ Mr.Xcoder Êtes-vous sûr cependant? J'ai vu les assistants de code ici faire des choses impossibles dans moins d'espace qu'un tweet.
J_F_B_M

Réponses:

11

JavaScript (ES6) 77 66 64 60 octets

(Enregistré quelques octets grâce à @Johan Karlsson et @Arnauld).

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

Rick Hitchcock
la source
(s,t=0)=>[...s].map(l=>t+=(1+'behknquxcfilorvysz'.indexOf(l)/8|0)+1)&&tpour 71 octets
Johan Karlsson
Merci, @JohanKarlsson, j'ai pensé la même chose sous la douche! Trouvé une autre optimisation pour raser 5 octets de plus.
Rick Hitchcock
6
J'ai trouvé une solution purement arithmétique pour 71 octets: 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, bien que cela ne soit pas plus court, c'est certainement plus intelligent.
Rick Hitchcock
1
@Neil Vous devez le poster.
M. Xcoder
7

05AB1E , 29 26 25 octets

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

Essayez-le en ligne!

Explication

ð¢                         # 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
la source
Désolé, mais pour une entrée vide, cela donne 10. C'est bien ailleurs
M. Xcoder
@ Mr.Xcoder: La chaîne vide ne donne aucune sortie, mais c'est toujours faux. Merci d'avoir signalé, je vais le réparer.
Emigna
2
Il donne 10 sur TIO.
M. Xcoder
@ Mr.Xcoder: Oui, vous devez donner explicitement la chaîne vide. Aucune entrée n'est différente d'une chaîne vide. C'est un peu déroutant je sais. Fixé maintenant cependant :)
Emigna
@ Mr.Xcoder: Une entrée de chaîne vide est donnée comme ceci
Emigna
7

Python 2 , 56 octets

Utilise le même algorithme que la solution Javascript de @ RickHitchcock

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

Essayez-le en ligne!

ovs
la source
Solution intéressante. Comment ça marche pour les espaces, je ne comprends pas>. <?
M. Xcoder
@ Mr.Xcoder pour tout ce qui n'est pas dans la chaîne '...'.find(c)retourne -1. En ajoutant 2, nous obtenons une pression sur une touche.
2017 à 13h59
Je savais que ça revenait -1, mais je ne savais pas que vous aviez un +2après le passe-partout ... Quoi qu'il en soit, la solution Python la plus courte de loin.
M. Xcoder
Oml, il m'est arrivé de faire exactement la même solution après avoir lentement joué à mon programme, jusqu'à ce que je réalise que vous l'avez posté :( Beau travail pour trouver cette solution aussi :)
Mario Ishac
5

Python 3 , 69 67 65 64 octets

1 octet merci à M. Xcoder.

1 octet merci à Felipe Nardi Batista.

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

Essayez-le en ligne!

Leaky Nun
la source
Économisez un octet en le remplaçant i==" "par i<"a", car vous ne recevez que des lettres et des espaces
M. Xcoder
4
61 minutes ... trop tard!
Erik the Outgolfer
5

Dyalog APL, 37 octets

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

Essayez-le en ligne!

Comment?

Obtenez le ndex de chaque caractère de l'entrée dans la chaîne 'adgjmptw behknqux~cfilorvy~'( set zsera par défaut à 28), divisez par 9, arrondissez et additionnez.

Uriel
la source
Vous pouvez utiliser 'adgjmptw ' 'behknqux' 'cfilorvy' 'sz'pour enregistrer quelques octets
Kritixi Lithos
49 octets
Leaky Nun
@LeakyNun onice
Uriel
Vous pouvez supprimer l'espace dans la chaîne
Kritixi Lithos
@Uriel attendez, vous n'avez pas besoin de compter f←, c'est donc 47 octets
Leaky Nun
4

JavaScript (ES6), 71 octets

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>

Ne cherchez pas de tables à lettres! Je ne comprenais pas très bien la formule de @ LeakyNun alors j'ai trouvé la mienne.

Neil
la source
Arithmétique pure :)
M. Xcoder
Que fait s=>[...s]pourquoi pas seulements=>s.map()...
Evan Carroll
1
@EvanCarroll sest une chaîne, vous ne pouvez donc pas le mapfaire directement. ...sitère sur s, tandis que [...s]convertit l'itération en un tableau, se divisant efficacement sen un tableau de caractères.
Neil
4

C, 211 196 octets

La première soumission ici ... semble assez longue et je vois que ce n'est pas une approche efficace, mais au moins ça marche :)

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

Version non golfée:

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
la source
*(k+i)peut être k[i].
CalculatorFeline
Vous pouvez couper l'espace après un *(par exemple char*n), et ajouter vos déclarations à votre fordéclaration vide (au lieu que int s=0,j=0;(for(;vous auriez for(int s=0,k=0;) et au lieu d' i==0utiliser!i
Tas
Merci pour ces indices. Je n'ai pas pu mettre sdans la boucle for car je l'utilise plus tard, mais j'ai rassemblé les intdéclarations et utilisé les assignemts là où j'en avais besoin.
dbuchmann
Yay un collègue golfeur C! Quoi qu'il en soit, quelques pointeurs: les boucles sont strictement meilleures que les boucles dans presque toutes les situations - profitez des points-virgules libres, en particulier dans l'expression d'itération. Utilisez des virgules au lieu de points-virgules dans la plupart des endroits, cela vous permet de vous en sortir sans avoir d'accolades dans la plupart des endroits. Il existe d'autres optimisations, mais elles dépendent plus de la version de C que vous compilez.
dj0wns
4

Haskell - 74 71 62 octets

Edit: supprimé 3 octets en utilisant une compréhension de liste au lieu d'un filtre

Edit: économisez 9 octets grâce à Siracusa, Laikoni et Zgarb!

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

Usage

λ> f "candela"
13
λ>

Essayez-le en ligne!

Henri
la source
Quel est le but des lettres en double?
M. Xcoder
@ Mr.Xcoder Il sert à compter les taps, j'ajouterai une explication.
Henry
Vous pouvez enregistrer un octet par la réécriture fà f=length.(=<<)(\x->x:[y|y<-l,y==x]), où (=<<)est concatMapici.
siracusa
Et un autre avec retour à filter:f=length.(=<<)(\x->x:filter(==x)l)
siracusa
1
Comme vous lne l' utilisez qu'une seule fois, il peut être inséré.
Laikoni
3

Clojure, 82 76 octets

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

Oh , il est plus simple de filteret countque l' utilisation frequencies. Original:

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

La chaîne encode combien de fois plus qu'une seule fois vous devez appuyer sur la touche d'un caractère donné :)

NikoNyrh
la source
2

Python 3 , 60 octets

Probablement sous-optimal, car c'est mon premier golf en Python.

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

Essayez-le en ligne!

Arnauld
la source
2

Java, 95 73 octets

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

Merci à Kevin Cruijssen d'avoir fait de la fonction une expression lambda (où aest de type String). 95 octets sont devenus 73 octets!

Une expression lambda résume le nombre de presse de chaque caractère utilisant map(). map()convertit chaque caractère (ASCII dans la plage minuscule est 97-122) dans le flux à la valeur appropriée ( qui ressemble à simple , vague de scie, mais en prenant en compte les 4 cycles est ennuyeux) en utilisant ce calcul: 1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112). Voici un graphique desmos de ce modèle.

Adam Mendenhall
la source
La liste des lacunes indique de ne pas publier d'extraits de code, même si tout le monde semble avoir fait cela jusqu'à présent. De toute façon, mon programme complet est de 130 octets . Le voici: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
Bienvenue chez PPCG! Vous avez en effet raison que les extraits de code ne sont pas autorisés, mais la valeur par défaut est programme ou fonction . Et avec Java 8, vous pouvez utiliser des lambdas. Donc, dans ce cas, a->{return a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum();}est autorisé. Et comme il s'agit d'une seule déclaration de retour, a->a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum()( 73 octets ) serait votre réponse. En outre, voici un lien TryItOnline de votre réponse que vous voudrez peut-être ajouter à votre réponse. Encore une fois: bienvenue et bonne réponse. +1 de moi.
Kevin Cruijssen
2
Quelques choses à noter sur les lambdas. Vous n'avez pas à compter f=ni le premier point-virgule ;. Et vous n'avez pas non plus à ajouter le type du paramètre tant que vous mentionnez ce qu'est le type (donc au lieu de (String a)->vous pouvez utiliser a->et mentionner que l'entrée aest un Stringdans votre réponse). Oh, et des conseils pour jouer au golf en Java et des conseils pour jouer au golf dans <toutes les langues> pourraient être intéressants à lire, au cas où vous ne l'auriez pas encore fait.
Kevin Cruijssen
1

Mathematica, 83 octets

c=Characters;Tr[Tr@Mod[c@"bc1def1ghi1jkl1mno1pqrstuv1wxyz "~Position~#,4]+1&/@c@#]&
J42161217
la source
Il semble généralement admis que les réponses Mathematica sont autorisées à utiliser des listes de caractères pour les variables de chaîne, telles que l'entrée de cette fonction. (Y a-t-il également un amanquant au début de "bc1..."?)
Greg Martin
c'est le code golf.this donne le bon résultat sans. "Tr" fait le travail
J42161217
1

QBIC , 94 octets

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

Explication

[    |      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
la source
1

Bash ,69 68 octets

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

Essayez-le en ligne!

Plie un caractère par ligne, translitère chaque nouvelle ligne avec +, chaque espace avec 1et chaque lettre avec le nombre correspondant de poussées. bc fait la somme.

marcosm
la source
sur votre machine, vous pourriez avoir besoinbc <(fold -1|tr "\n "adgjmptwbehknquxcfilorvysz +[1*9][2*8][3*8]44;echo 0)
marcosm
1

C, 92 88 octets

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;}
Rayon
la source
vous pouvez utiliser s=npour remplacer return net combiner s++;avec c=*s. Il pourrait être plus court de 9 octets.
Keyu Gan
@KeyuGan s=nne fonctionnerait pas, car il ss'agit d'un local. Et *s=ncela ne fonctionnerait pas car il n'y a que des CHAR_BITbits *s, ce qui ne serait pas suffisant pour certains messages. Mais vous avez raison s++. Merci.
Ray
1

APL (Dyalog) , 36 octets

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

Essayez-le en ligne!

Trouve les mod-3 indices dans l'alphabet sans S et Z . Puisque l'espace, S et Z ne sont pas trouvés, ils "ont" un indice 25 (un de plus que l'indice max), ce qui est bon pour l'espace. Ensuite , nous avons juste besoin d'ajouter 3 pour chaque S ou Z .

{ fonction anonyme où l'argument est représenté par :

⎕A~'SZ' l' alphabet majuscule A , sauf pour S et Z

819⌶ minuscule

⍵⍳⍨ les ɩ ndices de l'argument en ce que

¯1+ ajouter un négatif

3| mod-3

1+ ajouter un (cela convertit tous les 0-mods en 3)

(), Ajouter:

  ⍵∊'sz' Booléen où l'argument est s ou z

   multiplier par 3

+/ somme

Adam
la source
1

C (gcc) , 7577 octets

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

La chaîne non imprimable ""est une table de 04 01 02 03 01 02 03 04.

Essayez-le en ligne!

Keyu Gan
la source
@ceilingcat merci!
Keyu Gan
1

Pip , 100 90 octets

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

Vérifiez chaque caractère de l'entrée pour une correspondance dans chaque élément de b. L'index de cette correspondance plus 1 est ajouté au total.

Essayez-le en ligne!

Kenneth Taylor
la source