拼字游戏Anagram Generator

时间:2009-12-06 17:30:31

标签: java anagram

我正在尝试编写一个拼字游戏生成器。

到目前为止,我的代码有点工作,但它非常慢,并且有bug。一个是它将不止一次使用字母。例如:输入的信件:“ABCDEFG”。它会产生AB,但也会产生AA,这是不对的。

请帮忙。

public class Scrabble1
{
    private String[] dictionary2 = new String[97];
    private String[] dictionary3 = new String[978];
    private String[] dictionary4 = new String[3904];
    private String[] dictionary5 = new String[8635];
    private String[] dictionary6 = new String[15225];
    private String[] dictionary7 = new String[23097];
    public void sampleMethod(String s) throws FileNotFoundException
    {
        File in2 = new File( "dictionary2.txt" );
        File in3 = new File( "dictionary3.txt" );
        File in4 = new File( "dictionary4.txt" );
        File in5 = new File( "dictionary5.txt" );
        File in6 = new File( "dictionary6.txt" );
        File in7 = new File( "dictionary7.txt" );        
        Scanner dict2 = null,dict3 = null,dict4 = null,dict5 = null,dict6 = null,dict7 = null;

        try
        {
            dict2 = new Scanner(in2);
            dict3 = new Scanner(in3);   
            dict4 = new Scanner(in4);
            dict5 = new Scanner(in5);
            dict6 = new Scanner(in6);  
            dict7 = new Scanner(in7); 
            int c = 0;
            while(dict2.hasNext()&&dict3.hasNext()&&dict4.hasNext()&&dict5.hasNext()&&dict6.hasNext()&&dict7.hasNext())
            {
                dictionary2[c] = dict2.next();
                dictionary3[c] = dict3.next();
                dictionary4[c] = dict4.next();
                dictionary5[c] = dict5.next();
                dictionary6[c] = dict6.next();
                dictionary7[c] = dict7.next();
                c++;
            }
        }
        catch( FileNotFoundException e )
        {
            System.err.println( e.getMessage () );
            System.exit(1);
        }
        finally
        {
            dict2.close();
            dict3.close();
            dict4.close();
            dict5.close();
            dict6.close();
            dict7.close();
        }

       // for(int i= 0; i<80612; i++)
            //System.out.println(dicArray[i]);


        String temp = "";
        //All 2 letter anagrams  
        for(int k=0; k<=6; k++)
            for(int i=0; i<=6; i++)
                for(int d= 0; d<97; d++)
                {
                    temp = "" + s.charAt(k) + s.charAt(i);
                    if(temp.equals(dictionary2[d]))
                        System.out.println(temp  );
                }

        //All 3 letter anagrams  
        for(int j = 0; j<=6; j++)
            for(int k=0; k<=6; k++)
                for(int i=0; i<=6; i++)
                     for(int d= 0; d<978; d++)
                          {
                                temp = "" + s.charAt(j) + s.charAt(k)+ s.charAt(i);
                                if(temp.equals(dictionary3[d]))
                                    System.out.println(temp  );
                          }
        //All 4 letter anagrams  
        for(int j = 0; j<=6; j++)
            for(int k = 0; k<=6; k++)
                for(int i=0; i<=6; i++)
                    for(int l=0; l<=6; l++)
                          for(int d= 0; d<-3904; d++)
                          {
                                temp = "" + s.charAt(j) + s.charAt(k)+ s.charAt(i)+ s.charAt(l);
                                if(temp.equals(dictionary4[d]))
                                    System.out.println(temp );
                          }
         //All 5 letter anagrams
         for(int j = 0; j<=6; j++)
            for(int k = 0; k<=6; k++)
                for(int i=0; i<=6; i++)
                    for(int l=0; l<=6; l++)
                        for(int f=0; f<=6; f++)
                          for(int d= 0; d<8635; d++)
                          {
                                temp = "" + s.charAt(j) + s.charAt(k)+ s.charAt(i)+ s.charAt(l)+s.charAt(f);
                                if(temp.equals(dictionary5[d]))
                                    System.out.println(temp  );
                          }
          //All 6 letter anagrams
          for(int j = 0; j<=6; j++)
            for(int k = 0; k<=6; k++)
                for(int i=0; i<=6; i++)
                    for(int l=0; l<=6; l++)
                        for(int f=0; f<=6; f++)
                            for(int g=0; g<=6; g++)
                          for(int d= 0; d<15225; d++)
                          {
                                temp = "" + s.charAt(j) + s.charAt(k)+ s.charAt(i)+ s.charAt(l)+ s.charAt(f)+ s.charAt(g);
                                if(temp.equals(dictionary6[d]))
                                    System.out.println(temp  );
                          }
          //All 7 letter anagrams.
          for(int j = 0; j<=6; j++)
            for(int k = 0; k<=6; k++)
                for(int i=0; i<=6; i++)
                    for(int l=0; l<=6; l++)
                        for(int f=0; f<=6; f++)
                            for(int g=0; g<=6; g++)
                                for(int p=0; p<=6; p++)
                          for(int d= 0; d<23097; d++)
                          {
                                temp = "" + s.charAt(j) + s.charAt(k)+ s.charAt(i)+ s.charAt(l)+ s.charAt(f)+ s.charAt(g)+ s.charAt(p);
                                if(temp.equals(dictionary7[d]))
                                    System.out.println(temp  );

                          }




    }
}

