Скільки разів я повинен натискати це?


24

Ми всі звикли до старої школи клавіатури телефону, правда? Для довідки, ось як це виглядає:

Телефонна клавіатура


Враховуючи рядок, що складається лише з малих букв ASCII та одинарних пробілів , ваше завдання полягає в тому, щоб повернути кількість дотиків, які слід зробити, щоб набрати повну рядок за допомогою клавіатури телефону, як вище.

Для тих, хто з цим незнайомий, ось як це працює:

  • Наприклад, ключ із цифрою 2також містить рядок, abcзаписаний на ньому. Для введення aпотрібно натиснути цю клавішу один раз, оскільки bви повинні натиснути двічі, а для цього - cтричі.

  • Для послідовних листів, які знаходяться на одній клавіші, потрібно почекати 1 секунду, перш ніж знову натиснути. Отже, якщо ви хочете ввести cb, потрібно натиснути 3 рази c, зачекати секунду, а потім натиснути двічі b, тому ще 5 натискань.

  • Те саме стосується всіх інших клавіш, за винятком одного пробілу, на який потрібно лише 1 натискання. Також зауважте, що ключі 7і на 9них чотири літери. Застосовується той самий алгоритм, різниця лише в кількості букв. Рядки, що відповідають кожній клавіші, можна знайти на зображенні вище (але в нижньому регістрі) або в наступному списку, який містить усі символи, які ви можете отримати:

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

Випробування

Введення -> Вихід (Пояснення)

"" -> 0 (нічого не слід натискати)
"вода" -> 8 ("w, a, t" кожен потребує 1 крана (на клавішах 9, 2 і 8), "e" вимагає 2 крана (на клавіші 3), "r" вимагає 3 крана (на клавіші 7 ), 1 + 1 + 1 + 2 + 3 = 8)
"мило" -> 9 (4 + 3 + 1 + 1)
"кандела" -> 13 (3 + 1 + 2 + 1 + 2 + 3 + 1)
"кодовий гольф" -> 20 (3 + 3 + 1 + 2 + 1 (для місця) + 1 + 3 + 3 + 3)
"цар пагорба" -> 33 (2 + 3 + 2 + 1 + 1 + 3 + 3 + 1 + 1 + 2 + 2 + 1 + 2 + 3 + 3 + 3)

Технічні характеристики

  • Застосовуються стандартні правила вводу / виводу та лазівки за замовчуванням.

  • Ви можете брати дані лише в рідному типі String для вашої мови. Вихідним може бути ціле число або рядкове подання цього цілого числа.

  • Це , найкоротша відповідь на кожній мові виграє.




2
Я думаю, що це було б цікавішим питанням, якби ти робив 1 кран за секунду, і довелося чекати 1 секунду, а замість кранів рахувати секунди .
Якк

@Yakk Це було б занадто складно
містер Xcoder

@ Mr.Xcoder Ви впевнені, хоча? Я бачив, як майстри коду тут роблять неможливі речі за меншого простору, ніж твіт.
J_F_B_M

Відповіді:


11

JavaScript (ES6) 77 66 64 60 байт

(Збережено кілька байт завдяки @Johan Karlsson та @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)&&tза 71 байт
Йохан Карлссон

Дякую, @JohanKarlsson, я зрозумів те саме, що знаходився під душем! Знайшла ще одну оптимізацію для гоління ще 5 байт.
Рік Хічкок

6
Я знайшов чисто арифметичне рішення для 71 байт: f=s=>[...s].map(c=>t+=((c=parseInt(0+c,36))>23?c+3:c&&~-c%3)%7%4+1,t=0)|t.
Ніл

1
@Neil, хоча це може бути не коротшим, але він, безумовно, розумніший.
Рік Хічкок

1
@Neil Вам слід це опублікувати.
Містер Xcoder

7

05AB1E , 29 26 25 байт

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

Спробуйте в Інтернеті!

Пояснення

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

Вибачте, але для порожнього вводу це дає 10. Добре деінде
містер Xcoder

@ Mr.Xcoder: Порожня рядок не дає виводу, але вона все-таки неправильна. Дякую за повідомлення, я це виправлю.
Емінья

2
Це дає 10 на TIO.
Містер Xcoder

@ Mr.Xcoder: Так, ви повинні чітко дати порожній рядок. Жоден вхід не є таким же, як порожній рядок. Це трохи заплутано я знаю. Виправлено зараз, хоча :)
Emigna

