Порахуйте імпульси поворотного набору в телефонному номері (включаючи букви)


34

У день ваших бабусь і дідусів набір номера телефону робився за допомогою поворотного циферблата таким чином:

Щоб набрати кожну цифру, покладіть палець у відповідний отвір, потягніть його до упору і відпустіть. Механізм призведе до того, що циферблат повернеться до положення спокою, і телефон відключить і знову підключить ланцюг певну кількість разів, зробивши чутні клацання.

Набір цифри N вимагає N таких "імпульсів", за винятком N = 0, що становить десять імпульсів.

Поворотні телефони мають властивість, що для набору великих цифр (8, 9, 0) потрібно більше часу, ніж для малих цифр (1, 2, 3). Це було важливим фактором при складанні ранніх кодів кодів району, і чому Нью-Йорк з його щільною густотою населення (та телефонної лінії) отримав 212 (всього 5 імпульсів), тоді як 907 (26 імпульсів) пішли на малонаселену Аляску. Звичайно, все це стало неактуальним, коли набирали популярність сенсорний набір номера.

Змагання

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

Цифри

  • Цифри 1-9 вважаються такою кількістю імпульсів.
  • Цифра 0 вважається 10 імпульсами.

Листи

Зауважте, що цифри 2-9 на циферблаті мають літери латинського алфавіту, пов'язані з ними. Спочатку вони були призначені для іменних обмінів , але останні були повторно призначені для телефонних слів та для систем введення текстових повідомлень.

Ви повинні підтримувати наявність літер у своїх телефонних номерах, використовуючи призначення E.161 літер цифрам :

  • А, В, С = 2
  • D, E, F = 3
  • G, H, I = 4
  • J, K, L = 5
  • M, N, O = 6
  • P, Q, R, S = 7
  • T, U, V = 8
  • W, X, Y, Z = 9

Ви можете припустити, що дані вже були складені регістром у верхній або нижній регістр.

Інші персонажі

Ви повинні дозволити довільне використання символів ()+-./та пробілу як розділювачів форматування. Ви можете дозволити для цієї мети будь - який не буквено-цифровий символ, якщо це легше здійснити.

Ці символи не вносять внесок у кількість імпульсів.

Приклад коду

Таблиця пошуку та функції, що не використовується для гольфу в Python:

PULSES = {
    '1': 1,
    '2': 2, 'A': 2, 'B': 2, 'C': 2,
    '3': 3, 'D': 3, 'E': 3, 'F': 3,
    '4': 4, 'G': 4, 'H': 4, 'I': 4,
    '5': 5, 'J': 5, 'K': 5, 'L': 5,
    '6': 6, 'M': 6, 'N': 6, 'O': 6,
    '7': 7, 'P': 7, 'Q': 7, 'R': 7, 'S': 7,
    '8': 8, 'T': 8, 'U': 8, 'V': 8,
    '9': 9, 'W': 9, 'X': 9, 'Y': 9, 'Z': 9,
    '0': 10
}

def pulse_count(phone_num):
    return sum(PULSES.get(digit, 0) for digit in phone_num)

Приклад введення та виведення

  • 911 → 11
  • 867-5309 → 48
  • 713 555 0123 → 42
  • +1 (212) PE6-5000 → 57
  • 1-800-FLOWERS → 69
  • PUZZLES → 48

