Pythonでランダムに入力された文字から単語を検索します。どのアルゴリズムを使用するか、すでに存在するコードを選択しますか?

StackOverflow https://stackoverflow.com/questions/1570242

質問

このようなワードデスクランブラーをコード化しようとしています ここ これを実装するにはどのようなアルゴリズムを使用すればよいのか疑問に思っていました。また、誰かがこのための既存のコードを見つけることができれば、それも素晴らしいでしょう。基本的に、この機能は泥沼ソルバーのようなものになりますが、行列ではなく、文字列からすべての単語の可能性を検索するだけです。私はすでに十分な辞書を持っています。

これをPythonかRubyで行う予定でした。皆さん、よろしくお願いします!

役に立ちましたか?

解決

私はA トライするを使用すると思います。ここでは、Pythonで実装だ: http://jtauber.com/2005/02/trie.py (ジェームズ・タウバーにクレジット)

他のヒント

私はゲームを理解できていないかもしれませんが、「ジョーカー」(ワイルドカード)文字の導入、文字の欠落または追加、複数の単語などのルールの複雑さを除けば...次のアイデアは、問題を比較的面白くないものに変えるのに役立つと思います。:-(

本旨 索引語による 順序付けられました 彼らの手紙の並び.
たとえば、「computer」は「cemoprtu」としてキー設定されます。ランダムな描画が提供するものはすべて種類で並べ替えられ、一致する可能性のあるものを見つけるためのキーとして使用されます。使用する 試してみる perimosocordiae によって提案されている構造。これらの並べ替えられたキーと、「リーフ」ノード内の関連する単語/wordId の基礎となるストレージとして使用されます。 ルックアップは O(n) 時間で実行できます, ここで、n は文字数です (または、存在しない単語のため、平均値が適切です)。

インデックス作成をさらに支援するために、文字数ごとに 1 つずつ、複数のテーブル/辞書を作成できます。また、統計によっては、母音と子音を別々に処理することもできます。もう 1 つのトリックは、最も選択的な文字を最初に配置するカスタムの並べ替え順序を設定することです。

ゲームへの追加のひねり (文字のサブセットから作られた単語を見つけるなど) は、主に次の問題です。 を繰り返す パワーセット これらの手紙のうち 組み合わせごとに辞書を調べます。

いくつかのヒューリスティックを導入できる いくつかの組み合わせを取り除くのに役立ちます(たとえば、母音のない組み合わせ(および特定の長さの)は可能な解決策ではありませんなど)。検索コストは比較的小さいため、これらのヒューリスティックは慎重に管理する必要があります。

あなたの辞書のインデックスのために、(地図[バッグ[シャア]、一覧[文字列]])マップを構築します。あなたはO(1)ワード検索を得ることができるので、それはハッシュマップでなければなりません。 Aバッグ[シャア]は、文字の順にユニークアップしている単語のための識別子です。これは、基本的にはシャアからのIntにハッシュマップですです。シャアは、単語内の指定された文字であり、Intが文字が単語に表示された回数です。

例:

{'a'=>3, 'n'=>1, 'g'=>1, 'r'=>1, 'm'=>1} => ["anagram"]
{'s'=>3, 't'=>1, 'r'=>1, 'e'=>2, 'd'=>1} => ["stressed", "desserts"]
入力文字列から文字のすべての組み合わせを取り、このマップでそれを見て、言葉を見つけるために

。このアルゴリズムの複雑度は、入力文字列の長さはO(2 ^ N)です。特に、複雑さは、辞書の長さに依存しません。

ラビン - カープ文字列のようなこの音はには次のようになり、検索します良い選択。あなたはそれぞれの位置で、その後ローリングハッシュ関数を使用する場合は、1回のハッシュ値更新と1辞書検索を必要としています。また、セット内の最も短い単語にすべての単語を切り捨て、可能なマッチを再チェックするように、異なるワード長に対処するための良い方法を作成する必要があります。分割語別々の長さの範囲に設定し、ハッシュの仕事を増やすことを犠牲にして偽陽性の量を削減します。

これを行うには二つの方法があります。一つは、候補者は、単語の辞書であるかどうかを確認するために単語に文字のすべての候補順列をチェックすることです。それは、単語の長さに応じて、O(N!)操作です。

他の方法は、それが単語内に含まれていますかどうかを確認するために、辞書内のすべての候補語をチェックすることです。これは、辞書を集約することで高速化することができます。代わりに、すべての候補語のうちのいずれかがあなたの言葉に含まれている場合以来、あなたはそれらのすべてがあり、一度に互いのアナグラムであるすべての単語をチェックします。

だから、そのキー値キーのアナグラムある単語のリストである文字とのソート列である辞書を構築することから始めます:

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> with open(r"c:\temp\words.txt", "r") as f:
        for line in f.readlines():
            if line[0].isupper(): continue
            word = line.strip()
            key = "".join(sorted(word.lower()))
            d[key].append(word)

今、私たちは、単語が候補者が含まれているかどうかを確認する機能を必要としています。この機能は、それが文字でそれらを介して、両方の手紙を行くと、それは彼らが一致しないことを発見し、迅速ときあきらめることができるように、単語と候補が両方ソートされていることを前提としています。

>>> def contains(sorted_word, sorted_candidate):
        wchars = (c for c in sorted_word)
        for cc in sorted_candidate:
            while(True):
                try:
                    wc = wchars.next()
                except StopIteration:
                    return False
                if wc < cc: continue
                if wc == cc: break
                return False
        return True

今言葉によって含まれている辞書内のすべての候補キーを見つけ、1つのリストにそれらの値の全てを集約します:

>>> w = sorted("mythopoetic")
>>> result = []
>>> for k in d.keys():
        if contains(w, k): result.extend(d[k])
>>> len(result)
429
>>> sorted(result)[:20]
['c', 'ce', 'cep', 'ceti', 'che', 'chetty', 'chi', 'chime', 'chip', 'chit', 'chitty', 'cho', 'chomp', 'choop', 'chop', 'chott', 'chyme', 'cipo', 'cit', 'cite']

最後のステップは、私のラップトップ上の四分の一秒程度かかります。私の辞書に195Kのキー(私はBSD Unixの単語ファイルを使用しています)があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top