@ Mr.Xcoder: Пустий рядок вводиться таким чином
Emigna

7

Python 2 , 56 байт

Використовується той же алгоритм, що і рішення Javascript @ RickHitchcock

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

Спробуйте в Інтернеті!


Цікаве рішення. Як це працює для пробілів, я не розумію його>. <?
Містер Xcoder

@ Mr.Xcoder для нічого, що не є в рядку, '...'.find(c)повертається -1. Додавши 2, ми отримуємо одну клавішу натискання.
ов

Я знав, що це повернулося -1, але не зрозумів, що ти маєш +2після себе котельну плиту ... У будь-якому разі, найкоротше рішення Python на сьогоднішній день.
Містер Xcoder

Омл, мені трапилося саме таке рішення після того, як поволі переграли програму, поки я не зрозумів, що ти її розмістив :( Приємна робота і для пошуку цього рішення :)
Маріо Ішак

5

Python 3 , 69 67 65 64 байт

1 байт дякую містеру Xcoder.

1 байт завдяки Феліпе Нарді Батісті.

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

Спробуйте в Інтернеті!


Зберегти один байт, замінюючи i==" "з i<"a", тому що ви отримаєте тільки букви і прогалини
г -

4
61 хвилина ... занадто пізно!
Ерік Аутгольфер

5

Діалог APL, 37 байт

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

Спробуйте в Інтернеті!

Як?

Отримайте ndex кожного символу введення в рядку 'adgjmptw behknqux~cfilorvy~'( sі zбуде за замовчуванням 28), розділіть на 9, округніть і підсумовуйте.


Ви можете використати 'adgjmptw ' 'behknqux' 'cfilorvy' 'sz'для збереження декількох байт
Kritixi Lithos


@LeakyNun onice
Uriel

Ви можете залишити пробіл у рядку
Kritixi Lithos

@Uriel зачекайте, вам не потрібно рахувати, f←так що це 47 байт
Leaky Nun

4

JavaScript (ES6), 71 байт

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>

Не дивіться таблиць з літерами! Я не зовсім зрозумів формулу @ LeakyNun, тому придумав свою.


Чиста арифметика :)
Містер Xcoder

Що s=>[...s]робити, чому не простоs=>s.map()...
Еван Керролл

1
@EvanCarroll s- це рядок, тому ви не можете mapїї безпосередньо. ...sвона повторює s, [...s]перетворюючи ітерацію в масив, ефективно розбиваючись sна масив символів.
Ніл

4

C, 211 196 байт

Перше подання тут ... виглядає досить тривалим, і я бачу, що це не ефективний підхід, але принаймні це працює :)

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

Негольована версія:

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)може бути k[i].
CalculatorFeline

Ви можете скоротити пробіл після *(напр. char*n) І додати свої декларації до порожнього forвиступу (замість того, щоб у int s=0,j=0;(for(;вас було for(int s=0,k=0;) та замість i==0використання!i
Завдання

Дякую за ці підказки. Я не міг поставити sв цикл for, тому що використовую його згодом, але я склав intдекларації і використав assignemts там, де мені це потрібно.
dbuchmann

Так, гольф C! Як би там не було, деякі покажчики: петлі суворіші, ніж циклі майже у всіх ситуаціях - скористайтеся вільними крапками з комою, особливо в ітераційному виразі. Використовуйте коси замість крапки з комою в більшості місць, це дозволяє уникнути, не маючи фігурних дужок у більшості місць. Є й інші оптимізації, але вони більш залежать від того, до якої версії C ви компілюєте.
dj0wns

4

Haskell - 74 71 62 байт

Редагувати: видалено 3 байти за допомогою розуміння списку замість фільтра

Редагувати: Збережіть 9 байт завдяки Сиракузі, Лайконі та Згарбу!

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

Використання

λ> f "candela"
13
λ>

Спробуйте в Інтернеті!


Яке призначення копій букв?
Містер Xcoder

@ Mr.Xcoder Використовується для підрахунку дотиків, я додам пояснення.
Генрі

Ви можете зберегти один байт, переписавши fв f=length.(=<<)(\x->x:[y|y<-l,y==x]), де (=<<)знаходиться concatMapтут.
siracusa

І ще один із поверненням до filter:f=length.(=<<)(\x->x:filter(==x)l)
siracusa

1
Оскільки ви використовуєте lлише один раз, його можна накреслити.
Laikoni


3

Clojure, 82 76 байт

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

О, це простіше просто filterі countніж використовувати frequencies. Оригінал:

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

Рядок кодує в скільки разів більше, ніж раз, коли потрібно натиснути клавішу для заданого символу :)





2

Java, 95 73 байт

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

Завдяки Кевіну Крейсейну за те, що він зробив функцію лямбда-виразом (де aє тип String). 95 байт стали 73 байти!

Лямбда-вираз підсумовує кількість натискань кожного символу за допомогою map(). map()перетворює кожен символ (ASCII в діапазоні сатиричного є 97-122) в потоці до відповідного значення (виглядає як проста пила хвиля, але , беручи до уваги як 4 циклу напружує) , використовуючи цю математику: 1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112). Ось графік десмосу цієї моделі.


У списку лазівки написано не розміщувати фрагменти коду, хоча, схоже, це зробили всі досі. Так чи інакше, моя повна програма - 130 байт . Ось це: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());}}
Адам Менденхолл