Я припускаю, що довільні пунктуації та пробіли ASCII обмежені тими, що зазвичай використовуються для телефонних номерів ( +- ()*#.) так само, як літери обмежені великими літерами. Виправте мене, якщо я помиляюся.
Адам

1
@ Adám: Я обмежив необхідні розділові знаки лише кількома загальними розділовими знаками. Він навмисно не включає *та #, які мають особливі значення на телефонах із сенсорним тоном і не піддаються набору на ротарії.
dan04

1
Чи можемо ми використовувати вхід з малих літер замість великого верхнього регістру? Чи можемо ми взяти масив символів замість рядка?
Grimmy

1
Я подорож у часі! Я подорож у часі! Я подорож у часі! Оскільки я, безумовно, користувався такими телефонами, коли я був дитиною, я, Я МОЙ ВЛАСНИЙ ГРАНДФАТЕР !!!!!!! Що насправді досить примхливе, коли я думаю про це. Блея !!!
Боб Джарвіс - Відновіть Моніку

3
Я дідусь. Я використовував такі телефони в 1950-х. І коли я переїхав до містечка в сільській місцевості, я виявив, що телефонна компанія не пропонує послуги сенсорного тону. Це було в 1985 році! Без жартів! У моєї бабусі в салоні був телефон, в якому був гачок і кривошип. Ви зняли навушник з гачка і повернули кривошип, щоб отримати оператора розподільного щита. Її довелося замінити, коли було встановлено прямий дистанційний набір.
Вальтер Мітті

Відповіді:


25

05AB1E , 19 18 17 15 байт

AÁ0ªā6+žq÷9š‡þO

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

Це перша відповідь на використання π. Навіщо використовувати π, запитаєте ви? Ну, листи асоціюються з 22233344455566677778889999, по порядку. Зауважте, як більшість цифр повторюються 3 рази, але 7 повторень 4 рази. Можна сказати, що кожна цифра в середньому повторюється (3 + 1/7) разів. Цікаво, чи є якесь число, яке приблизно становить 3 + 1/7 і займає менше байтів, ніж 22/7 ...

Це дає лише 4 7s, а не 4 9s, тому нам все-таки потрібно обробити Z як особливий випадок.

A               # alphabet (abcdefghijklmnopqrstuvwxyz)
 Á              # rotate right (zabcdefghijklmnopqrstuvwxy)
  0ª            # append 0 (zabcdefghijklmnopqrstuvwxy0)

ā6+             # range [7..33]
   žq÷          # divide by π (22233344455566677778889991010)
      9š        # prepend 9 (922233344455566677778889991010)

‡               # transliterate the implicit input with the two lists above
                # this replaces z → 9, a → 2, … y → 9, 0 → 10
 þ              # remove all non-digits
  O             # sum

Чому малі літери замість великих літер?
dan04

1
@ dan04, тому що 05AB1E має вбудований для просування "abcdefghijklmnopqrstuvwxyz", але не для "ABCDEFGHIJKLMNOPQRSTUVWXYZ". Я міг би перетворити алфавіт у великі регістри, а не перетворити введення в малі, але це той самий рахунок.
Гріммі

1
Я відредагував питання, щоб зробити ваші перші дві команди непотрібними.
dan04

3
@Jonah Я почав з ідеї розділити діапазон на постійну, щоб отримати бажану послідовність, тоді, шукаючи найкращого способу виразити "трохи більше 3" в 05AB1E, я згадав, що pi був вбудованим.
Гріммі

2
+1 для використання pi
Драконіс

9

C # (Visual C # Interactive Compiler) , 51 байт

n=>n.Sum(x=>x>64?(x-59-x/83-x/90)/3:x>47?1-~x%~9:0)

Збережено 1 байт завдяки @recursive

Збережено 10 байт завдяки спостереженню @ ExpiredData, яке () +-/.буде лише у вводі

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

n =>                     // Function taking input as string
  n.Sum(x =>             // Map each value 'x' through the following
    x>64 ?               //   If 'x' is an uppercase letter
      (x-59-x/83-x/90)/3 //     Take each char's ASCII value subtracted by 59, and subtract
                         //     one if the char is 'S' and one if the char is 'Z'
    : x>47 ?             //   Else if the char is a digit
      1-~x%~9            //   Take 1 - (-x - 1) % -10 (Maps 0 to 10, and 1-9 to themselves
    : 0                  //   Else, 0
  )                      // And sum it all up, then return it

4
-10є ~9, який повинен працювати в контексті.
рекурсивна

@recursive Це розумно, дякую
Втілення

1
x <91 перевірка є зайвою, оскільки вхід буде складатися лише з () + -. / клавіша пробілу та числа, які всі <64, отже, ми можемо визначити, чи є символ великим регістром, просто перевіривши x> 64 (тому -5 байт)
Термін дії закінчився

Те ж саме стосується перевірки х <58, оскільки нічого в діапазоні 58-64 не буде на вході
Термін дії даних закінчився


5

APL (Dyalog Unicode) , 27 байт SBCS

Функція анонімного негласного префікса.

+/'@ADGJMPTW'∘⍸+11|(1⌽⎕D)∘⍳

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

()∘⍳ Знайдіть ɩ ndex * кожного символу в наступному рядку:
  * елементи, які не знайдені, отримайте індекс 1 + максимальний індекс, тобто 11
⎕D  цифр:"0123456789"

1⌽ циклічно обертати один крок вліво; "1234567890"

11| залишок ділення при діленні на 11 *
  * це дає 0 для всіх нецифрових значень
... + додайте це до наступного:

'@ADGJMPTW'∘⍸ɩ nterval ɩ NDEX * для кожного символу
  * Так [-∞, "@") дає 0, [ "@", "A") дає 1, [ "A", "D") дає 2 і т.д.
+/  сума,


5

Python 2 , 74 байти

lambda s:sum([(n-59-n/83-n/90)/3,1-~n%~9][n<58]for n in map(ord,s)if n>47)

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

Чи має деяку арифметику значення ASCII для кожного символу. Перший варіант перевіряє букви та другий варіант перевіряє цифри. Роз'яснення того, що всі знаки пунктуації, дозволені у введенні, мають значення ASCII, менші ніж 48, я можу спростити логіку, але новий метод взагалі може бути кращим.

Пітон 2 , 84 байти

lambda s:sum(1+'1xxxx2ABCx3DEFx4GHIx5JKLx6MNOx7PQRS8TUVx9WXYZ0'.find(c)/5for c in s)

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

Використовується твердо кодований рядок пошуку з кожним блоком з 5 символів, відповідним символам, що дають кожне значення, починаючи з 1. Пусті пробіли заповнюються x, які не можуть бути на вводі з великої літери. На щастя, символи, які не відображаються у рядку, створюють, -1для .findчого дається сума нуля.


5

JavaScript (Node.js) , ... 76 69 байт

s=>s.replace(/\w/g,q=>w+=1/q?+q||10:parseInt(q,35)*.32-1|0||9,w=0)&&w

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

-7 дякую @Arnauld!

Пояснення

 q |     1/q     |  +q  | parseInt(q,35)*.32 | parseInt(q,35)*.32-1|0 | Output
---+-------------+------+--------------------+------------------------+--------
 0 | Infinity(T) | 0(F) |         N/A        |           N/A          |   10
 1 |  1.0000(T)  | 1(T) |         N/A        |           N/A          |    1
 2 |  0.5000(T)  | 2(T) |         N/A        |           N/A          |    2
 3 |  0.3333(T)  | 3(T) |         N/A        |           N/A          |    3
 4 |  0.2500(T)  | 4(T) |         N/A        |           N/A          |    4
 5 |  0.2000(T)  | 5(T) |         N/A        |           N/A          |    5
 6 |  0.1666(T)  | 6(T) |         N/A        |           N/A          |    6
 7 |  0.1428(T)  | 7(T) |         N/A        |           N/A          |    7
 8 |  0.1250(T)  | 8(T) |         N/A        |           N/A          |    8
 9 |  0.1111(T)  | 9(T) |         N/A        |           N/A          |    9
 A |    NaN(F)   |  N/A |        3.20        |          2(T)          |    2
 B |    NaN(F)   |  N/A |        3.52        |          2(T)          |    2
 C |    NaN(F)   |  N/A |        3.84        |          2(T)          |    2
 D |    NaN(F)   |  N/A |        4.16        |          3(T)          |    3
 E |    NaN(F)   |  N/A |        4.48        |          3(T)          |    3
 F |    NaN(F)   |  N/A |        4.80        |          3(T)          |    3
 G |    NaN(F)   |  N/A |        5.12        |          4(T)          |    4
 H |    NaN(F)   |  N/A |        5.44        |          4(T)          |    4
 I |    NaN(F)   |  N/A |        5.76        |          4(T)          |    4
 J |    NaN(F)   |  N/A |        6.08        |          5(T)          |    5
 K |    NaN(F)   |  N/A |        6.40        |          5(T)          |    5
 L |    NaN(F)   |  N/A |        6.72        |          5(T)          |    5
 M |    NaN(F)   |  N/A |        7.04        |          6(T)          |    6
 N |    NaN(F)   |  N/A |        7.36        |          6(T)          |    6
 O |    NaN(F)   |  N/A |        7.68        |          6(T)          |    6
 P |    NaN(F)   |  N/A |        8.00        |          7(T)          |    7
 Q |    NaN(F)   |  N/A |        8.32        |          7(T)          |    7
 R |    NaN(F)   |  N/A |        8.64        |          7(T)          |    7
 S |    NaN(F)   |  N/A |        8.96        |          7(T)          |    7
 T |    NaN(F)   |  N/A |        9.28        |          8(T)          |    8
 U |    NaN(F)   |  N/A |        9.60        |          8(T)          |    8
 V |    NaN(F)   |  N/A |        9.92        |          8(T)          |    8
 W |    NaN(F)   |  N/A |       10.24        |          9(T)          |    9
 X |    NaN(F)   |  N/A |       10.56        |          9(T)          |    9
 Y |    NaN(F)   |  N/A |       10.88        |          9(T)          |    9
 Z |    NaN(F)   |  N/A |         NaN        |          0(F)          |    9

Всі [space]().+-/вони не захоплені /\w/g, тому вони не впливатимуть на загальну суму.




4

Сітківка 0,8,2 , 34 байти

T`WTPMJGDA`Rd
}T`L`2L
0
55
\d
$*
1

