Orthographe à touches multiples

21

Inspiré par le Google Code Challenge :

L'alphabet latin contient 26 caractères et les téléphones n'ont que dix chiffres sur le clavier. Nous aimerions faciliter l'écriture d'un message à votre ami en utilisant une séquence de touches pour indiquer les caractères souhaités. Les lettres sont mappées sur les chiffres comme indiqué ci-dessous. Pour insérer le caractère B par exemple, le programme doit appuyer sur 22. Afin d'insérer deux caractères en séquence à partir de la même touche, l'utilisateur doit faire une pause avant d'appuyer une deuxième fois sur la touche. Le caractère espace '' doit être imprimé pour indiquer une pause. Par exemple, 2 2 indique AA tandis que 22 indique B.

Chaque message sera composé uniquement de caractères minuscules az et d'espaces ''. Appuyer sur zéro émet un espace.

entrez la description de l'image ici

Votre défi consiste à écrire la plus petite fonction qui prend la chaîne d'entrée et renvoie la séquence de touches nécessaire pour produire l'entrée sous forme de chaîne ou la sortir vers stdout. La fonction qui a le moins d'octets gagne.

Exemple d'entrée / sortie

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

Autres clarifications

  • Les pauses ne doivent être ajoutées que lorsque cela est nécessaire et doivent être un espace ''.
  • Chaque message sera composé uniquement de caractères minuscules az et d'espaces ''. Imprimez 0pour signifier les espaces.
  • Pas de bibliothèques externes.
  • Seule la chaîne d'entrée peut être transmise à votre fonction.
  • Pour rendre d'autres langages compétitifs, la déclaration de fonction principale ne compte pas, pas plus que l'importation d'autres bibliothèques standard. #includes, imports et usings ne comptent pas. Tout le reste fait. Cela inclut les fonctions #defines et d'assistance. Voir la règle 2 dans cette question si vous êtes confus.
  • Plusieurs espaces peuvent être notés comme 00ou 0 0puisque vous n'avez pas vraiment besoin de faire une pause entre un espace
Danny
la source
1
Lié à cela: codegolf.stackexchange.com/questions/21327/…
Victor Stafusa
Pouvons-nous supposer que l'entrée est en minuscules / majuscules?
Phil H
@PhilH " caractères minuscules az et caractères d'espace ''"
Danny
Considérez-vous que les crochets font {}partie de la signature de la fonction? Par exemple, si mon code est function f(){alert('hi');}, dois-je compter les caractères de alert('hi');ou {alert('hi');}?
ProgramFOX
2
Pour autant que je me souvienne, cela t9fonctionne différemment: vous devez cliquer une fois sur chaque touche pour obtenir un mot.
VisioN

Réponses:

8

Rubis, 129 122 115 111 108 107 105

Fait avec le golf ...

Oups, j'ai complètement oublié de supprimer les espaces inutiles - corrigé ...

Enregistrement de 2 caractères grâce à Peter Taylor.

Version en ligne

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

Explication:

l'espace est traduit au caractère avec l'ordinal 96

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

les caractères sont d'abord mappés sur une série de nombres: - a à 2 - b à 22 - d à 3222 - h à 444333222

une expression régulière correspond alors au premier groupe de chiffres égaux

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

le tableau est joint

*' ')

tous les espaces dans les occurrences de "digit digit different_digit" sont supprimés

gsub /(\d) (?!\1)/,'\1'
David Herrmann
la source
1
Ne semble pas fonctionner à 100%. Je vois que 66666 ne devrait jamais avoir besoin d'être pressé 4 fois de suite.
Danny
Devrait être corrigé, merci;)
David Herrmann
1
Quel est l'intérêt de \2ce regex final? Assurément, le deuxième groupe est une affirmation de largeur nulle?
Peter Taylor
Vous avez absolument raison!
David Herrmann
6

REBEL - 154 110 103

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

Cette «fonction» accepte les entrées de stdin et envoie les résultats à stdout.

Test s'exécute (vous n'avez donc pas besoin d'installer l'interpréteur):

hi
44 444

hello world
4433555 555666096667775553

yes
999337777

kthxbai
558449922 2444
Kendall Frey
la source
Je ne pourrai jamais charger vos liens! :(
luser droog
4

JavaScript (124)

Exécutez dans Firefox.

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

GolfScript, 46 caractères

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

Comme d'habitude, lit l'entrée de stdin, imprime sur stdout. Voir la démo en ligne (avec entrée standard).

Notez que ce code repose sur une interprétation très stricte de la spécification d'entrée (uniquement les lettres minuscules et les espaces): en particulier, toute nouvelle ligne dans l'entrée la plantera! Ce problème peut être résolu, au prix de deux caractères supplémentaires, en ajoutant n-au code pour filtrer les nouvelles lignes.

Ilmari Karonen
la source
3

C ++ - 365 caractères sans 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;}}}

