Ortografia Multi-toque por Telefone

21

Inspirado no Google Code Challenge :

O alfabeto latino contém 26 caracteres e os telefones possuem apenas dez dígitos no teclado. Gostaríamos de facilitar a gravação de uma mensagem para seu amigo usando uma sequência de pressionamentos de tecla para indicar os caracteres desejados. As letras são mapeadas para os dígitos, como mostrado abaixo. Para inserir o caractere B, por exemplo, o programa pressionaria 22. Para inserir dois caracteres em sequência da mesma tecla, o usuário deve fazer uma pausa antes de pressionar a tecla uma segunda vez. O caractere de espaço '' deve ser impresso para indicar uma pausa. Por exemplo, 2 2 indica AA enquanto 22 indica B.

Cada mensagem consistirá apenas em caracteres minúsculos az e caracteres de espaço ''. Pressionar zero emite um espaço.

insira a descrição da imagem aqui

Seu desafio é escrever a menor função que pega a string de entrada e retorna a sequência de pressionamentos de tecla necessários para produzir a entrada como string ou enviá-la para stdout. A função com a menor quantidade de bytes vence.

Exemplo de entrada / saída

phone("hi")
44 444
phone("hello world")
4433555 555666096667775553

Outros esclarecimentos

  • As pausas devem ser adicionadas apenas quando necessário e devem ser um espaço ''.
  • Cada mensagem consistirá apenas em caracteres minúsculos az e caracteres de espaço ''. Imprima 0para significar espaços.
  • Nenhuma biblioteca externa.
  • Somente a string de entrada pode ser passada para sua função.
  • Para tornar outros idiomas competitivos, a declaração da função principal não conta e nem importa outras bibliotecas padrão. #includes, se importes usingnão contam. Tudo o resto faz. Isso inclui #definefunções se e auxiliar. Veja a regra 2 nesta pergunta se você estiver confuso.
  • Vários espaços podem ser indicados como 00ou 0 0já que você realmente não precisa fazer uma pausa entre um espaço
Danny
fonte
11
Relacionado com isso: codegolf.stackexchange.com/questions/21327/…
Victor Stafusa 4/14
Podemos assumir que a entrada está em maiúsculas / minúsculas?
Phil H
@PhilH " caracteres minúsculos az e caracteres de espaço ''"
Danny
Você considera os colchetes {}parte da assinatura da função? Por exemplo, se meu código for function f(){alert('hi');}, devo contar os caracteres de alert('hi');ou {alert('hi');}?
ProgramFOX
2
Tanto quanto me lembro, t9funciona de maneira diferente: você precisa clicar em cada tecla uma vez para obter uma palavra.
VisioN

Respostas:

8

Rubi, 129 122 115 111 108 107 105

Feito com golfe ...

Ops, esqueci completamente de remover espaços desnecessários - ...

Guardado 2 caracteres graças a Peter Taylor.

Versão online

def t9(t)
(t.tr(" ",?`).bytes.map{|c|"09998887777666555444333222"[96-c..-1][/(.)\1*/]}*' ').gsub /(\d) (?!\1)/,'\1'
end

Explicação:

espaço é traduzido para o char com o ordinal 96

(t.tr(" ",?`).bytes

os caracteres são mapeados primeiro para uma série de números: - a a 2 - b a 22 - d a 3222 - h a 444333222

uma expressão regex corresponde ao primeiro grupo de dígitos iguais

map{|c|"09998887777666555444333222"[96-c..-1][/(.)\1*/]}

a matriz está unida

*' ')

todos os espaços nas ocorrências de "espaço com dígitos diferentes_dígitos" são removidos

gsub /(\d) (?!\1)/,'\1'
David Herrmann
fonte
11
Não parece funcionar 100% certo. Eu vejo que 66666 não precisa ser pressionado 4 vezes seguidas.
21944 Danny
Deve ser fixada, graças;)
David Herrmann
11
Qual é o objetivo \2desse regex final? Certamente o segundo grupo é uma afirmação de largura zero?
Peter Taylor
Você está absolutamente correto!
David Herrmann
6

REBEL - 154 110 103

;0 2abc3def4ghi5jkl6mno7pqrs8tuv9wxyz/^;/$<;/([^\d-])(?=\D.*(\d)(\w)*\1)/$2$3-/(\d)-+\1/$1 $1/-//;/$>$`

