Tạo bàn phím T9


12

Câu hỏi này yêu cầu chức năng khớp từ điển T9, đây là một vấn đề rất thú vị. Nhưng T9 có một cách gõ khác và đó là gõ từng ký tự. Bạn sẽ KHÔNG cần một từ điển để thực hiện bàn phím này.

Đây là sơ đồ phím của bàn phím T9 nếu bạn quên:

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

Cách hoạt động của T9

Để nhập một ký tự bằng T9, bạn cần nhấn phím số đại diện cho số nlần ký tự đó . nlà thứ tự của ký tự đó được viết trên khóa đó. Số là ký tự cuối cùng bạn có thể nhập cho mỗi phím. Ví dụ, để gõ Btôi nhấn 2hai lần hoặc để gõ 5tôi nhấn 5bốn lần. Để hoàn thành việc gõ ký tự này, tôi nhấn #. *chỉ đơn giản là backspace. Trong phiên bản bàn phím của chúng tôi không có viết hoa.

Ví dụ đầu vào và đầu ra:

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

Giải trình:

  • 8chọn T#di chuyển đến nhân vật tiếp theo
  • 99999chọn ký tự cuối cùng của 9khóa đó 9#di chuyển đến trình duyệt tiếp theo
  • 0 chèn một khoảng trắng
  • 33chọn ký tự thứ hai của 3khóa đó K#di chuyển đến ký tự tiếp theo
  • Và như thế...

Quy tắc

Chức năng hoặc chương trình của bạn sẽ chấp nhận một chuỗi đại diện cho các phím T9. Đầu ra là văn bản kết quả từ các phím nhấn đó, như đã nêu ở trên.

Đây là mã golf cơ bản, vì vậy người chiến thắng là ngắn nhất theo byte và áp dụng quy tắc / sơ hở tiêu chuẩn.


Tiền thưởng không có ảnh hưởng gì đến điểm số? Tại sao tôi đi cho nó?
Tối ưu hóa

2
Ngoài ra, ví dụ của bạn T9 KEYBOARDlà hoàn toàn sai. Người ta đọcT9 JEYBARD
Trình tối ưu hóa

1
@Mohsen thông thường, tiền thưởng trong mã golf sẽ trừ đi một số tiền cố định từ điểm số. bạn sẽ phải tìm ra bao nhiêu là hợp lý. đối với phần thưởng đầu tiên có thể không quá 10 hoặc 20 byte. Phần thưởng thứ hai, tôi thậm chí không hiểu. Nếu tôi đưa ra chuỗi các lần nhấn phím như một chuỗi cho hàm, làm thế nào có bất kỳ loại thời gian nào giữa các lần nhấn phím? Tôi nghĩ rằng một phần thưởng hợp lý hơn sẽ là cho phép bỏ qua #nếu các nút liên tiếp khác nhau. Điều đó đang được nói: không có phần thưởng đó thì chuyện gì sẽ xảy ra nếu #bị bỏ qua?
Martin Ender

1
Bạn cần thêm một lợi ích đếm byte có thể cho các phần thưởng này. Tiền thưởng là tùy chọn nhưng bạn dường như hỏi mọi câu trả lời để thực hiện phần thưởng như thể chúng là bắt buộc. Vui lòng xóa âm báo, nếu chúng là bắt buộc, hãy chuyển chúng theo quy tắc, nếu không, đừng hỏi mọi câu trả lời để thực hiện phần thưởng. Tôi sẽ đợi một vài giờ để trả lời của bạn trước khi bỏ phiếu đóng cửa không rõ ràng.
Tối ưu hóa

2
Không trả lời ngay cả sau 18 giờ. Bỏ phiếu để đóng như không rõ ràng.
Tối ưu hóa

Câu trả lời:


5

CJam, 109 94 byte ( tiền thưởng thứ 2 )

Một giải pháp rất ngây thơ và dài

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

Đây là một chương trình đầy đủ, mặc dù một chức năng sẽ có cùng độ dài.

Đầu vào đi vào STDIN

Thí dụ:

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

Đầu ra:

T9 BOARD

Dùng thử trực tuyến tại đây


Bạn có thể làm cho nó hoạt động cho phần thưởng đầu tiên?
Mohsen

3
@Mohsen Không phải đến khi có một lợi ích thực sự của việc đi thưởng! Hãy nói rằng, giảm 25% chiều dài mã trong điểm số cuối cùng.
Tối ưu hóa

2

JavaScript ES6, 220-10 = 210 178 byte

Là một phần của CMC của Helka , tôi đã vượt qua thử thách đầu tiên của mình.

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

Đầu ra mẫu:

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

Giải trình

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

Điều này thực hiện thay thế đệ quy, thay thế tất cả các ký tự theo sau *cho đến khi không còn *s.

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

Điều này phù hợp với tất cả các chữ số liên tiếp, hoặc *s.

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

Điều này tạo ra từ điển mong muốn, có được phần được mã hóa từ chuỗi lớn, sau đó nối thêm chữ số mong muốn vào nó.

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

Cái này có được ký tự, ađộ dài của modulo .

.join``

Điều này chuẩn bị chuỗi để xử lý và loại bỏ *s.


1
Bạn có thể làm cho nó hoạt động với tiền thưởng đầu tiên?
Mohsen

@Mohsen Có, và điều đó thực sự có thể giúp nó. Tôi sẽ làm việc với nó cho đến hôm nay và ngày mai.
Conor O'Brien

Vui lòng ít nhất không quảng cáo một số điểm không chính xác vì câu trả lời thậm chí không đúng với thông số kỹ thuật.
Trình tối ưu hóa

@Mohsen Bây giờ nó đang hoạt động với phần thưởng đầu tiên.
Conor O'Brien

