<p>What would be the best strategy to generate anagrams.</p>

<blockquote>
<pre><code>An anagram is a type of word play, the result of rearranging the letters
of a word or phrase to produce a new  word or phrase, using all the original
letters exactly once; 
ex.
</code></pre>
  
  <ul>
  <li><strong>Eleven plus two</strong> is anagram of <strong><em>Twelve plus one</em></strong> </li>
  <li><strong>A decimal point</strong> is anagram of <strong><em>I'm a dot in place</em></strong></li>
  <li><strong>Astronomers</strong> is anagram of <strong><em>Moon starers</em></strong></li>
  </ul>
</blockquote>

<p>At first it looks straightforwardly simple, just to jumble the letters and generate all possible combinations. But what would be the efficient approach to generate only the words in dictionary.</p>

<p>I came across this page, <a href="http://lojic.com/blog/2007/10/22/solving-anagrams-in-ruby/" rel="noreferrer">Solving anagrams in Ruby</a>. </p>

<p>But what are your ideas?</p>

[{'answer_id': 55239, 'author': 'Serafina Brocious', 'author_id': 4977, 'author_profile': 'https://Stackoverflow.com/users/4977', 'pm_score': 0, 'selected': False, 'text': "<p>Off the top of my head, the solution that makes the most sense would be to pick a letter out of the input string randomly and filter the dictionary based on words that start with that.  Then pick another, filter on the second letter, etc.  In addition, filter out words that can't be made with the remaining text.  Then when you hit the end of a word, insert a space and start it over with the remaining letters.  You might also restrict words based on word type (e.g. you wouldn't have two verbs next to each other, you wouldn't have two articles next to each other, etc).</p>\n"}, {'answer_id': 55250, 'author': 'Jason Cohen', 'author_id': 4926, 'author_profile': 'https://Stackoverflow.com/users/4926', 'pm_score': 4, 'selected': False, 'text': '<p>For each word in the dictionary, sort the letters alphabetically.  So "foobar" becomes "abfoor."</p>\n\n<p>Then when the input anagram comes in, sort its letters too, then look it up.  <strong>It\'s as fast as a hashtable lookup!</strong></p>\n\n<p>For multiple words, you could do combinations of the sorted letters, sorting as you go.  Still <em>much</em> faster than generating all combinations.</p>\n\n<p><em>(see comments for more optimizations and details)</em></p>\n'}, {'answer_id': 55255, 'author': 'Jimmy', 'author_id': 4435, 'author_profile': 'https://Stackoverflow.com/users/4435', 'pm_score': 1, 'selected': False, 'text': '<p>How I see it: </p>\n\n<p>you\'d want to build a table that maps unordered sets of letters to lists words i.e. go through the dictionary so you\'d wind up with, say</p>\n\n<pre><code>lettermap[set(a,e,d,f)] = { "deaf", "fade" }\n</code></pre>\n\n<p>then from your starting word, you find the set of letters:</p>\n\n<pre><code> astronomers =&gt; (a,e,m,n,o,o,r,r,s,s,t)\n</code></pre>\n\n<p>then loop through all the partitions of that set ( this might be the most technical part, just generating all the possible partitions), and look up the words for that set of letters.</p>\n\n<p>edit: hmmm, this is pretty much what Jason Cohen posted.</p>\n\n<p>edit: furthermore, the comments on the question mention generating "good" anagrams, like the examples :). after you build your list of all possible anagrams, run them through WordNet and find ones that are semantically close to the original phrase :)</p>\n'}, {'answer_id': 55339, 'author': 'dbkk', 'author_id': 838, 'author_profile': 'https://Stackoverflow.com/users/838', 'pm_score': 0, 'selected': False, 'text': '<ol>\n<li>As Jason suggested, prepare a dictionary making hashtable with key being word sorted alphabetically, and value word itself (you may have multiple values per key). </li>\n<li>Remove whitespace and sort your query before looking it up. </li>\n</ol>\n\n<p>After this, you\'d need to do some sort of a recursive, exhaustive search. Pseudo code is very roughly:</p>\n\n<pre><code>function FindWords(solutionList, wordsSoFar, sortedQuery)\n  // base case\n  if sortedQuery is empty\n     solutionList.Add(wordsSoFar)\n     return\n\n  // recursive case\n\n  // InitialStrings("abc") is {"a","ab","abc"}\n  foreach initialStr in InitalStrings(sortedQuery)\n    // Remaining letters after initialStr\n    sortedQueryRec := sortedQuery.Substring(initialStr.Length)\n    words := words matching initialStr in the dictionary\n    // Note that sometimes words list will be empty\n    foreach word in words\n      // Append should return a new list, not change wordSoFar\n      wordsSoFarRec := Append(wordSoFar, word) \n      FindWords(solutionList, wordSoFarRec, sortedQueryRec)\n</code></pre>\n\n<p>In the end, you need to iterate through the solutionList, and print the words in each sublist with spaces between them. You might need to print all orderings for these cases (e.g. "I am Sam" and "Sam I am" are both solutions).</p>\n\n<p>Of course, I didn\'t test this, and it\'s a brute force approach.</p>\n'}, {'answer_id': 55422, 'author': 'hazzen', 'author_id': 5066, 'author_profile': 'https://Stackoverflow.com/users/5066', 'pm_score': 3, 'selected': False, 'text': '<p>See this <a href="http://www.cs.washington.edu/education/courses/cse143/08sp/handouts/23.html" rel="noreferrer">assignment</a> from the University of Washington CSE department.</p>\n\n<p>Basically, you have a data structure that just has the counts of each letter in a word (an array works for ascii, upgrade to a map if you want unicode support). You can subtract two of these letter sets; if a count is negative, you know one word can\'t be an anagram of another.</p>\n'}, {'answer_id': 55999, 'author': 'Tyler', 'author_id': 3561, 'author_profile': 'https://Stackoverflow.com/users/3561', 'pm_score': 3, 'selected': False, 'text': "<p>Pre-process:</p>\n\n<p>Build a trie with each leaf as a known word, keyed in alphabetical order.</p>\n\n<p>At search time:</p>\n\n<p>Consider the input string as a multiset.  Find the first sub-word by traversing the index trie as in a depth-first search.  At each branch you can ask, is letter x in the remainder of my input?  If you have a good multiset representation, this should be a constant time query (basically).</p>\n\n<p>Once you have the first sub-word, you can keep the remainder multiset and treat it as a new input to find the rest of that anagram (if any exists).</p>\n\n<p>Augment this procedure with memoization for faster look-ups on common remainder multisets.</p>\n\n<p>This is pretty fast - each trie traversal is guaranteed to give an actual subword, and each traversal takes linear time in the length of the subword (and subwords are usually pretty darn small, by coding standards).  However, if you <em>really</em> want something even faster, you could include all n-grams in your pre-process, where an n-gram is any string of n words in a row.  Of course, if W = #words, then you'll jump from index size O(W) to O(W^n).  Maybe n = 2 is realistic, depending on the size of your dictionary.</p>\n"}, {'answer_id': 60586, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 2, 'selected': False, 'text': '<p>I\'ve used the following way of computing anagrams a couple of month ago: </p>\n\n<ul>\n<li><p>Compute a "code" for each word in your dictionary: Create a lookup-table from letters in the alphabet to prime numbers, e.g. starting with [\'a\', 2] and ending with [\'z\', 101]. As a pre-processing step compute the code for each word in your dictionary by looking up the prime number for each letter it consists of in the lookup-table and multiply them together. For later lookup create a multimap of codes to words.</p></li>\n<li><p>Compute the code of your input word as outlined above.</p></li>\n<li><p>Compute codeInDictionary % inputCode for each code in the multimap. If the result is 0, you\'ve found an anagram and you can lookup the appropriate word. This also works for 2- or more-word anagrams as well.</p></li>\n</ul>\n\n<p>Hope that was helpful.</p>\n'}, {'answer_id': 65464, 'author': 'user9282', 'author_id': 9282, 'author_profile': 'https://Stackoverflow.com/users/9282', 'pm_score': 2, 'selected': False, 'text': '<p>The book <em>Programming Pearls</em> by Jon Bentley covers this kind of stuff quite nicely. A must-read.</p>\n'}, {'answer_id': 395596, 'author': 'martinus', 'author_id': 48181, 'author_profile': 'https://Stackoverflow.com/users/48181', 'pm_score': 1, 'selected': False, 'text': '<p>A while ago I have written a blog post about how to quickly find two word anagrams. It works really fast: finding all 44 two-word anagrams for a word with a textfile of more than 300,000 words (4 Megabyte) takes only 0.6 seconds in a Ruby program.</p>\n\n<p><a href="http://martin.ankerl.com/2008/08/09/two-word-anagram-finder-algorithm/" rel="nofollow noreferrer">Two Word Anagram Finder Algorithm (in Ruby)</a></p>\n\n<p>It is possible to make the application faster when it is allowed to preprocess the wordlist into a large hash mapping from words sorted by letters to a list of words using these letters. This preprocessed data can be serialized and used from then on.</p>\n'}, {'answer_id': 395639, 'author': 'plinth', 'author_id': 20481, 'author_profile': 'https://Stackoverflow.com/users/20481', 'pm_score': 2, 'selected': False, 'text': '<p>One of the seminal works on programmatic anagrams was by Michael Morton (Mr. Machine Tool), using a tool called Ars Magna.  Here is <a href="http://query.nytimes.com/gst/fullpage.html?res=9B06E6DB133EF93BA2575BC0A9639C8B63" rel="nofollow noreferrer">a light article</a> based on his work.</p>\n'}, {'answer_id': 1924561, 'author': 'FogleBird', 'author_id': 90308, 'author_profile': 'https://Stackoverflow.com/users/90308', 'pm_score': 6, 'selected': False, 'text': '<p>Most of these answers are horribly inefficient and/or will only give one-word solutions (no spaces).  My solution will handle any number of words and is very efficient.</p>\n\n<p>What you want is a trie data structure.  Here\'s a <strong>complete</strong> Python implementation.  You just need a word list saved in a file named <code>words.txt</code>  You can try the Scrabble dictionary word list here:</p>\n\n<p><a href="http://www.isc.ro/lists/twl06.zip" rel="noreferrer">http://www.isc.ro/lists/twl06.zip</a></p>\n\n<pre class="lang-py prettyprint-override"><code>MIN_WORD_SIZE = 4 # min size of a word in the output\n\nclass Node(object):\n    def __init__(self, letter=\'\', final=False, depth=0):\n        self.letter = letter\n        self.final = final\n        self.depth = depth\n        self.children = {}\n    def add(self, letters):\n        node = self\n        for index, letter in enumerate(letters):\n            if letter not in node.children:\n                node.children[letter] = Node(letter, index==len(letters)-1, index+1)\n            node = node.children[letter]\n    def anagram(self, letters):\n        tiles = {}\n        for letter in letters:\n            tiles[letter] = tiles.get(letter, 0) + 1\n        min_length = len(letters)\n        return self._anagram(tiles, [], self, min_length)\n    def _anagram(self, tiles, path, root, min_length):\n        if self.final and self.depth &gt;= MIN_WORD_SIZE:\n            word = \'\'.join(path)\n            length = len(word.replace(\' \', \'\'))\n            if length &gt;= min_length:\n                yield word\n            path.append(\' \')\n            for word in root._anagram(tiles, path, root, min_length):\n                yield word\n            path.pop()\n        for letter, node in self.children.iteritems():\n            count = tiles.get(letter, 0)\n            if count == 0:\n                continue\n            tiles[letter] = count - 1\n            path.append(letter)\n            for word in node._anagram(tiles, path, root, min_length):\n                yield word\n            path.pop()\n            tiles[letter] = count\n\ndef load_dictionary(path):\n    result = Node()\n    for line in open(path, \'r\'):\n        word = line.strip().lower()\n        result.add(word)\n    return result\n\ndef main():\n    print \'Loading word list.\'\n    words = load_dictionary(\'words.txt\')\n    while True:\n        letters = raw_input(\'Enter letters: \')\n        letters = letters.lower()\n        letters = letters.replace(\' \', \'\')\n        if not letters:\n            break\n        count = 0\n        for word in words.anagram(letters):\n            print word\n            count += 1\n        print \'%d results.\' % count\n\nif __name__ == \'__main__\':\n    main()\n</code></pre>\n\n<p>When you run the program, the words are loaded into a trie in memory.  After that, just type in the letters you want to search with and it will print the results.  It will only show results that use all of the input letters, nothing shorter.</p>\n\n<p>It filters short words from the output, otherwise the number of results is huge.  Feel free to tweak the <code>MIN_WORD_SIZE</code> setting.  Keep in mind, just using "astronomers" as input gives 233,549 results if <code>MIN_WORD_SIZE</code> is 1.  Perhaps you can find a shorter word list that only contains more common English words.</p>\n\n<p>Also, the contraction "I\'m" (from one of your examples) won\'t show up in the results unless you add "im" to the dictionary and set <code>MIN_WORD_SIZE</code> to 2.</p>\n\n<p>The trick to getting multiple words is to jump back to the root node in the trie whenever you encounter a complete word in the search.  Then you keep traversing the trie until all letters have been used.</p>\n'}, {'answer_id': 7724784, 'author': 'sanjiv', 'author_id': 989323, 'author_profile': 'https://Stackoverflow.com/users/989323', 'pm_score': 1, 'selected': False, 'text': '<p>If I take a dictionary as a Hash Map as every word is unique and the Key is a binary(or Hex) representation of the word. Then if I have a word I can easily find the meaning of it with O(1) complexity.</p>\n\n<p>Now, if we have to generate all the valid anagrams, we need to verify if the generated anagram is in the dictionary, if it is present in dictionary, its a valid one else we need to ignore that.</p>\n\n<p>I will assume that there can be a word of max 100 characters(or more but there is a limit).</p>\n\n<p>So any word we take it as a sequence  of indexes like a word "hello" can be represented like \n"1234".\nNow the anagrams of "1234" are "1243", "1242" ..etc </p>\n\n<p>The only thing we need to do is to store all such combinations of indexes for a particular number of characters. This is an one time task.\nAnd  then words can be generated from the combinations by picking the characters from the index.Hence we get the anagrams. </p>\n\n<p>To verify if the anagrams are valid or not, just index into the dictionary and validate.</p>\n\n<p>The only thing need to be handled is the duplicates.That can be done easily. As an when we need to compare with the previous ones that has been searched in dictionary.</p>\n\n<p>The solution emphasizes on performance. </p>\n'}, {'answer_id': 14132957, 'author': 'Parth', 'author_id': 1944006, 'author_profile': 'https://Stackoverflow.com/users/1944006', 'pm_score': 2, 'selected': False, 'text': '<p>So <a href="https://github.com/parekhparth/AnagramSolver" rel="nofollow">here\'s</a> the working solution, in Java, that Jason Cohen suggested and it performs somewhat better than the one using trie. Below are some of the main points:</p>\n\n<ul>\n<li>Only load dictionary with the words that are subsets of given set of words</li>\n<li>Dictionary will be a hash of sorted words as key and set of actual words as values (as suggested by Jason)</li>\n<li>Iterate through each word from dictionary key and do a recursive forward lookup to see if any valid anagram is found for that key</li>\n<li>Only do forward lookup because, anagrams for all the words that have already been traversed, should have already been found</li>\n<li>Merge all the words associated to the keys for e.g. if \'enlist\' is the word for which anagrams are to be found and one of the set of keys to merge are [ins] and [elt], and the actual words for key [ins] is [sin] and [ins], and for key [elt] is [let], then the final set of merge words would be [sin, let] and [ins, let] which will be part of our final anagrams list</li>\n<li>Also to note that, this logic will only list unique set of words i.e. "eleven plus two" and "two plus eleven" would be same and only one of them would be listed in the output</li>\n</ul>\n\n<p>Below is the main recursive code which finds the set of anagram keys:</p>\n\n<pre><code>// recursive function to find all the anagrams for charInventory characters\n// starting with the word at dictionaryIndex in dictionary keyList\nprivate Set&lt;Set&lt;String&gt;&gt; findAnagrams(int dictionaryIndex, char[] charInventory, List&lt;String&gt; keyList) {\n    // terminating condition if no words are found\n    if (dictionaryIndex &gt;= keyList.size() || charInventory.length &lt; minWordSize) {\n        return null;\n    }\n\n    String searchWord = keyList.get(dictionaryIndex);\n    char[] searchWordChars = searchWord.toCharArray();\n    // this is where you find the anagrams for whole word\n    if (AnagramSolverHelper.isEquivalent(searchWordChars, charInventory)) {\n        Set&lt;Set&lt;String&gt;&gt; anagramsSet = new HashSet&lt;Set&lt;String&gt;&gt;();\n        Set&lt;String&gt; anagramSet = new HashSet&lt;String&gt;();\n        anagramSet.add(searchWord);\n        anagramsSet.add(anagramSet);\n\n        return anagramsSet;\n    }\n\n    // this is where you find the anagrams with multiple words\n    if (AnagramSolverHelper.isSubset(searchWordChars, charInventory)) {\n        // update charInventory by removing the characters of the search\n        // word as it is subset of characters for the anagram search word\n        char[] newCharInventory = AnagramSolverHelper.setDifference(charInventory, searchWordChars);\n        if (newCharInventory.length &gt;= minWordSize) {\n            Set&lt;Set&lt;String&gt;&gt; anagramsSet = new HashSet&lt;Set&lt;String&gt;&gt;();\n            for (int index = dictionaryIndex + 1; index &lt; keyList.size(); index++) {\n                Set&lt;Set&lt;String&gt;&gt; searchWordAnagramsKeysSet = findAnagrams(index, newCharInventory, keyList);\n                if (searchWordAnagramsKeysSet != null) {\n                    Set&lt;Set&lt;String&gt;&gt; mergedSets = mergeWordToSets(searchWord, searchWordAnagramsKeysSet);\n                    anagramsSet.addAll(mergedSets);\n                }\n            }\n            return anagramsSet.isEmpty() ? null : anagramsSet;\n        }\n    }\n\n    // no anagrams found for current word\n    return null;\n}\n</code></pre>\n\n<p>You can fork the repo from <a href="https://github.com/parekhparth/AnagramSolver" rel="nofollow">here</a> and play with it. There are many optimizations that I might have missed. But the code works and does find all the anagrams.</p>\n'}, {'answer_id': 41226791, 'author': 'ACV', 'author_id': 912829, 'author_profile': 'https://Stackoverflow.com/users/912829', 'pm_score': 2, 'selected': False, 'text': '<p>And <a href="http://dev.vvirlan.com/new-algorithm-anagram/" rel="nofollow noreferrer">here</a> is my novel solution.</p>\n\n<p>Jon Bentley’s book Programming Pearls contains a problem about finding anagrams of words.\nThe statement:</p>\n\n<blockquote>\n  <p>Given a dictionary of english words, find all sets of anagrams. For\n  instance, “pots”, “stop” and “tops” are all anagrams of one another\n  because each can be formed by permuting the letters of the others.</p>\n</blockquote>\n\n<p>I thought a bit and it came to me that the solution would be to obtain the signature of the word you’re searching and comparing it with all the words in the dictionary. All anagrams of a word should have the same signature. But how to achieve this? My idea was to use the Fundamental Theorem of Arithmetic:</p>\n\n<p>The fundamental theorem of arithmetic states that</p>\n\n<blockquote>\n  <p>every positive integer (except the number 1) can be represented in\n  exactly one way apart from rearrangement as a product of one or more\n  primes</p>\n</blockquote>\n\n<p>So the idea is to use an array of the first 26 prime numbers. Then for each letter in the word we get the corresponding prime number A = 2, B = 3, C = 5, D = 7 … and then we calculate the product of our input word. Next we do this for each word in the dictionary and if a word matches our input word, then we add it to the resulting list.</p>\n\n<p>The performance is more or less acceptable. For a dictionary of 479828 words, it takes 160 ms to get all anagrams. This is roughly 0.0003 ms / word, or 0.3 microsecond / word. Algorithm’s complexity seems to be O(mn) or ~O(m) where m is the size of the dictionary and n is the length of the input word.</p>\n\n<p>Here’s the code:</p>\n\n<pre><code>package com.vvirlan;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileReader;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Scanner;\n\npublic class Words {\n    private int[] PRIMES = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73,\n            79, 83, 89, 97, 101, 103, 107, 109, 113 };\n\n    public static void main(String[] args) {\n        Scanner s = new Scanner(System.in);\n        String word = "hello";\n        System.out.println("Please type a word:");\n        if (s.hasNext()) {\n            word = s.next();\n        }\n        Words w = new Words();\n        w.start(word);\n    }\n\n    private void start(String word) {\n        measureTime();\n        char[] letters = word.toUpperCase().toCharArray();\n        long searchProduct = calculateProduct(letters);\n        System.out.println(searchProduct);\n        try {\n            findByProduct(searchProduct);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        measureTime();\n        System.out.println(matchingWords);\n        System.out.println("Total time: " + time);\n    }\n\n    private List&lt;String&gt; matchingWords = new ArrayList&lt;&gt;();\n\n    private void findByProduct(long searchProduct) throws IOException {\n        File f = new File("/usr/share/dict/words");\n        FileReader fr = new FileReader(f);\n        BufferedReader br = new BufferedReader(fr);\n        String line = null;\n        while ((line = br.readLine()) != null) {\n            char[] letters = line.toUpperCase().toCharArray();\n            long p = calculateProduct(letters);\n            if (p == -1) {\n                continue;\n            }\n            if (p == searchProduct) {\n                matchingWords.add(line);\n            }\n        }\n        br.close();\n    }\n\n    private long calculateProduct(char[] letters) {\n        long result = 1L;\n        for (char c : letters) {\n            if (c &lt; 65) {\n                return -1;\n            }\n            int pos = c - 65;\n            result *= PRIMES[pos];\n        }\n        return result;\n    }\n\n    private long time = 0L;\n\n    private void measureTime() {\n        long t = new Date().getTime();\n        if (time == 0L) {\n            time = t;\n        } else {\n            time = t - time;\n        }\n    }\n}\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/55210', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/123/']