Contare gli impulsi di selezione rotativa in un numero di telefono (comprese le lettere)


34

Ai giorni dei tuoi nonni, la composizione di un numero di telefono veniva effettuata con una manopola rotativa come questa:

Per comporre ciascuna cifra, inserire il dito nel foro corrispondente, tirarlo fino all'arresto e rilasciarlo. Un meccanismo farà tornare il quadrante in posizione di riposo e il telefono si disconnetterà e riconnetterà un circuito un numero specificato di volte, facendo clic udibili.

La composizione della cifra N richiede N di tali "impulsi", ad eccezione di N = 0 che è dieci impulsi.

I telefoni rotativi hanno la proprietà che le cifre grandi (8, 9, 0) richiedono più tempo per la composizione rispetto alle cifre piccole (1, 2, 3). Questa è stata una considerazione importante nella stesura delle prime mappe di prefisso, e perché New York City con la sua densa popolazione (e linea telefonica) ha ottenuto 212 (solo 5 impulsi), mentre 907 (26 impulsi) sono andati nell'Alaska scarsamente abitata. Naturalmente, tutto questo è diventato irrilevante quando la composizione a toni è diventata popolare.

La sfida

Scrivere, nel minor numero di byte possibile, un programma o una funzione che accetta come input una stringa (o sequenza di caratteri) contenente un numero di telefono e genera il suo numero di impulsi di selezione rotativa. Questi devono essere conteggiati come segue:

cifre

  • Le cifre 1-9 contano come quel numero di impulsi.
  • La cifra 0 conta come 10 impulsi.

Lettere

Si noti che le cifre 2-9 sul quadrante hanno lettere dell'alfabeto latino associate ad esse. Questi erano originariamente destinati agli scambi denominati , ma in seguito sono stati riappropriati per le parole telefoniche e per i sistemi di immissione dei messaggi di testo.

Devi supportare la presenza di lettere nei tuoi numeri di telefono, usando l' assegnazione di lettere E.161 alle cifre:

  • A, B, C = 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

Si può presumere che l'input sia già stato piegato in maiuscolo o in maiuscolo o minuscolo.

Altri caratteri

È necessario consentire l'uso arbitrario dei personaggi()+-./ e dello spazio come separatori di formattazione. È possibile scegliere di consentire qualsiasi carattere non alfanumerico per questo scopo, se è più facile da implementare.

Questi caratteri non contribuiscono al conteggio degli impulsi.

Codice di esempio

Una tabella di ricerca non golfizzata e funzione in 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)

Esempio di input e output

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

