t9のような機能を実装する


10

今日の課題は、t9のような機能を実装することです。

2つのパラメーターのみを持つ関数を実装します。
文字列で1つの電話番号と、単語のリストを含むテキストファイルのコンテンツを受け取ります(特定の改行スタイルは想定しないでください)。
リンクhttps://raw.githubusercontent.com/eneko/data-repository/master/data/words.txtを使用して機能をテストするか、使用することができます/usr/share/dict/words(詳細については、単語のリストを含むテキストファイルをチェックしてください[閉じる]情報)。

常に少なくとも2つの番号を受け取ると想定できます。

番号を指定すると、単語のリストから読み取って、それらの単語にマッピングされている文字で始まる単語を返します。これは、入力は2から9までの数字でなければならないことを意味し
ます。無効な入力を受け取った場合は、何でも好きなことができます。

一致が見つからない場合は、空のリストnull/ nilまたはを返すことができます0

携帯電話のキーは同等の文字にマッピングされていることに注意してください:

  • 0と1は無効です
  • 2件一致[abc]
  • 3一致[def]
  • 4試合[ghi]
  • 5一致[jkl]
  • 6一致[mno]
  • 7一致[pqrs]
  • 8試合[tuv]
  • そして9試合[wxyz]

例:

f('52726')
//returns ["Japan","japan","Japanee","Japanese","Japanesque"...,"larbowlines"]

f('552')
//returns ["Kjeldahl","kjeldahlization","kjeldahlize"...,"Lleu","Llew"]

f('1234')
//makes demons fly out your nose or divide by 0

f('9999')
//returns ["Zyzzogeton"]

f('999999')
//returns [] or null/nil or 0

関数を実行した後、任意の方法で関数を印刷できます。

ルール:

  • 標準の抜け穴は無効です
  • あなたが何かを返さなければなりません、たとえそれがnull/ 何もnil
    返さundefinedなければJavaScriptが返すので、このルール。
  • 他人の回答を使用または再実装したり、私の実装をコピーしたりすることはできません。
  • Javascriptの場合、ブラウザーが既に開かれており、自動要素のinnerText/ textContentが2番目のパラメーターとして渡されると想定できます。
  • コンパイルされた言語の場合、コンパイラに特別な引数を渡すことはできません
  • コンパイラの引数を介してファイル名を受け取ることができます
  • 変数、マクロ、グローバル変数、定数、非標準クラス、および関数内の他の値を渡すすべてのソートは無効と見なされます。
  • JavaScriptでは、キーワードのない変数はvarコードを無効にします
  • 関数に名前が付けられます f
  • 関数には2つの引数しか指定できません。
  • 実行するコードを500秒未満に保つようにしてください。
  • 空白を気にする必要はありません
  • ASCII印刷可能文字のみを使用する必要があります。
    例外は、印刷不可能な文字のみを使用する言語です(APLと空白は2つの例です)。

得点:

  • 最小バイト数が勝つ
  • 回答に無効なASCII印刷可能文字が含まれている場合、UTF-32でエンコードされる
    回答としてカウントされます。エンコーディングの例外により、回答は文字数でカウントされます
  • 関数本体のみがカウントされ、それ以外で行うことはカウントされません
  • 近隣または最も一般的な単語に基づいて予測システムを作成する場合、-30%のボーナス
  • 最初の数字に対応する各文字の最初の5つの一致のみを返す場合、サイズが-20%のボーナス(例:245は、「a」で始まる5ワード、「b」で始まる5ワード、「c」で始まる5ワードを返します)。

JavaScriptを使用した実装の例を次に示します。

function f(phone, words)
{
    var keypad=['','','abc','def','ghi','jkl','mno','pqrs','tuv','wxyz'];
    var regex='';

    for(var i=0,l=phone.length;i<l;i++)
    {
        regex+='['+keypad[phone[i]]+']';
    }

    var regexp=new RegExp('\\s('+regex+'[a-z]*)\\s','gi');

    return words.match(regexp);
}

これを実行するには、リストのリンクを開いて実行します。次に例を示します。

