Créer un clavier T9

12

Cette question demande une fonctionnalité de correspondance de dictionnaire T9 qui est un problème très intéressant. Mais T9 a une autre façon de taper et c'est de taper caractère par caractère. Vous n'auriez PAS besoin d'un dictionnaire pour implémenter ce clavier.

Voici le clavier d'un clavier T9 si vous avez oublié:

+-------+-------+-------+
|   1   |   2   |   3   |
|  .?!  |  ABC  |  DEF  |
+-------+-------+-------+
|   4   |   5   |   6   |
|  GHI  |  JKL  |  MNO  |
+-------+-------+-------+
|   7   |   8   |   9   |
| PQRS  |  TUV  |  WXYZ |
+-------+-------+-------+
|   *   |   0   |   #   |
|   ←   | SPACE |   →   |
+-------+-------+-------+

Comment fonctionne T9

Pour taper un caractère avec T9, vous devez appuyer sur la touche numérique représentant l' nheure de ce caractère . nest l'ordre de ce caractère écrit sur cette clé. Les chiffres sont le dernier caractère que vous pouvez saisir pour chaque touche. Par exemple, pour taper, Bj'appuie 2deux fois ou pour taper, 5j'appuie 5quatre fois. Pour finir de taper ce caractère, j'appuie sur #. *est simplement un retour arrière. Dans notre version du clavier, il n'y a pas de majuscule.

Exemples d'entrée et de sortie:

8#99999#055#33#999#22#666#2#777#3# → T9 KEYBOARD

Explication:

  • 8sélectionne Tet #passe au personnage suivant
  • 99999sélectionner le dernier caractère de la 9clé qui est 9et #passe au caractère suivant
  • 0 insère un espace
  • 33sélectionne le deuxième caractère de la 3clé qui est Ket #passe au caractère suivant
  • Etc...

Règles

Votre fonction ou programme doit accepter une chaîne représentant les touches T9. La sortie est le texte résultant de ces touches, comme indiqué ci-dessus.

Il s'agit du golf de code de base, donc le gagnant est le plus court en octets, et les règles / lacunes standard s'appliquent.

Mohsen
la source
Le bonus n'a aucun effet sur le score? Pourquoi devrais-je y aller?
Optimizer
2
De plus, votre exemple T9 KEYBOARDest complètement faux. Que l'on litT9 JEYBARD
Optimizer
1
@Mohsen habituellement, les bonus dans le golf de code soustraient un montant fixe du score. vous devrez déterminer combien est raisonnable. pour le premier bonus probablement pas plus de 10 ou 20 octets. le deuxième bonus, je ne comprends même pas. si je donne la séquence de touches sous forme de chaîne à la fonction, comment y aurait-il une sorte de temps entre les touches? Je pense qu'un bonus plus raisonnable serait de permettre d'omettre #si les boutons consécutifs sont de toute façon différents. cela étant dit: sans ce bonus, que devrait-il se passer si #est omis?
Martin Ender
1
Vous devez ajouter un avantage de comptage d'octets possible pour ces bonus. Les bonus sont facultatifs mais vous semblez demander toutes les réponses pour appliquer les bonus comme s'ils étaient obligatoires. Veuillez effacer le ton, si elles sont obligatoires, les déplacer vers les règles, si elles ne le sont pas, ne demandez pas toutes les réponses pour mettre en œuvre les bonus. J'attendrai quelques heures pour votre réponse avant de voter pour clore car pas clair.
Optimizer
2
Aucune réponse même après 18 heures. Voter pour clôturer car pas clair.
Optimizer

Réponses:

5

CJam, 109 94 octets (2 e bonus)

Une solution très naïve et longue

q'#/);{__'*-:A-,_g{){;}*A_}*;'0/{_,g{)~".?~1"a'[,65>292994 5b{/(X):X+\s}%+1:Xm>=\,=}*}%S*1/~}%

Il s'agit d'un programme complet, bien qu'une fonction soit de la même longueur.

L'entrée va dans STDIN

Exemple:

8#99999#055#33#999#***22#666#2#777#3#

Production:

T9 BOARD

Essayez-le en ligne ici

Optimiseur
la source
Pouvez-vous le faire fonctionner pour le premier bonus?
Mohsen
3
@Mohsen Pas avant qu'il y ait un réel avantage à aller chercher des bonus! Disons, une réduction de 25% de la longueur du code dans le score final.
Optimizer
2

JavaScript ES6, 220-10 = 210 178 octets

En tant que membre du CMC d' Helka , j'ai dépassé mon premier défi.

n=>(g=n=>n==(k=n.replace(/.\*/,""))?n:g(k))(n.match(/(\d)\1*|\*/g).map(e=>e<"0"?e:(a=" |.?!|ABC|DEF|GHI|JKL|MNO|PQRS|TUV|WXYZ".split`|`[+e[0]]+e[0])[~-e.length%a.length]).join``)

Exemples de sorties:

> f=n=>(g=n=>n==(k=n.replace(/.\*/,""))?n:g(k))(n.match(/(\d)\1*|\*/g).map(e=>e<"0"?e:(a=" |.?!|ABC|DEF|GHI|JKL|MNO|PQRS|TUV|WXYZ".split`|`[+e[0]]+e[0])[~-e.length%a.length]).join``)
[Function]
> f("8#99999#055#33#999#***22#666#2#777#3#")
'T9 BOARD'
> f("8#44#33#0#999#*77#88#444#222#55#0#22#777#666#9#66#0#333#666#99#0#5#88#6#7#7777#0#666#888#33#777#0#8#44#33#0#555#2#99#*9999#999#0#3#666#4#111#")
'THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG!'
> f("8#99999#055#33#999#***22#666#2#777#3#")
'T9 BOARD'

Explication

(g=n=>n==(k=n.replace(/.\*/,""))?n:g(k))

Cela implémente le remplacement récursif, en remplaçant tous les caractères suivis *jusqu'à ce qu'il n'y ait plus de *s.

n.match(/(\d)\1*|\*/g)

Cela correspond à toutes les séries de chiffres consécutifs, ou *s.

a=" |.?!|ABC|DEF|GHI|JKL|MNO|PQRS|TUV|WXYZ".split`|`[+e[0]]+e[0]

Cela crée le dictionnaire souhaité, obtenant la partie encodée à partir de la grande chaîne, puis y ajoutant le chiffre souhaité.

a[~-e.length%a.length]

Cela obtient le caractère, ala longueur du module .

.join``

Cela prépare la chaîne pour le traitement et la suppression de l' *art.

Conor O'Brien
la source
1
Pouvez-vous le faire fonctionner avec le premier bonus?
Mohsen
@Mohsen Oui, et cela pourrait vraiment l'aider. Je vais y travailler aujourd'hui et demain.
Conor O'Brien
Veuillez au moins ne pas annoncer un score incorrect car la réponse n'est même pas à la hauteur des spécifications.
Optimizer
@Mohsen Il fonctionne maintenant avec le premier bonus.
Conor O'Brien
t("2#2");donne Bau lieu de AA. Essayez de faire correspondre tout #au lieu de les supprimer.
Titus
1

Python, 167 157 151 octets

(ne prend pas en charge «*»)

Rien de spécial. J'utilise regex pour convertir l'entrée en une liste, puis je boucle les entrées. J'utilise le premier caractère et la longueur de chaque entrée pour la rechercher dans une liste de recherche:

def f(i):
  import re
  t9 = [" 0",".?!1","ABC2","DEF3","GHI4","JKL5","MNO6","PQRS7","TUV9","WXYZ9"]
  i = re.findall(r'[1-9]+|0+',i)
  answer = []
  for j in i:
    answer = answer + [t9[int(j[0])][len(j)-1]]
  return ''.join(answer)

Après un peu de golf, cela ressemble à ceci:

import re;m=lambda i:"".join([" 0,.?!1,ABC2,DEF3,GHI4,JKL5,MNO6,PQRS7,TUV9,WXYZ9".split(",")[int(j[0])][len(j)-1] for j in re.findall(r'[1-9]+|0+',i)])

Pas encore de bonus. Je ne sais pas comment j'implémenterais le premier bonus dans regex. Le deuxième bonus ajouterait beaucoup d'octets car les éléments de recherche ne sont pas de la même taille. Je ne comprends pas vraiment le troisième bonus.

Def
la source
1

Perl 5: 106 (code 104 + 2 drapeaux)

Modifié pour gérer les suppressions.

#!perl -lp
s/((\d)\2*)#?|./chr$2*5+length$1/ge;y//d 0-3.?!1 ABC2 DEF3 GHI4 JKL5 MNO6 P-S7TUV8 W-Z9/c;1while s/.?d//

Usage:

perl t9.pl <<<'8#99999#055#33#999#22#666#2#777#3#'
perl t9.pl <<<'899999055339992266627773'

Perl 5: 88 (code 86 + 2 drapeaux)

Ancienne version sans suppression d'étoile.

