Ile razy mam to naciskać?

24

Wszyscy jesteśmy przyzwyczajeni do old-schoolowej klawiatury telefonu, prawda? W celach informacyjnych wygląda to tak:

Klawiatura telefoniczna


Biorąc pod uwagę ciąg znaków składający się tylko z małych liter ASCII i pojedynczych spacji , Twoim zadaniem jest zwrócenie liczby naciśnięć, które należy wykonać, aby wpisać pełny ciąg za pomocą klawiatury telefonu, jak powyżej.

Dla tych, którzy nie są zaznajomieni z tym, oto jak to działa:

  • Na przykład klucz z cyfrą 2ma również abczapisany ciąg znaków . Aby pisać a, musisz nacisnąć ten klawisz jeden raz, ponieważ bmusisz nacisnąć dwa razy, a także ctrzy razy.

  • W przypadku kolejnych liter tego samego klawisza należy odczekać 1 sekundę przed ponownym naciśnięciem. Tak więc, jeśli chcesz pisać cb, musisz nacisnąć 3 razy c, poczekać sekundę, a następnie nacisnąć dwa razy b, aby nadal 5 dotknięć.

  • To samo dotyczy wszystkich pozostałych klawiszy, z wyjątkiem pojedynczej spacji, która wymaga tylko 1 naciśnięcia. Należy również pamiętać, że klucze 7i 9mają na nich cztery litery. Zastosowano ten sam algorytm, a jedyną różnicą jest liczba liter. Ciągi odpowiadające każdemu kluczowi można znaleźć na obrazku powyżej (ale małymi literami) lub na poniższej liście, która zawiera wszystkie znaki, które możesz otrzymać:

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

Przypadki testowe

Wejście -> Wyjście (objaśnienie)

„” -> 0 (nic nie należy stukać)
„woda” -> 8 („w, a, t” każdy wymaga 1 dotknięcia (na klawiszach 9, 2 i 8), „e” wymaga 2 uderzeń (na klawiszu 3), „r” wymaga 3 uderzeń (na klawiszu 7 ), 1 + 1 + 1 + 2 + 3 = 8)
„mydło” -> 9 (4 + 3 + 1 + 1)
„candela” -> 13 (3 + 1 + 2 + 1 + 2 + 3 + 1)
„kod golfa” -> 20 (3 + 3 + 1 + 2 + 1 (dla miejsca) + 1 + 3 + 3 + 3)
„król wzgórza” -> 33 (2 + 3 + 2 + 1 + 1 + 3 + 3 + 1 + 1 + 2 + 2 + 1 + 2 + 3 + 3 + 3)

Okular

  • Obowiązują standardowe reguły we / wy i domyślne luki.

  • Możesz wprowadzać dane tylko w rodzimym typie łańcucha w swoim języku. Wyjściem może być liczba całkowita lub ciąg znaków reprezentujący tę liczbę całkowitą.

  • To jest , wygrywa najkrótsza odpowiedź w każdym języku .

Pan Xcoder
źródło
Związane . Związane .
Kudłaty
2
Myślę, że byłoby to bardziej interesujące pytanie, jeśli wykonałeś 1 stuknięcie na sekundę i musiałeś poczekać 1 sekundę, a zamiast stuknięć odliczyć sekundy .
Yakk
@Yakk To byłoby zbyt skomplikowane
Pan Xcoder
@ Mr.Xcoder Czy jesteś jednak pewien? Widziałem, jak tutaj czarodzieje kodu wykonują niemożliwe rzeczy na mniejszej przestrzeni niż tweet.
J_F_B_M

Odpowiedzi:

11

JavaScript (ES6) 77 66 64 60 bajtów

(Zapisano kilka bajtów dzięki @Johan Karlsson i @Arnauld).

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

