Berapa kali saya harus menekan ini?

24

Kita semua terbiasa dengan tombol telepon sekolah lama, kan? Untuk referensi, berikut ini tampilannya:

Telepon Keybad


Diberikan String yang hanya terdiri dari huruf - huruf ASCII huruf kecil dan spasi tunggal , tugas Anda adalah mengembalikan jumlah ketukan yang harus dibuat untuk mengetikkan String penuh dengan keypad telepon seperti yang di atas.

Bagi mereka yang tidak terbiasa dengan ini, inilah cara kerjanya:

  • Kunci dengan digit 2, misalnya, juga memiliki string yang abcditulis di atasnya. Untuk mengetik a, Anda harus menekan tombol ini sekali, karena bAnda harus menekan dua kali dan untuk cAnda harus menekan tiga kali.

  • Untuk huruf berurutan yang menggunakan tombol yang sama, Anda harus menunggu 1 detik sebelum menekan lagi. Jadi, jika Anda ingin mengetik cb, Anda harus menekan 3 kali untuk c, tunggu sebentar dan kemudian tekan dua kali b, jadi masih 5 ketukan.

  • Hal yang sama berlaku untuk semua tombol lain, kecuali untuk satu ruang, yang hanya membutuhkan 1 tekan. Perhatikan juga bahwa tombol 7dan 9ada empat huruf di atasnya. Algoritma yang sama diterapkan, satu-satunya perbedaan adalah jumlah huruf. String yang terkait dengan setiap tombol dapat ditemukan pada gambar di atas (tetapi huruf kecil), atau dalam daftar berikut, yang berisi semua karakter yang mungkin Anda terima:

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

Uji Kasus

Input -> Output (Penjelasan)

"" -> 0 (tidak ada yang disadap)
"air" -> 8 ("w, a, t" masing-masing membutuhkan 1 keran (pada tombol 9, 2 dan 8), "e" memerlukan 2 keran (pada tombol 3), "r" membutuhkan 3 keran (pada tombol 7 ), 1 + 1 + 1 + 2 + 3 = 8)
"sabun" -> 9 (4 + 3 + 1 + 1)
"candela" -> 13 (3 + 1 + 2 + 1 + 2 + 3 + 1)
"kode golf" -> 20 (3 + 3 + 1 + 2 + 1 (untuk ruang) + 1 + 3 + 3 + 3)
"raja bukit" -> 33 (2 + 3 + 2 + 1 + 1 + 3 + 3 + 1 + 1 + 2 + 2 + 1 + 2 + 3 + 3 + 3)

Spesifikasi

  • Aturan I / O standar dan Celah Default berlaku.

  • Anda hanya dapat mengambil input dalam tipe String asli bahasa Anda. Output dapat berupa integer atau representasi string dari integer itu.

  • Ini adalah , jawaban terpendek dalam setiap bahasa menang.

Tuan Xcoder
sumber
Terkait . Terkait .
Shaggy
2
Saya pikir ini akan menjadi pertanyaan yang lebih menarik jika Anda melakukan 1 ketuk per detik, dan harus menunggu 1 detik, dan menghitung detik bukannya ketukan.
Yakk
@ Yakk Itu akan terlalu rumit
Tn. Xcoder
@ Mr.Xcoder Anda yakin? Saya telah melihat penyihir kode di sini melakukan hal-hal yang mustahil dalam ruang kurang dari tweet.
J_F_B_M

Jawaban:

11

JavaScript (ES6) 77 66 64 60 byte

(Menyimpan beberapa byte berkat @Johan Karlsson dan @Arnauld).

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

Rick Hitchcock
sumber
(s,t=0)=>[...s].map(l=>t+=(1+'behknquxcfilorvysz'.indexOf(l)/8|0)+1)&&tuntuk 71 byte
Johan Karlsson
Terima kasih, @JohanKarlsson, saya menemukan hal yang sama ketika sedang mandi! Menemukan pengoptimalan lain untuk mengurangi 5 byte lagi.
Rick Hitchcock
6
Saya menemukan solusi murni ilmu hitung untuk 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, sementara itu mungkin tidak lebih pendek, itu tentu lebih pintar.
Rick Hitchcock
1
@Nil Anda harus mempostingnya.
Tn. Xcoder
7