#!perl -lp
s/(\d)(\1*)#?/chr$1*5+length$2/ge;y// 0-3.?!1 ABC2 DEF3 GHI4 JKL5 MNO6 P-S7TUV8 W-Z9/c
nutki
la source
@Optimizer l'a essayé, et cela ne fonctionne pas avec *. Mais est-ce réellement nécessaire? Il dit: "Notez qu'il peut inclure * pour le retour arrière ..."
Def
Étant donné que cela ne fait pas partie du bonus. C'est une règle obligatoire.
Optimizer
Cela étant dit. la question n'est pas très claire sur ce qu'est une règle et ce qu'est un bonus. J'ai demandé des éclaircissements à OP il y a plusieurs heures. S'il n'y a pas de réponse, je vote pour clore cette question car elle n'est pas claire.
Optimizer
Désolé, j'ai été induit en erreur car les réponses actuelles dans les langues que je peux lire ne prennent pas en charge *.
nutki
Si vous faites référence à ma réponse en python, vous avez raison. J'ai mal interprété la question.
Def
1

AWK 211 octets (avec les bonus)

{split(".?!1-ABC2-DEF3-GHI4-JKL5-MNO6-PQRS7-TUV8-WXYZ9- 0",k,"-");split($0"#",a,"");while(1+(b=a[++i])){if(b==p)++c;else{for(g in k)if(p==substr(k[g],l=length(k[g])))printf(substr(k[g],1+((c-1)%l),1));c=1;p=b}}}

Il s'agit d'un programme complet qui lit l'entrée de stdin. Il serait plus efficace de ne pas replacer le clavier pour chaque ligne, mais cela allongerait le script.

De plus, si la touche "0" était autre chose que 0, le script serait plus court de 4 octets, mais cela fait partie du jeu: o)

LeFauve
la source
1

C (245 octets)

#define M "8#44#33#0#999#*77#88#444#222#55#0#22#777#666#9#66#0#333#666#99#0#5#88#6#7#7777#0#666#888#33#777#0#8#44#33#0#555#2#99#*9999#999#0#3#666#4#111#"

#include<stdio.h>
char K[][4]={" ",".?!","ABC","DEF","GHI","JKL","MNO","PQRS","TUV","WXYZ"},I[]=M;int       
i,j,k,r;main(){for(;I[i];++i){if(I[i]=='#')I[j++]=K[k][--r],r=k=0;else               
if(I[i]=='*')j?--j:0;else if(!r++)k=I[i]-'0';}I[j]=0;printf("%s\n",I);}

Production

THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG!

Explication

Le nombre d'octets n'inclut pas la chaîne d'entrée donnée dans le premier #define.

J'utilise un tableau à deux dimensions comme table de recherche pour quel caractère imprimer. Le programme lit en caractères délimités par '#'.

Pour chaque groupe, le numéro d'entrée détermine l'indice de tableau de première dimension et le nombre de répétitions du numéro d'entrée détermine l'indice de tableau de deuxième dimension. Le fait '*'reculer l'index du tableau pour la chaîne de sortie afin d'écraser la lettre précédente.

Ainsi, la chaîne d'entrée 44#(1 répétition de '4') est traduite en table de recherche K[4][1], qui est le caractère H.


Version non golfée

#define INPUT "8#44#33#0#999#*77#88#444#222#55#0#22#777#666#9#66#0#333#666#99#0#5#88#6#7#7777#0#666#888#33#777#0#8#44#33#0#555#2#99#*9999#999#0#3#666#4#"

#include<stdio.h>

