Erstellen Sie eine T9-Tastatur


12

Diese Frage fragt nach einer T9-Wörterbuch-Matching-Funktionalität, was ein sehr interessantes Problem darstellt. Aber T9 hat eine andere Art zu tippen, nämlich Zeichen für Zeichen. Sie benötigen KEIN Wörterbuch, um diese Tastatur zu implementieren.

Hier ist die Tastenkarte einer T9-Tastatur, wenn Sie vergessen haben:

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

Wie T9 funktioniert

Um ein Zeichen mit T9 einzugeben, müssen Sie die Zifferntaste drücken, die diese nZeichenzeiten darstellt. nist die Reihenfolge dieses Zeichens, die auf diesen Schlüssel geschrieben ist. Zahlen sind das letzte Zeichen, das Sie für jeden Schlüssel eingeben können. Zum Beispiel Bdrücke ich 2zweimal, um zu tippen, oder um zu tippen, 5drücke ich 5viermal. Um die Eingabe dieses Zeichens zu beenden, drücke ich #. *ist einfach Rücktaste. In unserer Tastaturversion gibt es keine Großschreibung.

Eingabe- und Ausgabebeispiele:

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

Erläuterung:

  • 8wählt aus Tund wechselt #zum nächsten Zeichen
  • 99999Wählen Sie das letzte Zeichen der 9Taste aus 9und #wechseln Sie zum nächsten Zeichen
  • 0 fügt ein Leerzeichen ein
  • 33Wählt das zweite Zeichen der 3Taste aus Kund wechselt #zum nächsten Zeichen
  • Und so weiter...

Regeln

Ihre Funktion oder Ihr Programm sollte eine Zeichenfolge akzeptieren, die T9-Tastendrücke darstellt. Die Ausgabe ist der resultierende Text aus diesen Tastendrücken, wie oben beschrieben.

Dies ist Basic Code Golf, daher ist der Gewinner in Bytes am kürzesten und es gelten Standardregeln / Lücken.


Bonus hat keinen Einfluss auf die Punktzahl? Warum sollte ich es versuchen?
Optimierer

2
Auch Ihr Beispiel T9 KEYBOARDist völlig falsch. Das liestT9 JEYBARD
Optimierer

1
@Mohsen Normalerweise ziehen Boni im Code-Golf einen festen Betrag von der Punktzahl ab. Sie müssen herausfinden, wie viel vernünftig ist. für den ersten Bonus wahrscheinlich nicht mehr als 10 oder 20 Bytes. Den zweiten Bonus verstehe ich nicht einmal. Wenn ich der Funktion die Reihenfolge der Tastendrücke als Zeichenfolge gebe, wie lange würde es zwischen den Tastendrücken dauern? Ich denke, ein vernünftigerer Bonus wäre es, das Weglassen zuzulassen, #wenn aufeinanderfolgende Schaltflächen sowieso unterschiedlich sind. Davon #abgesehen : Was soll ohne diesen Bonus passieren, wenn er weggelassen wird?
Martin Ender

1
Sie müssen einen möglichen Vorteil für die Anzahl der Bytes für diese Boni hinzufügen. Boni sind optional, aber Sie scheinen jede Antwort zu bitten, die Boni so umzusetzen, als ob sie obligatorisch wären. Bitte klären Sie den Ton, wenn sie obligatorisch sind, verschieben Sie sie in Regeln. Wenn dies nicht der Fall ist, bitten Sie nicht jede Antwort, die Boni umzusetzen. Ich werde ein paar Stunden auf Ihre Antwort warten, bevor ich abstimme, um als unklar zu schließen.
Optimierer

2
Keine Antwort auch nach 18 Stunden. Abstimmung zu schließen als unklar.
Optimierer

Antworten:


5

CJam, 109 94 Bytes (2 nd Bonus)

Eine sehr naive und lange Lösung

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

Dies ist ein vollständiges Programm, obwohl eine Funktion dieselbe Länge hat.

Der Eingang geht in STDIN

Beispiel:

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

Ausgabe:

T9 BOARD

Probieren Sie es hier online aus


Kannst du es für den ersten Bonus zum Laufen bringen?
Mohsen

3
@Mohsen Erst wenn es einen tatsächlichen Vorteil gibt, einen Bonus zu bekommen! Nehmen wir an, eine Reduzierung der Codelänge um 25% im Endergebnis.
Optimierer

2

JavaScript ES6, 220-10 = 210 178 Byte

Als Teil von Helkas CMC habe ich meine erste Herausforderung überholt.

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

Beispielausgaben:

> 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'

Erläuterung

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

Dies implementiert eine rekursive Ersetzung, wobei alle Zeichen ersetzt werden, gefolgt von den *verbleibenden Zeichen *.

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

Dies entspricht allen Läufen aufeinanderfolgender Ziffern oder *s.

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

Dadurch wird das gewünschte Wörterbuch erstellt, wobei der codierte Teil aus der großen Zeichenfolge abgerufen und anschließend die gewünschte Ziffer angehängt wird.

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

Dies erhält den Charakter, Modulos aLänge.

.join``

Dies bereitet den String für die Verarbeitung und Entfernung von *s vor.


1
Schaffst du es mit dem ersten Bonus?
Mohsen

@Mohsen Ja, und das könnte tatsächlich helfen. Ich werde heute und morgen daran arbeiten.
Conor O'Brien

Bitte machen Sie zumindest keine Werbung für eine falsche Punktzahl, da die Antwort nicht einmal der Spezifikation entspricht.
Optimierer

@Mohsen Es funktioniert jetzt mit dem ersten Bonus.
Conor O'Brien

t("2#2");gibt Bstatt AA. Versuchen Sie, eine zu finden, #anstatt sie zu entfernen.
Titus

