Beat the Puzzle Master Home
Beat the Puzzle Master!
A web site dedicated to solving the NPR Sunday Puzzle

Puzzle September 21, 2008


Podcast of the original challenge

Scoring A Touchdown

Didn't get enough puzzle challenge Sunday? Try these
Challenge: You are given two clues. The first answer is a word that starts with the sound T. Change this to a D, and phonetically you'll get a new word that answers the second clue. For example, if the clue is "to work hard" and "author Conan _______," the answer would be "toil" and "Doyle."

Clue:  
Word 1: Word 2:

 

From Eric Berlin of Milford, Conn.:

Take a common, two-word phrase with four letters in each word. Each word has a single O as its vowel. If you add an R somewhere in the second word, the two words become opposites. What is the phrase?

How To Solve it Yourself In Code!

Word

This was an interesting one because I got to use the programming capability of Microsoft Word to identify antonyms. You might be familiar with the MS office built-in programming language, VBA (Visual Basic for Applications). But fewer people know that you can utilize it's code abilities from programs you write. Yes, you can link to the MS Office dlls by adding a reference in your project. The same code engine that let's you write macros in Word, Excel and Access is then available to you for programming purposes. Since I don't have any other way of getting antonyms, programming with Word was a welcome option, and necessary to solve this puzzle.

Steps to Solve

There are three main steps in solving this one:
  1. Examine a good word list and build a list and a dictionary:
    • The list will contain of 5-letter words having both 'o' and 'r', and
    • We will store 4-letter words containing  'o' in our dictionary
  2. Now examine each 5-letter word in our list; if any of them can be used to construct a 4-letter word in our dictionary (by removing an 'r'), then
  3. Retrieve the antonym (using Word) of your 5-letter word and see if any of them match the corresponding 4-letter word.

A couple of notes: 1) You can get a good word list from Kevin's Word Lists 2) I used a dictionary for the 4-letter words because dictionaries function like a hash-table, i.e. when you check whether a potential word is in a dictionary, that operation is extremely fast.

The code to accomplish this is straightforward:
Dictionary<string, char> words4 = new Dictionary<string, char>();
List<string> words5 = new List<string>();
//Open a file to read from the word list (DIC_PATH):
using (FileStream fs = new FileStream(DIC_PATH, FileMode.Open, FileAccess.Read)) {
    using (StreamReader sr = new StreamReader(fs)) {
        while (sr.Peek() != -1) {
            string aLine = sr.ReadLine().ToLower();
            if (aLine.Length == 4) {
                if (aLine.Contains("o")) {
                    words4.Add(aLine, 'a');
                }
            } else if (aLine.Length == 5) {
                if (aLine.Contains("o") && aLine.Contains("r")) {
                    words5.Add(aLine);
                }
            }
        }
    }
}

Getting Antonym Lists with MS Word

To get antonyms via MS Word, you first need to add a reference to the Word library. Since I have an older version of Word, mine is a COM reference, not a .NET reference. Regardless of your version, you should look for available references something like 'Microsoft Word Object Library', as illustrated below:

Linking to Word

This code snippet shows how to make an instance of the word library, and also uses some special syntax to get a constant identifying the language we want to use:

Word.Application wrdApp;
wrdApp = new Word.Application();

//Get a constant we can use to specify we are working with US English:
object myLang = Word.WdLanguageID.wdEnglishUS;

Once we have an instance of the word object library, we can use it to find potential word pairs who are antonyms. Note the special syntax to get an Array object which is compatible with the MS Word object library - that was quite tricky to discover and I consider myself lucky to have stumbled upon it!

foreach (string aWord in words5) {
    int p = aWord.IndexOf('r');
    string noR = aWord.Remove(p, 1);
    if (words4.ContainsKey(noR)) {
        //We've discovered a word containing an 'o' and an 'r' that is still
        //a word after we remove 'r'. Now, look for the antonyms of this
        //word; if any have length 4 and contain an o: we have a solution!
        Word.SynonymInfo synList = wrdApp.get_SynonymInfo(aWord, ref myLang);
        Array antonyms = (Array)synList.AntonymList;
        foreach (string anAntonym in antonyms) {
            if (anAntonym.Length == 4 && (anAntonym.Contains("o") || 
                anAntonym.Contains("O"))) {
                //Score! Put the result in our listbox.
                lstResults.Items.Add(anAntonym + " " + noR);
            }
        }
    }
}

Click here to download my sample C# code. To run it, you will need a word list and a licensed version of MS Word. You will need to modify my code in two ways:

  1. To specify the path where your word list file is located
  2. To specify a reference to your version of Word, unless it happens to be the same as mine, Word 2003.

Take Home Challenge!

Open Office Logo

I've recently started using Open Office (a free competitor to MS Office) and I noticed that they have implemented some programming capability. See if you can modify my code and use Open Office instead of Word - if so, leave a comment describing your success!

Solve the Problem in Code!

Since my solution relies on MS word, I can't solve it for you in your browser. There is no way to link to a dll on your pc from JavaScript. Download my code if you want to see it solved in front of your eyes!






Reader Comments

Be the first to comment!

Add a Comment Show comment controls
Comment Details
Your Comment:

Name:
Password:
Your Name*:
Password*:
Confirm*:
Email*: (will not be published!)
  Your Gravatar image
Website?
About Me: