Buat keyboard T9

12

Pertanyaan ini menanyakan fungsionalitas pencocokan kamus T9 yang merupakan masalah yang sangat menarik. Tetapi T9 memiliki cara lain untuk mengetik dan itu adalah mengetik karakter demi karakter. Anda TIDAK perlu kamus untuk mengimplementasikan keyboard ini.

Berikut adalah peta-kunci keyboard T9 jika Anda lupa:

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

Cara kerja T9

Untuk mengetikkan karakter dengan T9, Anda perlu menekan tombol angka yang mewakili nwaktu karakter itu .nadalah urutan karakter yang tertulis pada kunci itu. Angka adalah karakter terakhir yang bisa Anda ketik untuk setiap tombol. Misalnya, untuk mengetik BI tekan 2dua kali, atau untuk mengetik 5I tekan 5empat kali. Untuk menyelesaikan mengetik karakter ini saya tekan #. *hanyalah backspace. Di versi keyboard kami tidak ada huruf besar.

Contoh input dan output:

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

Penjelasan:

  • 8 memilih T dan #pindah ke karakter berikutnya
  • 99999 pilih karakter terakhir 9 key yang ada 9dan #pindah ke charachter berikutnya
  • 0 menyisipkan spasi
  • 33 memilih karakter kedua dari 3 kunci yaitu Kdan #pindah ke karakter berikutnya
  • Dan seterusnya...

Aturan

Fungsi atau program Anda harus menerima string yang mewakili penekanan tombol T9. Output adalah teks yang dihasilkan dari penekanan tombol tersebut, seperti diuraikan di atas.

Ini adalah kode dasar golf, jadi pemenangnya adalah yang terpendek dalam byte, dan aturan standar / celah berlaku.

Mohsen
sumber
Bonus tidak berpengaruh pada skor? Kenapa aku harus melakukannya?
Pengoptimal
2
Juga, contoh Anda T9 KEYBOARDbenar-benar salah. Yang bertuliskanT9 JEYBARD
Pengoptimal
1
@Mohsen biasanya, bonus dalam kode golf akan mengurangi jumlah tetap dari skor. Anda harus mencari tahu seberapa masuk akal. untuk bonus pertama mungkin tidak lebih dari 10 atau 20 byte. bonus kedua, saya bahkan tidak mengerti. jika saya memberikan urutan penekanan tombol sebagai string ke fungsi, bagaimana akan ada semacam waktu antara penekanan tombol? Saya pikir bonus yang lebih masuk akal adalah untuk memungkinkan menghilangkan #jika tombol berturut-turut berbeda pula. yang dikatakan: tanpa bonus apa yang harus terjadi jika #dihilangkan?
Martin Ender
1
Anda perlu menambahkan kemungkinan manfaat jumlah byte untuk bonus ini. Bonus bersifat opsional tetapi Anda tampaknya meminta setiap jawaban untuk menerapkan bonus seolah-olah itu wajib. Harap hapus nada, jika wajib, pindahkan ke aturan, jika tidak, jangan minta setiap jawaban untuk menerapkan bonus. Saya akan menunggu beberapa jam untuk balasan Anda sebelum pemungutan suara untuk ditutup sebagai tidak jelas.
Pengoptimal
2
Tidak ada balasan bahkan setelah 18 jam. Voting untuk ditutup tidak jelas.
Pengoptimal

Jawaban:

5

CJam, 109 94 byte (2 nd bonus)

Solusi yang sangat naif dan panjang

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

Ini adalah program lengkap, meskipun suatu fungsi akan memiliki panjang yang sama.

Input masuk ke STDIN

Contoh:

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

Keluaran:

T9 BOARD

Cobalah online di sini

Pengoptimal
sumber
Bisakah Anda membuatnya bekerja untuk bonus pertama?
Mohsen
3
@Mohsen Tidak sampai ada manfaat sebenarnya dari mendapatkan bonus! Katakanlah, pengurangan panjang kode 25% dalam skor akhir.
Pengoptimal
2

JavaScript ES6, 220-10 = 210 178 byte

Sebagai bagian dari CMC Helka , saya mengalahkan tantangan pertama saya.

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

Output sampel:

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

Penjelasan

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

Ini mengimplementasikan penggantian rekursif, mengganti semua karakter diikuti oleh *sampai tidak ada *yang tersisa.

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

Ini cocok dengan semua digit beruntun, atau *s.

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

Ini menciptakan kamus yang diinginkan, mendapatkan bagian yang disandikan dari string besar, kemudian menambahkan digit yang diinginkan ke dalamnya.

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

Ini mendapatkan karakter, apanjang modulo .

.join``

Ini mempersiapkan string untuk pemrosesan dan penghapusan *s.

Conor O'Brien
sumber
1
Bisakah Anda membuatnya bekerja dengan bonus pertama?
Mohsen
@Mohsen Ya, dan itu mungkin bisa membantu. Saya akan mengerjakannya sampai hari ini dan besok.
Conor O'Brien
Harap setidaknya jangan mengiklankan skor yang salah karena jawabannya tidak sesuai spesifikasi.
Pengoptimal
@Mohsen Sekarang bekerja dengan bonus pertama.
Conor O'Brien
t("2#2");memberi Bbukannya AA. Cobalah untuk mencocokkan apa saja #daripada menghapusnya.
Titus
1

