Utwórz klawiaturę T9

12

To pytanie wymaga funkcji dopasowania słownika T9, co jest bardzo interesującym problemem. Ale T9 ma inny sposób pisania, czyli pisanie znak po znaku. NIE potrzebujesz słownika do implementacji tej klawiatury.

Oto mapa klawiszy klawiatury T9, jeśli zapomniałeś:

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

Jak działa T9

Aby wpisać znak za pomocą T9, musisz nacisnąć klawisz numeryczny reprezentujący nczasy tego znaku . njest kolejnością tego znaku zapisanego na tym kluczu. Cyfry to ostatni znak, który możesz wpisać dla każdego klawisza. Na przykład, aby wpisać BI, naciśnij 2dwa razy lub, aby wpisać 5I, naciśnij 5cztery razy. Aby zakończyć wpisywanie tego znaku, naciskam #. *jest po prostu backspace. W naszej wersji klawiatury nie ma wielkich liter.

Przykłady danych wejściowych i wyjściowych:

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

Wyjaśnienie:

  • 8wybiera Ti #przechodzi do następnej postaci
  • 99999wybierz ostatni znak 9klucza, który jest 9i #przechodzi do następnego znaku
  • 0 wstawia spację
  • 33wybiera drugi znak 3klawisza, który jest, Ki #przechodzi do następnego znaku
  • I tak dalej...

Zasady

Twoja funkcja lub program powinien akceptować ciąg reprezentujący naciśnięcia klawiszy T9. Wynik jest tekstem wynikowym z tych naciśnięć klawiszy, jak opisano powyżej.

Jest to podstawowy kod golfowy, więc zwycięzca ma najkrótszą bajt i obowiązują standardowe zasady / luki.

Mohsen
źródło
Bonus nie ma żadnego wpływu na wynik? Dlaczego miałbym to zrobić?
Optymalizator
2
Ponadto twój przykład T9 KEYBOARDjest całkowicie błędny. Ten czytaT9 JEYBARD
Optimizer
1
@Mohsen zwykle bonusy w golfie kodu odejmują ustaloną kwotę od wyniku. musisz dowiedzieć się, ile jest rozsądne. za pierwszą premię prawdopodobnie nie więcej niż 10 lub 20 bajtów. drugi bonus, nawet nie rozumiem. jeśli podam sekwencję naciśnięć klawiszy jako ciąg do funkcji, to jaki byłby czas pomiędzy naciśnięciami klawiszy? Myślę, że bardziej rozsądnym bonusem byłoby zezwolenie na pominięcie, #jeśli kolejne przyciski i tak są różne. powiedziane: bez tej premii, co by się stało, gdyby #zostało pominięte?
Martin Ender,
1
Musisz dodać możliwą korzyść z liczby bajtów dla tych bonusów. Bonusy są opcjonalne, ale wydaje się, że pytasz każdą odpowiedź, aby wprowadzić bonusy tak, jakby były obowiązkowe. Wyczyść ton, jeśli są obowiązkowe, przenieś je do zasad, jeśli nie są, nie pytaj wszystkich odpowiedzi, aby wprowadzić bonusy. Poczekam kilka godzin na twoją odpowiedź, zanim zagłosuję za niejasnym.
Optymalizator
2
Brak odpowiedzi nawet po 18 godzinach. Głosowanie na zakończenie jest niejasne.
Optymalizator

Odpowiedzi:

5

CJam, 109 94 bajtów (2 nd premii)

Bardzo naiwne i długie rozwiązanie

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

Jest to pełny program, chociaż funkcja będzie miała tę samą długość.

Wejście przechodzi w STDIN

Przykład:

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

Wynik:

T9 BOARD

Wypróbuj online tutaj

Optymalizator
źródło
Czy potrafisz sprawić, że zadziała dla pierwszego bonusu?
Mohsen
3
@Mohsen Nie, dopóki nie pojawi się faktyczna korzyść z przejścia na bonus! Załóżmy, że 25% zmniejszenie długości kodu w wyniku końcowym.
Optymalizator
2

JavaScript ES6, 220-10 = 210 178 bajtów

W ramach CMC Helki wygrałem pierwsze wyzwanie.

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

Przykładowe wyniki:

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

Wyjaśnienie

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

Wprowadza to zastępowanie rekurencyjne, zastępując wszystkie znaki, po których następuje, *dopóki nie ma już żadnych znaków *.

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

To pasuje do wszystkich przebiegów kolejnych cyfr lub *s.

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

Spowoduje to utworzenie pożądanego słownika, uzyskanie zakodowanej części z dużego łańcucha, a następnie dołączenie do niej żądanej cyfry.

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

To dostaje postać, adługość modulo .

.join``

To przygotowuje ciąg do przetwarzania i usuwania *s.

Conor O'Brien
źródło
1
Czy potrafisz sprawić, że zadziała z pierwszą premią?
Mohsen
@Mohsen Tak, a to może faktycznie pomóc. Popracuję nad tym dzisiaj i jutro.
Conor O'Brien,
Przynajmniej nie reklamuj wyniku, który jest niepoprawny, ponieważ odpowiedź nie jest nawet zgodna ze specyfikacją.
Optymalizator
@Mohsen Działa teraz z pierwszym bonusem.
Conor O'Brien,
t("2#2");daje Bzamiast AA. Spróbuj dopasować dowolne #zamiast je usuwać.
Tytus
1

