電話のマルチタップスペルチェック


21

Google Code Challengeに触発された:

ラテンアルファベットには26文字が含まれ、電話のキーパッドには10桁しかありません。キープレスのシーケンスを使用して目的の文字を示すことで、友人へのメッセージを簡単に書くことができます。以下に示すように、文字は数字にマッピングされます。たとえば、文字Bを挿入する場合、プログラムは22を押します。同じキーから2文字を連続して挿入するには、ユーザーはキーをもう一度押す前に一時停止する必要があります。一時停止を示すには、スペース文字「」を印刷する必要があります。たとえば、2 2はAAを示し、22はBを示します。

各メッセージは、小文字a〜zおよびスペース文字 ''のみで構成されます。ゼロを押すとスペースが放出されます。

ここに画像の説明を入力してください

あなたの挑戦は、入力文字列を受け取り、入力を文字列として生成するか、標準出力に出力するのに必要なキー押下のシーケンスを返す最小の関数を書くことです。最小のバイト数である関数が優先されます。

入出力の例

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

その他の説明

  • 一時停止必要な場合にのみ追加し、スペース「」にする必要があります。
  • 各メッセージは、小文字 a〜zおよびスペース文字 '' のみで構成されます。印刷0してスペースを示します。
  • 外部ライブラリはありません。
  • 入力文字列のみが関数に渡されます。
  • 他の言語の競争力を高めるために、主要な関数宣言は考慮されず、他の標準ライブラリのインポートも行いません。#includes、imports、およびusingsはカウントされません。他のすべてが行います。これには、#definesおよびヘルパー関数が含まれます。混乱している場合は、この質問のルール2を参照してください。
  • 複数のスペースは、スペースとして一時停止する必要がないため、00または0 0


入力が小文字/大文字であると想定できますか?
フィルH 14年

@PhilH " 小文字 a〜z およびスペース文字 ''"
ダニー14年

括弧{}は関数シグネチャの一部と考えていますか?たとえば、コードがの場合、またはfunction f(){alert('hi');}の文字を数える必要がありますalert('hi');{alert('hi');}
ProgramFOX 14年

2
覚えてt9いる限りでは、動作が異なります。単語を取得するには、各キーを1回クリックする必要があります。
ビジョン

回答:


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で文字に変換されます

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

文字は最初に一連の数字にマップされます。-aから2-bから22-dから3222-hから444333222

正規表現は、等しい数字の最初のグループと一致します

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

配列が結合されます

*' ')

「digit space different_digit」の出現箇所のすべてのスペースが削除されます

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

1
100%正しく動作するようには見えません。なるほど66666は、これまでの行に4回押しする必要はありません。
ダニー14年

修正する必要があります、ありがとう;)
デビッドハーマン14年

1
\2その最後の正規表現の意味は何ですか?確かに、2番目のグループはゼロ幅のアサーションですか?
ピーターテイラー14年

あなたは絶対に正しいです!
デビッドハーマン14年

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 14年

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-、改行を除外するためにコードの先頭に追加することにより、2文字の追加コストで修正できます。


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 14年

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

Forループ258

7/9キー(Dannyに感謝)の修正が追加され、多くの文字が追加されました。

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あなたの機能を使用して。
ダニー14年

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 14年

1
これはであると思いjavaます。他の答えがそうであるように、あなたはそれを見出しに入れることができますか?
デジタル外傷14年

1
ワンゴルフ:置き換えるt.length10
ジャスティン・

また、それを考慮することiを反復処理するためにのみ使用されString、それを削除して、foreachループを実行しますfor(char c:s.toCharArray())
ジャスティン

また、適切なに変更if(c==' '){o+='0';continue;}if(c==' ')o+='0';else{て追加します}
ジャスティン14年

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または、ungolfedでは、1〜25のポイントでy←(0.315×⍳25),7.99 ◇ 2+⌊y適切に傾斜したライン(y = 0.315 x)をサンプリングします。6桁目の数字5555を除き、これらのy値の下限が繰り返しパターン000111 ... 777になるように、ラインが傾斜します。最後の配列に2を加えたものが22233344455566677778889999になるように、最後に数字を追加して4番目の7を取得します。
  • ⌈3.1×y-⌊y これらのy値とそれらの下限値の差を増幅し、差の上限が4つの数字の2つのグループの最後の数字に4のパターン123123 ...を与えるようにします。
  • '0',⍨( ... )/¨⍕¨ ...または(( ... ) /¨ ⍕¨ ...),'0' 、後者の結果を使用して前者の数字を複製するため、出力は正しい「7777」および「 9999 "で、末尾に" 0 "が追加されます。
  • ⍵⍳⍨⎕UCS 96+⍳26または(⎕UCS 96+⍳26)⍳⍵、各入力文字のインデックスを計算します。「a」は1、「z」は26、スペース(およびその他すべての文字)は27です。
  • { ... }/( ... )[ ... ] 後者の結果である各入力文字のインデックスを使用して、各文字をそれぞれ数字の文字列に変換し、中括弧内の関数を使用して文字列を連結します。
  • {⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}または{(⍺,(=/↑¨⍺,⍵)↑''),⍵}、新しい文字列eachをそれぞれアキュムレータ⍺に追加し、両方の引数が同じ文字で始まる場合にのみ1つのスペースを挿入します。

      {{⍵,⍨⍺,''↑⍨=/↑¨⍺⍵}/('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

パイソン155 150

私はこのXDの方が良かったと思います。関数定義はカウントされません。最初のインデントレベルはスペース、2番目はタブ、3番目は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='')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.