电话多次点击拼写


21

受到Google代码挑战赛的启发:

拉丁字母包含26个字符,电话机的键盘上只有10位数字。我们希望使用一系列按键来指示您想要的字符,从而更轻松地向您的朋友写消息。字母映射到数字,如下所示。例如,要插入字符B,程序将按22。为了从同一键顺序插入两个字符,用户必须暂停,然后再按一次键。应该打印空格字符“”以指示暂停。例如,2 2表示AA,而22表示B。

每个消息将仅包含小写字母az和空格字符''。按下零会发出一个空格。

在此处输入图片说明

您的挑战是编写最小的函数,该函数接受输入字符串,并返回将输入生成为字符串或将其输出到stdout所需的按键序列。最小字节数的函数获胜。

输入/输出示例

phone("hi")
44 444
phone("hello world")
4433555 555666096667775553

其他说明

  • 暂停必须只在必要时添加的,必须是一个空格“”。
  • 每个消息将仅包含小写字母 az和空格字符''。打印0以表示空格。
  • 没有外部库。
  • 仅输入字符串可以传递给您的函数。
  • 为了使其他语言更具竞争力,主函数声明不计算在内,也不会导入其他标准库。#includes,imports和usings不计算在内。其他一切都做。这确实包括#define和辅助功能。如果您感到困惑,请参阅此问题中的规则2
  • 多个空格可以表示为,00或者0 0因为您实际上不必在空格之间暂停


我们可以假设输入是小写/大写吗?
Phil H

@PhilH“ 小写字母 az和空格字符''”
Danny

您是否认为方括号{}是功能签名的一部分?例如,如果我的代码是function f(){alert('hi');},我应该计算alert('hi');或的字符{alert('hi');}吗?
ProgramFOX

2
据我记得的t9工作方式不同:您必须单击每个键一次才能听到一个单词。
2014年

Answers:


8

红宝石, 129 122 115 111 108 107 105

做完高尔夫球...

糟糕,完全忘记删除不必要的空格-已修复...

感谢Peter Taylor节省了2个字符。

在线版

def t9(t)
(t.tr(" ",?`).bytes.map{|c|"09998887777666555444333222"[96-c..-1][/(.)\1*/]}*' ').gsub /(\d) (?!\1)/,'\1'
end

说明:

用序号96将空格转换为char

(t.tr(" ",?`).bytes

字符首先映射到一系列数字:-a到2-b到22-d到3222-h到444333222

一个正则表达式然后匹配第一组相等的数字

map{|c|"09998887777666555444333222"[96-c..-1][/(.)\1*/]}

数组已加入

*' ')

出现“数字空间different_digit”的所有空格均被删除

gsub /(\d) (?!\1)/,'\1'

1
看起来不能100%正确地工作。我看到6666连续6次不需要按6次。
Danny

应该修正,谢谢;)
David Herrmann

1
什么是点\2在这最后的正则表达式?第二组肯定是零宽度的断言吗?
彼得·泰勒

你是绝对正确的!
David Herrmann 2014年

6

REBEL - 154 110 103

;0 2abc3def4ghi5jkl6mno7pqrs8tuv9wxyz/^;/$<;/([^\d-])(?=\D.*(\d)(\w)*\1)/$2$3-/(\d)-+\1/$1 $1/-//;/$>$`

此“函数”接受来自stdin的输入,并将结果发送到stdout。

测试运行(因此您不必安装解释器):

hi
44 444

hello world
4433555 555666096667775553

yes
999337777

kthxbai
558449922 2444

