如何在Scrabble游戏中优化单词的排列?

时间:2013-09-05 16:14:01

标签: java algorithm permutation pseudocode anagram

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

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

我遇到的问题是optimization。因为这个anagram使用recursion并运行最多8个阶乘,所以生成的许多“垃圾”词往往不存在于任何字典中,例如重复单个字母。

必须进行某种检查,以确定排列是否有效,而不仅仅是重复1个字符。到目前为止,我对如何快速 这两个方面都感到茫然。

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

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


我的问题是:

任何人都可以建议一种方法,它可以100%的时间来优化生成的排列数吗?


我不需要生成无用的东西,但这些都是生成的大部分内容。

我认为这是一个很好的方法,但与此同时我相信我必须错过一些更快,更适合我想要达到的目标。

如果有人可以建议一种方法来检查单词是否真的可行,或者如果你能提出更好的方法来处理这种情况,那就非常感激了。

感谢。

2 个答案:

答案 0 :(得分:0)

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

如果走几条图的路线,你可以为字母表的每个字母创建一个图形,然后创建一个1度连接到字典中该字母后面的每个字母。

所以,说你有字典[和,手臂,蚂蚁,蚂蚁,蚂蚁,军队]

你会得到如下图表:

[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]

答案 1 :(得分:0)

(免责声明:伪代码可能不是有效的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];
    }
}