Utilise le même raisonnement que ma réponse ici , en utilisant uniquement des forboucles pour sortir chaque lettre le nombre approprié de fois.

Hosch250
la source
Vous pouvez utiliser à la s[i]==32place de s[i]==' '. La valeur ASCII de l'espace est de 32.
user12205
@ace Bien sûr.
Hosch250
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

Voici ma solution précédente dans 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

Tests:

hi
 44 444

hello world
 4433555 555666096667775553

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

VBA 220 253/258/219

Sans compter les Functionlignes ici:

Avec 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

Avec une Forboucle 258 :

Ajout de corrections pour la clé 7/9 (merci, Danny), qui a ajouté beaucoup de caractères.

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

Utilisation de Choose 219 :

Je ne voulais pas courir avec celui - ci, depuis est plus basique dans la fonctionnalité, mais il est le code plus court ...

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
la source
yesdevrait être 999337777. J'utilise 10338votre fonction.
Danny
3

C, 165 163 153 149 138 caractères

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

Ma première tentative de golf de code, toutes les suggestions sont appréciées.

user18204
la source
2

C ++ - 170 168 160

Golfé:

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

Non golfé

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
la source
2

C: 136 caractères

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

Et légèrement non golfé (oui, c'est comme ça que c'était écrit):

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

Je pourrais peut-être le réduire un peu en appliquant de la récursivité, de la magie noire et une bonne quantité de poudre de chili.

Fors
la source
2

Java - 243

Solution java assez naïve. Merci aux commentateurs pour leurs suggestions.

Correction d'un bug qui insérait parfois des espaces inutiles, par exemple pour l'entrée "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;
    }
caractère générique
la source
4
Très bien, mais vous devez jouer au golf et fournir le score.
Hosch250
1
Je suppose que c'est le cas java. Pouvez-vous mettre cela dans votre titre, comme le font les autres réponses?
Digital Trauma
1
Un golf: remplacer t.lengthpar10
Justin
En outre, étant donné que celui-ci in'est utilisé que pour itérer à travers le String, supprimez-le et faites une boucle foreach:for(char c:s.toCharArray())
Justin
En outre, le changement if(c==' '){o+='0';continue;}à if(c==' ')o+='0';else{et ajouter le approprié }.
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
la source
1

APL, 77 caractères

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

Explication

  • 2+⌊y←7.99,⍨.315×⍳25ou, sans golf, y←(0.315×⍳25),7.99 ◇ 2+⌊yéchantillonne une ligne convenablement inclinée (y = 0,315 x) sur les points de 1 à 25; la ligne est inclinée de telle sorte que le plancher de ces valeurs y suit le motif répétitif 000111 ... 777 à l'exception du sixième groupe de chiffres 5555; un nombre est ajouté à la fin pour obtenir le quatrième 7, de sorte que le tableau final plus 2 est 22233344455566677778889999;
  • ⌈3.1×y-⌊y amplifie la différence entre ces valeurs y et leurs étages, de sorte que les plafonds des différences donnent le motif 123123 ... avec un 4 sur les derniers chiffres des deux groupes de 4 chiffres;
  • '0',⍨( ... )/¨⍕¨ ...ou (( ... ) /¨ ⍕¨ ...),'0' utilise le dernier résultat pour dupliquer les chiffres du premier, de sorte que la sortie soit le tableau de chaînes "2" "22" "222" "3" "33" "333" ... avec les bons "7777" et " 9999 "en place et un" 0 "ajouté à la fin;
  • ⍵⍳⍨⎕UCS 96+⍳26ou (⎕UCS 96+⍳26)⍳⍵calcule l'indice de chaque caractère d'entrée, où "a" est 1, "z" est 26 et l'espace (et tous les autres caractères) est 27;
  • { ... }/( ... )[ ... ] prend le dernier résultat, l'index pour chaque caractère d'entrée, pour traduire chaque caractère dans la chaîne de chiffres respective, puis concatène les chaînes en utilisant la fonction entre accolades;
  • {⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}ou {(⍺,(=/↑¨⍺,⍵)↑''),⍵}ajoute chaque nouvelle chaîne ⍺ à l'accumulateur ⍵, en interposant un seul espace uniquement si les deux arguments commencent par le même caractère.

Exemples

      {{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('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
la source
1

Python 155 150

Je souhaite que je sois meilleur dans ce XD. Définition de fonction non comptée. Le premier niveau d'indentation est un espace, le deuxième est un onglet et le troisième 2 onglets.

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
la source
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
la source
0

R 224

Je suis sûr qu'il existe une meilleure façon de procéder, donc je vais continuer à y travailler.

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
la source