Presumo che la punteggiatura e gli spazi ASCII arbitrari siano limitati a quelli normalmente utilizzati per i numeri di telefono ( +- ()*#.) proprio come le lettere sono limitate in maiuscolo. Correggimi se sbaglio.
Adám

1
@Adám: ho limitato i segni di punteggiatura richiesti a pochi separatori comuni. Non include deliberatamente *e #, che hanno significati speciali sui telefoni touch-tone e non sono dialable sui rotary.
dan04,

1
Possiamo usare l'input tutto in minuscolo anziché tutto in maiuscolo? Possiamo prendere una matrice di caratteri anziché una stringa?
Grimmy,

1
Sono un viaggiatore nel tempo! Sono un viaggiatore nel tempo! Sono un viaggiatore nel tempo! Da quando ho usato sicuramente telefoni come questo da bambino, chiaramente SONO IL MIO PROPRIO NONNO !!!!!!! Il che in realtà è piuttosto icky quando ci penso. Bleah !!!
Bob Jarvis - Ripristina Monica

3
Sono il nonno. Ho usato telefoni come questo negli anni '50. E quando mi sono trasferito in una città in campagna, ho scoperto che la compagnia telefonica non offriva un servizio a toni. Era il 1985! Non scherzo! Mia nonna aveva un telefono in salotto con un gancio e una manovella. Hai rimosso l'auricolare dal gancio e girato la manovella per ottenere un operatore del centralino. Ha dovuto sostituirlo quando è stata impostata la composizione diretta a distanza.
Walter Mitty,

Risposte:


25

05AB1E , 19 18 17 15 byte

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

Provalo online!

Questa è la prima risposta per usare π. Perché usare π, potresti chiedere? Bene, le lettere sono associate a 22233344455566677778889999, in ordine. Nota come la maggior parte delle cifre si ripete 3 volte, ma 7 si ripete 4 volte. Si potrebbe dire che ogni cifra si ripete (3 + 1/7) volte, in media. Mi chiedo se c'è qualche numero che è approssimativamente 3 + 1/7 e richiede meno byte di 22/7 ...

Questo dà solo 4 7, non 4 9, quindi dobbiamo ancora gestire Z come caso speciale.

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

Perché lettere minuscole anziché maiuscole?
dan04,

1
@ dan04 perché 05AB1E ha un built-in da spingere "abcdefghijklmnopqrstuvwxyz", ma non per "ABCDEFGHIJKLMNOPQRSTUVWXYZ". Potrei convertire l'alfabeto in maiuscolo piuttosto che convertire l'input in minuscolo, ma questo è lo stesso conteggio.
Grimmy,

1
Ho modificato la domanda per rendere inutili i tuoi primi due comandi.
dan04,

3
@Jonah Ho iniziato con l'idea di dividere un intervallo per una costante per ottenere la sequenza desiderata, quindi mentre cercavo il modo migliore per esprimere "leggermente più di 3" in 05AB1E mi sono ricordato che pi era un built-in.
Grimmy,

2
+1 per l'uso di pi
Draconis

9

C # (compilatore interattivo Visual C #) , 51 byte

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

Salvato 1 byte grazie a @recursive

10 byte salvati grazie all'osservazione di @ ExpiredData che () +-/.sarà solo nell'input

Provalo online!

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, che dovrebbe funzionare nel contesto.
ricorsivo

@recursive È intelligente, grazie
Incarnazione dell'ignoranza

1
Il controllo x <91 è ridondante poiché l'input consisterà solo di () + -. / la chiave spaziale e i numeri che sono tutti <64, quindi possiamo determinare se il carattere è maiuscolo semplicemente controllando x> 64 (quindi -5 byte)
Dati scaduti

Lo stesso vale per il controllo x <58, poiché nell'input non sarà presente nulla nell'intervallo 58-64
Dati scaduti


5

APL (Dyalog Unicode) , 27 byte SBCS

Funzione prefisso tacito anonimo.

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

Provalo online!

(... )∘⍳ trova il ɩ ndex * di ciascun carattere nella seguente stringa:
  * elementi che non vengono trovati, ottengono l'indice 1 + l'indice massimo, ovvero 11
⎕D  le cifre:"0123456789"

1⌽ ruotare ciclicamente di un passo a sinistra; "1234567890"

11| resto della divisione se diviso per 11 *
  * questo dà 0 per tutte le non cifre
... + aggiungilo al seguente:

'@ADGJMPTW'∘⍸ il ɩ nterval ɩ ndex * per ogni carattere
  * Quindi [−∞, "@") dà 0, ["@", "A") dà 1, ["A", "D") dà 2, ecc.
+/  somma che


5

Python 2 , 74 byte

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

Provalo online!

Fa un po 'di aritmetica sul valore ASCII per ogni personaggio. La prima opzione controlla la presenza di lettere e la seconda opzione verifica la presenza di numeri. Il chiarimento che tutti i caratteri di punteggiatura consentiti nell'input sono quelli con valori ASCII inferiori a 48 mi consente di semplificare la logica, ma un nuovo metodo potrebbe ora essere migliore.

Python 2 , 84 byte

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

Provalo online!

Utilizza una stringa di ricerca codificata, con ogni blocco di 5 caratteri corrispondenti ai caratteri che danno ciascun valore che inizia con 1. Vengono riempiti gli spazi vuoti x, che non possono essere nell'input in maiuscolo. Fortunatamente, i caratteri che non compaiono nella stringa producono -1per il .findquale si ottiene una somma di zero.


5

JavaScript (Node.js) , ... 76 69 byte

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

Provalo online!

-7 grazie @Arnauld!

Spiegazione

 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

Non tutti [space]().+-/vengono catturati da /\w/g, quindi non influenzeranno il totale.


5

Perl 5 -p , 52 51 byte

@Grimy ottiene credito per -1

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

Provalo online!


/\d/gdovrebbe essere /./gper -1 (sì, gestisce ancora correttamente la punteggiatura).
Grimmy,


4

Retina 0.8.2 , 34 byte

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

Provalo online! Il link include casi di test. Spiegazione:

T`WTPMJGDA`Rd

Converti le lettere WTPMJGDA in cifre 9..0.

}T`L`2L

Mischia tutte le lettere rimanenti in basso di 1 e ripeti fino a quando tutte le lettere non sono state convertite in cifre.

0
55

Sostituire 0 con 55poiché prendono lo stesso numero di impulsi per comporre il numero.

\d
$*
1

Prendi la somma digitale.


3

K4 , 44 byte

Soluzione:

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

Esempi:

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

Spiegazione:

Approccio ingenuo, probabilmente piuttosto giocabile. Indice di ricerca del personaggio, punteggio di ricerca, somma.