Rick Hitchcock
źródło
(s,t=0)=>[...s].map(l=>t+=(1+'behknquxcfilorvysz'.indexOf(l)/8|0)+1)&&tdla 71 bajtów
Johan Karlsson
Dzięki, @JohanKarlsson, wymyśliłem to samo pod prysznicem! Znalazłem kolejną optymalizację, aby zmniejszyć liczbę kolejnych 5 bajtów.
Rick Hitchcock
6
Znalazłem rozwiązanie czysto arytmetycznego 71 bajtów: 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, choć może nie być krótszy, z pewnością jest mądrzejszy.
Rick Hitchcock
1
@Neil Powinieneś to opublikować.
Pan Xcoder
7

05AB1E , 29 26 25 bajtów

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

Wypróbuj online!

Wyjaśnienie

ð¢                         # 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
źródło
Przepraszam, ale dla pustego wejścia daje to 10. W porządku jest gdzie indziej
Pan Xcoder
@ Mr.Xcoder: Pusty ciąg nie daje danych wyjściowych, ale nadal jest nieprawidłowy. Dzięki za powiadomienie, naprawię to.
Emigna
2
Daje 10 na TIO.
Pan Xcoder
@ Mr.Xcoder: Tak, musisz jawnie podać pusty ciąg. Żadne dane wejściowe nie są takie same jak pusty ciąg. Wiem, to trochę mylące. Naprawiono teraz :)
Emigna
@ Mr.Xcoder: Pusty ciąg wejściowy jest podane jak to
Emigna
7

Python 2 , 56 bajtów

Używa tego samego algorytmu, co rozwiązanie Javascript @ RickHitchcock

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

Wypróbuj online!

ovs
źródło
Ciekawe rozwiązanie Jak to działa na spacje, nie rozumiem>. <?
Pan Xcoder
@ Mr.Xcoder dla wszystkiego, co nie jest w ciągu, '...'.find(c)zwraca -1. Dodając 2, otrzymujemy jedno naciśnięcie klawisza.
ovs
Wiedziałem, że wrócił -1, ale nie zdawałem sobie sprawy, że masz płytę +2główną ... W każdym razie, najkrótsze rozwiązanie Pythona.
Pan Xcoder
Oml, zdarzyło mi się stworzyć dokładnie to samo rozwiązanie po powolnym graniu w golfa mojego programu, dopóki nie zdałem sobie sprawy, że go opublikowałeś :(
Dobra
5

Python 3 , 69 67 65 64 bajtów

1 bajt dzięki Mr. Xcoder.

1 bajt dzięki Felipe Nardi Batista.

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

Wypróbuj online!

Leaky Nun
źródło
Oszczędź jeden bajt, zastępując i==" "go i<"a", ponieważ otrzymujesz tylko litery i spacje
Mr. Xcoder
4
61 minut ... za późno!
Erik the Outgolfer
5

Dyalog APL, 37 bajtów

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

Wypróbuj online!

W jaki sposób?

Uzyskaj ndex każdego znaku wejściowego w ciągu 'adgjmptw behknqux~cfilorvy~'( si zdomyślnie wyniesie 28), podziel przez 9, zaokrąglij w górę i zsumuj.

Uriel
źródło
Możesz użyć, 'adgjmptw ' 'behknqux' 'cfilorvy' 'sz'aby zapisać niektóre bajty
Kritixi Lithos
49 bajtów
Leaky Nun
@LeakyNun onice
Uriel
Możesz upuścić miejsce w ciągu
Kritixi Lithos
@Uriel czekaj, nie musisz liczyć, f←więc jest 47 bajtów
Leaky Nun
4

JavaScript (ES6), 71 bajtów

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>

Nie szukaj tablic z literami! Nie do końca zrozumiałem formułę @ LeakyNun, więc wymyśliłem własną.

Neil
źródło
Czysta arytmetyka :)
Pan Xcoder
Co robi s=>[...s], dlaczego nie tylkos=>s.map()...
Evan Carroll
1
@EvanCarroll sjest ciągiem, więc nie możesz mapgo bezpośrednio. ...siteruje się s, a [...s]konwertuje iterację do tablicy, skutecznie dzieląc ją sna tablicę znaków.
Neil
4

