============================ Nanagram the Anagram Maker ============================ ----------------------------------- Your Word Jumbling Desktop Friend ----------------------------------- .. raw:: html
:Author: `Michael Foord `_ :Version: Nanagram 1.4.0 :Date: 2006/02/28 :Homepage: `Nanagram Homepage `_ :License: `Voidspace License `_ :Mailing List: `Voidspace Shareware Mailing List `_ .. image:: images/nanagram1.jpg :width: 248 :height: 396 :alt: The Nanagram GUI :align: center :class: image .. note:: **Nanagram 1.4** includes lots of changes and improvements on the previous versions. It's now faster, with several new features. .. contents:: Nanagram the Word Jumbler Introduction ============ An anagram is *A word or phrase formed by reordering the letters of another* *word or phrase*. For example, did you know that : * **George W Bush** is an anagram of 'whose bugger' [#]_... * **Tony Blair** : 'bony trail'... * **Ronald Reagan** : 'adrenal groan' or 'loan aranged'... * **Osama Bin Laden** : 'bald nose mania' or 'bad neon salami'... * **Mother Theresa** : 'hot rare themes' or 'earth theorems'... * **Michael Foord** : 'cool firm head'... remember, the anagram never lies {sm;:-)} Nanagram is a program for making anagrams. Astound and annoy your friends by discovering what silly anagrams can be made from their names. There is also an `online version `_ to play with [#]_. Nanagram is *shareware*. There is a free demo version with a small dictionary and a restricted set of features. You can obtain the full version by visiting the `Voidspace Shop `_. Versions ======== You can try **Nanagram** in several different ways. All of these, as well as various other fun and interesting programs, can be found at `Voidspace Shareware `_. Demo Version ------------ There is a freeware demo version of Nanagram available for download from the `Voidspace Shop`_. Feel free to try it, and give it to all your friends. {sm;:wink:} This is a slightly restricted version, with the following limitations : * It displays a nag screen on opening and closing. * It is restricted to a much smaller dictionary. * You can't load new dictionaries. * You can't use the advanced options. Other than that it is fully working, and still worth playing with. .. raw:: html
There is also a `Windows Executable Demo `_ that doesn't need to be installed. The Full Version ---------------- You can download the full version for the very low price of only £4.99. Don't forget to join the `Voidspace Shareware Mailing List`_, so that you hear as soon as new versions come out. .. raw:: html
There is also a `Windows Executable `_ that doesn't need to be installed. The Online Version ------------------ There is a free `Online Version`_. It doesn't have all the features of the *desktop gooey* version, but is still a silly way to while away a few moments. The Source Code --------------- If you want to look at the Python_ source code, or use **Nanagram** on a non-windows platform, you can get the source to Version 1.3. * `Nanagram 1.3 Source Distribution `_ This is released under the `Voidspace Shareware License `_. You will need Python and ``Tkinter`` installed to run it. Using Nanagram ============== Using Nanagram is very easy. Type the words you want an anagram of and hit ``enter`` ! (or *'Go Nanagram'*.) You can include spaces, apostrophes or dashes etc, but they won't appear in the results. .. image:: images/anagrams.jpg :width: 317 :height: 459 :alt: The Nanagram GUI :align: center :class: image Once you've produced a list of anagrams you can save it to a text file, for posterity and the greater benefit of mankind. {sm;:roll:} The Basic Options ----------------- **Nanagram** has a few simple options to control it's behaviour. These are all the options on the main GUI. Some of these are useful for *reducing* the number of anagrams that Nanagram finds. When it finds hundreds, it can be difficult to pick out the really funny ones {sm;:grin:}. Nanagram will automatically show you anagrams using less words first (because these tend to be the best); but see the `Hints for Searching`_ section on how to use the **Advanced** options to further refine your search. About ~~~~~ The **About** button launches this documentation page. {sm;:-)} Quit ~~~~ Can you guess what this does ? {sm;:wink:} Anagram Must Contain ~~~~~~~~~~~~~~~~~~~~ This text entry box allows you to restrict the anagrams to ones containing a certain word or phrase. For example, you might only want to find anagrams of **Michael Foord** that contain the word **cool**. Disturbingly enough, the results include : | *Cool Firm Head* | *Cool if Harmed* I know which I prefer. Using this feature can be especially useful for finding long anagrams. It effectively reduces the number of letters that Nanagram has to search through, making it quicker. See `Hints for Searching`_ for how you can use this to speed up your searches for really long anagrams. Min Word Length ~~~~~~~~~~~~~~~ This radio button lets you choose the minimum length of words that will be included in your anagram. The higher the setting here, the less anagrams it will return, but the faster it will work. Output Whilst Thinking ~~~~~~~~~~~~~~~~~~~~~~ .. image:: images/output_window.jpg :width: 360 :height: 507 :alt: The Output Window :align: center :class: image It can be pretty boring waiting for Nanagram to finish its search. This option gets it to display the results *as it finds them*. Be warned though, this means it can take much longer to find all the possible anagrams. The output window has a **Stop** button on it, so you can halt Nanagram if it is taking too long. If you hit Stop, Nanagram will show you all the anagrams it has found so far. Progress Bar ~~~~~~~~~~~~ .. image:: images/progress_bar.jpg :width: 285 :height: 406 :alt: Anagrams in Progress. :align: center :class: image This option (on by default), shows you a progress bar while Nanagram is calculating the anagram. Having this on does slow down the process a *bit*, but nothing like so much as having Nanagram display the results as it finds them. The progress bar also has a **Stop** button on it, in case you want to stop Nanagram before it has found all possible combinations. Include Common Small Words ~~~~~~~~~~~~~~~~~~~~~~~~~~ To search for anagrams at a reasonable speed it is normal to search with **Min Word Length** set to four or five letters. Unfortunately, this means that you might miss some interesting anagrams that could be found if you included such common words as ``a`` or ``if``. The **Include Common Small Words** (on by default) allows you to include 176 common small words (all three letters or less) in all your searches. This does slow down the search, but not as much as choosing a lower value for **Min Word Length**. In the full version you can add to this list (only words of three letters or less), but you will need to delete ``common.dat`` (in the dictionaries directory) and restart Nanagram for this to take effect. Load New Dict ------------- Nanagram uses a dictionary of words to search from. By default Nanagram uses ``'dictionary.txt'`` which has (only) 57 000 words in it. You can increase the speed by using a smaller dictionary, or increase the number of anagrams found by using a bigger one - you can also add words to any of them if you want. Whenever you load a dictionary it saves it out in its own format - this makes it quicker to load and also means Nanagram will automatically use the new dictionary next time. To use a dictionary after adding new words, you need to either delete ``dictionary.dat`` or reload the dictionary using the **Load New Dict** button. .. note:: Nanagram works with dictionaries that include accented characters (anything from the ``latin-1`` character set). It actually maps them to their nearest {acro;ASCII} equivalent - so e-acute matches for e etc - but they appear correctly when displayed. This means you should be able to use nanagram with non-English dictionaries. The GUI ------- By the way, the name **'Nanagram - Gooey'** comes from the computer term {acro;GUI} which means *Graphical User Interface*. Unlike old fashioned computers where you had to type every command out {sm;:wink:}, modern computers have given us fancy window based interfaces - with a lovely acronym... the GUI. The Dictionaries ================ **Nanagram** comes with the following dictionary files. They are all located in the ``dictionaries`` directory. They are simple wordlists, with one word per line. .. note:: You will only be able to use new dictionaries if you have bought the full version. * ``dictionary.txt`` (The default dictionary). This contains 57047 words. * ``smalldict`` (The dictionary used by the free trial version and also the online one). This contains 17890 word. * ``largedict.txt``. This contains 117971 words. * ``french_dictionary.txt``. A dictionary of 22740 French words. * ``verysmalldict.txt``. A dictionary of the 3029 most common words. If you want to experiment with some alternative dictionaries you can download the following zip file. It contains 3 extra English dictionary files, two very large and one very small. {sm;:-)} * `Extra Dictionaries (1.3mb) `_ Hints For Searching =================== I've not set a maximum number of letters that Nanagram will let you enter. In practise I've found that any more than about 15 and Nanagram slows to a crawl (although it always returns the answers in the end... even if it takes a long time). Increasing the minimum number of letter setting helps, because it reduces the number of words that Nanagram has to check. Setting a 'containing' word has the same effect - it reduces the number of letters that Nanagram has to work with. If you select the checkbox saying *'output whilst thinking'* then Nanagram will open a temporary window and display anagrams as it finds them. This is less boring to watch but slows Nanagram down a lot. Using **Output Whilst Thinking**, or the **Progress Bar** also gives you the option of stopping the search if it's taking too long. Hunting for anagrams is a 'processor-intensive' task, so the window can be unresponsive. It will do what you tell it in the end. {sm;:-)} If you hit *'Go Nanagram'* and nothing appears to happen - except maybe everything else on your computer slows down - then Nanagram is desperately searching its database for matches. Sometimes it can take a minute or more to find matches. In fact I've waited ten minutes for some. 'Stephen Uncompromising' on my machine took 591 seconds even when set to 5 letters or more. Sometimes it can take so long that to all intents and purposes it's dead - and you have to close it down and start again. Here are a couple of hints to avoid that happening : * Always do your first search with minimum word length set to five. It's less frustrating to try again with less letters than it is to have to restart Nanagram. * If you wonder if a set of words is too much, try just entering part of it and see how long Nanagram takes. * Using ``Contains`` greatly speeds a search. So - do a *Partial* Search First. Sometimes you want to search for anagrams of someone's full name - ``Samuel Alexander Burling`` for example - but you know Nanagram ain't gonna cope. If you do a partial search *first* - e.g. ``Samuel Burling`` - you will get several results. These include : - *umbrella suing* - *numb guerrillas* - *musing rubella* We can now do a search against the full name, but ask for only anagrams containing the word ``'Guerrillas'``, or only anagrams containing the word ``'umbrellas'``. Because using the 'containing' section effectively reduces the number of letters that Nanagram has to match against - we can enter more words to start with. We now get results like : - *urban guerrillas mend axle* - *guerrillas axeman blunder* We could try a different search for anagrams containing rubella, or axeman to get a varied set of results - these in turn will throw up new words we can use as well. * To increase the variety of answers returned when searching with 4 or 5 letter minimum set - you can search for answers containing 'a' or 'an' or other smaller words. They wouldn't normally be returned when searching with the higher minimum size - but you sometimes find some interesting ones like this. For example, my friend ``'Daniel Lantsbery'`` has the anagram ``'a tyrannised bell'``. - if you just search with minimum letters set to 4 then you don't find it. If you try with 'containing' set to 'a', then it appears. * As a last resort, using one of the smaller dictionaries drastically improves search times. The Advanced Options -------------------- .. image:: images/advanced.jpg :width: 285 :height: 261 :alt: Advanced Options :align: center :class: image There is also an **Advanced button**, which brings up a couple more interesting ways to refine the way Nanagram does it's searches. Here you get a choice of limiting the number of words that Nanagram will allow and also the maximum number of *'combinations'* that it will find before quitting. The maximum number of words is useful, simply because the most interesting anagrams usually only have two or three words. This also helps to speed up the search - once it's reached the maximum number of words it can give up with that combination. Setting the maximum number of combinations that Nanagram will find before giving up is nearly the same as setting the maximum number of answers that it will find - but not quite ! If you look in the `How it Works`_ section you'll see that once it's found anagrams involving the word ``'rare'`` it's also found ones involving the word ``'rear'``, without doing any extra work ! This means if you set it to find 100 combinations - you might actually have 160 answers or so ! Again this can speed up the search - but it also means you might miss some of the most interesting anagrams. Even with this value set really low, it can still take Nanagram a long time to find answers if you give it a lot of letters. Even if their only are a few answers it might take a long time to find them.... Anyway - experiment with different combinations, the very worst thing that can happen is that you'll waste time when you're meant to be working. {sm;:lol:} .. raw:: html
How It Works ============ .. image:: images/nanagram3.jpg :width: 271 :height: 396 :alt: Getting Results :align: center :class: image Ok, so I admit it... I didn't think up the idea for Nanagram entirely by myself. A craze amongst a few of my friends for using internet based anagram finders inspired me. First off I wrote a short script that would find every possible combination of letters for a word. This was a nice exercise in remembering how recursion [#]_ works. Unfortunately, for every letter you add it increases the complexity of this algorithm by an order of magnitude, and it's long lists of jumbled letters aren't very useful anyway. You can have a look at this code (if you want) at `word-jumble.py `_. I knew that a dictionary based one, that checked for real words, was the only way forward. Simple Explanation ------------------ We go through the full word list and compare it against the words we're matching. If a word is longer than the ones we're matching, or it contains letters not in the one we're matching, we discard it. This drastically reduces the number of words we have to check. If we set the minimum size of the words we are looking for we can also discard any words that are shorter than this. Next we take each word, one by one. We remove it's letters from our words. We can then check the next word and see if it will fit what is left. If a word fits, we remove it's letters and start again with what is left... We finally either get to the position where there are no letters left - a match, we have an anagram - or none of the words fit and we have to throw away that combination. We do this in a loop to test against every word. Because once we have chopped some of the letters out we are effectively looking for any words that are an anagram (or partial anagram) of what is left - the function can just call itself. This is the recursion and means that the main loop is actually very short... only a few lines of code. The whole program including the GUI and my comments is only 21k - but when I bundle it as a windoze executable the python core and graphics libraries make the whole program 7 MB... ouch. {sm;:x} There's one more neat trick to reduce the number of words we have to search against. This trick comes from the coder forum above. A Neat Trick ------------ You'll notice that some words are actually anagrams of each other - like rare and rear for example. If we find an anagram that involves the word rare, then if we swap rare for rear it will still be an anagram. To make use of this the code forms a ``hash table`` of all words that are anagrams of each other. To do this we sort the letters of each word into alphabetical order (the 'hash'). For words that are anagrams of each other this will be the same. For both rare and rear the 'hash' will be 'aerr'. We store a table of which words match which hash, and just search against the hashes (which is obviously a smaller list). When we have found our matches we just convert these hashes back into all the possible combinations. This saves us up to a third of the words we need to search for. There's *another* neat trick as well. With what we've said so far, if there was an anagram found when we'd got to the word fish for example - say ``'fish home rag'`` was an anagram - then when it got to the word home, it would also find ``'home fish rag'``, in fact it would find ``'home rag fish'`` and so on as well. With Nanagram, every time the loop finishes with a word it knocks it off the list. Having completely searched for anagrams using that word it knows it never has to check for that word again. This makes each loop progressively quicker *and* removes duplicates [#]_. If you want to see the raw *algorithm* then check out `Nana.py `_. This is the bare bones of the code from before I added the GUI. It is only 6k and is what became `Nanagram-CGI `_. TODO ==== The next version of **Nanagram** will include several great changes. It may take a few months to do though, so don't hold your breath. {sm;:lol:} The proposed improvements include : * Add a crossword 'word solver', for finding words when you know the length and a few of the words. * A better dictionary choosing dialog. * Better support for foreign languages. * Improve the save format. * Add a spellchecker. This could include a personal word list that is shared with the anagram dictionary. * A GUI option to add words to the dictionary. * Disable "include common short words" button, when minimum length is one. * Make output "whilst thinking" and "progress bar" mutually a radio bar along with a third ("neither") option. * Add an 'exclude words' option. * Save a config file with the last used settings. * If ``dictionary.txt`` isn't found raise an error dialog (plus a dialog to choose one). * Progress bar should be logarithmic, not linear. If you have any more feature requests or suggestions, feel free to make them on the `Mailing List `_. CHANGELOG ========= 28th Feb 2006 Version 1.4.0 -------------------------------- Lots of changes : * Improved the GUI. * Sped up the anagram finding by around 20%. * Now built with Python 2.4 and psyco 1.5 for even more speed. * Added the progress bar. * Added the option to include common short words. * Optimised sorting the results. * We can now find anagrams where a word fits more than once into the original phrase. Plus various other minor changes and improvements. 23rd Feb 2004 Version 1.3.1 -------------------------------- Added support for non-English dictionaries (accented characters allowed now). Also added the French dictionary to the dictionaries available for download. 21st Feb 2004 Version 1.3.0 -------------------------------- Added *another* feature.... There is now a checkbox asking if you want it to output the results as it finds them. This slows down the search for anagrams, but is less boring. It also allows you to stop the search whilst it's in progress. 17th Feb 2004 Version 1.2.0 -------------------------------- Added sorting to the results, so that anagrams using less words (and likely to be more interesting) are shown first. Added the advanced options to set the maximum number of answers it finds and the maximum number of words to accept in the answers. 06th Feb 2004 Version 1.1.0 -------------------------------- Added support for the psyco compiler. The executable is faster as a result. In the source code version it is only faster if psyco is installed. Added support for loading alternative dictionaries. It also saves out the loaded dictionary in an internal format - both to avoid having to save a config pointing to the dictionary and to speed up the loading time. ------------------ Footnotes ========= .. [#] And disturbingly enough, also *he grew bogus*. {sm;:-p} .. [#] You can also download the online version and include it on your own website (or just play around with the source code). See the `Nanagram-CGI homepage `_. .. [#] Recursion is a neat trick when programming. You create chunks of code that call themselves. Of course using this technique it's very easy write code that never ends {sm;:biggrin:}. .. [#] With the *slight* disadvantage that if a word is contained more than once in our phrase we won't discover this. The speed advantage makes it worth it though. Nanagram (not Nangram as it is often misspelt) is a great anagram creator, anagram finder, anagram generator, anagram creator and word jumbler. It is written by `Michael Foord`_, in the `Python `_ programming language. .. raw:: html