Считайте импульсы поворотного набора в номере телефона (включая буквы)

34

В день ваших бабушек и дедушек, набор номера телефона был сделан с помощью поворотного набора, как это:

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

Набор цифры N требует N таких «импульсов», за исключением N = 0, что составляет десять импульсов.

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

Соревнование

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

Digits

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

Письма

Обратите внимание, что цифры 2-9 на циферблате имеют связанные с ними буквы латинского алфавита. Первоначально они предназначались для именованных обменов , но позднее были переназначены для фоновых слов и для систем ввода текстовых сообщений.

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

  • А, В, С = 2
  • D, E, F = 3
  • G, H, I = 4
  • J, K, L = 5
  • М, Н, О = 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
dan04
источник
Я предполагаю, что произвольная пунктуация ASCII и пробелы ограничены теми, которые обычно используются для телефонных номеров ( +- ()*#.), точно так же, как буквы ограничены заглавными буквами. Поправьте меня если я ошибаюсь.
Адам
1
@ Adám: я ограничил обязательные знаки препинания несколькими общими разделителями. Он намеренно не включает *и #, которые имеют особое значение для телефонов с тональным набором и не набираются на поворотных устройствах.
Dan04
1
Можем ли мы использовать ввод всех строчных букв вместо прописных? Можем ли мы взять массив символов вместо строки?
Grimmy
1
Я путешественник во времени! Я путешественник во времени! Я путешественник во времени! Поскольку я определенно пользовался такими телефонами, когда был ребенком, я, очевидно, мой собственный дед !!!!!!! Что на самом деле довольно неприятно, когда я думаю об этом. Bleah !!!
Боб Джарвис - Восстановить Монику
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 7 с, а не 4 9 с, поэтому нам все еще нужно обрабатывать 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
Grimmy
источник
Почему строчные вместо прописных?
dan04
1
@ dan04, потому что 05AB1E имеет встроенную функцию для нажатия "abcdefghijklmnopqrstuvwxyz", но не для "ABCDEFGHIJKLMNOPQRSTUVWXYZ". Я мог бы преобразовать алфавит в верхний регистр, а не преобразовывать ввод в нижний регистр, но это то же самое по количеству символов.
Grimmy
1
Я отредактировал вопрос, чтобы сделать ваши первые две команды ненужными.
dan04
3
@Jonah Я начал с идеи деления диапазона на константу, чтобы получить желаемую последовательность, затем, когда искал лучший способ выразить «чуть больше 3» в 05AB1E, я вспомнил, что pi является встроенным.
Гримми
2
+1 за использование пи
Драконис
9

C # (интерактивный компилятор Visual C #) , 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 байт)
Просроченные данные
То же самое относится и к проверке x <58, поскольку на входе ничего не будет в диапазоне 58-64
Истекшие данные
51 байт
Просроченные данные
5

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

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

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

Попробуйте онлайн!

()∘⍳ Найти de 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, позвольте мне упростить логику, но теперь новый метод может быть лучше.

Python 2 , 84 байта

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

Попробуйте онлайн!

Используется жестко запрограммированная строка поиска, где каждый блок из 5 символов соответствует символам, дающим каждое значение, начинающееся с 1. Пробелы заполняются пробелом x, который не может быть на входе с заглавными буквами. Случайно, символы, не появляющиеся в строке, производят -1для .findкоторого слагаемое равно нулю.

XNOR
источник
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, поэтому они не влияют на общее количество.

Сиеру Асакото
источник
5

Perl 5 -p , 52 51 байт

@ Грими получает кредит за -1

y/A-Z/22233344455566677778889/;map$\+=$_||10,/./g}{

Попробуйте онлайн!

Xcali
источник
/\d/gдолжен быть равен /./g-1 (да, он по-прежнему правильно обрабатывает знаки препинания).
Grimmy
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

K4 , 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
streetster
источник
3

C (gcc) , 94 89 86 80 байт

Спасибо потолку, Nwellnhof и Rogem за предложения.

c;f(char*s){c=*s-48;s=*s?(c<10U?c?c:10:c-17<26U?(c-11-c/35-c/42)/3:0)+f(s+1):0;}

Попробуйте онлайн!

ErikF
источник
80 байтов , используя рекурсию вместо цикла.
Предлагаю c<43Uвместоc-17<26U
потолок кошка
2

Баш , 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 инструмент:

[Bash с 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

Попробуйте онлайн!

PJF
источник
Один алгоритм, который я пропустил, конечно, это сделать некоторую замену / перевод строки на AZ. Это было бы хорошо. Я исправлю вышеупомянутое, чтобы удовлетворить.
PJF
while((${#p}))работает, сохраняя три байта. c=${p:0:1};case c in ([0-9]) ((d+=c?c:10));;сохраняет еще 16. С tr -dc 0-9добавлением в конвейер tr вам вообще не нужен оператор case, и сложение можно сложить в whileусловие с помощью &&.
Боже мой,
Спасибо ОМГ. Я не часто использую троичное назначение, поэтому я пропустил это. Интересное использование удаления delete также (но это предполагает, что мое решение игнорирует любой другой символ). Мне удалось уменьшить его до 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

Желе , 33 24 байта

7r32:ØP«9Ṿ€ØAżFyfØDV€o⁵S

Попробуйте онлайн!

Монадическая ссылка, принимающая строку в качестве аргумента и возвращающая количество импульсов. Переписанный, вдохновленный ответом @ Grimy's 05AB1E, так что обязательно проголосуйте за них!

Ник Кеннеди
источник
2

PowerShell , 109 102 87 байт

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

Попробуйте онлайн!

РЕДАКТИРОВАТЬ: Использовал идею @ mazzy для переключателя регулярных выражений с некоторым форматированием строки, чтобы привести char -> int -> string и получить только первую «цифру»

Оригинал:

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

Я надеялся получить <100 байтов, поэтому я буду продолжать смотреть на это, чтобы увидеть, есть ли что-нибудь еще, что я могу сделать. Там, вероятно, есть способ удалить строку номера

Извините, если это сбивает с толку, поскольку я вложил массивы в логические операторы индексации, но -

Объяснение:

[char[]]"$args"|%{читает входные данные, приведенные в виде строки, а затем разбивает их на массив символов и начинает цикл for-each с проверкой, введен ()[$_-gt47]ли какой-либо из них ()+-./(все имеют значения символов ascii <48).
Примечание: Powershell принимает $trueи $falseas 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просто выводит наше окончательное значение post для каждого цикла

Синусоида
источник
Вы можете сэкономить несколько байтов. Попробуйте онлайн!
Маззи
Ах, да, у меня были некоторые дополнительные скобки и =там, оставшиеся от моих предыдущих методов решения этой проблемы, спасибо за улов! Хотя я раньше не видел t*y, не могли бы вы объяснить, почему это работает, чтобы взорвать строку в массив символов?
Синусоида
получить «<100 байт»: попробуйте онлайн! :)
Маззи
хорошая идея с -fи [0].
Маззи
2

PowerShell , 95 85 79 байт

вдохновленный ответом nwellnhof .

вдохновленный [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
Mazzy
источник
1
Командная работа! : D
Синусоида
0

Python 3 , 134 123 байта

f=lambda n:sum(map(int,n.translate(n.maketrans('ADGJMPTWBEHKNQUXCFILORVYSZ','23456789'*3+'79','()+-./ '))))+10*n.count('0')

Попробуйте онлайн!

-11 байт благодаря @ dan04

Артемида поддерживает Монику
источник
1
Переставляя буквы в 'ADGJMPTWBEHKNQUXCFILNRVYSZ', вы можете уменьшить строку цифр до '23456789'*3+'79'.
dan04