Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

A command line crossword solving assistant UNIX
I'd been looking for a simple way to leverage OS X's built-in Unix dictionary to solve crossword clues, and came up with this little gem of a script:
#!/bin/bash

echo -n "Please enter a word pattern to search for (use a . for unknowns): "
read text

echo `grep -w $text /usr/share/dict/words`
Just paste into your text editor of choice, save somewhere, make sure to chmod +x the file and boom, you have yourself a very simple crossword solver! Granted it isn't perfect, but it's a good start.

[robg adds: Just to clarify, the Unix dictionary isn't the same as the built-in dictionary you access through the Dictionary program. While the Unix words file does hold a large number of words, it doesn't have everything you'll find in Dictionary app.]
    •    
  • Currently 1.71 / 5
  You rated: 4 / 5 (7 votes cast)
 
[11,521 views]  

A command line crossword solving assistant | 20 comments | Create New Account
Click here to return to the 'A command line crossword solving assistant' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
uppercase and lowercase
Authored by: doctype on Feb 28, '08 09:53:15AM
As grep is case-sensitive, I'd suggest to add the -i option (ignore case distinctions):

echo `grep -w -i $text /usr/share/dict/words`

[ Reply to This | # ]
source of words file
Authored by: doctype on Feb 28, '08 09:57:56AM

FYI, the words file contains precisely 234,936 words from Webster's Second International dictionary from 1934 (copyright elapsed).
See README file at /usr/share/dict/README



[ Reply to This | # ]
That's what I did!
Authored by: LightYear on Feb 28, '08 01:39:43PM
That's essentially what I used to create XWordLookup the Dashboard Widget. My flags were -a (in case someone selected a binary file as their dictionary) and -i for case insensitivity. I could have used -w (match entire words), but just surround the search string with ^ and $ instead (match start and end of line).

It came about when on holiday with my family, my father had no Internet connection to help him out with a crossword. It occurred to me that a combination of grep and the UNIX dict file ought to help. About 1 minute of hacking produced a script very similar to the one in this tip. My father was so impressed (I wasn't, because it was just too simple compared to the complex shell scripting I had been doing!) that I made a Widget out of it. It has been quite popular. No one needs to know that's it is just one line at the command prompt ;-)

---
* Nothing is foolproof to a sufficiently talented fool *

[ Reply to This | # ]

A command line crossword solving assistant
Authored by: TGV on Feb 29, '08 12:53:51AM

To leverage? You don't need a cross-word solver, you need a thesaurus!



[ Reply to This | # ]
A command line crossword solving assistant
Authored by: kholburn on Mar 01, '08 02:05:25PM
I'm not sure what the echo and backticks are for. Why not simply use:

grep -w $text /usr/share/dict/words
If you really want the result in one line try something like:

grep -w $text /usr/share/dict/words | tr -d '\n'


[ Reply to This | # ]
Use Dictionary.app
Authored by: kholburn on Mar 02, '08 01:50:57PM
You can use the words from the built in Dictionary.

If you're from the UK, Australia, NZ or another English speaking country apart from the US you may be out of luck.


 perl -p -e 's/>/>\n/g' /Library/Dictionaries/New\ Oxford\ American\ Dictionary.dict/Contents/dict_body |grep -w $text|grep '<o:ent ' |cut -d'"' -f4



[ Reply to This | # ]
Use Dictionary.app
Authored by: kholburn on Mar 02, '08 02:28:50PM
a faster version:

perl -n -e 'while  (/<o:ent [^>"]+"[^>"]+"[^>"]+"([^>"]+)"/g) { $a=$1; if ($a =~ /\b'$text'\b/) { print $a,"\n";} }' /Library/Dictionaries/New\ Oxford\ American\ Dictionary.dict/Contents/dict_body


[ Reply to This | # ]
Perl version
Authored by: hamarkus on Mar 04, '08 10:17:35AM
While I think I understand the Perl code, it does not find anything (as opposed to the original version of the hint).
Though I cannot find the -n and -e flags in man perl, I assume the command simply calls Perl with the supplied file as the default input argument and executes the actual Perl code. I guess the while condition is some fancy regular expressions code that simply chops up the dictionary file into individual words, stores each word in $a and compares $a with $text and prints it if it finds a match.
However, I think somewhere the reading of library file does not work, as the following simplified code should just read the file 'Untitled.txt' and print its contents:
perl -n -e 'while(/"]+"[^>"]+"[^>"]+"([^>"]+)"/g) { print $1,"n"; }' ~/Desktop/Untitled.txt

[ Reply to This | # ]
Perl version
Authored by: kholburn on Mar 04, '08 01:38:51PM
I should mention that this works for 10.4. I haven't upgraded yet, just about backed up and ready to go. So the 10.5 dictionary may be in a different place and may be a different format.

The command switches are documented in "man perlrun".

-n makes perl read the input file in a while loop until the file is read completely.

-e indicates the next argument is a script.

The regex looks for a pattern like
<o:ent ..."...."..."..."...."> 
which indicates an entry in the dictionary. The actual entry word is between the last 2 double quotes which is caught by the brackets and referenced by the $1 in the while loop. The /g modifier at the end of the regex allows the while loop to loop through the file. The $a is needed to retain the "word" through another regex. The backslash-b's makes the regex the equivalent of -w.

Is that clear? Perl is a strange language.

[ Reply to This | # ]
Perl version
Authored by: hamarkus on Mar 04, '08 04:27:07PM

The dictionary indeed has a slightly different name in 10.5 but I corrected that already.
I had checked 'man perl' not 'man perlrun', thanks for pointing me to that.

Perl is still ok, regular expressions are what often throws me off.



[ Reply to This | # ]
Stupid question
Authored by: hamarkus on Mar 03, '08 10:28:12AM

I've created a file with the content presented above. Saved it as crosswords.sh on my Desktop and made it executable. Navigated in the Terminal to my Desktop, nothing happens. How am I supposed to use this?

./crosswords.sh
(nothing happens, no error message)

crosswords.sh or crosswords
(unknown command)

./crosswords.sh 'a..a'
(nothing happens)



[ Reply to This | # ]
Stupid question
Authored by: kholburn on Mar 03, '08 12:45:12PM

try using the extension "command" as in "crosswords.command".



[ Reply to This | # ]
Stupid question
Authored by: hamarkus on Mar 03, '08 12:50:30PM

Thanks, but this does not change the behaviour a bit.
./crosswords.command still results in nothing.



[ Reply to This | # ]
Stupid question
Authored by: kholburn on Mar 04, '08 12:43:34AM

Hmmm... that's odd. If you create a new file and paste the script into it? A .command file should open a Terminal.app window. That's what it does on my system. If you do "get info" you should see that it says open with Terminal.app

You can even use it to ask for keyboard input using a "read" command in bash.



[ Reply to This | # ]
I found the solution
Authored by: hamarkus on Mar 04, '08 09:47:15AM

As so often, it would have been best to trust one's first instincts. They were not to trust SubEthaEdit and use TextWrangler instead.

The problem was that copying the code out of Camino created text with CR as newline commands. When pasting this into SubEthaEdit, the program asks whether to keep the line endings or convert them. I naturally don't allow any apps to convert things without telling me exactly what it does. That means, I ended up with a file that had CR as newline commands but was happily showing LF at the bottom (which I naturally checked once things did not work and is my default for new files in SubEthaEdit).

Therefore, don't use SubEthaEdit because it allows you to do nonsense (mixed line endings in the same file) without any means to see which lines have which ending and without an obvious way to change the line endings (the only way to change line endings in file with mixed ones in SubEthaEdit is copy and paste all into a new file and ask it to convert the line endings).



[ Reply to This | # ]
Stupid question
Authored by: kholburn on Mar 03, '08 12:51:58PM
Or there's an application called Platypus that creates a .app out of a script. It 's here.

[ Reply to This | # ]
Stupid question
Authored by: hamarkus on Mar 03, '08 01:40:18PM

I've used Platypus successfully with Perl scripts. The problem is that Platypus won't provide me with an input method to supply my search query. Its only way of providing input to a script turned application is files dropped on the resulting application.
(Incidentally, Platypus complained about /bin/bash not being a valid interpreter, after adding a space after the '#!' it did no longer complain.)



[ Reply to This | # ]
Stupid question
Authored by: kholburn on Mar 04, '08 12:36:42AM

If you want input you probably need to go to applescript. Open a dialog and then use applescript to run the shell script.



[ Reply to This | # ]
A command line crossword solving assistant
Authored by: staiger on Mar 04, '08 02:14:46PM
The tip looks good if you want to verify a word you've already thought of. If you're looking to your computer for hints, given a few letters, you could try a regular expression:
cat /usr/share/dict/words | perl -e 'while(){ print if( /^a.m.e.s$/i ); }'
aimless
almners
armless
armlets
This script will only print lines that match the pattern 'a m e s', as in the word starts with an 'a', ends with an 's', and you have an 'm' and an 'e' in the middle. The other three leters, you don't know.
cat /usr/share/dict/words | perl -e 'while(){ print if( /^..ple$/i ); }'
ample
Apple
apple
diple
duple
maple
Niple
n-ple
saple
Siple
tiple
tuple


[ Reply to This | # ]
A command line crossword solving assistant
Authored by: staiger on Mar 04, '08 02:16:52PM

Oops.

That should be:

cat /usr/share/dict/words | perl -e 'while(<>){ print if( /^.pp.e$/i ); }'

The filter swallowed my '<>'.



[ Reply to This | # ]