05AB1E , 29 26 25 byte

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

Cobalah online!

Penjelasan

ð¢                         # 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
sumber
Maaf, tetapi untuk input kosong ini memberikan 10. Ini baik-baik saja di tempat lain
Tn. Xcoder
@ Mr.Xcoder: String kosong tidak menghasilkan, tetapi masih salah. Terima kasih telah memberi tahu, saya akan memperbaikinya.
Emigna
2
Ini memberi 10 pada TIO.
Tn. Xcoder
@ Mr.Xcoder: Ya, Anda harus memberikan string kosong secara eksplisit. Tidak ada input yang tidak sama dengan string kosong. Agak membingungkan saya tahu. Tetap sekarang :)
Emigna
@ Mr.Xcoder: Input string kosong diberikan seperti ini
Emigna
7

Python 2 , 56 byte

Menggunakan algoritma yang sama dengan solusi Javascript @ RickHitchcock

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

Cobalah online!

ovs
sumber
Solusi menarik. Bagaimana cara kerjanya untuk ruang, saya tidak mengerti>. <?
Tn. Xcoder
@ Mr.Xcoder untuk apa pun yang tidak ada dalam string, '...'.find(c)kembali -1. Dengan menambahkan 2 kita mendapatkan satu penekanan tombol.
ovs
Saya tahu itu kembali -1, tetapi tidak menyadari Anda memiliki +2setelah boilerplate ... Pokoknya, solusi Python terpendek sejauh ini.
Tn. Xcoder
Oml, saya kebetulan membuat solusi yang persis sama setelah perlahan-lahan menurunkan program saya, sampai saya menyadari Anda mempostingnya :( Pekerjaan yang bagus untuk menemukan solusi ini juga :)
Mario Ishac
5

Python 3 , 69 67 65 64 byte

1 byte terima kasih kepada Tn. Xcoder.

1 byte terima kasih kepada Felipe Nardi Batista.

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

Cobalah online!

Biarawati Bocor
sumber
Simpan satu byte dengan menggantinya i==" "dengan i<"a", karena Anda hanya menerima huruf dan spasi
Tn. Xcoder
4
61 menit ... terlambat!
Erik the Outgolfer
5

Dyalog APL, 37 byte

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

Cobalah online!

Bagaimana?

Dapatkan ndex dari setiap karakter input dalam string 'adgjmptw behknqux~cfilorvy~'( sdan zakan default ke 28), bagi dengan 9, bulatkan dan jumlahkan.

Uriel
sumber
Anda dapat menggunakan 'adgjmptw ' 'behknqux' 'cfilorvy' 'sz'untuk menyimpan beberapa byte
Kritixi Lithos
49 bytes
Leaky Nun
@LeakyNun onice
Uriel
Anda dapat menjatuhkan ruang dalam string
Kritixi Lithos
@Uriel tunggu, Anda tidak perlu menghitung f←sehingga itu adalah 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>

Tidak terlihat meja surat! Saya tidak begitu mengerti formula @ LeakyNun jadi saya membuat sendiri.

Neil
sumber
Aritmatika murni :)
Tn. Xcoder
Apa yang s=>[...s]dilakukan mengapa tidak adils=>s.map()...
Evan Carroll
1
@EvanCarroll sadalah sebuah string, jadi Anda tidak mapbisa langsung melakukannya. ...siterates over s, sementara [...s]mengubah iterasi menjadi array, secara efektif membelah smenjadi array karakter.
Neil
4

C, 211 196 byte