Python, 167 157 151 byte

(tidak mendukung '*')

Tidak ada yang spesial. Saya menggunakan regex untuk mengonversi input ke daftar, lalu saya memutarkan entri. Saya menggunakan karakter pertama dan panjang setiap entri untuk mencarinya di daftar pencarian:

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)

Setelah bermain golf, tampilannya seperti ini:

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

Tidak ada bonus (belum). Saya tidak tahu bagaimana saya akan menerapkan bonus pertama di regex. Bonus kedua akan menambahkan banyak byte karena elemen pencarian tidak berukuran sama. Tidak terlalu mengerti bonus ketiga.

Def
sumber
1

Perl 5: 106 (104 kode + 2 bendera)

Dimodifikasi untuk menangani penghapusan.

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

Pemakaian:

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

Perl 5: 88 (86 kode + 2 bendera)

Versi lama tanpa penghapusan bintang.

#!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
sumber
@Optimizer mencobanya, dan memang tidak bekerja dengan *. Apakah ini benar-benar diperlukan? Dikatakan: "Perhatikan bahwa ia dapat menyertakan * untuk backspace ..."
Def
Karena ini bukan bagian dari bonus. Ini aturan wajib.
Pengoptimal
Yang telah dibilang. pertanyaannya sangat tidak jelas tentang apa aturannya dan apa bonusnya. Saya meminta OP untuk klarifikasi beberapa jam yang lalu. Jika tidak ada tanggapan, saya memberikan suara untuk menutup pertanyaan ini sebagai tidak jelas.
Pengoptimal
Maaf, saya disesatkan karena jawaban saat ini dalam bahasa yang dapat saya baca juga tidak mendukung *.
nutki
Jika Anda merujuk ke jawaban python saya, Anda benar. Saya salah menafsirkan pertanyaan itu.
Def
1

AWK 211 byte (dengan 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}}}

Ini adalah program lengkap yang membaca input dari stdin. Akan lebih efisien untuk tidak memasang kembali keyboard untuk setiap baris, tetapi akan membuat skrip lebih panjang.

Juga jika kunci "0" lebih dari 0, skrip akan menjadi 4 byte lebih pendek, tapi itu bagian dari permainan: o)

LeFauve
sumber
1

C (245 byte)

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

Keluaran

THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG!

Penjelasan

Hitungan byte tidak termasuk string input yang diberikan pada yang pertama #define.

Saya menggunakan array dua dimensi sebagai tabel pencarian untuk karakter apa yang akan dicetak. Program membaca dalam karakter yang dibatasi oleh'#' .

Untuk setiap grup, nomor input menentukan indeks array dimensi pertama, dan jumlah pengulangan nomor input menentukan indeks array dimensi kedua. The '*'bergerak kembali indeks array untuk string output sehingga dapat menimpa surat sebelumnya.

Jadi string input 44#(1 pengulangan '4') diterjemahkan ke tabel pencarian K[4][1], yang merupakan karakter H.


Versi Tidak Serigala

#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
sumber
1

Ruby 254 , 248 , 229 byte

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

Tidak Disatukan:

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

Semua spesifikasi ini harus berhasil:

  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

The 0 0Jawabannya terlihat sedikit seperti solusi Hacky. Akan melihatnya ketika aku punya waktu.

Biketire
sumber
0

PHP, 183-10 = 173 byte

Semua versi mengambil input dari argumen baris perintah; panggilan dengan php -r '<code>' <string>.

Catatan : Semua versi memberikan peringatan jika input dimulai *.
Tambahkan $o=[];kode untuk menghapus cacat itu.

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);
  • tidak perlu tag hash
  • gagal jika tombol terlalu sering ditekan

210-10 - ?? = ??? byte

$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);
  • tidak perlu tag hash
  • berputar jika tombol terlalu sering ditekan

181 byte, tidak ada 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);

kerusakan

Versi "tanpa tag hash" membagi string menjadi (coretan angka yang sama) dan (tanda bintang) dan melupakan yang lainnya. Versi no-bonus mengambil (nomor beruntun diikuti oleh# ) dan (tanda bintang).

Kemudian lewati pencocokan: Jika '*' ditemukan, hapus elemen terakhir dari array hasil.

Perbedaan antara versi ada di elsebagian:

  • tidak ada versi bonus: offset string peta ke (kunci * 5), lalu tambahkan (penekanan tombol = panjang kata-1) -1, tambahkan karakter dari posisi itu ke hasil.
  • versi tanpa tag sederhana: hampir sama, tetapi: (penekanan tombol = panjang kata); menambahkan karakter ke string peta untuk menghilangkan yang lain -1.
  • rotating version: ambil item (key) dari array peta, tambahkan karakter (penekanan tombol% ​​item length-1) dari item itu ke hasil.
Titus
sumber
0

JavaScript, 147 byte

Jawaban Conor diperbaiki dengan regex dari jawaban PHP saya dan diturunkan.

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

kerusakan

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

versi rotasi, 158 byte

ditambahkan s=untuk mengingat string dan %s.lengthmemutar.

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
sumber