DO, 211 196 bajtów

Pierwsze zgłoszenie tutaj ... wygląda na dość długie i widzę, że nie jest to skuteczne podejście, ale przynajmniej działa :)

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

Wersja bez golfa:

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
źródło
*(k+i)może być k[i].
CalculatorFeline
Możesz wyciąć przestrzeń po *(np. char*n) I dodać swoje deklaracje do pustej forinstrukcji (zamiast int s=0,j=0;(for(;tego for(int s=0,k=0;) i zamiast i==0używać!i
Tas
Dziękuję za te wskazówki. Nie mogłem umieścić sw pętli for, ponieważ używam go później, ale intzłożyłem deklaracje razem i użyłem przypisań tam, gdzie ich potrzebowałem.
dbuchmann
Tak, inny golfista C! Tak czy inaczej, niektóre wskaźniki: dla pętli są zdecydowanie lepsze niż podczas pętli podczas prawie wszystkich sytuacji - skorzystaj z wolnych średników, szczególnie w wyrażeniu iteracyjnym. W większości miejsc używaj przecinków zamiast średników, co pozwala uniknąć zakręconych nawiasów klamrowych w większości miejsc. Istnieją inne optymalizacje, ale są one bardziej zależne od tego, do której wersji C kompilujesz.
dj0wns
4

Haskell - 74 71 62 bajtów

Edycja: usunąłem 3 bajty, używając zrozumienia listy zamiast filtru

Edycja: Zaoszczędź 9 bajtów dzięki Siracusa, Laikoni i Zgarb!

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

Stosowanie

λ> f "candela"
13
λ>

Wypróbuj online!

Henz
źródło
Jaki jest cel duplikatów liter?
Mr. Xcoder
@ Mr.Xcoder Służy do liczenia uderzeń, dodam wyjaśnienie.
Henry
Możesz zapisać jeden bajt, przepisując fdo f=length.(=<<)(\x->x:[y|y<-l,y==x]), gdzie (=<<)jest concatMaptutaj.
siracusa
I kolejny z powrotem do filter:f=length.(=<<)(\x->x:filter(==x)l)
Siracusa
1
Ponieważ używasz ltylko raz, można wstawić.
Laikoni
3

Clojure, 82 76 bajtów

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

Och, jest prostszy w użyciu filteri countniż w użyciu frequencies. Oryginalny:

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

Ciąg koduje, ile razy więcej niż raz trzeba nacisnąć klawisz dla danego znaku :)

NikoNyrh
źródło
2

Python 3 , 60 bajtów

Prawdopodobnie nieoptymalny, ponieważ jest to mój pierwszy golf w Pythonie.

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

Wypróbuj online!

Arnauld
źródło
2

Java, 95 73 bajtów

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

Podziękowania dla Kevina Cruijssena za uczynienie tej funkcji wyrażeniem lambda (gdzie ajest typu String). 95 bajtów stało się 73 bajtami!

Wyrażenie lambda podsumowuje liczbę naciśnięć każdego użytego znaku map(). map()konwertuje każdy znak (ASCII w dolnym zakresie sprawa jest 97-122) w strumieniu na odpowiednią wartość (wygląda jak prosty fali piły, ale biorąc pod uwagę zarówno 4 cykle to denerwujące) za pomocą tej matematyki: 1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112). Oto wykres desmos tego modelu.

Adam Mendenhall
źródło
Lista luk mówi, żeby nie pisać fragmentów kodu, chociaż wygląda na to, że wszyscy do tej pory to zrobili. Tak czy inaczej, mój pełny program ma 130 bajtów . Oto on: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
Witamy w PPCG! Rzeczywiście masz rację, że fragmenty nie są dozwolone, ale domyślnie jest to program lub funkcja . A w Javie 8 możesz używać lambd. Więc w tym przypadku a->{return a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum();}jest dozwolone. A ponieważ jest to pojedyncza instrukcja zwracająca, a->a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum()( 73 bajty ) byłaby twoją odpowiedzią. Oto link TryItOnline do odpowiedzi, którą możesz chcieć dodać do swojej odpowiedzi. Ponownie: witamy i miła odpowiedź. +1 ode mnie
Kevin Cruijssen
2
Kilka rzeczy do zapamiętania na temat lambdas. Nie musisz liczyć f=ani wiodącego średnika ;. Nie musisz także dodawać typu parametru, o ile wspominasz, jaki jest typ (więc zamiast tego (String a)->możesz użyć a->i wspomnieć, że dane wejściowe aStringw odpowiedzi). Aha, i porady dotyczące gry w golfa w Javie oraz porady dotyczące gry w golfa w <wszystkich językach> mogą być interesujące do przeczytania, na wypadek gdybyś jeszcze tego nie zrobił.
Kevin Cruijssen
1

Mathematica, 83 bajty

c=Characters;Tr[Tr@Mod[c@"bc1def1ghi1jkl1mno1pqrstuv1wxyz "~Position~#,4]+1&/@c@#]&
J42161217
źródło
Wydaje się, że ogólnie przyjmuje się, że odpowiedzi Mathematica mogą używać list znaków dla zmiennych łańcuchowych, takich jak dane wejściowe do tej funkcji. (Czy też abrakuje na początku "bc1..."?)
Greg Martin
to jest kod golf. daje to właściwy wynik bez a. „Tr” wykonuje robotę
J42161217
1

QBIC , 94 bajty

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

Wyjaśnienie

[    |      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
źródło
1

Bash ,69 68 bajtów

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

Wypróbuj online!

Składa jeden znak w wierszu, transliteruje każdą nową linię, +każdą spację 1i każdą literę z odpowiednią liczbą naciśnięć. bc robi sumę.

marcosm
źródło
na twoim komputerze możesz potrzebowaćbc <(fold -1|tr "\n "adgjmptwbehknquxcfilorvysz +[1*9][2*8][3*8]44;echo 0)
marcosm
1

C, 92 88 bajtów

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;}
Promień
źródło
możesz użyć s=ndo zastąpienia return ni połączenia s++;z c=*s. Może być o 9 bajtów krótszy.
Keyu Gan
@KeyuGan s=nnie działa, ponieważ sjest to lokalny. I *s=nnie zadziałałoby, ponieważ są tylko CHAR_BITbity *s, co nie wystarczyłoby dla niektórych wiadomości. Ale masz rację co do s++. Dzięki.
Ray
1

APL (Dyalog) , 36 bajtów

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

Wypróbuj online!

Znajdzie mod-3 wskaźniki alfabetu bez S i Z . Ponieważ nie znaleziono spacji, S i Z , mają one „indeks” 25 (jeden więcej niż indeks maksymalny), co jest dobre dla spacji. Następnie wystarczy dodać 3 dla każdego S lub Z .

{ funkcja anonimowa, w której argument jest reprezentowany przez :

⎕A~'SZ' wielkie litery lphabet wyjątkiem S i Z.

819⌶ małe litery

⍵⍳⍨ z ɩ ndices z argumentem, że

¯1+ dodaj jeden negatywny

3| mod-3

1+ dodaj jeden (konwertuje wszystkie 0-mody do 3)

(), Poprzedzają:

  ⍵∊'sz' Boolean, gdzie argument to s lub z

   pomnóż przez 3

+/ suma

Adám
źródło
1

C (gcc) , 7577 bajty

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

Ciąg niedrukowalny ""to tabela 04 01 02 03 01 02 03 04.

Wypróbuj online!

Keyu Gan
źródło
@ceilingcat dzięki!
Keyu Gan
1

Pip , 100 90 bajtów

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

Sprawdź, czy każdy znak wejściowy jest zgodny w każdym elemencie b. Indeks tego meczu plus 1 zostaje dodany do sumy.

Wypróbuj online!

Kenneth Taylor
źródło