+/(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


3

C (cc) , 94 89 86 80 byte

Grazie a ceilingcat, nwellnhof e Rogem per i suggerimenti.

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

Provalo online!


80 byte utilizzando la ricorsione invece di un ciclo.

Suggerisci c<43Uinvece dic-17<26U
ceilingcat il

2

Bash , 256 byte

È possibile sostituire il (( … )) costrutti con letun numero di byte identico. Potrebbe esserci un buon algoritmo per ridurre le dichiarazioni del caso, ma non è stato trovato finora. Con un po 'di rilavorazione potresti renderlo una funzione anche (ma non in uguali o meno byte a meno che non sia possibile scartare la parte function fname { … }superiore e la coda).

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

Provalo online!

Una soluzione migliore che utilizza la tecnica dei caratteri della mappa fa uso di tr strumento:

[Bash con tr], 173 byte

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

Provalo online!


Un algoritmo che mi è sfuggito, ovviamente, è quello di fare un po 'di sostituzione / traduzione della stringa su AZ. Questo sarebbe buono Modificherò quanto sopra per adattarlo.
PJF,

while((${#p}))funziona, salvando tre byte. c=${p:0:1};case c in ([0-9]) ((d+=c?c:10));;ne salva un altro 16. Con l' tr -dc 0-9aggiunta alla pipeline di tr non è necessaria alcuna istruzione case e l'aggiunta può essere piegata nella whilecondizione con &&.
Oh mio Dio,

Grazie OMG. Non uso spesso compiti ternari, quindi mi sono perso. Anche l'uso interessante del complemento di eliminazione (ma ciò presuppone che la mia soluzione ignori qualsiasi altro carattere). Sono riuscito a farlo scendere a 133 byte come in: 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.. gli ultimi tre 9 non sono necessari perché tr riutilizzerà l'ultimo carattere di sostituzione se il secondo argomento è troppo corto.
Oh mio Dio,

1
Il primo esempio può essere ridotto da 256 a 236 rimuovendo alcuni spazi non necessari. 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
steve


2

PowerShell , 109 102 87 byte

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

Provalo online!

EDIT: usato l'idea di @ mazzy per un interruttore regex con una formattazione di stringhe per lanciare char -> int -> string e prendere solo la prima 'cifra'

Originale:

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

Speravo di ottenere <100 byte, quindi continuerò a guardarlo per vedere se c'è qualcos'altro che posso fare. C'è probabilmente un modo per rimuovere la stringa numerica

Scusate se questo è confuso poiché ho annidato array con dichiarazioni di indicizzazione booleane ma -

Spiegazione:

[char[]]"$args"|%{legge l'input cast come stringa, quindi lo esplode in un array di caratteri e inizia un ciclo for-each controllando ()[$_-gt47]se ne è ()+-./stato inserito uno (tutti hanno valori di caratteri ASCII <48)
Nota: Powershell accetta $truee $falsecome 1e0 rispettivamente per indici di array

Quindi otteniamo o 48per i simboli o:
('22233344455566677778889999'[$_-65],(58,$_)[$_-ne48])[$_-lt64]

Gli [$_-lt64]assegni per un numero o una lettera (qui si assume tutto il capitale). Se è una lettera, la '22233344455566677778889999'[$_-65]modifica in 0-25 per indicizzarla nell'array e generare il valore dell'impulso (come carattere). Se il personaggio è un numero, guardiamo invece a: (58,$_)[$_-ne48]controllo 0e produzione58 o solo il carattere numerico stesso.

Intorno a tutto $a+= ... -=48 inizializza una variabile numerica $ a at 0e quindi aggiunge l'output. L'output è il valore del carattere ASCII di un numero, quindi sottrarre48 .

Nota: se l'input era un simbolo, otteniamo $a+=48-48, ignorandolo efficacemente. Se fosse0 , $a+=58-48otteniamo il nostro +10

Infine, ;$agenera solo il nostro post del valore finale per ogni loop


potresti risparmiare qualche byte Provalo online!
mazzy

Ah, sì, avevo alcune parentesi extra e l'interno =, rimasto dai miei precedenti metodi di risoluzione, grazie per la cattura! Tuttavia, non ho mai visto t*yprima, potresti spiegare perché funziona per far esplodere la stringa in una matrice di caratteri?
Sinusoide,


per ottenere "<100 byte": provalo online! :)
mazzy

buona idea con -fe [0].
mazzy

2

PowerShell , 95 85 79 byte

ispirato dalla risposta di nwellnhof .

ispirato [0]dalla risposta di Sinusoid .

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

Provalo online!

Versione non srotolata:

$(
    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
Sforzo di gruppo! : D
Sinusoide,



0

Python 3 , 134 123 byte

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

Provalo online!

-11 byte grazie a @ dan04


1
Riorganizzando le lettere in 'ADGJMPTWBEHKNQUXCFILNRVYSZ', è possibile ridurre la stringa di numeri a '23456789'*3+'79'.
dan04
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.