创建一个T9键盘


12

这个问题要求T9词典匹配功能,这是一个非常有趣的问题。但是T9还有另一种打字方式,那就是逐个字符地打字。您不需要字典即可实现此键盘。

如果您忘记了,这是T9键盘的按键图:

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

T9的运作方式

要使用T9键入字符,您需要按代表该字符n时间的数字键。n是那个字符写在那个键上的顺序。数字是您可以为每个键键入的最后一个字符。例如,要键入BI按2两次,或要键入5I按5四次。要完成此字符的输入,请按#*只是退格键。在我们的键盘版本中,没有大写字母。

输入和输出示例:

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

说明:

  • 8选择T#移至下一个字符
  • 99999选择9键的最后一个字符,9#移动到下一个字符
  • 0 插入一个空格
  • 33选择3键的第二个字符, K然后#移至下一个字符
  • 等等...

规则

您的函数或程序应接受表示T9按键的字符串。如上所述,输出是这些按键的结果文本。

这是基本代码高尔夫,因此获胜者的字节数最少,并且适用标准规则/漏洞。


奖金对分数没有影响吗?我为什么要去呢?
Optimizer

2
另外,您的示例T9 KEYBOARD完全错误。一个读T9 JEYBARD
优化

1
@Mohsen通常,代码高尔夫中的奖金将从分数中减去固定的金额。您必须找出多少是合理的。第一奖金可能不超过10或20个字节。第二个奖金,我什至不明白。如果我将按键的序列作为字符串提供给函数,那么按键之间会有怎样的时间?我认为更合理的奖励是#如果连续按钮仍然不同,则可以省略。话虽这么说:如果没有那笔红利,如果#省略了该怎么办?
马丁·恩德2014年

1
您需要为这些奖金添加可能的字节数好处。奖金是可选的,但您似乎要求每一个答案来实施奖金,就好像它们是强制性的一样。请清除语气,如果是强制性的,请将其移至规则,如果不是强制性的,请不要回答所有答案以实施奖金。投票结果不清楚之前,我将等待几个小时才能收到您的答复。
Optimizer

2
18小时后也没有回复。投票结束不清楚。
Optimizer

Answers:


5

CJam,109 94字节(第二奖金)

一个非常幼稚的长期解决方案

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

这是一个完整的程序,尽管一个函数的长度相同。

输入进入STDIN

例:

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

输出:

T9 BOARD

在这里在线尝试


您能使它获得第一笔奖金吗?
Mohsen 2014年

3
@Mohsen直到获得奖金的实际好处之前,不行!可以说,最终得分减少了25%的代码长度。
Optimizer

2

JavaScript ES6,220-10 = 210178字节

作为Helka CMC的一部分,我超越了我的第一个挑战。

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

样本输出:

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

说明

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

这实现了递归替换,替换所有字符,然后替换所有字符,*直到没有*s 为止。

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

这与所有连续的连续数字*s 匹配。

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

这将创建所需的字典,从大字符串中获取编码部分,然后将所需的数字附加到该字典中。

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

这将得到字符,取模a的长度。

.join``

这将准备用于处理和删除*s 的字符串。


1
您能否使它获得第一笔奖金?
Mohsen

@Mohsen是的,这可能会有所帮助。我将在今天和明天继续努力。
科纳·奥布莱恩2014年

请至少不要公布不正确的分数,因为答案甚至不符合规范。
Optimizer

@Mohsen现在正在使用第一笔奖金。
科纳·奥布莱恩

t("2#2");给出B而不是AA。尝试匹配任何内容#而不是删除它们。
泰特斯(Titus)

1

Python,第167个 157 151字节

(不支持“ *”)

没什么特别的。我使用正则表达式将输入转换为列表,然后循环输入。我使用每个条目的第一个字符和长度在查找列表中进行搜索:

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)

打完高尔夫球后,它看起来像这样:

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

没有奖金(尚未)。我不知道我将如何在正则表达式中实现第一笔奖金。第二个好处是会增加很多字节,因为查找元素的大小不相同。不太了解第三项奖金。


1

Perl 5:106(104码+ 2个标志)

修改以处理删除。

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

用法:

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

Perl 5:88(86码+ 2个标志)

没有星号删除的旧版本。

#!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尝试过,它确实不适用于*。确实需要吗?它说:“请注意,它可以包含*用于退格...”
Def 2014年

由于它不是奖金的一部分。它是强制性规则。
Optimizer

话虽如此。关于什么是规则和什么是奖金这个问题还不清楚。我几个小时前要求OP进行澄清。如果没有回应,我将投票结束这个问题,因为尚不清楚。
Optimizer

抱歉,我被误以为我可以阅读的语言的当前答案也不支持*。
nutki 2014年

如果您指的是我的python答案,那是对的。我误解了这个问题。
Def 2014年

1

AWK 211字节(含奖金)

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

这是一个完整的程序,可从stdin读取输入。不为每行重新分割键盘会更有效,但是会使脚本更长。

另外,如果“ 0”键不是0,脚本将短4个字节,但这就是游戏的一部分:o)


1

C(245字节)

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

输出量

THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG!

说明

字节数不包括first中给定的输入字符串#define

我使用二维数组作为要打印什么字符的查找表。程序读取以分隔的字符'#'

对于每个组,输入数字确定第一维数组索引,输入数字的重复次数确定第二维数组索引。该'*'向后移动所述阵列的索引输出的字符串,以便覆盖以前的信。

因此,输入字符串44#(重复1个'4')被转换为查找表K[4][1],即字符H


非高尔夫版本

#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

红宝石254248,229个字节

打高尔夫球:

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

取消高尔夫:

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

所有这些规格都应该成功:

  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 0答案看起来有点像一个哈克的解决方案。有空的时候会调查一下。


0

PHP,183-10 = 173字节

所有版本均从命令行参数获取输入。致电php -r '<code>' <string>

注意:如果输入以开头,则所有版本都会发出警告*
附加$o=[];代码以消除该缺陷。

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);
  • 不需要哈希标签
  • 如果过于频繁地按下某个键,则失败

210-10-?? = ??? 个字节

$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);
  • 不需要哈希标签
  • 如果过于频繁地按下一个键则旋转

181字节,无奖金

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

分解

“无哈希标签”版本将字符串拆分为(等号的条纹)和(星号),而忽略了其他所有内容。无奖金版本采用(数字连字符#)和(星号)。

然后循环进行匹配:如果找到'*',则删除结果数组的最后一个元素。

版本之间的差异在于else

  • 没有奖励版本:将映射字符串偏移到(key * 5),然后添加(keystrokes = word length-1)-1,从该位置添加字符以得到结果。
  • 简单的无标签版本:几乎相同,但是:(击键=字长);在地图字符串中添加了一个字符以摆脱其他字符-1
  • 旋转版本:从地图数组中获取项(键),然后从该项中添加字符(击键%项长度为1)以得到结果。

0

JavaScript,147个字节

Conor的答案已使用我的PHP答案中的正则表达式进行了修正,然后打了下来。

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

分解

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

旋转版本,158字节

添加s=以记住字符串并%s.length旋转。

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,"")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.