1

Python, 167 157 151 Bytes

(unterstützt '*' nicht)

Nichts Besonderes. Ich verwende Regex, um die Eingabe in eine Liste umzuwandeln, dann schleife ich die Einträge. Ich benutze das erste Zeichen und die Länge jedes Eintrags, um ihn in einer Suchliste zu suchen:

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)

Nach einigem Golfen sieht es so aus:

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

(Noch) keine Boni. Ich weiß nicht, wie ich den ersten Bonus in Regex implementieren würde. Der zweite Bonus würde viele Bytes hinzufügen, da die Suchelemente nicht dieselbe Größe haben. Verstehe den dritten Bonus nicht wirklich.


1

Perl 5: 106 (104 Code + 2 Flags)

Geändert, um Löschungen zu behandeln.

#!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//

Verwendung:

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

Perl 5: 88 (86 Code + 2 Flags)

Alte Version ohne Sternenlöschung.

#!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

@Optimizer hat es versucht und es funktioniert tatsächlich nicht mit *. Ist es tatsächlich erforderlich? Es heißt: "Beachten Sie, dass es * für Rücktaste enthalten kann ..."
Def

Da es nicht Teil des Bonus ist. Es ist eine verbindliche Regel.
Optimierer

Davon abgesehen. Die Frage ist sehr unklar, was eine Regel und was ein Bonus ist. Ich habe OP vor einigen Stunden um Klarstellung gebeten. Wenn es keine Antwort gibt, stimme ich dafür, diese Frage als unklar zu schließen.
Optimierer

Entschuldigung, ich wurde irregeführt, da aktuelle Antworten in den Sprachen, die ich lesen kann, auch nicht unterstützen *.
Nutki

Wenn Sie sich auf meine Python-Antwort beziehen, haben Sie Recht. Ich habe die Frage falsch interpretiert.
Def

1

AWK 211 Bytes (mit den Boni)

{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}}}

Dies ist ein vollständiges Programm, das die Eingabe von stdin liest. Es wäre effizienter, die Tastatur nicht für jede Zeile neu zu teilen, aber das Skript würde länger.

Auch wenn die "0" -Taste etwas anderes als 0 wäre, wäre das Skript 4 Bytes kürzer, aber das ist Teil des Spiels: o)


1

C (245 Bytes)

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

Ausgabe

THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG!

Erläuterung

Die Byteanzahl enthält nicht die im ersten angegebene Eingabezeichenfolge #define.

Ich verwende ein zweidimensionales Array als Nachschlagetabelle für das zu druckende Zeichen. Das Programm liest durch Zeichen getrennte Zeichen ein '#'.

Für jede Gruppe bestimmt die Eingabenummer den Array-Index der ersten Dimension, und die Anzahl der Wiederholungen der Eingabenummer bestimmt den Array-Index der zweiten Dimension. Das '*'verschiebt den Index des Arrays für die Ausgabezeichenfolge zurück, um den vorherigen Buchstaben zu überschreiben.

Die Eingabezeichenfolge 44#(1 Wiederholung von '4') wird also in die Nachschlagetabelle übersetzt K[4][1], bei der es sich um das Zeichen handelt H.


Ungolfed Version

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

1

Ruby 254 , 248 , 229 Bytes

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*""}

Ungolfed:

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

Alle diese Spezifikationen sollten erfolgreich sein:

  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

Die 0 0Antwort sieht ein bisschen wie eine hackige Lösung aus. Werde mich darum kümmern, wenn ich Zeit habe.


0

PHP, 183-10 = 173 Bytes

Alle Versionen werden vom Befehlszeilenargument eingegeben. mit anrufen php -r '<code>' <string>.

Hinweis : Alle Versionen geben eine Warnung aus, wenn die Eingabe mit beginnt *.
Stellen Sie $o=[];den Code voran , um diesen Fehler zu beheben .

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);
  • benötigt keine Hash-Tags
  • schlägt fehl, wenn eine Taste zu oft gedrückt wird

210-10 - ?? = ??? Bytes

$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);
  • benötigt keine Hash-Tags
  • dreht sich, wenn eine Taste zu oft gedrückt wird

181 Bytes, kein 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);

Nervenzusammenbruch

Die "no hash tags" -Versionen teilen die Zeichenfolge in (Streifen gleicher Anzahl) und (Sternchen) und vergessen alles andere. Die No-Bonus-Version nimmt (Streifen von Zahlen gefolgt von #) und (Sternchen).

Durchlaufen Sie dann die Übereinstimmungen: Wenn ein '*' gefunden wird, entfernen Sie das letzte Element des Ergebnisarrays.

Der Unterschied zwischen den Versionen liegt im elseTeil:

  • Keine Bonusversion: Versetzen Sie die Zeichenfolge auf (Taste * 5), fügen Sie dann (Tastenanschläge = Wortlänge-1) -1 hinzu und fügen Sie das Zeichen von dieser Position zum Ergebnis hinzu.
  • einfache No-Tag-Version: fast gleich, aber: (Tastenanschläge = Wortlänge); fügte der Kartenzeichenfolge ein Zeichen hinzu, um das andere zu entfernen -1.
  • rotierende Version: Nehmen Sie das Element (den Schlüssel) aus dem Kartenarray und fügen Sie dem Ergebnis ein Zeichen (Tastenanschläge% Elementlänge-1) hinzu.

0

JavaScript, 147 Bytes

Conors Antwort wurde mit dem regulären Ausdruck meiner PHP-Antwort korrigiert und nach unten gespielt.

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

Nervenzusammenbruch

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

rotierende Version, 158 Bytes

hinzugefügt s=, um die Zeichenfolge %s.lengthzu speichern und zu drehen.

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,"")
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.