字典文件只按字大小排序。

6 个答案:

答案 0 :(得分:1)

您的问题可归结为以下基本算法:

我还应该注意,当前代码的一个问题是所有内部循环都从0开始,这是不正确的。这就是生成“AA”的原因(因为你最终会为索引0返回两次字符)。


Java中的位域计数器

package com.stackoverflow.samples;

import java.lang.String;

public class Main {
    public static void main(String[] args) {            
        String input = "ABCDE";        
        printAllSubsets(input);
    }

    private static void printAllSubsets(String input) {
        int n = input.length();
        int last = 2 << n;
        char[] subset = new char[n];

        for (int bits = 0; bits < last; ++bits) {
            int j = 0;
            for (int i = 0; i < n; ++i) {
                if (bitIsSet(bits, i)) {
                    subset[j] = input.charAt(i);
                    ++j;
                }
            }

            printSubset(subset, j);
        }
    }

    private static void printSubset(char[] subset, int n) {
        System.out.print('{');

        for (int i = 0; i < n; ++i) {
            System.out.print(subset[i]);
        }

        System.out.println('}');
    }

    private static boolean bitIsSet(int bits, int position) {
        return ((bits >> position) & 1) == 1;
    }
}

答案 1 :(得分:1)

您可以从字典中构建trie并遍历它。对于输入字符串中的每个字符,转到trie中的相应节点,从输入中删除字符并递归重复。

的伪代码:

function check(trie_node)
    if trie_node is terminal
        output trie_node
    else
        for each child of trie_node
            let c be the character of the child
            if input contains at least one c
                remove one c from input
                check(child)
                put c back into input
            end
        end
    end
end

check(trie_root)

您可以使用查找表快速检查输入中剩余的特定字符的数量(恒定时间检查)。

答案 2 :(得分:1)

我会通过首先将所有词典统一到一个巨型词典中,然后对您构建的词典中的字母进行排序以及搜索名为searchWord的子集的单词来解决此问题。

我会做这样的事情

String findAllScrabbleWords (String searchWord)
  searchWord = searchWord.sortLetters();

  Dictionary<String,List<String>> wordlist = new Dictionary <String, List<String>>()

  foreach file in fileList
    foreach word in file
    sortedword = word.sortLetters();
    // Add a new key if it isn't there then add the new word
    if (!wordlist.containsKey(sortedword))
      wordlist[sortedword] = new List<String>();
    wordlist[sortedword].add(word);
  end

  // Now search for the words.
  return findScrabbleWords ("", sortedword, wordList);

end