我永远无法加载您的链接!:(
luser droog 2014年

4

的JavaScript(124)

在Firefox中运行。

t9=s=>s.replace(/./g,c=>'099998887777666555444333222'.slice(36-parseInt(c,36)).match(/(.)\1*/)[0]+' ').replace(/(.) (?!\1)/g,'$1')

4

GolfScript,46个字符

{).," adgjmptw"&.,.1>*`@@)\;-*}/]{.2$^!" "*\}*

像往常一样,从stdin读取输入,打印到stdout。请参阅在线演示(带有固定输入)。

请注意,此代码依赖于对输入规范的非常严格的解释(仅小写字母和空格):尤其是输入中的任何换行符都会使其崩溃!可以通过n-在代码之前过滤掉任何换行符来解决此问题,但要花费两个额外的字符。


3

C ++-365个字符,不含 int main(){}

#include<iostream>
#include<string>
#include<cmath>
#define o std::cout<<
int main(){std::string s;getline(std::cin,s);for(int i=0;i<s.size();i++){if(s[i]==32)o 0;int j=s[i]-97;if(i>0&&j/3==(s[i-1]-97)/3)o ' ';if(-1<j&j<15){for(int k=j-j%3-1;k<j;k++)o 2+j/3;}if(14<j&j<19){for(int k=14;k<j;k++)o 7;}if(18<j&j<22){for(int k=18;k<j;k++)o 8;}if(21<j&j<26){for(int k=21;k<j;k++)o 9;}}}

使用相同的推理我的答案在这里,只使用for循环输出每个字母的适当次数。


您可以使用s[i]==32代替s[i]==' '。的空间中的ASCII值是32
user12205

@ace当然可以。
Hosch250 2014年

3

的Perl - 107 110

$_=<>;y/ /0/;$z='a';$==2;for$l((3)x5,4,3,4){for$q(1..$l){s/$z/$=x$q.$"/ge,$z++}$=++}s/(.) (?!\1)/\1/g;print

这里是我以前在120溶液128 130 155

$_=<>;s//_/g;y/sz/79/;for$x(cfilorvy,behknqux,adgjmptw){s/(\d)_/\1\1_/g,eval"y/$x/2-9/"}y/ _/0 /;s/(.) (?!\1)/\1/g;print

测试:

hi
 44 444

hello world
 4433555 555666096667775553

jackdaws loves my big sphinx
 52 222553297777055566688833777706999022444 407777 744 4446699

3

VBA 220 253/258/219

Function这里不算行:

String253

Function t(s)
For Each c In Split(StrConv(s,64),Chr(0))
If c<>""Then If c=" "Then t=t & 0 Else b=Asc(c)-91:n=String(IIf(b>27,(b-4)Mod 4+1,IIf(b>23,(b-1)Mod 4+1,b Mod 3+1)),Trim(Str(Int(b/3)-IIf(b=24Or b=27Or b>29,1,0)))):t=t &IIf(Right(t,1)=Left(n,1)," " &n,n)
Next
End Function

有了For258

添加了对7/9键的更正(谢谢,丹尼),增加了许多字符。

Function t(s)
For Each c In Split(StrConv(s,64),Chr(0))
If c<>""Then
n=""
b=Asc(c)-91
For i=1To IIf(b>27,(b-4)Mod 4+1,IIf(b>23,(b-1)Mod 4+1,b Mod 3+1))
n=n &Int(b/3)-IIf(b=24Or b=27Or b>29,1,0)
Next
t=t &IIf(c=" ",0,IIf(Right(t,1)=Left(n,1)," " &n,n))
End If
Next
End Function

使用Choose 219

我不想与这一个跑,因为是在功能上更基本的,但它在更短的代码...

Function t(s)
For Each c In Split(StrConv(s,64),Chr(0))
If c<>"" Then:b=Asc(c)-96:n=Choose(b,2,22,222,3,33,333,4,44,444,5,55,555,6,66,666,7,77,777,7777,8,88,888,9,99,999,9999):t=t &IIf(c=" ",0,IIf(Right(t,1)=Left(n,1)," " &n,n))
Next
End Function

yes应该是999337777。我正在10338使用您的功能。
Danny

3

C,165 163 153 149 138个字符

k(char*s){char*m="`cfilosvz",l=0,i,c;while(*s^0){for(i=0;*s>m[i];i++);c=*s-m[i-1];i==0?i=-1,c=1:i==l?putchar(32):1;while(c--)putchar(i+49);l=i;s++;}}

我第一次尝试打高尔夫球,任何建议都值得赞赏。


2

C ++ - 170 168 160

打高尔夫球:

#define t std::cout<< 
void g(char*s){char v,p,b,l=1;while(*s){v=*s++-97;p=(v==18)+(v==25)+(v-=v/18+v/25)%3;b=v<0?48:v/3+50;if(l==b)t' ';while(p--+1){t(l=b);}}}

不打高尔夫球

void numpresses(char* s)
{
char lastbutton = 1;
const char asciiOffset = 97;

while(*s)
{
    char val = *s++ - asciiOffset;

    char presses = 
        (val == 18) + (val == 25)           //Z and S are special cases. Check for their ascii codes.
        + (val -= val / 18 + val / 25) % 3; //Simple mod 3 for number of presses. Also apply offset for characters above s and z.

    char button =
        val < 0                             //If the character is a space...
        ? '0'                               //The button character needs to be 0
        : val / 3 + '2';                    //Buttons are offset by the ascii code for the number 2


    if (lastbutton == button)               //Add a space if we need to pause
    {
        std::cout << ' ';
    }

    while (presses-- + 1)                   //Print the button once for each press required
    {
        std::cout << button;
        lastbutton = button;            
    }
}
}

2

C:136个字符

p(char*s){int i,c,l=1;while(c=*s%32,*s++)for(i=l!=(l=(c+149-c/18-c/25)/3-!c);i++<(c-!!c-c/18-c/25)%3+(c==19)+c/26+2;putchar(i^1?l:32));}

并略微松懈(是的,这就是它的写法):

p(char*s){
        int i,c,l=1;
        while(c=*s%32,*s++)for(
                i=l!=(l=(c+149-c/18-c/25)/3-!c);
                i++<(c-!!c-c/18-c/25)%3+(c==19)+c/26+2;
                putchar(i^1?l:32)
        );
}

通过应用一些递归,黑魔法和大量的辣椒粉,我也许可以减少一点。


2

Java-243

相当幼稚的Java解决方案。感谢评论者的建议。

修复了有时会插入不必要空格的错误,例如用于输入“ hello worlds sup”的错误。

    private static void t9(String s) {
        String[]t=",,abc,def,ghi,jkl,mno,pqrs,tuv,wxyz".split(",");String o="";int i,j,k,l=0;for(char c:s.toCharArray()){if(c==32){o+='0';l=0;}else for(j=0;j<10;j++){int n=t[j].indexOf(c);if(n>=0){if(j==l)o+=' ';for(k=0;k<n+1;k++)o+=j;l=j;}}}return o;
    }

4
很好,但是您需要打高尔夫球并提供得分。
Hosch250

1
我认为这是java。您可以像其他答案一样将其放在标题中吗?
Digital Trauma 2014年

1
一个高尔夫球:更换t.length10
贾斯汀

此外,考虑到i仅用于遍历String,将其删除并进行foreach循环:for(char c:s.toCharArray())
贾斯汀

另外,更改if(c==' '){o+='0';continue;}if(c==' ')o+='0';else{并添加相应的}
贾斯汀

1

CoffeeScript-202(210-8)

t9=(s)->
    t=[3,3,3,3,3,4,3,4];l=-1;r=""
    for c in s
        n="";d=c.charCodeAt(0)-96
        if c is ' '
            n=0
        else((n+=k+2 for x in[0...d];break)if d<=v;d-=v)for v,k in t
        r+=if n[0]is l[0] then " "+n else n
        l=n
    r

1

APL,77个字符

{{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('0',⍨(⌈3.1×y-⌊y)/¨⍕¨2+⌊y←7.99,⍨.315×⍳25)[⍵⍳⍨⎕UCS 96+⍳26]}

说明

  • 2+⌊y←7.99,⍨.315×⍳25或者,在未打高尔夫球的情况下,y←(0.315×⍳25),7.99 ◇ 2+⌊y在1到25的点上采样一条适当倾斜的线(y = 0.315 x);或者 线以这样的方式倾斜,使得这些y值的底数遵循重复模式000111 ... 777,但第六组数字5555除外;在末尾附加一个数字以获得第四个7,因此最终数组加2为22233344455566677778889999;
  • ⌈3.1×y-⌊y 放大这些y值与其底值之间的差异,以使差异的上限给出模式123123 ...,在两组4位数字的最后一位数字上为4;
  • '0',⍨( ... )/¨⍕¨ ...(( ... ) /¨ ⍕¨ ...),'0' 使用后者的结果来复制前者的数字,从而输出为字符串数组“ 2”,“ 22”,“ 222”,“ 3”,“ 33”,“ 333” ...以及正确的“ 7777”和“ 9999”,并在末尾附加“ 0”;
  • ⍵⍳⍨⎕UCS 96+⍳26(⎕UCS 96+⍳26)⍳⍵计算每个输入字符的索引,其中“ a”为1,“ z”为26,空间(以及其他所有char)为27;或者
  • { ... }/( ... )[ ... ] 取后一个结果,即每个输入字符的索引,将每个字符转换为相应的数字字符串,然后使用大括号中的函数将字符串连接起来;
  • {⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}{(⍺,(=/↑¨⍺,⍵)↑''),⍵}将每个新字符串append附加到累加器⍵,仅当两个参数以相同的char开头时,才插入一个空格。

例子

      {{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('0',⍨(⌈3.1×y-⌊y)/¨⍕¨2+⌊y←7.99,⍨.315×⍳25)[⍵⍳⍨⎕UCS 96+⍳26]} 'hello world'
 4433555 555666096667775553 
      {{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('0',⍨(⌈3.1×y-⌊y)/¨⍕¨2+⌊y←7.99,⍨.315×⍳25)[⍵⍳⍨⎕UCS 96+⍳26]} 'the quick brown fox jumped over the lazy dog'
 84433077884442225502277766696603336669905886733 3066688833777084433055529999 999036664 

1

Python的155 150

我希望我在这个XD方面更好。功能定义不计算在内。第一个缩进级别是一个空格,第二个是制表符,第三个2个制表符。

def p(s,l=None):
 for c in s:
    for i,g in enumerate(" ,,abc,def,ghi,jkl,mno,pqrs,tuv,wxyz".split(",")):
        if c in g:print"\b"+[""," "][l==i]+str(i)*(g.index(c)+1),;l=i

0

的JavaScript 234

for(l=-1,r="",I=0,y=(s=prompt()).length;I<y;I++){c=s[I];n="";d=c.charCodeAt(0)-96;if(0>d)n=0;else for(k=J=0;J<8;k=++J){v="33333434"[k];if(d<=v){for(x=K=0;0<=d?K<d:K>d;x=0<=d?++K:--K)n+=k+2;break}d-=v}r+=n[0]==l[0]?" "+n:n;l=n}alert(r)


0

R 224

我确信有更好的方法可以做到这一点,因此我将继续努力。

a=strtoi(charToRaw(scan(,'',sep='\n')),16L)-95;a[a<0]=1;b=c(0,2,22,222,3,33,333,4,44,444,5,55,555,6,66,666,7,77,777,7777,8,88,888,9,99,999,9999)[a];c=append(b[-1],0)%%10;d=b%%10;b[c==d]=paste(b[c==d],'');paste(b,collapse='')
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.