【问题标题】:Why doesn't thins Boggle Solver work?为什么稀薄的 Boggle Solver 不起作用?
【发布时间】:2012-12-03 22:03:59
【问题描述】:

我正在编写一个 boggle 求解器,但我不知道我的编码哪里出错了。这是我目前所拥有的:

public class Boggle {
char[][] letters;
ArrayList <String> wordsPossible;
boolean[][] lettersUsed;
ArrayList<String> wordsMade = new ArrayList<String>();


public static void main(String[] args) {
    Boggle boggle = new Boggle();

    boggle.findWords();
}

public Boggle(){
    letters = new char[4][4];
    letters[0][0] = 'a';
    letters[0][1] = 'd';
    letters[0][2] = 'e';
    letters[0][3] = 'h';
    letters[1][0] = 's';
    letters[1][1] = 't';
    letters[1][2] = 'i';
    letters[1][3] = 'p';
    letters[2][0] = 's';
    letters[2][1] = 'k';
    letters[2][2] = 'c';
    letters[2][3] = 'e';
    letters[3][0] = 'u';
    letters[3][1] = 'f';
    letters[3][2] = 'r';
    letters[3][3] = 'o';

    Scanner scanner = null;
    try {
        scanner = new Scanner(new File("brit-a-z.txt"));
    } catch (FileNotFoundException ex) {
        Logger.getLogger(Boggle.class.getName()).log(Level.SEVERE, null, ex);
    }
    wordsPossible = new ArrayList<String>();
    while(scanner.hasNext()){
        String str = scanner.nextLine();
        wordsPossible.add(str);
    }
    lettersUsed = new boolean[4][4];
}

public void findWords(){
    for(int i=0; i<letters.length; i++){
        for(int j=0; j<letters[i].length; j++){
            //findWords(jLabels[i][j].getText(), i, j, labelsUsed);
            findWords(Character.toString(letters[i][j]), i, j, lettersUsed);
            System.out.println("Done");
        }
    }
    for(int i=0; i<wordsMade.size(); i++){
        System.out.println(wordsMade.get(i));
    }
}

public void findWords(String word, int iLoc, int jLoc, boolean[][] lettersUsed){
    if(iLoc < 0 || iLoc >= 4 || jLoc < 0 || jLoc >= 4){
        return;
    }

    if(lettersUsed[iLoc][jLoc] == true){
        return;
    }

    word += letters[iLoc][jLoc];
    lettersUsed[iLoc][jLoc] = true;

    if(word.length() >= 3 && wordsPossible.contains(word)){
        System.out.println(word);
        wordsMade.add(word);
    }

    findWords(word, iLoc-1, jLoc, lettersUsed);
    findWords(word, iLoc+1, jLoc, lettersUsed);
    findWords(word, iLoc, jLoc-1, lettersUsed);
    findWords(word, iLoc, jLoc+1, lettersUsed);
    findWords(word, iLoc-1, jLoc+1, lettersUsed);
    findWords(word, iLoc-1, jLoc-1, lettersUsed);
    findWords(word, iLoc+1, jLoc-1, lettersUsed);
    findWords(word, iLoc+1, jLoc+1, lettersUsed);

    lettersUsed[iLoc][jLoc] = false;
}

}

它只是运行,很少会说找到了一个词。它也需要很长时间才能运行,大约一个小时。我看不出我的错误在哪里,我看不出我可以在哪里犯错。任何帮助都会很棒!

【问题讨论】:

  • 只是出于好奇,brit-a-z.txt 有多大。它是否包含英语中的每个单词?
  • 该文件大约有 80,000 字

标签: java algorithm boggle


【解决方案1】:

这将在所有 10-、11-、12-、13-、14- 等字母词中进行组合爆炸。一旦当前的word 不是字典中任何单词的前缀,您应该添加代码来修剪搜索。

此外,您正在使用 ArrayList 作为单词列表。使用wordsPossible.contains(word) 搜索平面列表非常慢,因为它每次都会扫描整个列表。平均而言,这需要 40,000 次迭代才能获得 80,000 个单词的词典。

更合适的数据结构是tree setprefix tree(或trie)。两者都针对快速查找进行了优化,非常适合上述前缀检查。对于树集,ceiling() 方法会很方便。有关 Java 尝试的信息,请参阅 this question

【讨论】:

  • 好的,我之前也想过,但我认为这不会有帮助。在意识到测试了多少无用的单词之后,我将实现这一点。谢谢!
  • 感谢您的建议和链接。我现在正在测试单词以查看它们是否是字典中单词的前缀。这种方法效果很好,但是,它从来没有说任何潜在的词都是实际的词。对此有何建议?
【解决方案2】:

这个 ArrayList 将会非常庞大​​!您应该尝试使用更好的数据结构,例如ArrayList&lt;ArrayList&lt;ArrayList&lt;String&gt;&gt;&gt;,其中第一个索引是单词的第一个字母,第二个索引是单词的第二个字母。

wordsPossible = new ArrayList<ArrayList<ArrayList<String>>>(26);
for (char c = 'a'; c <= 'z'; c++) {
    ArrayList<ArrayList<String>> temp = new ArrayList<ArrayList<String>>(26);
    wordsPossible.add(temp);
    for(char d = 'a'; d <= 'z'; d++) { 
        ArrayList<String> innerTemp = new ArrayList<String>();
        temp.add(innerTemp);
    }
}

// Snip

while(scanner.hasNext()){
  String str = scanner.nextLine();
  addWord(str);
}

// Snip

public void addWord(String str) {
  int first = str.toLowerCase().charAt(0) - 'a';
  int second = str.toLowerCase().charAt(1) - 'a';
  wordsPossible.get(first).get(second).add(str);
}

然后通过首先找到正确的内部ArrayList 来查找匹配的单词,而无需进行大量搜索。

【讨论】:

  • 这是有道理的。它会有很多搜索。我也会实现这个。谢谢!
  • 没问题。不要忘记投票/勾选有用的答案!
  • 我会,但我是新来的,现在还没有,抱歉:(。
猜你喜欢
  • 2019-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-24
相关资源
最近更新 更多