Спробуйте в Інтернеті! Посилання включає тестові випадки. Пояснення:

T`WTPMJGDA`Rd

Перетворіть букви WTPMJGDAв цифри 9..0.

}T`L`2L

Перемішайте всі інші літери вниз на 1 і повторюйте, поки всі літери не перетворяться в цифри.

0
55

Замініть 0їх, 55оскільки вони набирають однакову кількість імпульсів для набору.

\d
$*
1

Візьміть цифрову суму.


3

К4 , 44 байти

Рішення:

+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?

Приклади:

q)k)+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?"911"
11
q)k)+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?"867-5309"
48
q)k)+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?"+1 (212) PE6-5000"
57
q)k)+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")?"1-800-FLOWERS"
69

Пояснення:

Наївний підхід, швидше за все, досить погане. Індекс пошуку символів, оцінка пошуку, сума.

+/(1+(1+&(5#3),4 3 4),!10)(.Q.A,1_.Q.n,"0")? / the solution
                                           ? / lookup
                          (               )  / do this together
                                       "0"   / string "0"
                                      ,      / join with
                                  .Q.n       / string "0123456789"
                                1_           / drop first
                               ,             / join with
                           .Q.A              / "A..Z"
  (                      )                   / do this together
                      !10                    / range 0..9
                     ,                       / join with
     (              )                        / do this together
               4 3 4                         / list (4;3;4)
              ,                              / join with
         (5#3)                               / list (3;3;3;3;3)
        &                                    / where, creates list 0 0 0 1 1 1 2 2 etc
      1+                                     / add 1
   1+                                        / add 1
+/                                           / sum up



2

Bash , 256 байт

Ви можете замінити (( … ))конструкції letна однакове число байтів. Можливо, існує хороший алгоритм для зменшення випадок, але поки що його не знайдено. Трохи переробляючи, ви також можете зробити його функцією (але не в однакових або менших байтах, якщо ви не зможете знизити function fname { … }верхню частину і хвіст).

read p;while ((${#p}>0));do case ${p:0:1} in ([1-9]) ((d+=${p:0:1}));; ([0]) ((d+=10));; ([ABC) ((d+=2));; ([P-S]) ((d+=7));; ([W-Z]) ((d+=9));;([DEF]) ((d+=3));; ([GHI]) ((d+=4));; ([JKL]) ((d+=5));; ([MNO]) ((d+=6));; (?) d=$d; esac;p=${p#?};done;echo $d

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

Краще рішення за допомогою техніки символів карти використовує trінструмент:

[Баш з тр], 173 байт

read p;p=$(echo $p|tr A-Z 22233344455566677778889999);while ((${#p}>0));do case ${p:0:1} in ([1-9]) ((d+=${p:0:1}));; ([0]) ((d+=10));; (?) d=$d; esac;p=${p#?}; done;echo $d

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


Один алгоритм, який я пропустив, звичайно, це зробити заміну / переклад рядків на AZ. Це було б добре. Я зміню вищезазначене, щоб задовольнити.
PJF

while((${#p}))працює, економлячи три байти. c=${p:0:1};case c in ([0-9]) ((d+=c?c:10));;економить ще 16. Якщо tr -dc 0-9додано до трубопроводу tr, ви взагалі не потребуєте заявки справи, і додаток можна скласти в whileумову &&.
О, Боже мій,

Дякую OMG. Я не часто використовую потрійне завдання, тому це пропустив. Цікаве також використання доповнення видалення (але це передбачає, що моє рішення ігнорує будь-який інший символ). Мені вдалося зменшити його до 133 байт, як у: read p;p=$(echo $p|tr A-Z 22233344455566677778889999|tr -dc [0-9]);while ((${#p}));do c=${p:0:1}&&((d+=c?c:10));p=${p#?};done;echo $d
PJF

1
118: p=$(head -1|tr A-Z 22233344455566677778889|tr -dc 0-9);while((${#p}));do((d+=(c=${p:0:1})?c:10));p=${p#?};done;echo $d.. останні три 9 не потрібні, оскільки tr повторно використає останній символ заміни, якщо другий аргумент занадто короткий.
О, Боже мій,

1
Перший приклад можна зняти з 256 до 236, видаливши кілька зайвих пробілів. read p;while((${#p}>0));do case ${p:0:1} in ([1-9])((d+=${p:0:1}));;([0])((d+=10));;([ABC)((d+=2));;([P-S])((d+=7));;([W-Z])((d+=9));;([DEF])((d+=3));;([GHI])((d+=4));;([JKL])((d+=5));;([MNO])((d+=6));;(?)d=$d;esac;p=${p#?};done;echo $d
Стів


2

PowerShell , 109 102 87 байт

$(switch -r($args|% t*y){\d{$_}[A-Y]{("{0}"-f(.313*$_-18))[0]}[Z]{9}0{10}})-join'+'|iex

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

EDIT: Використовується ідея @ mazzy для перемикача регулярних виразів з деяким форматуванням рядків для виведення символу char -> int -> та захоплення лише першої "цифри"

Оригінал:

[char[]]"$args"|%{$a+=(48,(('22233344455566677778889999')[$_-65],(58,$_)[$_-ne48])[$_-lt64])[$_-gt47]-=48};$a

Я сподівався отримати <100 байт, тому буду продовжувати дивитись, щоб побачити, чи є ще щось, що я можу зробити. Напевно, існує спосіб видалити рядок з цифрами

Вибачте, якщо це заплутано, оскільки я вклав масиви з булевими операторами індексації, але -

Пояснення:

[char[]]"$args"|%{зчитує вхід, поданий як рядок, а потім вибухає його в масив char і починає цикл для кожного з перевірки, ()[$_-gt47]чи ()+-./було введено якесь (всі мають значення символів ascii <48)
Примітка: Powershell приймає $trueі $falseяк 1і0 відповідно для індексів масиву

Тоді ми отримуємо або 48символи, або:
('22233344455566677778889999'[$_-65],(58,$_)[$_-ne48])[$_-lt64]

У [$_-lt64]перевіряє номера або букви (всі передбачуваний капітал тут). Якщо це лист, '22233344455566677778889999'[$_-65]змініть його на 0-25, щоб індексувати в масив і виводити значення імпульсу (як знак). Якщо символ є числом, ми замість цього дивимось на: (58,$_)[$_-ne48]перевірку 0та виведення58 чи просто числовий символ.

Навколо всього $a+= ... -=48ініціалізується числова змінна $ a at, 0а потім додається результат. Вихід - це значення ascii char числа, тому віднімайте48 .

Примітка: якщо вхід був символом, ми отримуємо $a+=48-48, фактично ігноруючи його. Якщо це було 0, ми отримуємо$a+=58-48 отримуємо свої +10

Нарешті, ;$aпросто виводиться остаточне значення для кожного циклу


Ви можете зберегти кілька байт. Спробуйте в Інтернеті!
mazzy

Ага, так, у мене було кілька додаткових дужок і =там, що залишилися від моїх попередніх методів вирішення цього питання, дякую за улов! Хоча я ще не бачив цього t*y, чи не могли б ви пояснити, чому це працює, щоб вибухати рядок в масив символів?
Синусоїд


щоб отримати <<100 байт ': спробуйте в Інтернеті! :)
mazzy

гарна ідея з -fі [0].
маззи

2

PowerShell , 95 85 79 байт

натхненний відповіддю Нуелленгофа .

натхненний [0]від відповіді синусоїди в .

$(switch -r($args|% t*y){\d{$_}0{10}[A-Y]{"$(.313*$_-18)"[0]}Z{9}})-join'+'|iex

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

Нерозгорнута версія:

$(
    switch -r($args|% toCharArray){
        \d    {$_}
        0     {10}
        [A-Y] {"$(.313*$_-18)"[0]}
        Z     {9}
    }
)-join '+'|Invoke-Expression
key .313*$_-18 "$(...)"[0]
--- ---------- -----------
  A      2.345 2
  B      2.658 2
  C      2.971 2
  D      3.284 3
  E      3.597 3
  F      3.910 3
  G      4.223 4
  H      4.536 4
  I      4.849 4
  J      5.162 5
  K      5.475 5
  L      5.788 5
  M      6.101 6
  N      6.414 6
  O      6.727 6
  P      7.040 7
  Q      7.353 7
  R      7.666 7
  S      7.979 7
  T      8.292 8
  U      8.605 8
  V      8.918 8
  W      9.231 9
  X      9.544 9
  Y      9.857 9

1
Командні зусилля! : D
Синусоїд



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