1
Ласкаво просимо до PPCG! Ви справді праві, що фрагменти заборонені, але за замовчуванням - це програма чи функція . А з Java 8 ви можете використовувати лямбда. Так що в цьому випадку a->{return a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum();}дозволено. А оскільки це єдине твердження про повернення, a->a.chars().map(b->1+(b<64?0:b+(Math.abs(b-115)<4?4:5))%(3+b/112)).sum()( 73 байти ) було б вашою відповіддю. Також, ось TryItOnline-посилання вашої відповіді, яке ви можете додати до своєї відповіді. Знову: ласкаво просимо, і приємна відповідь. +1 від мене.
Kevin Cruijssen

2
Деякі речі, які слід зазначити про лямбда. Вам не доведеться рахувати f=ні провідну напівкрапку ;. І вам також не потрібно додавати тип параметра до тих пір, поки ви згадаєте, що це за тип (тому замість цього (String a)->ви можете використовувати a->та згадувати, що вхід aє Stringу вашій відповіді). О, і Поради щодо гольфу на Java та Поради щодо гольфу на <всіх мовах> можуть бути цікавими для читання, якщо ви цього ще не зробили.
Кевін Круїссен

1

Математика, 83 байти

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

Здається, загальновизнаним є те, що у відповідях Mathematica дозволяється використовувати списки символів для рядкових змінних, таких як вхід до цієї функції. (Також є aвідсутність на початку "bc1..."?)
Грег Мартін

це код golf.це дає правильний результат без а. "Tr" робить роботу
J42161217

1

QBIC , 94 байти

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

Пояснення

[    |      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 байт

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

Спробуйте в Інтернеті!

Складає по одному знаку на рядок, транслітерує кожний новий рядок +, кожний пробіл 1і кожну букву з відповідною кількістю натискань. bc робить суму.


на вашій машині вам може знадобитисяbc <(fold -1|tr "\n "adgjmptwbehknquxcfilorvysz +[1*9][2*8][3*8]44;echo 0)
marcosm

1

C, 92 88 байт

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

Ви можете використовувати s=nдля заміни return n, і поєднувати s++;з c=*s. Це може бути на 9 байт коротше.
Кейу Ган

@KeyuGan s=nне працюватиме, оскільки sце місцевий характер. І *s=nце не працює, оскільки є лише CHAR_BITбіти *s, яких не вистачить для деяких повідомлень. Але ти прав про те s++. Спасибі.
Рей

1

APL (Dyalog) , 36 байт

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

Спробуйте в Інтернеті!

Знаходять моди-3 індексів в алфавіті без S і Z . Оскільки простір S і Z не знайдені, вони "мають" індекс 25 (на один більше, ніж максимальний індекс), що добре для простору. Тоді нам просто потрібно додати 3 для кожного S або Z .

{ анонімна функція, де аргумент представлений :

⎕A~'SZ' верхній регістр A lphabet, за винятком S і Z

819⌶ малі літери

⍵⍳⍨ в ɩ ndices аргументу в тому , що

¯1+ додати негативну

3| мод-3

1+ додати один (це перетворює всі 0-моди в 3)

(), Доплата:

  ⍵∊'sz' Булевий, де аргумент або s, або z

   помножити на 3

+/ сума



1

Піп , 100 90 байт

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

Перевірте кожен символ введення на відповідність у кожному елементі b. Індекс цієї відповідності плюс 1 додається до загальної суми.

Спробуйте в Інтернеті!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.