Letras em números de telefone


23

Problema:

Você está criando um novo telefone em que as pessoas podem digitar números de telefone especializados, por exemplo 1-800-program, e eles seriam convertidos automaticamente em um número de telefone utilizável, como 1-800-7764726(no exemplo anterior).

Seu programa receberá uma string, se houver algum comprimento, com números, letras e traços, e converterá todas as letras em seus números correspondentes.

Aqui está um teclado, para referência:

teclado

Regras:

  • Seu programa receberá uma string
  • Ele processará e retornará / imprimirá outra string
  • Qualquer idioma é aceito
  • Como é , o código mais curto ganha

O programa deve lidar com letras maiúsculas e minúsculas na entrada?
19414 Mattnewport

3
@mattnewport - não, assumir a variável foi transformado em minúsculas já
TheDoctor

Respostas:


8

GolfScript, 24 caracteres

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

Entrada de teste:

0123456789-abcdefghijklmnopqrstuvwxyz

Saída de teste:

0123456789-22233344455566677778889999

Explicação:

  • { }% aplica o código entre chaves a cada caractere da entrada.

  • .96>{ }* executa o código entre chaves se e somente se o código ASCII do caractere for maior que 96 (ou seja, é uma letra minúscula).

  • O primeiro ,transforma o caractere em uma lista de todos os caracteres com códigos ASCII inferiores e 91,'qx'+-filtra todos os caracteres com códigos ASCII menores que 91, assim como as letras qe x, da lista. Assim, por exemplo, o personagem aé transformado na lista de 6 caracteres [\]^_`, enquanto zé transformado na lista de 29 caracteres [\]^_`abcdefghijklmnoprstuvwy.

  • O segundo ,conta os elementos restantes na lista e 3/divide essa contagem por três (arredondamento para baixo). Finalmente, `transforma o número resultante (no intervalo de 2 a 9) em uma sequência.

Assim, conforme as especificações, hífens e números permanecem inalterados, enquanto letras minúsculas são mapeadas em números de acordo com o diagrama do teclado de referência. O código vai realmente limpa passar por todos os caracteres ASCII imprimíveis exceto para letras minúsculas (que, como mapeadas como descrito) e os personagens {, |e }(que são mapeados para a string de dois caracteres 10). A entrada não-ASCII de 8 bits produzirá todos os tipos de saída numérica estranha.

Depois de tudo isso, é um pouco decepcionante que isso só supere a solução trivial do bash em apenas seis caracteres.


50

Bash, 30

Edit: Obrigado Maçaneta por eliminar 3 caracteres

tr a-z 22233344455566677778889

Exemplo:


10
Você não pode remover os últimos 3 9s?
Maçaneta

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
Boa matemática. Só quero dizer que você pode reduzir um caractere assumindo EOF é -1 e fazer~(c=getchar())
user12205

Você não poderia usar em getch()vez de getchar()?
starsplusplus

Estritamente falando, getch()não é o padrão C, como resultado, acho que não está vinculado ao ideone. De qualquer forma, eu testei no MSVC e ele realmente não funciona tristemente - como consome diretamente a entrada do teclado, não há como sair do programa, embora traduza o que você digita em tempo real, o que é bem legal.
mattnewport

4

Javascript - 103 caracteres

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
Eu não sabia que você poderia fazer isso com .place. Voto para você!
SuperJedi224

Você pode substituir charCodeAt(0)por charCodeAt()e você pode usar a função de seta para function(y)...economizar alguns bytes e para ~~(y/3)você poder usary/3|0
chau giang 20/09

3

Ruby, 75 caracteres

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

Usa o charsbloco obsoleto com e imprime cada letra individualmente com $><<. Eu também gosto [[*?a..?z].index(c)||-1]; ele pega o caractere correspondente à letra do alfabeto, se for uma letra, e o último caractere (que passa a ser o caractere de teste inalterado), se não for.

Ruby, 43 (ou 35) caracteres

Roubando descaradamente de @ace;)

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

Raspe 8 caracteres se eu puder executar no IRB com a variável scomo a string:

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

3

C ++ - 222 caracteres

Solução mais longa até agora:

#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, eu não acho solução mais longo é o objetivo aqui ...
Danny

@ Danny C ++ não se presta bem ao código-golfe . Java e C # são as únicas linguagens piores que eu conheço (todas as classes, criação de objetos e nomes longos para saída ...).
Hosch250

Eu sei, achei engraçado você mencionar "Solução mais longa".
21914 Danny

3

Frink, 92

Uma linguagem bastante detalhada, eu sei. Isso verifica 8 valores em vez de 26 sem precisar digitar as comparações. Qualquer uma das soluções "222333444 .." acima pode ser reduzida de maneira semelhante?

Usando estruturas embutidas, 107

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

Usando uma função recursiva personalizada, 92

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

+1 para reduzir o método de conversão de cadeia para uma pesquisa de 8 caracteres. Bom toque.
Jonathan Van Matre

2

Smalltalk, 79 70

entrada é s:

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

provavelmente não é candidato por ser o mais baixo - mas pode ser interessante para um truque antigo para evitar um teste para uma condição não encontrada (indexOf: retorna 0 nesse caso). Portanto, nenhum teste especial para letras é necessário. Alguns Smalltalks, no entanto, têm seqüências imutáveis, e precisamos de mais 4 caracteres ("cópia").

Ah, uma versão melhor, que até lida com seqüências imutáveis ​​em 70 caracteres:

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

2

Mathematica 90

Isso segue a lógica da solução do @ ace:

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

Exemplo

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

8437889


Sua representação de caracteres seta não é aceite pelo MMA em um copiar / colar
Dr. belisarius

Além disso, você não precisa o 1em #1:)
Dr. belisarius

Belisarius, mudei a flecha para trás e removi o 1. Ainda 90 caracteres, mas cortar e colar irá funcionar. Você entende, é claro, a motivação para usar a seta de caractere único.
19414

Lembra-se, feito isso :)
Dr. belisarius

2

Perl, 50

Outra cópia óbvia da resposta do bash de Ace

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

1
Este código está funcionando corretamente, mas há espaço para melhorias. Vamos nos livrar do $ ARGV [0] e usar o -pswitch, que permite que você passe por cada linha de stdin. Enquanto estamos nisso, o intervalo em y /// não precisa ser colocado entre colchetes. Também podemos nos livrar de três 9s, deixando apenas um e remover o ponto-e-vírgula final: -p y/a-z/22233344455566677778889/ Pronto, 30 + 1 para -p. Obrigado por usar os Serviços de Otimização e Golfe Enterprise Perl da China e tenha um bom dia.
chinese perl goth

2

R, muito longo, mas divertido

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 caracteres]

{(.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

O JavaScript nunca vai vencer as guerras do golfe, mas eu gosto e queria fazer algo diferente do que pular na onda @ace.

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

2

PHP, 141

Não é o mais curto, mas mais divertido:

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

Mais legível:

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

O OP disse que a entrada já está em minúscula, para que você possa remover ostrtolower
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),

Eu sou novo em python, então tenho certeza de que deve haver uma maneira de jogar isso ainda mais , é uma abordagem diferente, espero que vocês gostem, meu deus, é bonito em python!

Execute o exemplo:

  • entrada: 01-800-abcdefghijklmnopqrstuvwxyz
  • saída: 01-800-22233344455566677778889999

2

T-SQL, 216 bytes

Passei bastante tempo nas últimas duas noites criando meticulosamente uma função de sequência matemática que seria arredondada corretamente para gerar os códigos ASCII adequados para os números dos códigos ASCII alfabéticos. Tinha um número ridículo de casas decimais nos coeficientes, mas funcionou.

No entanto, a abordagem racional de mattnewport também funciona em SQL, a um custo muito menor de bytes, então estou descaradamente descarrilando minha própria matemática em favor da dele. Suba para votar nele, é uma solução elegante!

Aqui está o meu:

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

Isso usa um CTE recursivo para criar uma pilha de caracteres improvisados ​​no número de telefone e traduzir as letras rapidamente, depois um pouco de truque SQL (SELECT @ p = @ p ​​+ columnValue) para recompor a sequência do CTE sem exigir outra construção de recursão.

Saída:

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),


Mais golfed

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


Como não tenho reputação suficiente para comentar a resposta de @ anakata, fiz um post separado aqui. Eu tive a mesma idéia (fazendo o módulo 3 da ordenança), mas não consegui descobrir como imprimir os números certos para s-z .

Enfim, as melhorias de golfe que fiz:

  • alterado raw_inputparainput

  • removeu os nomes estranhos '\b'e parênteses e aspas simples

  • removeu o +2deslocamento e o colocou na subtração original (97 - (3 * 2) = 91)

Testado com o intérprete Python 2.7.6. Supõe, de acordo com as regras, uma entrada de sequência.


você também pode remover o espaço entre a) e a se
Willem

Você está certo. boa captura Willem
zheshishei

1

PHP, 87

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

1

q [38 caracteres]

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

Inspirado na solução da @ ace

Exemplo

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

1

XQuery, 71

O BaseX foi usado como processador XQuery. $ié entrada.

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

Não é a resposta mais curta, mas bastante curta e muito legível.


1

Python, muito ungolfed

Como todo mundo está copiando o ás, decidi postar o código que criei antes de enviar a pergunta:

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

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

Espera iconter a sequência.

Experimente em qualquer versão recente do Firefox. Eu não experimentei o 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

Python

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

0

ECMASCRIPT, 101 (com entrada)

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

Nova linha adicionada para maior clareza. 85 caracteres se a entrada estiver em uma variável.


0

Perl, 54

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

Atire, @RobHoare ainda me venceu por 4 caracteres. :)


0

QBasic, 155

Ah, as memórias ...

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

Isso deveria ter sido mais curto, mas eu estava testando com repl.it , que não permite IFinstruções de linha única e se comporta de maneira estranha se você deixar a variável desativada NEXT i. Ele também não reconhece a ASCfunção, portanto, para executar o código, você precisará adicionar esta solução alternativa no início:

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

(Na segunda vez em que você o executar, o intérprete reclamará, a menos que você remova a DECLARE FUNCTIONlinha, siga em frente.)


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

Exemplo:

> 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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.