static const char keyboard[10][4] = {" ", ".?!", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ"};

int main(void)
{
  char input[] = INPUT;
  char output[256];
  int i, j;
  int key = 0;
  int reps = 0;

  for (i = j = 0; input[i] != '\0'; ++i) {
    switch (input[i]) {
    case '#':
      output[j] = keyboard[key][reps - 1];
      ++j;
      reps = key = 0;
      break;
    case '*':
      if (j > 0) --j;
      break;
    default:
      if (reps == 0)  {
        key = (int)input[i] - '0';
      }
      ++reps;
      break;
    }
  }

  output[j] = '\0';
  printf("%s\n", output);

  return(0);
}
musarithmie
la source
1

Ruby 254 , 248 , 229 octets

Golfé:

n=->(t){r,m,b=[]," _.?!1_ABC2_DEF3_GHI4_JKL5_MNO6_PQRS7_TUV8_WXYZ9_*_0_#".split("_"),nil;t.scan(/((.)\2*)/){|l,_|(!(l=~/\#/)?(l=~/\*/?(r.pop l.size):(l=="00"?r<<(b ? "0 ":" 0"):(c=m[l[0].to_i];r<<c[l.size%c.size-1]))):b=l)};r*""}

Non golfé:

def t9totext(t)
  bonq = nil
  numpad = [" ",".?!1","ABC2","DEF3","GHI4","JKL5","MNO6","PQRS7","TUV8","WXYZ9","*","0","#"]

  r = []
  t.scan(/((.)\2*)/) do |l, _|
    if !(l =~ /\#/)
      if l =~ /\*/
        r.pop(l.size)
      elsif l == "00"
        r << (bonq ? "0 " : " 0")
      else
        c = numpad[l[0].to_i]
        r << c[l.size % c.size - 1]
      end
    else
      bonq = l
    end
  end
  r.join
end

Toutes ces spécifications devraient réussir:

  it "outputs the correct word" do
    expect(n.call('8#99999#055#33#999#22#666#2#777#3#1')).to eq("T9 KEYBOARD.")
    expect(n.call('4433555#55566609666666677755533*3111')).to eq("HELLO WORLD!")
    expect(n.call('7##222#222**7#222#4')).to eq('PPCG')
    expect(n.call('00#0#00')).to eq(' 0 0 ')
  end

La 0 0réponse ressemble un peu à une solution hacky. J'y reviendrai quand j'aurai le temps.

Biketire
la source
0

PHP, 183-10 = 173 octets

Toutes les versions prennent l'entrée de l'argument de ligne de commande; appeler avec php -r '<code>' <string>.

Remarque : Toutes les versions lancent un avertissement si l'entrée commence par *.
Ajoutez $o=[];le code pour supprimer cette faille.

preg_match_all("%(\d)\1*|\*%",$argv[1],$m);foreach($m[0]as$w)if("*"==$w)array_pop($o);else$o[]="- 0   .?!1 ABC2 DEF3 GHI4 JKL5 MNO6 PQRS7TUV8 WXYZ9"[$w[0]*5+strlen($w)];echo join($o);
  • n'a pas besoin de balises de hachage
  • échoue si une touche est pressée trop souvent

210-10 - ?? = ??? octets

$a=[" 0",".?!1",ABC2,DEF3,GHI4,JKL5,MNO6,PQRS7,TUV8,WXYZ9];preg_match_all("%(\d)\1*|\*%",$argv[1],$m);foreach($m[0]as$w)if("*"==$w)array_pop($o);else$o[]=$a[$w[0]][strlen($w)%strlen($a[$w[0]])-1];echo join($o);
  • n'a pas besoin de balises de hachage
  • tourne si une touche est pressée trop souvent

181 octets, pas de bonus

preg_match_all("%\d+#|\*%",$argv[1],$m);foreach($m[0]as$w)if("*"==$w)array_pop($o);else$o[]=" 0   .?!1 ABC2 DEF3 GHI4 JKL5 MNO6 PQRS7TUV8 WXYZ9"[$w[0]*5+strlen($w)-2];echo join($o);

panne

Les versions sans balises de hachage divisent la chaîne en (séquence de nombres égaux) et (astérisque) et oublient tout le reste. La version sans bonus prend (séquence de chiffres suivie de #) et (astérisque).

Parcourez ensuite les correspondances: Si un «*» est trouvé, supprimez le dernier élément du tableau de résultats.

La différence entre les versions est dans la elsepartie:

  • pas de version bonus: décaler la chaîne de carte vers (touche * 5), puis ajouter (frappes = longueur du mot-1) -1, ajouter le caractère de cette position au résultat.
  • version simple sans étiquette: presque la même, mais: (frappes = longueur du mot); ajouté un caractère à la chaîne de carte pour se débarrasser de l'autre -1.
  • version rotative: prendre l'élément (clé) du tableau de cartes, ajouter le caractère (frappes% longueur de l'élément-1) de cet élément pour obtenir le résultat.
Titus
la source
0

JavaScript, 147 octets

La réponse de Conor a été corrigée avec l'expression régulière de ma réponse PHP et a joué au golf.

t=i=>i.match(/(\d)\1*|\*/g).map(w=>(" 0~.?!1~ABC2~DEF3~GHI4~JKL5~MNO6~PQRS7~TUV8~WXYZ9".split`~`[w[0]]||"*")[w.length-1]).join``.replace(/.\*/g,"")

panne

t=i=>i
    .match(/(\d)\1*|\*/g)   // split input to streaks of equal numbers and single `*`
    .map(w=>                // replace each item with ...
                            // .. take string depending on the digit
        (" 0~.?!1~ABC2~DEF3~GHI4~JKL5~MNO6~PQRS7~TUV8~WXYZ9".split`~`[w[0]]
        ||"*")              // .. ("*" for not a digit)
        [w.length-1]        // -> the (item length)th character of that string
    )
    .join``                 // join without delimiter
    .replace(/.\*/g,"")     // and recursively remove every (letter,asterisk) combination

version tournante, 158 octets

ajouté s=pour mémoriser la chaîne et %s.lengthpour faire pivoter.

t=i=>i.match(/(\d)\1*|\*/g).map(w=>(s=" 0~.?!1~ABC2~DEF3~GHI4~JKL5~MNO6~PQRS7~TUV8~WXYZ9".split`~`[w[0]]||"*")[w.length%s.length-1]).join``.replace(/.\*/g,"")
Titus
la source