Lettres dans les numéros de téléphone


23

Problème:

Vous créez un nouveau téléphone où les gens peuvent taper des numéros de téléphone spécialisés, par exemple 1-800-program, et ils seraient convertis automatiquement en un numéro de téléphone utilisable, comme1-800-7764726 (pour l'exemple précédent).

Votre programme recevra une chaîne s'il y a une longueur avec des chiffres, des lettres et des tirets, et convertira toutes les lettres en leurs nombres correspondants.

Voici un clavier, pour référence:

clavier

Règles:

  • Votre programme recevra une chaîne
  • Il le traitera et retournera / imprimera une autre chaîne
  • N'importe quelle langue est acceptée
  • Puisqu'il s'agit de , le code le plus court l'emporte

Le programme doit-il gérer les majuscules et les minuscules dans l'entrée?
mattnewport

3
@mattnewport - non, supposez que la variable a déjà été transformée en minuscules
TheDoctor

Réponses:


8

GolfScript, 24 caractères

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

Entrée de test:

0123456789-abcdefghijklmnopqrstuvwxyz

Sortie de test:

0123456789-22233344455566677778889999

Explication:

  • { }% applique le code entre les accolades à chaque caractère de l'entrée.

  • .96>{ }* exécute le code entre les accolades intérieures si et seulement si le code ASCII du caractère est supérieur à 96 (c'est-à-dire qu'il s'agit d'une lettre minuscule).

  • Le premier ,transforme le caractère en une liste de tous les caractères avec des codes ASCII inférieurs et 91,'qx'+-filtre tous les caractères avec des codes ASCII inférieurs à 91, ainsi que les lettres qet x, de la liste. Ainsi, par exemple, le caractère aest transformé en liste à 6 caractères [\]^_`, tandis que zse transforme en liste à 29 caractères [\]^_`abcdefghijklmnoprstuvwy.

  • Le second ,compte les éléments restants dans la liste et 3/divise ce nombre par trois (arrondi vers le bas). Enfin, le `transforme le nombre résultant (compris entre 2 et 9) en chaîne.

Ainsi, selon la spécification, les tirets et les chiffres restent inchangés, tandis que les lettres minuscules sont mappées en chiffres conformément au diagramme du clavier de référence. Le code passera en fait proprement à travers tous les caractères ASCII imprimables à l'exception des lettres minuscules (qui sont mappées comme décrit) et des caractères {, |et }(qui sont mappés à la chaîne de deux caractères 10). L'entrée 8 bits non ASCII produira toutes sortes de sorties numériques étranges.

Après tout cela, il est un peu décevant que cela ne bat la solution triviale de bash que par six caractères.


50

Bash, 30

Edit: Merci Doorknob pour avoir éliminé 3 caractères

tr a-z 22233344455566677778889

Exemple:


10
Vous ne pouvez pas supprimer les 3 dernières 9secondes?
Poignée de porte

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
Nice math. Je veux juste dire que vous pouvez réduire 1 caractère en supposant que EOF est -1 et faites~(c=getchar())
user12205

Ne pourriez-vous pas utiliser à la getch()place de getchar()?
starsplusplus

À proprement parler, ce getch()n'est pas la norme C, par conséquent je suppose que cela ne fait pas de lien avec l'idéone. Je l'ai quand même testé dans MSVC et cela ne fonctionne pas vraiment malheureusement - car il consomme directement les entrées du clavier, il n'y a aucun moyen de quitter le programme, bien qu'il traduise ce que vous tapez à la volée, ce qui est plutôt bien.
mattnewport

4

Javascript - 103 caractères

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
Je ne savais pas que tu pouvais faire ça avec .replace. Votez pour vous!
SuperJedi224

Vous pouvez remplacer charCodeAt(0)par charCodeAt()et vous pouvez utiliser la fonction flèche pour function(y)...économiser quelques octets et pour ~~(y/3)vous pouvez utilisery/3|0
chau giang

3

Rubis, 75 caractères

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

Utilise le charsbloc obsolète avec et imprime chaque lettre individuellement avec $><<. J'aime aussi [[*?a..?z].index(c)||-1]; il saisit le caractère correspondant à cette lettre de l'alphabet s'il s'agit d'une lettre, et le dernier caractère (qui se trouve être le caractère de test inchangé) sinon.

Ruby, 43 (ou 35) caractères

Vol flagrant de @ace;)

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

Raser 8 caractères si je peux exécuter en IRB avec la variable scomme chaîne:

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

3

C ++ - 222 caractères

La solution la plus longue à ce jour:

#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, je ne pense pas que la solution la plus longue soit l'objectif ici ...
Danny

@Danny C ++ ne se prête pas bien au code-golf . Java et C # sont les seuls langages qui sont pires, à ma connaissance (toutes les classes, la création d'objets et les noms longs pour la sortie ...).
Hosch250

Je sais, je pensais juste que c'était drôle que vous ayez mentionné "la solution la plus longue".
Danny

3

Frink, 92

Une langue assez verbeuse, je sais. Cela vérifie 8 valeurs au lieu de 26 sans avoir à taper les comparaisons. Est-ce qu'une des solutions ci-dessus "222333444 .." peut être réduite de la même manière?

Utilisation de structures intégrées, 107

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

Utilisation d'une fonction récursive personnalisée, 92

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

+1 pour réduire la méthode de traduction des chaînes à une recherche à 8 caractères. Belle touche.
Jonathan Van Matre

2

Smalltalk, 79 70

l'entrée est s:

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

probablement pas un candidat pour être le plus court - mais peut être intéressant pour une vieille astuce pour éviter un test pour une condition non trouvée (indexOf: renvoie 0 dans ce cas). Aucun test spécial pour les lettres n'est donc nécessaire. Cependant, certains Smalltalks ont des chaînes immuables et nous avons besoin de 4 caractères supplémentaires ("copie").

Oh, une meilleure version, qui traite même des chaînes immuables en 70 caractères:

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

2

Mathematica 90

Cela suit la logique de la solution de @ ace:

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

Exemple

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

8437889


Votre représentation de caractère de flèche n'est pas acceptée par Mma dans un copier / coller
Dr. belisarius

, Vous n'avez pas besoin aussi 1dans #1:)
Dr Bélisaire

Bélisaire, j'ai changé la flèche en arrière et retiré le 1. Toujours 90 chars mais couper et coller fonctionnera. Vous comprenez bien sûr la motivation à utiliser la flèche à caractère unique.
DavidC


2

Perl, 50

Une autre copie évidente de la réponse bash d'Ace

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

1
Ce code fonctionne correctement mais il y a place à amélioration. Débarrassons-nous de $ ARGV [0] et utilisons -pplutôt switch qui vous permet de bien parcourir chaque ligne de stdin. Pendant que nous y sommes, la plage en y /// n'a pas besoin d'être mise entre crochets. Nous pouvons également nous débarrasser de trois 9 en ne laissant qu'un seul et supprimer le dernier point-virgule: -p y/a-z/22233344455566677778889/ Voilà, 30 + 1 pour -p. Merci d'utiliser les services d'optimisation et de golf Enterprise Chinese Perl et bonne journée.
chinese perl goth

2

R, très long mais amusant

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 caractères]

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

Usage

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

2

JavaScript, 85

JavaScript ne gagnera jamais les guerres de golf, mais j'aime ça et je voulais faire quelque chose de différent que de sauter dans le train @ace.

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

2

PHP, 141

Pas le plus court, mais le plus amusant:

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

Plus lisible:

<?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 a déclaré que l'entrée est déjà en minuscules, vous pouvez donc supprimer lestrtolower
Einacio

2

Python 2.7, 80

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

Je suis nouveau sur python, donc je suis sûr qu'il doit y avoir un moyen de jouer au golf encore plus loin , c'est une approche différente, j'espère que vous l'aimez, mon dieu, le python est joli!

Exemple d'exécution:

  • entrée: 01-800-abcdefghijklmnopqrstuvwxyz
  • sortie: 01-800-22233344455566677778889999

2

T-SQL, 216 octets

J'ai passé pas mal de temps au cours des deux dernières nuits à créer minutieusement une fonction de séquence mathématique qui arrondirait correctement pour générer les codes ASCII appropriés pour les nombres à partir des codes ASCII alphabétiques. Il y avait un nombre ridicule de décimales dans les coefficients, mais cela a fonctionné.

Cependant, l'approche rationnelle de mattnewport fonctionne également en SQL, à un coût d'octets beaucoup plus bas, donc je suis sans vergogne abandonnant mes propres calculs en faveur des siens. Montez le voter, c'est une solution élégante!

Voilà le mien:

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

Cela utilise un CTE récursif pour créer une pile impromptue des caractères du numéro de téléphone et traduire les lettres à la volée, puis un peu de ruse SQL (SELECT @ p = @ p ​​+ columnValue) pour recomposer la chaîne du CTE sans nécessiter une autre construction de récursivité.

Sortie:

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

2

Python 2.7, 66 65


L'original d'Anakata

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


Golfé plus loin

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


Je n'ai pas assez de réputation pour commenter la réponse de @ anakata, j'ai donc fait un post séparé ici. J'ai eu la même idée (en prenant le module d'ordonnance 3) mais je n'ai pas réussi à savoir comment imprimer les bons nombres pour s - z .

Quoi qu'il en soit, les améliorations que j'ai apportées au golf:

  • changé raw_inputeninput

  • supprimé les '\b'parenthèses superflues et simples

  • supprimé le +2décalage et placé celui-ci dans la soustraction d'origine (97 - (3 * 2) = 91)

Testé avec l'interpréteur Python 2.7.6. Suppose, selon les règles, une entrée de chaîne.


vous pouvez également supprimer l'espace entre le) et le si
Willem

Tu as raison. good catch willem
zheshishei

1

PHP, 87

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

1

q [38 caractères]

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

Inspiré par la solution de @ ace

Exemple

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

1

XQuery, 71

BaseX a été utilisé comme processeur XQuery. $iest entrée.

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

Pas la réponse la plus courte, mais assez courte et très lisible.


1

Python, très non golfé

Comme tout le monde copie Ace, j'ai décidé de publier le code que j'ai inventé avant de soumettre la question:

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 octets):

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

S'attend ià contenir la chaîne.

Essayez-le dans n'importe quelle version récente de Firefox. Je n'ai pas essayé 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")

Usage

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

Python

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

0

ECMASCRIPT, 101 (avec entrée)

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

Ajout d'une nouvelle ligne pour plus de clarté. 85 caractères si l'entrée est dans une variable.


0

Perl, 54

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

Shoot, @RobHoare m'a toujours battu de 4 personnages. :)


0

QBasic, 155

Ah, les souvenirs ...

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

Cela aurait dû être plus court, mais je testais avec repl.it , qui ne permet pas les IFinstructions sur une seule ligne et se comporte étrangement si vous laissez la variable hors de NEXT i. Il ne reconnaît pas non plus la ASCfonction, donc pour exécuter le code, vous devrez ajouter cette solution de contournement au début:

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 deuxième fois que vous l'exécutez, l'interprète se plaindra à moins que vous ne supprimiez la DECLARE FUNCTIONligne, allez comprendre.)


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="")

Exemple:

> 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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.