// We do this recursively so we don't have to worry about how long the search
// string is. 
String function findScrabbleWords (String headString, String tailString, Dictionary<String,List<String>> wordList)
  if (tailString == "")
    return "";
  end

  String returnValue = "";

  for (pos = 0; pos < tailString.length; pos++)

    // Add an element of the tail to the current string and remove
    // that letter from the tail.
    String currString = headString + tailString[pos];
    String remainderString = tailString.removeAt(pos,1);

    if (wordList.containsKey(currString))
      foreach word in wordList[currString]
        returnValue += word + " ";
      end
    end

    // Now check the strings that contain the new currString
    returnValue += findScrabbleWords(currString,remainderString,wordList);

  end

  return returnValue;
end 

答案 3 :(得分:0)

在Python中:

import itertools
mystring = "ABCDEFG"
for perm in itertools.permutations(mystring):
    print "".join(perm)

如果您想查看算法,请查看source/docs

def permutations(iterable, r=None):
    # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
    # permutations(range(3)) --> 012 021 102 120 201 210
    pool = tuple(iterable)
    n = len(pool)
    r = n if r is None else r
    if r > n:
        return
    indices = range(n)
    cycles = range(n, n-r, -1)
    yield tuple(pool[i] for i in indices[:r])
    while n:
        for i in reversed(range(r)):
            cycles[i] -= 1
            if cycles[i] == 0:
                indices[i:] = indices[i+1:] + indices[i:i+1]
                cycles[i] = n - i
            else:
                j = cycles[i]
                indices[i], indices[-j] = indices[-j], indices[i]
                yield tuple(pool[i] for i in indices[:r])
                break
        else:
            return

答案 4 :(得分:0)

Jon Bentley的书Programming Pearls,有一个很好的例子,可以为字谜做这个,我相信你可以适应它。请参阅code for column 2(甚至更好地抓住这本书!)。

我将在这里草拟一个实现:

1)通过一本字典,每个单词将字母排序为顺序(例如,鱼会变成“fihs”,“驴”会变成“dekony”。这个键可以让你查找所有可能的单词用这一系列字母制作。将这些信息存储在数据结构Map&lt; String,Set&lt; String&gt;&gt;中。例如,对于单词dog,你最终会得到两个条目dog - &gt;(god,dog)。

3)现在,当您想要找到一个单词时,如上所述对机架中的字母序列进行排序并查询地图(例如,在您制作的地图中查找该键)。这将为您提供由该系列字母组成的所有可能单词的列表。

你可以对Scrabble进行一些改编,因为原始算法是针对字谜的,但它应该只是简单地查询地图更多次(例如,如果你有字母dayvgea那么你需要查询不仅适用于aadgeyv,也适用于6个字母及以下的每个组合。不同combinations of 7 items的数量仅为128,因此要找到最佳单词,您只需要在数据结构中进行固定数量的查找。 / p>

答案 5 :(得分:0)

我感谢您提供的所有帮助。我采取了一种更简单的方法,这里是:它看起来非常有效,但我仍然计划调查你提出的所有替代方案。

public class Unscramble 
{
 public final static String letters = JOptionPane.showInputDialog("Please input your tiles").toLowerCase();
 public static LinkedList<String> words = new LinkedList();

 public static void main(String[] args) throws FileNotFoundException, IOException 
 {
  checkWords(new FileReader("ospd3.txt"));
  for(int i = 0; i < words.size(); i++)
  {
   System.out.println(words.get(i));
  }
 }
 private static void checkWords(FileReader dict) throws IOException
 {
  BufferedReader bf = new BufferedReader(dict);
  String line = "";
  while((line = bf.readLine()) != null)
  {
   if(hasWord(line))
   {
    words.add(line);
   }
  }
  bf.close();
  dict.close();
 }
 public static boolean hasWord(String word)
 {
    String copy = letters;
    for(int u = 0; u < word.length(); u++)
    {
        if(copy.contains(String.valueOf(word.charAt(u))))
     {
        copy = copy.replaceFirst(String.valueOf(word.charAt(u)), "");
     }
     else
     {
        return false;
     }
    }
    return true;
 } 
}