Python, 167 157 151 bajtów

(nie obsługuje „*”)

Nic specjalnego. Używam wyrażenia regularnego, aby przekonwertować dane wejściowe na listę, a następnie zapętlić wpisy. Używam pierwszego znaku i długości każdego wpisu, aby wyszukać go na liście odnośników:

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)

Po golfie wygląda to tak:

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

Brak bonusów (jeszcze). Nie wiem, jak zaimplementowałbym pierwszy bonus w regexie. Drugi bonus dodałby dużo bajtów, ponieważ elementy wyszukiwania nie są tego samego rozmiaru. Naprawdę nie rozumiem trzeciej premii.

Def
źródło
1

Perl 5: 106 (kod 104 + 2 flagi)

Zmodyfikowany do obsługi usuwania.

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

Stosowanie:

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

Perl 5: 88 (kod 86 + 2 flagi)

Stara wersja bez gwiazdki-delete.

#!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
źródło
@Optimizer wypróbował to i rzeczywiście nie działa z *. Czy to jest jednak wymagane? Mówi: „Pamiętaj, że może zawierać * backspace ...”
Def
Ponieważ nie jest częścią premii. Jest to obowiązkowa zasada.
Optymalizator
To powiedziawszy. pytanie jest bardzo niejasne, jaka jest reguła i co jest premią. Poprosiłem OP o wyjaśnienia kilka godzin temu. Jeśli nie ma odpowiedzi, głosuję za zamknięciem tego pytania jako niejasne.
Optymalizator
Przepraszam, że wprowadzono mnie w błąd, ponieważ bieżące odpowiedzi w językach, które czytam, również nie obsługują *.
nutki
Jeśli masz na myśli moją odpowiedź w python, masz rację. Źle zinterpretowałem pytanie.
Def
1

AWK 211 bajtów (z bonusami)

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

Jest to pełny program, który odczytuje dane wejściowe ze standardowego wejścia. Bardziej efektywne byłoby nierelitowanie klawiatury dla każdej linii, ale wydłużyłoby skrypt.

Również jeśli klucz „0” byłby inny niż 0, skrypt byłby o 4 bajty krótszy, ale to część gry: o)

LeFauve
źródło
1

C (245 bajtów)

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

Wynik

THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG!

Wyjaśnienie

Liczba bajtów nie obejmuje ciągu wejściowego podanego w pierwszym #define.

Używam dwuwymiarowej tablicy jako tabeli odnośników do wydrukowania znaku. Program wczytuje znaki rozdzielane przez '#'.

Dla każdej grupy numer wejściowy określa indeks tablicy pierwszego wymiaru, a liczba powtórzeń numeru wejściowego określa indeks tablicy drugiego wymiaru. W '*'cofa indeks tablicy do łańcucha wyjściowego tak, aby zastąpić poprzedni list.

Tak więc łańcuch wejściowy 44#(1 powtórzenie '4') jest tłumaczony na tablicę odnośników K[4][1], która jest znakiem H.


Wersja bez golfa

#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);
}
musarithmia
źródło
1

Ruby 254 , 248 , 229 bajtów

Gra w golfa:

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

Nie golfowany:

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

Wszystkie te specyfikacje powinny się powieść:

  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

0 0Odpowiedź wygląda trochę jak hacky rozwiązania. Zajmę się tym, kiedy będę miał czas.

Biketire
źródło
0

PHP, 183-10 = 173 bajtów

Wszystkie wersje pobierają dane wejściowe z argumentu wiersza poleceń; zadzwoń z php -r '<code>' <string>.

Uwaga : Wszystkie wersje generują ostrzeżenie, jeśli dane wejściowe zaczynają się od *.
Przygotuj $o=[];się do kodu, aby usunąć tę wadę.

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);
  • nie potrzebuje znaczników skrótu
  • kończy się niepowodzeniem, jeśli klawisz jest naciskany zbyt często

210-10 - ?? = ??? bajty

$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);
  • nie potrzebuje znaczników skrótu
  • obraca się, jeśli klawisz jest naciskany zbyt często

181 bajtów, bez premii

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

awaria

Wersje „no hash tags” dzielą ciąg na (ciąg równych liczb) i (gwiazdka) i zapominają o wszystkim innym. Wersja bez bonusu ma (pasmo liczb, po których następuje #) i (gwiazdka).

Następnie przejdź przez dopasowania: Jeśli zostanie znalezione „*”, usuń ostatni element tablicy wyników.

Różnica między wersjami polega na elseczęści:

  • brak wersji premiowej: przesunąć ciąg mapy do (klawisz * 5), a następnie dodać (naciśnięcia klawiszy = długość słowa-1) -1, dodać znak z tej pozycji, aby uzyskać wynik.
  • prosta wersja bez tagu: prawie taka sama, ale: (naciśnięcia klawiszy = długość słowa); dodał znak do ciągu mapy, aby się go pozbyć -1.
  • wersja rotacyjna: weź element (klucz) z tablicy mapy, dodaj znak (naciśnięcia klawiszy% element długość-1) z tego elementu, aby uzyskać wynik.
Tytus
źródło
0

JavaScript, 147 bajtów

Odpowiedź Conora naprawiona przez regex z mojej odpowiedzi PHP i grała w golfa.

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

awaria

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

wersja obrotowa, 158 bajtów

dodano, s=aby zapamiętać ciąg i %s.lengthobrócić.

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,"")
Tytus
źródło