Lettere in numeri di telefono


23

Problema:

Stai creando un nuovo telefono in cui le persone possono digitare numeri di telefono specializzati, ad esempio 1-800-program, e verrebbero convertiti automaticamente in un numero di telefono utilizzabile, come 1-800-7764726(per l'esempio precedente).

Il tuo programma riceverà una stringa di qualsiasi lunghezza con numeri, lettere e trattini e convertirà tutte le lettere nei loro numeri corrispondenti.

Ecco una tastiera, per riferimento:

tastiera

Regole:

  • Il tuo programma riceverà una stringa
  • Lo elaborerà e restituirà / stamperà un'altra stringa
  • È accettata qualsiasi lingua
  • Dato che si tratta di , vince il codice più corto

Il programma dovrebbe gestire sia lettere maiuscole che minuscole nell'input?
Mattnewport,

3
@mattnewport - no, supponiamo che la variabile sia già stata trasformata in minuscolo
TheDoctor

Risposte:


8

GolfScript, 24 caratteri

{.96>{,91,'qx'+-,3/`}*}%

Test input:

0123456789-abcdefghijklmnopqrstuvwxyz

Uscita di prova:

0123456789-22233344455566677778889999

Spiegazione:

  • { }% applica il codice tra le parentesi graffe per ciascun carattere dell'input.

  • .96>{ }* esegue il codice tra parentesi graffe interne se e solo se il codice ASCII del carattere è maggiore di 96 (ovvero è una lettera minuscola).

  • Il primo ,trasforma il carattere in un elenco di tutti i caratteri con codici ASCII inferiori e 91,'qx'+-filtra tutti i caratteri con codici ASCII inferiori a 91, nonché le lettere qe x, dall'elenco. Pertanto, ad esempio, il personaggio aviene trasformato nella lista di 6 caratteri [\]^_`, mentre zviene trasformato nella lista di 29 caratteri [\]^_`abcdefghijklmnoprstuvwy.

  • Il secondo ,conta gli elementi rimanenti nell'elenco e 3/divide questo conteggio per tre (arrotondamento per difetto). Infine, `trasforma il numero risultante (nell'intervallo 2 - 9) in una stringa.

Pertanto, come da specifica, trattini e numeri rimangono invariati, mentre le lettere minuscole vengono mappate in numeri secondo il diagramma della tastiera di riferimento. Il codice sarà effettivamente passare pulito attraverso tutti i caratteri ASCII stampabili eccetto lettere minuscole (che come mappati come descritto) ei caratteri {, |e }(che sono mappati alla stringa di due caratteri 10). L'ingresso a 8 bit non ASCII produrrà tutti i tipi di strano output numerico.

Dopo tutto questo, è un po 'deludente che questo batti la banale soluzione bash di soli sei caratteri.


50

Bash, 30

Modifica: grazie Doorknob per aver eliminato 3 caratteri

tr a-z 22233344455566677778889

Esempio:


10
Non riesci a rimuovere gli ultimi 3 9secondi?
Maniglia della porta

16

C, 83 78 77 65 63 62

main(c){for(;~(c=getchar());putchar(c>96?20-c/122+5*c/16:c));}

http://ideone.com/qMsIFQ


3
Bella matematica. Voglio solo dire che puoi ridurre 1 carattere supponendo che EOF sia -1 e fallo~(c=getchar())
user12205

Non potresti usare al getch()posto di getchar()?
starsplusplus,

A rigor di termini, getch()non è standard C, di conseguenza immagino che non si colleghi in ideone. L'ho provato comunque in MSVC e non funziona davvero tristemente - poiché consuma direttamente l'input da tastiera non c'è modo di uscire dal programma, anche se traduce ciò che digiti al volo che è un po 'pulito.
Mattnewport,

4

Javascript - 103 caratteri

alert(prompt().replace(/[a-z]/g,function(y){y=y.charCodeAt(0)-91;return y>27?9:y>24?8:y>20?7:~~(y/3)}))

1
Non sapevo che avresti potuto farlo con .replace. Vota per te!
SuperJedi224,

Puoi sostituirlo charCodeAt(0)con charCodeAt()e puoi usare la funzione freccia per function(y)...salvare pochi byte e per ~~(y/3)te puoi usarey/3|0
chau giang

3

Rubino, 75 caratteri

gets.chars{|c|$><<"22233344455566677778889999#{c}"[[*?a..?z].index(c)||-1]}

Utilizza il deprecato charscon blocco e stampa ogni lettera singolarmente con $><<. Mi piace anche [[*?a..?z].index(c)||-1]; prende il carattere corrispondente a quella lettera dell'alfabeto se è una lettera e l'ultimo carattere (che risulta essere il personaggio di prova invariato) in caso contrario.

Rubino, 43 (o 35) caratteri

Evidentemente rubare da @ace;)

puts gets.tr'a-z','22233344455566677778889'

Elimina 8 caratteri se riesco a eseguire in IRB con la variabile scome stringa:

s.tr'a-z','22233344455566677778889'

3

C ++ - 222 caratteri

La soluzione più lunga finora:

#include<iostream>
#include<string>
#define o std::cout<<
int main(){std::string s;std::cin>>s;for(int i=0;i<s.size();i++){int j=s[i]-97;if(j<0)o s[i];if(0<=j&j<15)o 2+j/3;if(14<j&j<19)o 7;if(18<j&j<22)o 8;if(21<j&j<26)o 9;}}

1
Lol, non credo che la soluzione più lunga sia l'obiettivo qui ...
Danny,

@Danny C ++ non si presta bene al code-golf . Java e C # sono gli unici linguaggi peggiori che conosco (tutte le classi, la creazione di oggetti e nomi lunghi per l'output ...).
Hosch250,

Lo so, ho pensato che fosse divertente che tu abbia menzionato "La soluzione più lunga".
Danny,

3

Frink, 92

Un linguaggio piuttosto prolisso, lo so. Questo controlla 8 valori invece di 26 senza dover digitare i confronti. Una delle soluzioni "222333444 .." sopra descritte può essere ridotta in modo simile?

Utilizzando strutture integrate, 107

co=new OrderedList
co.insertAll[charList["cfilosv{"]]
println[input[""]=~%s/([a-z])/co.binarySearch[$1]+2/eg]

Utilizzo di una funzione ricorsiva personalizzata, 92

fn[x,a]:=x<=(charList["cfilosv{"])@a?a+2:fn[x,a+1]
println[input[""]=~%s/([a-z])/fn[$1,0]/eg]

+1 per ridurre il metodo di traduzione delle stringhe a una ricerca di 8 caratteri. Bel tocco.
Jonathan Van Matre,

2

Smalltalk, 79 70

l'input è s:

s collect:[:c|' 22233344455566677778889999'at:1put:c;at:(($ato:$z)indexOf:c)+1]

probabilmente non è un candidato per essere il più breve - ma potrebbe essere interessante per un vecchio trucco per evitare un test per una condizione non trovata (indexOf: restituisce 0 in questo caso). Quindi non è necessario alcun test speciale per le lettere. Tuttavia, alcuni Smalltal hanno stringhe immutabili e abbiamo bisogno di altri 4 caratteri ("copia").

Oh, una versione migliore, che si occupa anche di stringhe immutabili in 70 caratteri:

s collect:[:c|c,'22233344455566677778889999'at:(($ato:$z)indexOf:c)+1]

2

Mathematica 90

Questo segue la logica della soluzione di @ ace:

StringReplace[#,Thread[CharacterRange["A","Z"]->Characters@"22233344455566677778889999"]]&

Esempio

StringReplace[#1,Thread[CharacterRange["A","Z"]-> 
Characters@"22233344455566677778889999"]]&["VI37889"]

8437889


La tua rappresentazione del personaggio freccia non è accettata da Mma in una copia / incolla
Dr. belisarius,

Inoltre, non hai bisogno di 1in #1:)
Dr. belisarius,

Belisario, ho cambiato la freccia indietro e rimosso il 1. Ancora 90 caratteri ma taglia e incolla funzionerà. Comprendi ovviamente la motivazione per usare la freccia a carattere singolo.
DavidC,

Ci sono stato, fatto :)
Dr. belisarius,

2

Perl, 50

Un'altra copia ovvia della risposta bash di Ace

($_)=@ARGV;y/a-z/22233344455566677778889999/;print

1
Questo codice funziona correttamente ma c'è spazio per miglioramenti. Sbarazziamoci di $ ARGV [0] e usiamo -pinvece switch che ti permette di passare attraverso ogni linea di stdin. Mentre ci siamo, l'intervallo in y /// non deve essere inserito tra parentesi quadre. Possiamo anche sbarazzarci di tre 9 lasciando solo uno e rimuovere il punto e virgola finale: -p y/a-z/22233344455566677778889/ Ecco qua, 30 + 1 per -p. Grazie per aver utilizzato i servizi di golf e ottimizzazione di Enterprise Chinese Perl e buona giornata.
cinese perl goth,

2

R, molto lungo ma divertente

foo <- '1-800-splurghazquieaobuer57'
oof <- unlist(strsplit(foo,''))
#don't count that part - it's input formatting :-) 
digout <- unlist(strsplit('22233344455566677778889999','')) 
oof[oof%in%letters[1:26]] <- unlist(sapply(oof[oof%in%letters[1:26]], function(j) digout[which(letters[1:26]==j)] ))

2

k [32 caratteri]

{(.Q.a!|,/(4 3 4,5#3)#'|$2+!8)x}

uso

{(.Q.a!|,/(4 3 4,5#3)#'|$2+!8)x}"stack exchange"
"78225 39242643"

2

JavaScript, 85

JavaScript non vincerà mai le guerre di golf, ma mi piace e volevo fare qualcosa di diverso che saltare sul carro @ace.

alert(prompt().replace(/[a-z]/g,function(a){for(i=7;a<"dgjmptw{"[i--];);return i+4}))

2

PHP, 141

Non il più breve, ma più divertente:

<?php foreach(str_split($argv[1])as$c){$v=ord($c);if($v>114){$v--;}if($v==121){$v--;}if($v<123&$v>96){echo chr(ceil($v/3+17));}else{echo$c;}}

Più leggibile:

<?php 
foreach (str_split($argv[1]) as $c) {
  $v=ord($c);
  if ($v>114) {$v--;}
  if ($v==121){$v--;}
  if ($v<123 & $v>96){
    echo chr(ceil($v/3+17));
    } else {echo $c;}
}

OP ha affermato che l'ingresso è già in minuscolo, quindi è possibile rimuoverestrtolower
Einacio il

2

Python 2.7, 80

for c in raw_input():print'\b'+(`(ord(c)-97)/3+2-(c in('svyz'))`if c>'`'else c),

Sono nuovo di Python, quindi sono sicuro che ci deve essere un modo per giocare a golf ancora di più , è un approccio diverso, spero che vi piaccia ragazzi, mio Dio, è carino Python!

Esegui esempio:

  • input: 01-800-abcdefghijklmnopqrstuvwxyz
  • uscita: 01-800-22233344455566677778889999

2

T-SQL, 216 byte

Ho trascorso un bel po 'di tempo nelle ultime due notti a creare scrupolosamente una funzione di sequenza matematica che si arrotondasse correttamente per generare i codici ASCII appropriati per i numeri dai codici alfabetici ASCII. Aveva un numero ridicolo di decimali nei coefficienti, ma ha funzionato.

Tuttavia, l'approccio razionale di mattnewport funziona anche in SQL, a un costo molto più basso di byte, quindi sto sfamando senza vergogna la mia matematica a favore della sua. Sali di voto, è una soluzione elegante!

Ecco il mio:

DECLARE @p VARCHAR(MAX)='';WITH t AS(SELECT ASCII(LEFT(@s,1))c,2 i UNION ALL SELECT ASCII(SUBSTRING(@s,i,1)),i+1FROM t WHERE i<=LEN(@s))SELECT @p=@p+CHAR(CASE WHEN c>96THEN 20-c/122+5*c/16 ELSE c END)FROM t;SELECT @p

Questo utilizza un CTE ricorsivo per creare uno stack improvvisato di caratteri nel numero di telefono e tradurre le lettere al volo, quindi un po 'di trucco SQL (SELECT @ p = @ p ​​+ columnValue) per ricomporre la stringa dal CTE senza richiedere un altro costrutto ricorsivo.

Produzione:

DECLARE @s VARCHAR(MAX)='1-800-abcdefghijklmnopqrstuvwxyz'
--above code runs here
1-800-22233344455566677778889999

2

Python 2.7, 66 65


Anakata's Original

for c in raw_input():print'\b'+(`(ord(c)-97)/3+2-(c in('svyz'))`if c>'`'else c),


Ulteriore golf

for c in input():print(ord(c)-91)/3-(c in('svyz'))if c>'`'else c,


Non ho abbastanza reputazione per commentare la risposta di @ anakata, quindi ho fatto un post separato qui. Ho avuto la stessa idea (prendendo il modulo delle ordinanze 3) ma non sono riuscito a capire come stampare i numeri giusti per s - z .

Ad ogni modo, i miglioramenti del golf che ho apportato:

  • cambiato raw_inputininput

  • rimosso l'estraneo '\b'e le parentesi e le virgolette singole

  • rimosso l' +2offset e collocato quello nella sottrazione originale (97 - (3 * 2) = 91)

Testato con l'interprete Python 2.7.6. Presuppone, secondo le regole, un input di stringa.


potresti anche rimuovere lo spazio tra il) e il if
Willem

Hai ragione. good catch willem
zheshishei

1

PHP, 87

echo str_ireplace(range('a','z'),str_split('22233344455566677778889999'),fgets(STDIN));

1

q [38 caratteri]

{(.Q.a!"22233344455566677778889999")x}

Ispirato dalla soluzione di @ ace

Esempio

{(.Q.a!"22233344455566677778889999")x}"stack exchange"
"78225 39242643"

1

XQuery, 71

BaseX è stato usato come processore XQuery. $iè inserito.

translate($i,"abcdefghijklmnopqrstuvwxyz","22233344455566677778889999")

Non la risposta più breve, ma piuttosto breve e molto leggibile.


1

Python, molto ungolfed

Dato che tutti copiano l'asso, ho deciso di pubblicare il codice che ho inventato prima di inviare la domanda:

def phonekeypad(text):
    c = ['','','abc','def','ghi','jkl','mno','pqrs','tuv','wxyz']
    st = ""
    for i in list(text):
        a = False
        for t in range(len(c)):
            if i in c[t]:
                st += str(t)
                a=True
        if a == False:
            st += str(i)
    return st

1

EcmaScript 6 (103 byte):

i.replace(/[a-z]/g,x=>keys(a='00abc0def0ghi0jkl0mno0pqrs0tuv0wxyz'.split(0)).find(X=>a[X].contains(x)))

Si aspetta idi contenere la stringa.

Provalo in qualsiasi versione recente di Firefox. Non ho provato Google Chrome.


1

Python 3, 121

print("".join((lambda x:"22233344455566677778889999"[ord(x)-97] if ord(x)>96 and ord(x)<123 else x)(i) for i in input()))

1

Haskell, 93C

t[]_ a=a
t(b:c)(d:e)a
 |a==b=d
 |True=t c e a
y=map(t['a'..'z']"22233344455566677778889999")

uso

y "1-800-program"

1

C # 140

using System.Linq;class P{static void Main(string[]a){System.Console.Write(string.Concat(a[0].Select(d=>(char)(d>96?20-d/122+5*d/16:d))));}}

0

Pitone

import string          
trans = str.maketrans(string.ascii_lowercase,
                      '22233344455566677778889999')                                                                                         
print("1-800-ask-usps".translate(trans))

0

ECMASCRIPT, 101 (con input)

"1-800-PROGRAM".replace(/./g,function(c){
return "22233344455566677778889999"[c.charCodeAt(0)-65]||c})

Newline aggiunto per chiarezza. 85 caratteri se l'input è in una variabile.


0

Perl, 54

print map{/[a-y]/?int(5/16*ord)-28:/z/?9:$_}<>=~/./gs

Spara, @RobHoare mi batte ancora di 4 personaggi. :)


0

QBasic, 155

Ah, i ricordi ...

INPUT n$
FOR i=1 TO LEN(n$)
c$=MID$(n$,i,1)
a=ASC(c$)
IF 97>a THEN
PRINT c$;
ELSE IF 122>a THEN
PRINT STR$(a\3.2-28);
ELSE
PRINT 9;
END IF
NEXT i

Questo avrebbe dovuto essere più breve, ma stavo testando con repl.it , il che non consente IFistruzioni a riga singola e si comporta in modo strano se si lascia fuori la variabile NEXT i. Inoltre non riconosce la ASCfunzione, quindi per eseguire il codice è necessario aggiungere questa soluzione alternativa all'inizio:

DECLARE FUNCTION ASC(s$)
FUNCTION ASC(s$)
FOR j=1 TO 255
IF CHR$(j)=LEFT$(s$,1) THEN
ASC=j
END IF
NEXT j
END FUNCTION

(La seconda volta che lo esegui, l'interprete si lamenterà a meno che non rimuova la DECLARE FUNCTIONriga, vai in figura.)


0

R, 110

s=strsplit(scan(,""),"")[[1]];i=grep("[a-z]",s);s[i]=sort(c(1:24%%8+2,7,9))[match(s[i],letters)];cat(s,sep="")

Esempio:

> s=strsplit(scan(,""),"")[[1]];i=grep("[a-z]",s);s[i]=sort(c(1:24%%8+2,7,9))[match(s[i],letters)];cat(s,sep="")
1: 1-800-program
2: 
Read 1 item
1-800-7764726
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.