如何优化拼字游戏中的单词排列?

Posted

技术标签:

【中文标题】如何优化拼字游戏中的单词排列?【英文标题】:How can I optimize permutations of words in a Scrabble game? 【发布时间】:2013-09-09 13:52:27 【问题描述】:

我正在尝试在拼字游戏中为对手制定逻辑。

我做了很多思考,得出的结论是我需要使用anagrams 并根据字典文件中的单词列表检查这些字谜,看看生成的单词是否实际上是包含在字典文件。

我遇到的问题是optimization。由于此字谜使用recursion 并运行多达 8 个阶乘,因此往往会生成许多在任何字典中都不存在的“垃圾”词,例如单个字母的重复。

必须进行某种检查以查看排列是否有效,而不仅仅是重复 1 个字符。到目前为止,我不知道如何快速准确做到这一点。

在英语中,单词似乎由元音和辅音组成。我正在考虑检查一个单词是否包含至少 1 个元音和至少 1 个辅音,但是有一些例外情况,单词只能包含元音或辅音。所以这个方法似乎已经走到了尽头。

现在我可能遗漏了一些重要的东西,但是我没有通过所有排列强制我的方式,我不知道如何以足够快的方式进行检查以进行游戏。


我的问题是:

谁能推荐一种可以 100% 工作的方法来优化生成的排列数量?


我不需要生成无用的,而这些最终是生成的大部分。

我相信这是一个很好的方法,但同时我相信我一定错过了一些更快、更适合我想要实现的东西。

如果有人可以建议一种方法来检查单词是否真的可行,或者如果您可以建议一种更好的方法来处理这种情况,我们将不胜感激。

谢谢。

【问题讨论】:

谷歌搜索“计算机拼字游戏”发现了这个scotthyoung.com/blog/2013/02/21/wordsmith 【参考方案1】:

(免责声明:伪代码可能不是有效的 java,即使它看起来像)

听起来你有一堆乱七八糟的字母,想找出所有可以用它们拼写的英文单词。

如果对两个字符串进行排序时它们比较相等,则它们是彼此的字谜。排列候选词中的字母顺序以查看它们是否是合法的英语单词是昂贵的。相反,对字母进行排序并将其与您的单词列表进行比较:

boolean is_anagram(string word_a, string word_b)
    return sorted(word_a).equals(sorted(word_b));


List<string> valid_anagrams(string candidate_word)
    anagrams = new List<string>();
    foreach(string word : list_of_words)
        if (is_anagram(candidate, word))
            anagrams.push(word);
        
    
    return anagrams;

如果单词列表中的单词数量小于候选单词大小的阶乘,则效率更高。例如,Words With Friends 中的合法词数约为 170,000,因此您更倾向于使用上述方法来检查长度为 9 或以上的词。

如果您打算检查大量候选词,那么您可以通过保存所有有效词的排序形式来节省时间。创建一个字典,其中键是已排序的字符串,值是英语单词列表,这些单词是该字符串的变位词。它应该是这样的:


    "act": ["act", "cat", "tab"],
    "abll": ["ball"],
    "aeprs": ["asper", "parse", "pears", "reaps", "spare", "spear"]

您可以在程序开始时构建这个字典一次,如下所示:

d = new Dictionary<string, List<string>>();
foreach (string word in list_of_words)
    string key = sorted(word)
    if (!d.contains_key(key))
        d[key] = new List<string>();
    
    d[key].push(word);

那么为字符串找到有效的字谜只是访问字典的问题。

List<string> valid_anagrams(string candidate_word)
    string key = sorted(candidate_word);
    if (!d.contains_key(key))
        return new List<string>();
    
    else
        return d[key];
    

【讨论】:

我是这么想的,但谢谢你从另一个角度提出建议。【参考方案2】:

如果您想要一种快速检查字谜的方法,您可以从字典或加权图构建二叉树,然后使用字谜遍历图。这可能会在内存中变得昂贵,具体取决于字典的大小,并且在初始化时构建图形可能需要一些时间。

如果采用多个图表的路线,您可以为字母表中的每个字母创建一个图表,然后为字典中该字母后面的每个字母创建一个 1 度连接。

假设你有字典 [and, arm, ant, an, ants, antsy, Army]

你会得到如下图:

[a][ar:1][an:3]
[ar][arm:2]
[an]["":0][and:1][ant:2]
[arm]["":0][army:1]
[and]["":0]
[ant]["":0][ants:2]
[ants]["":0][antsy:1]
[army]["":0]
[antsy]["":0]

【讨论】:

以上是关于如何优化拼字游戏中的单词排列?的主要内容,如果未能解决你的问题,请参考以下文章

获取所有子串(拼字游戏)的字谜的所有单词列表的算法?

如何自动对字典中的单词进行分类?

我怎样才能找到部分单词匹配/找到c ++

简化 CLP 难题中的约束

如何在 Phaser 3 中启用单击数组中的单个项目并将每个项目显示在屏幕的不同部分?

拼字游戏字谜生成器