f('9999',document.getElementsByTagName('pre')[0].innerText);
//returns [" Zyzzogeton "]

この例はテスト済みで、Windows 7 Home Edition 64ビットのOpera 12.17 64ビットで動作します。


プログラムの2番目の引数は、単語または単語のリスト自体を含むファイル名ですか?
オプティマイザ、2014

@MartinBüttnerUTF-8は不公平ではありません(ただし、ASCII文字は1バイトとしてカウントされます)が、ルールを変更しました。
Ismael Miguel 14

@Optimizer 2番目の引数は単語のリストです。必要に応じて、コンパイラの引数を介してファイル名を渡し、ファイルを読み取ることができます。ただし、重要なのは関数本体だけです。
Ismael Miguel

@MartinBüttnerASCIIとしてカウントすることにより、バイトとしてカウントされます。あなたは私にAPLコードが8ビットのサイズを持つ1バイトを持つと言いたいですか?
Ismael Miguel 14

2
不適切な制限の場合は-1
AJMansfield '12

回答:


3

CJam、28バイト

q~{el{'h-_9/-D+3/}%s1$#!},p;

次の形式で入力を受け取ります "<number>" [<list of words>]

例:

"52726" ["Japan" "japan" "Japanee" "Japanese" "Japanesque" "larbowlines" "ablution" "ablutionary" "abluvion" "ably" "abmho" "Abnaki" "abnegate"]

出力:

["Japan" "japan" "Japanee" "Japanese" "Japanesque" "larbowlines"]

今のところボーナスはありません。

ここでコードをオンラインで試しますが、実際の時間を測定するには、Javaコンパイラで実行します

CJamは次のような空のリストを表すことに注意してください ""

生の単語リストをCJamリストに変換するには、単語リストを入力として次のコードを使用します。

qN/p

「文字列で1つの電話番号と単語のリストを含むテキストファイルのコンテンツを受け取ります」->別のブロックに、ファイルを使用可能なリストに読み込むために必要なコードを実装できますか?
Ismael Miguel 14

@IsmaelMiguelこのコードの一部ではなく、リストを正しい形式に変換するヘルパーコードだけですか?
オプティマイザ

丁度。提供された例として、単語のリストを使用できることを証明するのに十分ではないコード。とにかく、私は賛成票を投じました。そのヘルパーコードが欲しかったのです。
Ismael Miguel 14

答えに追加できますか?編集として、別の部分
Ismael Miguel 14

丁度。それは私が話しているものです!それをさらに最適化できるかどうかを見てみましょう
Ismael Miguel 14

2

Java:395

これは、各番号に使用できる文字に基づいて正規表現パターンを形成し、その後に末尾の。*を追加して、後続の文字と一致させます。

これがゴルフ版です:

static ArrayList<String> f(String n,ArrayList<String> d){String[] k={"","","([A-Ca-c])","([D-Fd-f])","([G-Ig-i])","([J-Lj-l])","([M-Om-o])","([P-Sp-s])","([T-Vt-v])","([W-Zw-z])"};String r="";for(int i=0;i<n.length();++i)r+=k[n.charAt(i)-'0'];r += ".*";Pattern p=Pattern.compile(r);ArrayList<String> a=new ArrayList<String>();for(String w:dictionary)if(p.matcher(w).matches())a.add(w);return a;}

そして、これは読みやすさのための非ゴルフバージョンです

public static ArrayList<String> f(String phoneNumber, ArrayList<String> dictionary) {

    String[] KEY_VALUES = {"", "", "([A-Ca-c])", "([D-Fd-f])", "([G-Ig-i])",
                                            "([J-Lj-l])", "([M-Om-o])", "([P-Sp-s])",
                                            "([T-Vt-v])", "([W-Zw-z])"};

    String regex = "";
    for (int i = 0; i < phoneNumber.length(); ++i) {
        regex += KEY_VALUES[phoneNumber.charAt(i) - '0'];
    }
    regex += ".*";
    Pattern p = Pattern.compile(regex);
    ArrayList<String> answers = new ArrayList<String>();
    for (String word : dictionary) {
        if (p.matcher(word).matches()) {
            answers.add(word);
        }
    }
    return answers;
}

コードはルール番号7に違反します。「変数、マクロ、グローバル変数、定数、非標準クラス、および関数内の他の値を渡すすべてのソートは無効と見なされます。」ルール3に少し反します。「他者の回答を使用または再実装したり、私の実装をコピーしたりすることはできません。」しかし、コードではそれは議論の余地があります。また、ルール9:「関数には名前が付けられます」にも違反しますf
Ismael Miguel

@IsmaelMiguelおっと。ルール7は、関数内で定数を移動することで簡単に修正できます。プログラミングスタイルを改善するために、関数の外に引っ張っていました。ルール9も簡単に修正できます。私はあなたの答えを読んでいないことを告白しますので、意図的にそれをコピーしようとはしませんでした。コンテストに近すぎると思われる場合は、回答を削除できます。
Brian J

あなたの答えは大丈夫です。コードにバグがあります。最後の定数(([W-Zw-z)])は、それでなければなりません([W-Zw-z])。また、コードゴルフでは、プログラミングスタイルや良い習慣について心配する必要はありません。コードは、必要なパラメーターを使用して、それを実行するだけです。私の答えを確認すると、次の行が表示されます$s=[2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz];。これは、PHPでのひどい「犯罪」です。基本的に、PHPに存在しない定数を文字列に変換するように強制しています。これはまったく問題ありません。また$t、そのように使用する前に変数を配列に設定していないこともわかります
Ismael Miguel

@IsmaelMiguel正規表現エラーのキャッチ。指摘してくれてありがとう。明日は実際にゴルフしてみるつもりです。このサイトでJavaの例をいくつか見つけることができます。
Brian J 14

私はJavaプログラマではありませんが、いくつかのことをお話します。codegolf.stackexchange.com/questions/6671/…をチェックして、ヒントを取得できます。一般的なヒントには、不要な空白(改行、スペース、タブ)、1文字の変数名の削除、コードサイズを可能な限り小さくするためにできることはすべて含まれています。
Ismael Miguel

1

C#.NET 4.5 235

これはうまくいくはずです:

IEnumerable<string>F(string n,string d){IEnumerable<string>w=d.Split(null).ToList();string[]a={"","","abc","def","ghi", "jkl","mno","pqrs","tuv","wxyz"};foreach(var i in n){w=w.Where(x=>x.IndexOfAny(a[i-'0'].ToArray())>0);}return w;}

PPCGへようこそ。あなたのコードは機能しますが、それでもそれをも​​っともっと減らす必要があります。不要な空白(スペース、タブ、改行)をすべて削除することで、コードを167バイトに減らすことができました。このコードはもっともっと減らすことができると私は確信している。codegolf.stackexchange.com/questions/173/…を読んで、コードをさらに短くすることをお勧めします。少しわかりやすくするために、単語リストは改行で区切られた文字列であり、その中ですでにaを使用できると想定しているようですforeach。既にそうであると思われるIEnumerable場合は、外部で使用されているコードを含めてください
Ismael Miguel 14

@IsmaelMiguel TY見ていきます。リストはIEnumerableであり、私が投稿したもの以外にコードはありません。
Chaossie 14

関数の仕様を見ると、2番目のパラメータも文字列であることがわかります。(引用:「文字列で1つの電話番号と、単語のリストを含むテキストファイルのコンテンツを受け取ります(特定の改行スタイルを想定しないでください)。」そして、avarに1つの無駄な空白があります。
Ismael Miguel

私はあなたの質問の改善に気づき、あなたに賛成票を与えました。ただし、変数に1バイトを保存することはできますa。しかし、私は本当に顕著な改善を見ています!良い仕事を続けてください。
Ismael Miguel

1

Python 2(155バイト)

適切な置換(string-> bytesb文字列の接頭辞など)を使用して、Python 3でも動作するはずです。

maketrans関数の外での呼び出しが「公正」と見なされるかどうかはわかりませんでした。そうでない場合、関数は内部に移動した134バイトです。

編集:愚かな見落としから1バイトを削除しました。

準備済みmaketrans、67バイト:

from string import maketrans
t=maketrans('abcdefghijklmnopqrstuvwxyz','22233344455566677778889999')

def f(n,w):
    return[x for x in w.split()if x.lower().translate(t).startswith(n)]

maketrans体内で、134バイト:

from string import maketrans

def f(n,w):
    return[x for x in w.split()if x.lower().translate(maketrans('abcdefghijklmnopqrstuvwxyz','22233344455566677778889999')).startswith(n)]

importし、maketrans体内で、155バイト:

def f(n,w):
    return[x for x in w.split()if x.lower().translate(__import__('string').maketrans('abcdefghijklmnopqrstuvwxyz','22233344455566677778889999')).startswith(n)]

テスト通話:

print f('9999',open('words.txt','rt').read())

maketrans関数本体の一部です。あなたはそれを移動する必要があります。可能かどうかはわかりませんが、を直接使用してみてくださいimport。どこかで見たと思いますが...あなたのコードは本当にいいです!
Ismael Miguel

インポート移動することを意味します、体内への呼び出しを?はい、それもできると思います。
criptychはモニカの2014

について考えていましたt=(from stirng import maketrans)([...])。それが可能かどうかさえわかりません。しかし、多分あなたもfrom string import as x t=x([...])それが可能であるかどうか私にはわからないものを使うことができます:/
Ismael Miguel 14

正しいバージョンが最後のバージョンです。しかし、私の意見では現状のままの回答は受け入れられます。の+1 __import__('string').maketran
Ismael Miguel

わかりました。無効な回答を削除しました。
クリプティクはモニカの2014

0

PHP 5.4以降(171 186-20%= 148.8バイト):

まあ、これはかなり大きな答えですが、まあ。

これでもっと多くの人に答えてもらいたいと思います。

この関数は、生のコンテンツが読み取られることを想定しています。

これがコードです:

function f($_,$a){$s=[2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz];$a=preg_split('@\r\n|\r|\n@',$a);for($i=0;$c=$_[$i];++$i)foreach($a as$k=>$v)if(!strpos(1..$s[$c],$v[$i])||$t[$v[0]]++>4)unset($a[$k]);return$a;}

これは、その文字が許可された文字のリストにあることを確認することで機能します。

例:入力361abc、単語の最初の文字が1defあり、2番目の文字があるかどうかをチェックします。

1文字が1番目の位置にあるかどうかをチェックしないように追加します(これは返さ0れ、に評価されますfalse)。if(!strpos(1..$s[$c],$v[$i]))またはif(!strpos($c.$s[$c],$v[$i]))同じ効果がありますが、1回目はさらに混乱し、私はそれが好きです。

そうしないと、単語が削除されます。

単語が残っていない場合、空の配列を返します。

これをオンラインでテストするには、http://writecodeonline.com/php/にアクセスして、行の単語を含む単純な変数を作成します

テスト可能な例:

function f($_,$a)
{
    $s=array(2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz);
    $a=preg_split('@\r\n|\r|\n@',$a);

    for($i=0;$c=$_[$i];++$i)
        foreach($a as$k=>$v)
            if(!strpos(1..$s[$c],$v[$i]) || $t[$v[0]]++>4)
                unset($a[$k]);
    return$a;
}

$lines=<<<WORDS
one
two
three
four
five
six
seven
eight
nine
ten
WORDS;

var_dump(f('36',$lines));

これは出力するはずです:

array(1) {
    [3]=>
      string(4) "four"
}

古いバージョンのphpで作業するには$s=[2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz];$s=array(2=>abc,def,ghi,jkl,mno,pqrs,tuv,wxyz);


20%ボーナスの場合:

コードを減らすために、||$t[$v[0]]++>4最初の文字が使用された回数をチェックするだけで追加しました。

PHPでは、$t定義する必要がないため、37.2バイトの大きなチャンクを削減できます。

この効果を確認するには、次の変数を2番目の引数として使用します。

$lines=<<<WORDS
one
two
three
four
five
six
seven
eight
nine
ten
twelve
time
tutor
test
truth
WORDS;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.