<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>stacyprowell.com &#187; puzzler</title>
	<atom:link href="http://stacyprowell.com/blog/tag/puzzler/feed/" rel="self" type="application/rss+xml" />
	<link>http://stacyprowell.com/blog</link>
	<description>Ugh, Stacy&#039;s talking again...</description>
	<lastBuildDate>Sat, 04 Feb 2012 06:01:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Car Talk and the Longest Word</title>
		<link>http://stacyprowell.com/blog/2009/06/14/car-talk-and-the-longest-word/</link>
		<comments>http://stacyprowell.com/blog/2009/06/14/car-talk-and-the-longest-word/#comments</comments>
		<pubDate>Sun, 14 Jun 2009 02:50:47 +0000</pubDate>
		<dc:creator>stacy</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[linkedin]]></category>
		<category><![CDATA[puzzler]]></category>

		<guid isPermaLink="false">http://stacyprowell.com/blog/?p=284</guid>
		<description><![CDATA[I recently heard about a Car Talk puzzler.  I don&#8217;t listen to Car Talk as much as I used to.  Anyway, you can read about the puzzler and the fellow who solved it here.  This is an excerpt. During Christmas week on the popular National Public Radio show Car Talk, the weekly puzzler required listeners [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_235" class="wp-caption alignright" style="width: 160px"><img class="size-full wp-image-235" title="programming" src="http://stacyprowell.com/blog/wp-content/uploads/2009/05/1ebeb1d2f212046a4e47fcd414dbad9b1-150x150.jpg" alt="Programming" width="150" height="150" /><p class="wp-caption-text">Programming</p></div>
<p>I recently heard about a <a href="http://www.cartalk.com/" target="_blank">Car Talk</a> puzzler.  I don&#8217;t listen to Car Talk as much as I used to.  Anyway, you can read about the puzzler and the fellow who solved it <a href="http://www.hmc.edu/newsandevents/thomasbarr.html" target="_blank">here</a>.  This is an excerpt.</p>
<blockquote><p>During Christmas week on the popular National Public Radio show Car Talk, the weekly puzzler required listeners to find the longest English word that remains a valid English word as you remove its letters one at a time, but without rearranging any of the letters. For example: sprite, spit, pit, it, I. There are many such words, but, as Barr discovered, only one with 11 letters.</p></blockquote>
<p>So, only one word with eleven letters: <em>complecting</em>.  Maybe.  I&#8217;m not convinced, but finding out is easy.<br />
<span id="more-284"></span></p>
<h2>Recursion</h2>
<p>Okay, so how would you know?  Well, suppose you had a list of valid words.  The statement of the problem suggests a simple recursive algorithm to find a solution.</p>
<ul>
<li>Put the words in a heap, ordered longest to shortest.</li>
<li>Iterate until the heap is empty.
<ul>
<li>Take the next word $w$ from the heap, and perform $\mbox{search}(w)$</li>
</ul>
</li>
</ul>
<p>The procedure $\mbox{search}(w)$ works as follows.  It returns true if it finds a solution.</p>
<ul>
<li>If $w$ is the empty string, then return true.</li>
<li>For each letter $l$ of $w$, do the following.
<ul>
<li>Drop $l$ from $w$, generating the candidate word $v$.</li>
<li>If $v$ is in the dictionary, then execute $r=\mbox{search}(v)$.
<ul>
<li>If $r$ is true, then write out $w$ and return true.</li>
</ul>
</li>
</ul>
</li>
<li>The word $w$ is a dead end; drop it from the dictionary and return false.</li>
</ul>
<p>Dropping the words from the dictionary, or otherwise marking them as dead ends in some other way is necessary to avoid re-searching them later.  The time complexity is roughly $O(n)$, where $n$ is the size of the dictionary to search.  If the average length of a word is $k$, then we can be more specific, and say the complexity is $O(kn)$, but $k$ is very small with respect to $n$, and does not vary much with the data size, so it can be safely ignored.</p>
<h2>Iteration</h2>
<p>The problem was explained to me in the reverse fashion.  Given a letter, generate words by adding a single letter at a time.  Every word must be in the dictionary.  Find the longest word you can generate from a single letter.  This suggests a different algorithm.</p>
<ul>
<li>Put the words in a heap, ordered shortest to longest.</li>
<li>Mark the empty string as reachable and set $long$ to the empty string.</li>
<li>Iterate through the heap, considering each word $w$.
<ul>
<li>For each position $i$ of $w$, do the following.
<ul>
<li>Drop the $i$th letter from $w$, generating the candidate word $v$.
<ul>
<li>If $v$ is marked as reachable, then mark $w$ as reachable by omitting $i$, and set $long=w$.</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>While $long$ is not the empty string, do the following.
<ul>
<li>Write $long$.</li>
<li>Omit the character $i$ by which $long$ was reached, and set $long$ equal to the new word.</li>
</ul>
</li>
</ul>
<p>We can improve this by checking against the length of the longest word reached.  If we ever have $|w|&gt;|longest|+1$, then we can stop the loop immediately, since we cannot reach any further words.  We can&#8217;t do that with the prior algorithm.</p>
<h2>So&#8230; What&#8217;s the Longest Word?</h2>
<p>The solution given was <em>complecting</em>, at 11 letters.  When I download the <a href="http://aspell.net/" target="_blank">aspell</a> dictionaries, and run the algorithm (the iterative one), I find the following derivation.</p>
<p>-&gt; a<br />
-&gt; ah<br />
-&gt; ach<br />
-&gt; bach<br />
-&gt; banch<br />
-&gt; banchi<br />
-&gt; branchi<br />
-&gt; branchia<br />
-&gt; branchiae<br />
-&gt; branchiate<br />
-&gt; abranchiate<br />
-&gt; abranchiates</p>
<p>Ooh.  12 letters.  But, it&#8217;s a plural.  Does that count?  Well, complecting is a participle, so it seems it should.  Time to send a note to Tom and Ray?</p>
<h2>So&#8230; Which Algorithm?</h2>
<p>Well, I coded up the iterative one in Java, since originally I was asked how I would code it in Java.  Again, the question suggesting the solution.  I suspect there are a lot of long words that are not reachable, so it seemed better to use the trick to terminate the search when the current word is longer than the longest found (so far) plus one.  Plus, it isn&#8217;t recursive, and I don&#8217;t have to modify the data structure by deleting an item from the heap.</p>
<h2>The Java</h2>
<p>So&#8230; here&#8217;s the Java source.  Enjoy!</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * Given some iterable object that provides strings, find the longest
 * string in the collection that can be reached from the empty string
 * by adding one character at a time such that every intermediate step
 * is also in the collection.
 *
&nbsp;
 * For example, if the collection is {@code {@literal {}a,
 * at, cat, chat, chart, cart, car{@literal }}},
 * then the longst word is {@code chart}, and it's derivation is:
 * {@code a =&amp;gt; at =&amp;gt; cat =&amp;gt; cart =&amp;gt; chart}.  If there are multiple
 * longest words, then only one is detected.
 *
&nbsp;
 * Note that if single letters are not in the collection, then no words
 * can be derived, and only the empty derivation is returned.
 *
 * @param strings    An iterable providing the strings.
 * @return    The derivation of the longest, from the shortest word to the
 *             longest.  If there is no longest word, then the empty
 *             derivation is returned.
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">List</span> search<span style="color: #009900;">&#40;</span>Iterable strings<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>strings <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">NullPointerException</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;The string iterator is null.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Read each string from the iterable.  The strings assumed to be</span>
    <span style="color: #666666; font-style: italic;">// single words, and the words are not assumed to occur in any</span>
    <span style="color: #666666; font-style: italic;">// particular order.  We put the words we read into a heap, ordered</span>
    <span style="color: #666666; font-style: italic;">// by length.  Our &quot;heap&quot; is a sorted map.</span>
    <span style="color: #666666; font-style: italic;">//</span>
    <span style="color: #666666; font-style: italic;">// Every entry in the map has an associated integer value, which</span>
    <span style="color: #666666; font-style: italic;">// tells us the position of the last inserted character.  This can</span>
    <span style="color: #666666; font-style: italic;">// be used to &quot;unwind&quot; the derivation of the word.  If there is not</span>
    <span style="color: #666666; font-style: italic;">// (yet) any way to reach the word, then the word is mapped to -1.</span>
    <span style="color: #003399;">TreeMap</span> heap <span style="color: #339933;">=</span>
        <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">TreeMap</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Comparator</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">int</span> compare<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> first, <span style="color: #003399;">String</span> second<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #666666; font-style: italic;">// Okay, we sort first by length, and then alphabetically.</span>
                <span style="color: #666666; font-style: italic;">// This is necessary because of the way TreeMap tests</span>
                <span style="color: #666666; font-style: italic;">// equality; it uses the comparator.  Thus we must only</span>
                <span style="color: #666666; font-style: italic;">// return zero if the two are actually equal.  So, we</span>
                <span style="color: #666666; font-style: italic;">// first order by length, and then for items of the same</span>
                <span style="color: #666666; font-style: italic;">// length, we order using the natural comparator for</span>
                <span style="color: #666666; font-style: italic;">// strings.</span>
                <span style="color: #000066; font-weight: bold;">int</span> order <span style="color: #339933;">=</span> first.<span style="color: #006633;">length</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> second.<span style="color: #006633;">length</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>order <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    order <span style="color: #339933;">=</span> first.<span style="color: #006633;">compareToIgnoreCase</span><span style="color: #009900;">&#40;</span>second<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #000000; font-weight: bold;">return</span> order<span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> str <span style="color: #339933;">:</span> strings<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        heap.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>str,<span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #666666; font-style: italic;">// Add all strings to the heap.</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Prime the pump by adding the empty string as &quot;reachable.&quot;</span>
    <span style="color: #003399;">String</span> longest <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">int</span> length <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    heap.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&quot;</span>, <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// At this point the heap is constructed.  We now iterate over the</span>
    <span style="color: #666666; font-style: italic;">// heap looking for connected words.  If we find one, we mark it.</span>
    <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> str <span style="color: #339933;">:</span> heap.<span style="color: #006633;">keySet</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Watch for a case where we skip a length.  If we do, we're done.</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>str.<span style="color: #006633;">length</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span> length<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        length <span style="color: #339933;">=</span> str.<span style="color: #006633;">length</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Now we have a string, we need to find out if the string is</span>
        <span style="color: #666666; font-style: italic;">// reachable from a previously-reached string.  We drop each</span>
        <span style="color: #666666; font-style: italic;">// character, and then check if the resulting string is</span>
        <span style="color: #666666; font-style: italic;">// present in the heap and is marked.</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> index <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> index <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> str.<span style="color: #006633;">length</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> index<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// Omit the character at position index.</span>
            <span style="color: #003399;">String</span> test <span style="color: #339933;">=</span> str.<span style="color: #006633;">substring</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span>,index<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> str.<span style="color: #006633;">substring</span><span style="color: #009900;">&#40;</span>index<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #666666; font-style: italic;">// See if the resulting test string is in the heap.</span>
            <span style="color: #003399;">Integer</span> pos <span style="color: #339933;">=</span> heap.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>test<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// Now there are three cases:</span>
            <span style="color: #666666; font-style: italic;">// (1) The test string is not in the heap.</span>
            <span style="color: #666666; font-style: italic;">// (2) The test string is in the heap, but not reachable.</span>
            <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>pos <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">||</span> pos <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000000; font-weight: bold;">continue</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
            <span style="color: #666666; font-style: italic;">// (3) The test string is in the heap, and is reachable.</span>
            <span style="color: #666666; font-style: italic;">// In this last case we know we can reach the current string</span>
            <span style="color: #666666; font-style: italic;">// from the test string by adding the character at position</span>
            <span style="color: #666666; font-style: italic;">// index, so put this in the heap.</span>
            heap.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>str, index<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #666666; font-style: italic;">// Note that whenever this happens, we might have just found</span>
            <span style="color: #666666; font-style: italic;">// (one of) the longest words, so save it.</span>
            longest <span style="color: #339933;">=</span> str<span style="color: #339933;">;</span>
            <span style="color: #666666; font-style: italic;">// We don't need to test any other positions.</span>
            <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #666666; font-style: italic;">// Construct new words by omitting each character.</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #666666; font-style: italic;">// Search the heap for words.</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Now we have (hopefully) found a long word.  We need to generate</span>
    <span style="color: #666666; font-style: italic;">// the derivation and return it.</span>
    <span style="color: #003399;">List</span> derivation <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">LinkedList</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>longest.<span style="color: #006633;">length</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Get the insertion position from the heap.</span>
        <span style="color: #000066; font-weight: bold;">int</span> pos <span style="color: #339933;">=</span> heap.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>longest<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">// Add the word to the derivation.</span>
        derivation.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span>, longest<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">// Generate the prior string in the derivation.</span>
        longest <span style="color: #339933;">=</span> longest.<span style="color: #006633;">substring</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span>, pos<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> longest.<span style="color: #006633;">substring</span><span style="color: #009900;">&#40;</span>pos<span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #666666; font-style: italic;">// Build the derivation.</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Done!  Return the derivation.</span>
    <span style="color: #000000; font-weight: bold;">return</span> derivation<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The code isn&#8217;t optimal, but it is commented.  I assume you are all capable of putting this in a class and feeding it a dictionary.  Have fun!</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fstacyprowell.com%2Fblog%2F2009%2F06%2F14%2Fcar-talk-and-the-longest-word%2F&amp;title=Car%20Talk%20and%20the%20Longest%20Word" id="wpa2a_2"><img src="http://stacyprowell.com/blog/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://stacyprowell.com/blog/2009/06/14/car-talk-and-the-longest-word/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