Pengajuan pertama di sini ... terlihat cukup panjang dan saya melihat bahwa ini bukan pendekatan yang efisien, tetapi setidaknya berhasil :)

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 tidak disatukan:

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
sumber
*(k+i)bisa k[i].
CalculatorFeline
Anda dapat memotong spasi setelah *(misalnya char*n), dan menambahkan deklarasi Anda ke forpernyataan kosong Anda (bukan int s=0,j=0;(for(;Anda akan for(int s=0,k=0;) dan bukannya i==0menggunakan!i
Tas
Terima kasih atas petunjuknya. Saya tidak bisa memasukkan ske dalam for loop karena saya menggunakannya nanti, tapi saya menempatkan intdeklarasi bersama dan menggunakan assignemts di mana saya membutuhkannya.
dbuchmann
Yay sesama pegolf C! Bagaimanapun, beberapa petunjuk: untuk loop benar-benar lebih baik daripada sementara loop di hampir semua situasi - mengambil keuntungan dari titik koma gratis, terutama dalam ekspresi iterasi. Gunakan koma alih-alih titik koma di sebagian besar tempat, ini memungkinkan Anda untuk pergi dengan tidak memiliki kurung kurawal di sebagian besar tempat. Ada optimasi lain tetapi mereka lebih bergantung pada versi C yang Anda kompilasi.
dj0wns
4

Haskell - 74 71 62 byte

Sunting: dihapus 3 byte dengan menggunakan pemahaman daftar alih-alih filter

Sunting: Hemat 9 byte berkat Siracusa, Laikoni dan Zgarb!

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

Pemakaian

λ> f "candela"
13
λ>

Cobalah online!

Henry
sumber
Apa tujuan dari surat duplikat?
Tn. Xcoder
@ Mr.Xcoder Ini digunakan untuk menghitung ketukan, saya akan menambahkan penjelasan.
Henry
Anda dapat menyimpan satu byte dengan menulis ulang fke f=length.(=<<)(\x->x:[y|y<-l,y==x]), di mana (=<<)adalah concatMapdi sini.
siracusa
Dan satu lagi dengan kembali ke filter:f=length.(=<<)(\x->x:filter(==x)l)
siracusa
1
Karena Anda lhanya menggunakan sekali, itu bisa diuraikan.
Laikoni
3

Clojure, 82 76 byte

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

Oh itu lebih sederhana untuk digunakan filterdan countdigunakan frequencies. Asli:

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

String mengkodekan berapa kali lebih dari sekali Anda perlu menekan tombol untuk karakter yang diberikan :)

NikoNyrh
sumber
2

Python 3 , 91 byte

lambda x:sum(j.find(i)+1for j in' !abc!def!ghi!jkl!mno!pqrs!tuv!wxyz'.split('!')for i in x)

Cobalah online!

officialaimm
sumber
2

Python 3 , 60 byte

Mungkin kurang optimal, karena ini adalah golf pertama saya di Python.

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

Cobalah online!

Arnauld
sumber
2

Retina , 46 36 byte

Terima kasih kepada CalculatorFeline untuk menghemat 6 byte.

s|z
,c
[cfilorvy]
,b
[behknqux]
,,
.

Cobalah online!

Martin Ender
sumber
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()

Terima kasih kepada Kevin Cruijssen karena membuat fungsi ekspresi lambda (di mana atipenya String). 95 byte menjadi 73 byte!

Ekspresi lambda merangkum jumlah pers dari setiap karakter menggunakan map(). map()bertobat masing-masing karakter (ASCII di kisaran huruf kecil adalah 97-122) di sungai dengan nilai yang sesuai (terlihat seperti gelombang gergaji sederhana, namun dengan mempertimbangkan baik 4 siklus menjengkelkan) menggunakan matematika ini: 1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112). Inilah grafik desmos dari model itu.

Adam Mendenhall
sumber
Daftar celah mengatakan tidak memposting potongan kode meskipun sepertinya semua orang sejauh ini telah melakukan itu. Either way, program lengkap saya adalah 130 byte . Ini dia: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
Selamat datang di PPCG! Anda memang benar bahwa snippet tidak diizinkan, tetapi defaultnya adalah program atau fungsi . Dan dengan Java 8 Anda dapat menggunakan lambdas. Jadi dalam hal a->{return a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum();}ini diperbolehkan. Dan karena itu adalah pernyataan pengembalian tunggal, a->a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum()( 73 byte ) akan menjadi jawaban Anda. Juga, di sini ada tautan TryItOnline dari jawaban Anda yang mungkin ingin Anda tambahkan ke jawaban Anda. Sekali lagi: selamat datang, dan jawaban yang bagus. +1 dari saya.
Kevin Cruijssen
2
Beberapa hal yang perlu diperhatikan tentang lambdas. Anda tidak harus menghitung f=atau semi-colon terkemuka ;. Dan Anda juga tidak perlu menambahkan jenis parameter selama Anda menyebutkan apa jenisnya (jadi alih-alih (String a)->Anda dapat menggunakan a->dan menyebutkan bahwa input aadalah Stringjawaban Anda). Oh, dan Tip untuk bermain golf di Jawa dan Tips untuk bermain golf di <semua bahasa> mungkin menarik untuk dibaca, jika Anda belum.
Kevin Cruijssen
1

Mathematica, 83 byte

c=Characters;Tr[Tr@Mod[c@"bc1def1ghi1jkl1mno1pqrstuv1wxyz "~Position~#,4]+1&/@c@#]&
J42161217
sumber
Tampaknya diterima secara umum bahwa jawaban Mathematica diizinkan untuk menggunakan daftar karakter untuk variabel string, seperti input ke fungsi ini. (Juga apakah ada yang ahilang pada awal "bc1..."?)
Greg Martin
ini adalah kode golf.ini memberikan hasil yang tepat tanpa "Tr" melakukan pekerjaan
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

Penjelasan

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

Bash ,69 68 byte

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

Cobalah online!

Lipat satu karakter per baris, transliterasikan setiap baris baru dengan +, setiap spasi dengan 1dan setiap huruf dengan jumlah push yang sesuai. bc melakukan penjumlahan.

marcosm
sumber
pada mesin Anda, Anda mungkin perlubc <(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;}
sinar
sumber
Anda dapat menggunakan s=nuntuk mengganti return n, dan menggabungkan s++;dengan c=*s. Itu bisa lebih pendek 9 byte.
Keyu Gan
@KeyuGan s=ntidak akan berfungsi, karena sini adalah lokal. Dan *s=ntidak akan berfungsi karena hanya ada CHAR_BITbit di *sdalamnya, yang tidak akan cukup untuk beberapa pesan. Tapi Anda benar tentang itu s++. Terima kasih.
Ray
1

APL (Dyalog) , 36 byte

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

Cobalah online!

Menemukan mod-3 indeks dalam alfabet tanpa S dan Z . Karena ruang, S , dan Z tidak ditemukan, mereka "memiliki" indeks 25 (satu lebih dari indeks maks), yang baik untuk ruang. Kemudian kita hanya perlu menambahkan 3 untuk masing-masing S atau Z .

{ fungsi anonim di mana argumen diwakili oleh :

⎕A~'SZ'lfabet  huruf besar A , kecuali untuk S dan Z

819⌶ huruf kecil

⍵⍳⍨ yang ɩ ndices argumen bahwa

¯1+ tambahkan yang negatif

3| mod-3

1+ tambahkan satu (ini mengkonversi semua 0-mod ke 3)

(... ), tambahkan:

  ⍵∊'sz' Boolean di mana argumennya adalah s atau z

   kalikan dengan 3

+/ jumlah

Adám
sumber
1

C (gcc) , 7577 byte

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

String yang tidak dapat dicetak ""adalah tabel dari 04 01 02 03 01 02 03 04.

Cobalah online!

Keyu Gan
sumber
@ceilingcat terima kasih!
Keyu Gan
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

Periksa setiap karakter input untuk kecocokan di setiap elemen b. Indeks kecocokan itu ditambah 1 akan ditambahkan ke total.

Cobalah online!

Kenneth Taylor
sumber