Esta 'função' aceita entrada do stdin e envia resultados para o stdout.

Execuções de teste (para que você não precise instalar o intérprete):

hi
44 444

hello world
4433555 555666096667775553

yes
999337777

kthxbai
558449922 2444
Kendall Frey
fonte
Eu nunca consigo carregar seus links! :(
luser Droog
4

JavaScript (124)

Execute no Firefox.

t9=s=>s.replace(/./g,c=>'099998887777666555444333222'.slice(36-parseInt(c,36)).match(/(.)\1*/)[0]+' ').replace(/(.) (?!\1)/g,'$1')
FizzyTea
fonte
4

GolfScript, 46 caracteres

{).," adgjmptw"&.,.1>*`@@)\;-*}/]{.2$^!" "*\}*

Como de costume, lê as entradas de stdin, imprime em stdout. Veja demonstração on-line (com entrada em lata).

Observe que este código se baseia em uma interpretação muito rigorosa da especificação de entrada (apenas letras minúsculas e espaços): em particular, qualquer nova linha na entrada o trava! Esse problema pode ser corrigido, ao custo de dois caracteres extras, anexando n-o código para filtrar as novas linhas.

Ilmari Karonen
fonte
3

C ++ - 365 caracteres sem int main(){}

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

Usa o mesmo raciocínio da minha resposta aqui , usando apenas forloops para gerar cada letra o número apropriado de vezes.

Hosch250
fonte
Você pode usar em s[i]==32vez de s[i]==' '. O valor ASCII do espaço é 32.
user12205 4/14
@ace Coisa certa.
precisa saber é o seguinte
3

Perl - 107 110

$_=<>;y/ /0/;$z='a';$==2;for$l((3)x5,4,3,4){for$q(1..$l){s/$z/$=x$q.$"/ge,$z++}$=++}s/(.) (?!\1)/\1/g;print

Aqui está minha solução anterior em 120 128 130 155 :

$_=<>;s//_/g;y/sz/79/;for$x(cfilorvy,behknqux,adgjmptw){s/(\d)_/\1\1_/g,eval"y/$x/2-9/"}y/ _/0 /;s/(.) (?!\1)/\1/g;print

Testes:

hi
 44 444

hello world
 4433555 555666096667775553

jackdaws loves my big sphinx
 52 222553297777055566688833777706999022444 407777 744 4446699
mniip
fonte
3

VBA 220 253/258/219

Não contando Functionlinhas aqui:

Com String, 253 :

Function t(s)
For Each c In Split(StrConv(s,64),Chr(0))
If c<>""Then If c=" "Then t=t & 0 Else b=Asc(c)-91:n=String(IIf(b>27,(b-4)Mod 4+1,IIf(b>23,(b-1)Mod 4+1,b Mod 3+1)),Trim(Str(Int(b/3)-IIf(b=24Or b=27Or b>29,1,0)))):t=t &IIf(Right(t,1)=Left(n,1)," " &n,n)
Next
End Function

Com um Forloop 258 :

Correções adicionadas à tecla 7/9 (obrigado, Danny), que adicionaram muitos caracteres.

Function t(s)
For Each c In Split(StrConv(s,64),Chr(0))
If c<>""Then
n=""
b=Asc(c)-91
For i=1To IIf(b>27,(b-4)Mod 4+1,IIf(b>23,(b-1)Mod 4+1,b Mod 3+1))
n=n &Int(b/3)-IIf(b=24Or b=27Or b>29,1,0)
Next
t=t &IIf(c=" ",0,IIf(Right(t,1)=Left(n,1)," " &n,n))
End If
Next
End Function

Usando Choose 219 :

Eu não queria rodar com este, pois é mais básico em funcionalidade, mas é o código mais curto ...

Function t(s)
For Each c In Split(StrConv(s,64),Chr(0))
If c<>"" Then:b=Asc(c)-96:n=Choose(b,2,22,222,3,33,333,4,44,444,5,55,555,6,66,666,7,77,777,7777,8,88,888,9,99,999,9999):t=t &IIf(c=" ",0,IIf(Right(t,1)=Left(n,1)," " &n,n))
Next
End Function
Gaffi
fonte
yesdeveria ser 999337777. Eu 10338uso sua função.
21944 Danny
3

C, 165 163 153 149 138 caracteres

k(char*s){char*m="`cfilosvz",l=0,i,c;while(*s^0){for(i=0;*s>m[i];i++);c=*s-m[i-1];i==0?i=-1,c=1:i==l?putchar(32):1;while(c--)putchar(i+49);l=i;s++;}}

Minha primeira tentativa no código de golfe, todas as sugestões são apreciadas.

user18204
fonte
2

C ++ - 170 168 160

Golfe:

#define t std::cout<< 
void g(char*s){char v,p,b,l=1;while(*s){v=*s++-97;p=(v==18)+(v==25)+(v-=v/18+v/25)%3;b=v<0?48:v/3+50;if(l==b)t' ';while(p--+1){t(l=b);}}}

Ungolfed

void numpresses(char* s)
{
char lastbutton = 1;
const char asciiOffset = 97;

while(*s)
{
    char val = *s++ - asciiOffset;

    char presses = 
        (val == 18) + (val == 25)           //Z and S are special cases. Check for their ascii codes.
        + (val -= val / 18 + val / 25) % 3; //Simple mod 3 for number of presses. Also apply offset for characters above s and z.

    char button =
        val < 0                             //If the character is a space...
        ? '0'                               //The button character needs to be 0
        : val / 3 + '2';                    //Buttons are offset by the ascii code for the number 2


    if (lastbutton == button)               //Add a space if we need to pause
    {
        std::cout << ' ';
    }

    while (presses-- + 1)                   //Print the button once for each press required
    {
        std::cout << button;
        lastbutton = button;            
    }
}
}
Tharwen
fonte
2

C: 136 caracteres

p(char*s){int i,c,l=1;while(c=*s%32,*s++)for(i=l!=(l=(c+149-c/18-c/25)/3-!c);i++<(c-!!c-c/18-c/25)%3+(c==19)+c/26+2;putchar(i^1?l:32));}

E um pouco não-destruído (sim, é assim que foi escrito):

p(char*s){
        int i,c,l=1;
        while(c=*s%32,*s++)for(
                i=l!=(l=(c+149-c/18-c/25)/3-!c);
                i++<(c-!!c-c/18-c/25)%3+(c==19)+c/26+2;
                putchar(i^1?l:32)
        );
}

Talvez eu consiga reduzir um pouco aplicando alguma recursão, magia negra e uma boa quantidade de pimenta em pó.

Para s
fonte
2

Java - 243

Solução java bastante ingênua. Obrigado aos comentadores por sugestões.

Corrigido um erro que algumas vezes inseria espaços desnecessários, por exemplo, para a entrada "hello worlds sup".

    private static void t9(String s) {
        String[]t=",,abc,def,ghi,jkl,mno,pqrs,tuv,wxyz".split(",");String o="";int i,j,k,l=0;for(char c:s.toCharArray()){if(c==32){o+='0';l=0;}else for(j=0;j<10;j++){int n=t[j].indexOf(c);if(n>=0){if(j==l)o+=' ';for(k=0;k<n+1;k++)o+=j;l=j;}}}return o;
    }
curinga
fonte
4
Muito bom, mas você precisa jogar golfe e fornecer a pontuação.
precisa saber é o seguinte
11
Eu assumo isso java. Você pode colocar isso em sua posição, como as outras respostas?
Digital Trauma
11
Um golfe: substitua t.lengthpor10
Justin
Além disso, considerando que ele ié usado apenas para iterar através do String, remova-o e faça um loop foreach:for(char c:s.toCharArray())
Justin
Além disso, a mudança if(c==' '){o+='0';continue;}para if(c==' ')o+='0';else{e adicionar o apropriado }.
Justin
1

CoffeeScript - 202 (210 - 8)

t9=(s)->
    t=[3,3,3,3,3,4,3,4];l=-1;r=""
    for c in s
        n="";d=c.charCodeAt(0)-96
        if c is ' '
            n=0
        else((n+=k+2 for x in[0...d];break)if d<=v;d-=v)for v,k in t
        r+=if n[0]is l[0] then " "+n else n
        l=n
    r
TimWolla
fonte
1

APL, 77 caracteres

{{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('0',⍨(⌈3.1×y-⌊y)/¨⍕¨2+⌊y←7.99,⍨.315×⍳25)[⍵⍳⍨⎕UCS 96+⍳26]}

Explicação

  • 2+⌊y←7.99,⍨.315×⍳25ou, sem ser golpeado, y←(0.315×⍳25),7.99 ◇ 2+⌊ymostra uma linha adequadamente inclinada (y = 0,315 x) nos pontos de 1 a 25; a linha é inclinada de forma que o piso desses valores y siga o padrão de repetição 000111 ... 777, exceto o sexto grupo de dígitos 5555; um número é anexado no final para obter o quarto 7, para que a matriz final mais 2 seja 22233344455566677778889999;
  • ⌈3.1×y-⌊y amplifica a diferença entre esses valores y e seus pisos, de modo que os limites máximos das diferenças dêem o padrão 123123 ... com um 4 nos últimos dígitos dos dois grupos de 4 dígitos;
  • '0',⍨( ... )/¨⍕¨ ...ou (( ... ) /¨ ⍕¨ ...),'0' usa o último resultado para duplicar dígitos do anterior, de modo que a saída seja a matriz de cadeias "2" "22" "222" "3" "33" "333" ... com os "7777" e "corretos" 9999 "no lugar e um" 0 "anexado ao final;
  • ⍵⍳⍨⎕UCS 96+⍳26ou (⎕UCS 96+⍳26)⍳⍵calcula o índice de cada caractere de entrada, onde "a" é 1, "z" é 26 e o ​​espaço (e todos os outros caracteres) é 27;
  • { ... }/( ... )[ ... ] pega o último resultado, o índice de cada caractere de entrada, para converter cada caractere na respectiva sequência de dígitos e concatena as sequências usando a função entre chaves;
  • {⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}ou {(⍺,(=/↑¨⍺,⍵)↑''),⍵}anexa cada nova string ⍺ ao acumulador ⍵, interpondo um único espaço apenas se os dois argumentos começarem com o mesmo caractere.

Exemplos

      {{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('0',⍨(⌈3.1×y-⌊y)/¨⍕¨2+⌊y←7.99,⍨.315×⍳25)[⍵⍳⍨⎕UCS 96+⍳26]} 'hello world'
 4433555 555666096667775553 
      {{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('0',⍨(⌈3.1×y-⌊y)/¨⍕¨2+⌊y←7.99,⍨.315×⍳25)[⍵⍳⍨⎕UCS 96+⍳26]} 'the quick brown fox jumped over the lazy dog'
 84433077884442225502277766696603336669905886733 3066688833777084433055529999 999036664 
Tobia
fonte
1

Python 155 150

Eu gostaria de ser melhor neste XD. Definição de função não contada. O primeiro nível de indentação é um espaço, o segundo é uma guia e as terceiras 2 guias.

def p(s,l=None):
 for c in s:
    for i,g in enumerate(" ,,abc,def,ghi,jkl,mno,pqrs,tuv,wxyz".split(",")):
        if c in g:print"\b"+[""," "][l==i]+str(i)*(g.index(c)+1),;l=i
gcq
fonte
0

JavaScript 234

for(l=-1,r="",I=0,y=(s=prompt()).length;I<y;I++){c=s[I];n="";d=c.charCodeAt(0)-96;if(0>d)n=0;else for(k=J=0;J<8;k=++J){v="33333434"[k];if(d<=v){for(x=K=0;0<=d?K<d:K>d;x=0<=d?++K:--K)n+=k+2;break}d-=v}r+=n[0]==l[0]?" "+n:n;l=n}alert(r)

WallyWest
fonte
0

R 224

Tenho certeza de que há uma maneira melhor de fazer isso, então continuarei trabalhando nisso.

a=strtoi(charToRaw(scan(,'',sep='\n')),16L)-95;a[a<0]=1;b=c(0,2,22,222,3,33,333,4,44,444,5,55,555,6,66,666,7,77,777,7777,8,88,888,9,99,999,9999)[a];c=append(b[-1],0)%%10;d=b%%10;b[c==d]=paste(b[c==d],'');paste(b,collapse='')
Gaffi
fonte