t("2#2");cho Bthay vì AA. Cố gắng phù hợp với bất kỳ #thay vì loại bỏ chúng.
Tít

1

Python, 167 157 151 byte

(không hỗ trợ '*')

Không có gì đặc biệt. Tôi sử dụng regex để chuyển đổi đầu vào thành một danh sách, sau đó tôi lặp các mục. Tôi sử dụng ký tự đầu tiên và độ dài của mỗi mục để tìm kiếm nó trong danh sách tra cứu:

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)

Sau khi chơi golf, nó trông như thế này:

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

Không có tiền thưởng (chưa). Tôi không biết làm thế nào tôi sẽ thực hiện phần thưởng đầu tiên trong regex. Phần thưởng thứ hai sẽ thêm rất nhiều byte vì các phần tử tra cứu không cùng kích thước. Đừng thực sự hiểu phần thưởng thứ ba.


1

Perl 5: 106 (104 mã + 2 cờ)

Sửa đổi để xử lý xóa.

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

Sử dụng:

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

Perl 5: 88 (mã 86 + 2 cờ)

Phiên bản cũ không có sao xóa.

#!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 đã thử nó, và nó thực sự không hoạt động với *. Có thực sự cần thiết mặc dù? Nó nói: "Lưu ý rằng nó có thể bao gồm * cho backspace ..."
Def

Vì nó không phải là một phần của tiền thưởng. Đó là một quy tắc bắt buộc.
Tối ưu hóa

Điều đó đang được nói. câu hỏi rất không rõ ràng về quy tắc và phần thưởng là gì. Tôi đã yêu cầu OP làm rõ vài giờ trước. Nếu không có phản hồi, tôi sẽ bỏ phiếu để đóng câu hỏi này là không rõ ràng.
Tối ưu hóa

Xin lỗi, tôi đã nhầm lẫn là câu trả lời hiện tại trong các ngôn ngữ mà tôi có thể đọc cũng không hỗ trợ *.
nutki

Nếu bạn đang đề cập đến câu trả lời trăn của tôi, bạn đã đúng. Tôi giải thích sai câu hỏi.
Def

1

AWK 211 byte (có tiền thưởng)

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

Đây là một chương trình đầy đủ đọc đầu vào từ stdin. Sẽ hiệu quả hơn nếu không đặt lại bàn phím cho mỗi dòng, nhưng nó sẽ làm cho tập lệnh dài hơn.

Ngoài ra, nếu phím "0" là bất cứ thứ gì khác 0, tập lệnh sẽ ngắn hơn 4 byte, nhưng đó là một phần của trò chơi: o)


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

Đầu ra

THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG!

Giải trình

Số lượng byte không bao gồm chuỗi đầu vào được đưa ra trong lần đầu tiên #define.

Tôi sử dụng một mảng hai chiều làm bảng tra cứu cho nhân vật nào sẽ in. Chương trình đọc trong các ký tự được phân định bởi '#'.

Đối với mỗi nhóm, số đầu vào xác định chỉ số mảng thứ nhất và số lần lặp lại của số đầu vào xác định chỉ số mảng thứ hai. Việc '*'di chuyển trở lại chỉ mục của mảng cho chuỗi đầu ra để ghi đè lên chữ cái trước đó.

Vì vậy, chuỗi đầu vào 44#(1 lần lặp lại '4') được dịch sang bảng tra cứu K[4][1], đó là ký tự H.


Phiên bản Ungolfed

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

Chơi gôn

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

Ung dung:

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

Tất cả các thông số kỹ thuật nên thành công:

  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

Câu 0 0trả lời trông hơi giống một giải pháp hacky. Sẽ xem xét nó khi tôi có thời gian.


0

PHP, 183-10 = 173 byte

Tất cả các phiên bản lấy đầu vào từ đối số dòng lệnh; gọi với php -r '<code>' <string>.

Lưu ý : Tất cả các phiên bản đưa ra cảnh báo nếu đầu vào bắt đầu bằng *.
Chuẩn $o=[];bị mã để loại bỏ lỗ hổng đó.

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);
  • không cần thẻ băm
  • thất bại nếu nhấn phím quá thường xuyên

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);
  • không cần thẻ băm
  • xoay nếu một phím được nhấn quá thường xuyên

181 byte, không có tiền thưởng

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

phá vỡ

Các phiên bản "không có thẻ băm" chia chuỗi thành (chuỗi các số bằng nhau) và (dấu hoa thị) và quên mọi thứ khác. Phiên bản không có phần thưởng mất (chuỗi số theo sau #) và (dấu hoa thị).

Sau đó lặp qua các kết quả khớp: Nếu tìm thấy '*', hãy xóa phần tử cuối cùng của mảng kết quả.

Sự khác biệt giữa các phiên bản nằm ở elsephần:

  • không có phiên bản thưởng: chuỗi bản đồ bù vào (khóa * 5), sau đó thêm (keystrokes = word length-1) -1, thêm ký tự từ vị trí đó vào kết quả.
  • phiên bản không có thẻ đơn giản: gần giống nhau, nhưng: (keystrokes = word length); đã thêm một ký tự vào chuỗi bản đồ để loại bỏ ký tự kia -1.
  • phiên bản xoay vòng: lấy mục (khóa) từ mảng bản đồ, thêm ký tự (tổ hợp phím% mục chiều dài-1) từ mục đó để kết quả.

0

JavaScript, 147 byte

Conor hès trả lời cố định với regex từ câu trả lời PHP của tôi và đánh gôn xuống.

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

phá vỡ

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

phiên bản xoay, 158 byte

thêm vào s=để nhớ chuỗi và %s.lengthđể xoay.

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,"")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.