<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Justin Kramer</title>
	<atom:link href="http://jkkramer.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://jkkramer.wordpress.com</link>
	<description></description>
	<lastBuildDate>Wed, 16 Nov 2011 21:23:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='jkkramer.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Justin Kramer</title>
		<link>http://jkkramer.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://jkkramer.wordpress.com/osd.xml" title="Justin Kramer" />
	<atom:link rel='hub' href='http://jkkramer.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Clojure &amp; Python, Side by Side</title>
		<link>http://jkkramer.wordpress.com/2011/03/29/clojure-python-side-by-side/</link>
		<comments>http://jkkramer.wordpress.com/2011/03/29/clojure-python-side-by-side/#comments</comments>
		<pubDate>Tue, 29 Mar 2011 14:04:03 +0000</pubDate>
		<dc:creator>Justin Kramer</dc:creator>
				<category><![CDATA[Clojure]]></category>
		<category><![CDATA[Coding]]></category>

		<guid isPermaLink="false">http://jkkramer.wordpress.com/?p=351</guid>
		<description><![CDATA[As an exercise, I translated Peter Norvig&#8217;s Sudoku solver from Python to Clojure. There have been a couple other attempts before, but they both leaned on Clojure&#8217;s reference types as a mutability-crutch. This implementation uses only immutable data structures. To &#8230; <a href="http://jkkramer.wordpress.com/2011/03/29/clojure-python-side-by-side/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jkkramer.wordpress.com&amp;blog=15411386&amp;post=351&amp;subd=jkkramer&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>As an exercise, I translated <a href="http://norvig.com/sudoku.html">Peter Norvig&#8217;s Sudoku solver</a> from Python to Clojure. There have been a couple other attempts before, but they both leaned on Clojure&#8217;s reference types as a mutability-crutch. This implementation uses only immutable data structures.</p>
<p>To facilitate side-by-side comparison, I tried to retain the algorithm and basic code structure of Dr. Norvig&#8217;s implementation: variables, functions, and sections are named the same, etc. Some of the functions could be broken up into smaller pieces, but they&#8217;re not sinfully long.</p>
<p><a href="http://tin.nu/sudoku.html" target="_blank">Click here to see the Clojure and Python versions side-by-side</a>.</p>
<p>What I didn&#8217;t do was focus on performance &#8211; beyond choosing what I thought were appropriate data structures up front. I wanted to bang it out using the tools that Clojure puts within close reach, and not worry about bleeding-edge speed.</p>
<h2>Similarities</h2>
<p>On the surface, the two versions are comparable in length and expressiveness. They both make extensive use of list comprehensions and their language&#8217;s particular idioms to help make things concise.</p>
<p>The algorithm remained intact for the most part. Dr. Norvig&#8217;s code didn&#8217;t rely too much on side effects so it wasn&#8217;t terribly difficult.</p>
<h2>Differences</h2>
<p>To avoid mutation, the Clojure version relies heavily on <code>reduce</code> to build a succession of game states. One challenge was that vanilla <code>reduce</code> wasn&#8217;t a perfect fit: the algorithms in <code>assign</code> and <code>eliminate</code> need to short circuit if a contradiction is encountered, which in turn allows the game-tree search to move on to better prospects. I resorted to creating <code>reduce-true</code>, which acts like regular <code>reduce</code> except that it stops feeding in values if any intermediate reductions produce a logically false value (which <code>eliminate</code> does when a contradiction is detected). Other alternatives crossed my mind (monads!?) but this seemed the most natural.</p>
<p>The <code>eliminate</code> and <code>random-puzzle</code> functions were the trickiest to translate. I&#8217;ve been practicing translating imperative algorithms into functional style a lot lately, and it&#8217;s getting easier. Thinking functionally forces you to become acutely aware of the values at play in your code &#8212; how and <em>when</em> one value gives rise to another, and what other values it depends on to do so.</p>
<p>The Clojure version didn&#8217;t have to worry about copying (see the <code>search</code> function), since everything is immutable. Immutability makes doing backtracking-style searches easy: no need to &#8220;undo&#8221; changes, since you never changed anything in the first place!</p>
<p>A bit to my surprise, the Python version is faster. This may be due to the choice of data structures: I chose to use vectors and sets to represent the Sudoku squares and digits, whereas the Python version uses strings, which are relatively lightweight. Changing it now would be too much work, but if anyone is curious enough to make the effort, speak up.</p>
<p>Just for kicks, I made a token attempt at parallelizing the algorithm by using <code>pmap</code> in <code>search</code>&#8216;s first run (spawning between 2 and 4 threads usually). That didn&#8217;t help, probably because it causes extraneous work to be done when the solution is usually within close range in the game tree.</p>
<p>There are surely faster methods and algorithms possible. Again, my main goal was to practice thinking functionally, and compare the expressiveness of the resulting code to Python&#8217;s clean style. I think the Clojure code compares favorably in this light.</p>
<h2>Stats</h2>
<p>Clojure version:</p>
<pre><code>Solved 50 of 50 easy puzzles (avg 0.01 secs (101 Hz), max 0.02 secs).
Solved 95 of 95 hard puzzles (avg 0.03 secs (33 Hz), max 0.16 secs).
Solved 11 of 11 hardest puzzles (avg 0.02 secs (64 Hz), max 0.04 secs).
Solved 99 of 99 random puzzles (avg 0.01 secs (97 Hz), max 0.02 secs).</code></pre>
<p>Python version:</p>
<pre><code>Solved 50 of 50 easy puzzles (avg 0.01 secs (126 Hz), max 0.01 secs).
Solved 95 of 95 hard puzzles (avg 0.03 secs (34 Hz), max 0.13 secs).
Solved 11 of 11 hardest puzzles (avg 0.01 secs (93 Hz), max 0.02 secs).
Solved 99 of 99 random puzzles (avg 0.01 secs (118 Hz), max 0.01 secs).</code></pre>
<p>(The unpredictable spikes mentioned by Dr. Norvig persist in the Clojure version. Every once and a while, <code>random-puzzle</code> generates a puzzle that takes a very long time to solve. I didn&#8217;t make any effort to correct the problem.)</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jkkramer.wordpress.com/351/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jkkramer.wordpress.com/351/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jkkramer.wordpress.com/351/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jkkramer.wordpress.com/351/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jkkramer.wordpress.com/351/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jkkramer.wordpress.com/351/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jkkramer.wordpress.com/351/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jkkramer.wordpress.com/351/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jkkramer.wordpress.com/351/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jkkramer.wordpress.com/351/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jkkramer.wordpress.com/351/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jkkramer.wordpress.com/351/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jkkramer.wordpress.com/351/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jkkramer.wordpress.com/351/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jkkramer.wordpress.com&amp;blog=15411386&amp;post=351&amp;subd=jkkramer&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jkkramer.wordpress.com/2011/03/29/clojure-python-side-by-side/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/693b9bfd287e55741c2a4af6f7de0d72?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jkkramer</media:title>
		</media:content>
	</item>
		<item>
		<title>Launched YumTab</title>
		<link>http://jkkramer.wordpress.com/2011/01/24/launched-yumtab/</link>
		<comments>http://jkkramer.wordpress.com/2011/01/24/launched-yumtab/#comments</comments>
		<pubDate>Mon, 24 Jan 2011 19:49:51 +0000</pubDate>
		<dc:creator>Justin Kramer</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://jkkramer.wordpress.com/?p=303</guid>
		<description><![CDATA[My side project, which uses Clojure and some basic machine learning to extract recipe information from websites, has launched: YumTab. I&#8217;ll be updating the blog periodically with progress reports and possibly some juicy technical info.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jkkramer.wordpress.com&amp;blog=15411386&amp;post=303&amp;subd=jkkramer&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>My side project, which uses Clojure and some basic machine learning to extract recipe information from websites, has launched: <a href="http://yumtab.com/">YumTab</a>.</p>
<p>I&#8217;ll be updating <a href="http://blog.yumtab.com/">the blog</a> periodically with progress reports and possibly some juicy technical info.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jkkramer.wordpress.com/303/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jkkramer.wordpress.com/303/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jkkramer.wordpress.com/303/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jkkramer.wordpress.com/303/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jkkramer.wordpress.com/303/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jkkramer.wordpress.com/303/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jkkramer.wordpress.com/303/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jkkramer.wordpress.com/303/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jkkramer.wordpress.com/303/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jkkramer.wordpress.com/303/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jkkramer.wordpress.com/303/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jkkramer.wordpress.com/303/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jkkramer.wordpress.com/303/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jkkramer.wordpress.com/303/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jkkramer.wordpress.com&amp;blog=15411386&amp;post=303&amp;subd=jkkramer&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jkkramer.wordpress.com/2011/01/24/launched-yumtab/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/693b9bfd287e55741c2a4af6f7de0d72?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jkkramer</media:title>
		</media:content>
	</item>
		<item>
		<title>Say something nice about every programming language you&#8217;ve used</title>
		<link>http://jkkramer.wordpress.com/2010/12/09/say-something-nice-about-every-programming-language-youve-used/</link>
		<comments>http://jkkramer.wordpress.com/2010/12/09/say-something-nice-about-every-programming-language-youve-used/#comments</comments>
		<pubDate>Thu, 09 Dec 2010 17:05:35 +0000</pubDate>
		<dc:creator>Justin Kramer</dc:creator>
				<category><![CDATA[Clojure]]></category>
		<category><![CDATA[Coding]]></category>

		<guid isPermaLink="false">http://jkkramer.wordpress.com/?p=278</guid>
		<description><![CDATA[Prompted by this blog post, an attempt to say something nice about every language I&#8217;ve used, roughly in the order that I learned them: Pascal &#8211; My first love. Allowed me to create awesome text adventures, even though the code &#8230; <a href="http://jkkramer.wordpress.com/2010/12/09/say-something-nice-about-every-programming-language-youve-used/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jkkramer.wordpress.com&amp;blog=15411386&amp;post=278&amp;subd=jkkramer&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Prompted by <a href="http://blog.darevay.com/2010/12/say-something-nice-about-every-language-youve-used/">this blog post</a>, an attempt to say something nice about every language I&#8217;ve used, roughly in the order that I learned them:</p>
<ul>
<li><b>Pascal</b> &#8211; My first love. Allowed me to create awesome text adventures, even though the code consisted entirely of spaghetti.</li>
<li><b>C</b> &#8211; Gave me an appreciation for bit twiddling and memory poking, and opened the door to the demoscene and games with <i>real</i> graphics &#8212; like, with <i>256 colors</i>.</li>
<li><b>C++</b> &#8211; A summer fling that I appreciated but never fully knew. Using <code>&lt;&lt;</code> and <code>&gt;&gt;</code> for IO was neat.</li>
<li><b>x86 Assembly</b> &#8211; Let me put pixels on the screen <i>really fast</i>, and made me feel smarter than a computer. INT 21h!
<li><b>Perl</b> &#8211; Gave me the power to bend any piece of text to my will in 3 lines or less.</li>
<li><b>PHP</b> &#8211; Made web development easy and fun (security be damned). People actually wanted to <i>pay</i> me to do it, how cool is that?</li>
<li><b>Java</b> &#8211; Abstraction is great! Objects are kind of neat.</li>
<li><b>JavaScript</b> &#8211; Light-weight objects! First-class functions! Closures! Asynchronous processing! Prototypal inheritence! JavaScript gave me many lightbulb moments, thanks largely to <a href="http://javascript.crockford.com/javascript.html">Douglas Crockford</a>.</li>
<li><b>Python</b> &#8211; Providing <a href="http://www.python.org/dev/peps/pep-0020/">one way to do it</a> has benefits. List comprehensions are powerful.</li>
<li><b>Ruby</b> &#8211; Code can make you chuckle. Rails corollary: CRUD apps don&#8217;t have to be tedious.</li>
<li><b>Clojure</b> &#8211; So many insights:
<ul>
<li>Choosing the right abstractions makes all the difference.</li>
<li><a href="http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey">Identity, value, and state</a> should not be conflated.</li>
<li><a href="http://www.paulgraham.com/reesoo.html">OO</a> is best served à la carte.</li>
<li>REPLs aid exploration and provide the groundwork for good tests.</li>
<li>When solving nontrivial problems, thinking should dominate typing.</li>
<li>Favor libraries over frameworks.</li>
<li><a href="http://www.slideshare.net/cgrand/dsl-5537797">Macros are the icing, not the cake.</a></li>
<li>Functional programmers are well-balanced, friendly people.</li>
<li><em>Functional programming is really fun!</em>
</ul>
</ul>
<p>Haskell gets an honorable mention for being so beautiful, but most of my time with it has been spent reading, not writing. There are other languages I&#8217;ve dabbled in but they didn&#8217;t provide any particular insights.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jkkramer.wordpress.com/278/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jkkramer.wordpress.com/278/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jkkramer.wordpress.com/278/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jkkramer.wordpress.com/278/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jkkramer.wordpress.com/278/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jkkramer.wordpress.com/278/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jkkramer.wordpress.com/278/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jkkramer.wordpress.com/278/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jkkramer.wordpress.com/278/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jkkramer.wordpress.com/278/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jkkramer.wordpress.com/278/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jkkramer.wordpress.com/278/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jkkramer.wordpress.com/278/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jkkramer.wordpress.com/278/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jkkramer.wordpress.com&amp;blog=15411386&amp;post=278&amp;subd=jkkramer&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jkkramer.wordpress.com/2010/12/09/say-something-nice-about-every-programming-language-youve-used/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/693b9bfd287e55741c2a4af6f7de0d72?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jkkramer</media:title>
		</media:content>
	</item>
		<item>
		<title>Fun with Clojure: Turning Cats into Dogs in Hanoi</title>
		<link>http://jkkramer.wordpress.com/2010/08/27/fun-with-clojure%c2%a0turning-cats-into-dogs-in-hanoi/</link>
		<comments>http://jkkramer.wordpress.com/2010/08/27/fun-with-clojure%c2%a0turning-cats-into-dogs-in-hanoi/#comments</comments>
		<pubDate>Fri, 27 Aug 2010 21:32:03 +0000</pubDate>
		<dc:creator>Justin Kramer</dc:creator>
				<category><![CDATA[Clojure]]></category>

		<guid isPermaLink="false">http://jkkramer.wordpress.com/?p=3</guid>
		<description><![CDATA[Finding a Connection I&#8217;ve been having fun brushing up on basic graph theory lately. It&#8217;s amazing how many problems can be modeled with it. To that end, I did a code kata the other day that lent itself to a &#8230; <a href="http://jkkramer.wordpress.com/2010/08/27/fun-with-clojure%c2%a0turning-cats-into-dogs-in-hanoi/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jkkramer.wordpress.com&amp;blog=15411386&amp;post=3&amp;subd=jkkramer&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://jkkramer.files.wordpress.com/2010/09/cat-cot-dot-dog.png"><img class="aligncenter size-full wp-image-73" title="cat-cot-dot-dog" src="http://jkkramer.files.wordpress.com/2010/09/cat-cot-dot-dog.png?w=640&#038;h=303" alt="" width="640" height="303" /></a></p>
<h3>Finding a Connection</h3>
<p>I&#8217;ve been having fun brushing up on basic graph theory lately. It&#8217;s amazing how many problems can be modeled  with it. To that end, I did a <a href="http://codekata.pragprog.com/2007/01/kata_nineteen_w.html">code kata</a> the other day that lent itself to a graph-based solution:</p>
<blockquote><p>. . . the challenge is to build a chain of words, starting with one particular word and ending with another. Successive entries in the chain must all be real words, and each can differ from the previous word by just one letter.</p></blockquote>
<p>One way to approach this is to think of all valid words as nodes in a graph, where words that differ from each other by one letter are connected. To find a path between one word, say &#8220;cat&#8221;, and another, &#8220;dog&#8221;, traverse the graph <a href="http://en.wikipedia.org/wiki/Breadth-first_search">breadth-first</a> starting at the &#8220;cat&#8221; node until you find the &#8220;dog&#8221; node.</p>
<p>Implementing this in Clojure is a cinch. First let&#8217;s create a dictionary of the words we&#8217;ll use:</p>
<p><pre class="brush: clojure;">
(def dictionary
  (-&gt;&gt; (slurp &quot;/usr/share/dict/words&quot;)
       split-lines
       (map lower-case)
       (into #{})))
</pre></p>
<p>This takes in words from a file (OS X&#8217;s built-in dict here) and sticks them in a set. Having the words in a set gives us a fast and easy way to check whether a word is valid:</p>
<p><pre class="brush: clojure;">
(filter dictionary [&quot;cuspidor&quot; &quot;cromulent&quot; &quot;xebec&quot;])
=&gt; (&quot;cuspidor&quot; &quot;xebec&quot;)
</pre></p>
<p>Next we need a function to give us a word&#8217;s neighbors:</p>
<p><pre class="brush: clojure;">
(def alphabet &quot;abcdefghijklmnopqrstuvwxyz&quot;)

(defn edits [^String word]
  &quot;Returns words that differ from word by one letter. E.g.,
  cat =&gt; fat, cut, can, etc.&quot;
  (-&gt;&gt; word
       (map-indexed (fn [i c]
                      (let [sb (StringBuilder. word)]
                        (for [altc alphabet :when (not= altc c)]
                          (str (doto sb (.setCharAt i altc)))))))
       (apply concat)
       (filter dictionary)))
</pre></p>
<p>For every letter in a word, replace it with every other letter in the alphabet; collect all these variations together and then keep only the legit ones.</p>
<p>Lastly, we need a function to actually perform the search:</p>
<p><pre class="brush: clojure;">
(defn find-path [neighbors start end]
  &quot;Return a path from start to end with the fewest hops (i.e. irrespective
  of edge weights), neighbors being a function that returns adjacent nodes&quot;
  (loop [queue (conj clojure.lang.PersistentQueue/EMPTY start)
         preds {start nil}]
    (when-let [node (peek queue)]
      (let [nbrs (remove #(contains? preds %) (neighbors node))]
        (if (some #{end} nbrs)
          (reverse (cons end (take-while identity (iterate preds node))))
          (recur (into (pop queue) nbrs)
                 (reduce #(assoc %1 %2 node) preds nbrs)))))))
</pre></p>
<p>This is a fairly straight translation of the imperative algorithm.<sup><big><a href="#footnote1">1</a></big></sup> We use a <code>PersistentQueue</code> to keep track of nodes to visit next. The <code>preds</code> map does double-duty: it keeps track of nodes already seen, and allows us to trace our path back to the beginning once we reach our destination.</p>
<p>Now we&#8217;re ready to actually run the search:</p>
<p><pre class="brush: clojure;">
(find-path edits &quot;cat&quot; &quot;dog&quot;)
=&gt; (&quot;cat&quot; &quot;cot&quot; &quot;dot&quot; &quot;dog&quot;)
(find-path edits &quot;four&quot; &quot;five&quot;)
=&gt; (&quot;four&quot; &quot;foud&quot; &quot;fold&quot; &quot;fole&quot; &quot;file&quot; &quot;five&quot;)
(find-path edits &quot;bleak&quot; &quot;bloke&quot;)
=&gt; (&quot;bleak&quot; &quot;bleat&quot; &quot;blest&quot; &quot;blast&quot; &quot;blase&quot; &quot;blake&quot; &quot;bloke&quot;)
</pre></p>
<p>Nice. The longest of these runs in just over 100ms on my machine &#8212; not too shabby (though we can certainly do better). There are about 200k nodes and 100k edges in the word-chain graph.</p>
<h3>Seeing it Through</h3>
<p>I&#8217;m a visually-oriented person. Getting a correct result is well and good, but I want to <em>see the process</em>. To do that,  I <a href="http://en.wiktionary.org/wiki/yak_shaving">shaved an enormous yak</a> and wrote a <a href="http://github.com/jkk/loom">graph library for Clojure</a>.</p>
<p>This new library helped me create pretty diagrams like the one at the top of this article. It outsources most of the hard work to the awesome <a href="http://graphviz.org/">GraphViz</a> and the also-awesome <a href="http://ubietylab.net/ubigraph/">Ubigraph</a> tool, which lets you visualize graph structures and algorithms in realtime. Like this:</p>
<div class='embed-vimeo' style='text-align:center;'><iframe src='http://player.vimeo.com/video/15117084' width='600' height='450' frameborder='0'></iframe></div>
<h3>Expanding our Horizons</h3>
<p>Another place graph traversal comes in handy is finding solutions to certain types of games, like Towers of Hanoi. Think of each possible position in the game as a node. Nodes connect to each other via valid moves.</p>
<p>So to solve a game, instead of an <code>edits</code> function, we need a <code>moves</code> function that takes a game state and returns valid neighboring states. Let&#8217;s solve Towers of Hanoi:</p>
<p><a href="http://jkkramer.files.wordpress.com/2010/08/hanoi-3-3.png"><img class="aligncenter size-medium wp-image-57" title="hanoi-3-3" src="http://jkkramer.files.wordpress.com/2010/08/hanoi-3-3.png?w=450" alt="Towers of Hanoi, 3 disks 3 pegs" width="450" /></a></p>
<p>As our game state, we&#8217;ll use vector with an entry for each peg. Each peg will contain a sorted set of disks, in order of smallest to biggest. The game state where all disks are on the leftmost peg would look like this (assuming three disks and three pegs):</p>
<p><pre class="brush: clojure;">
[#{0 1 2} #{} #{}]
</pre></p>
<p>Here&#8217;s the <code>moves</code> function:</p>
<p><pre class="brush: clojure;">
(defn moves
  [state]
  (for [[from-peg disk] (map-indexed #(vector %1 (first %2)) state)
        to-peg (range (count state))
        :when (and disk
                   (not= from-peg to-peg)
                   (or (empty? (state to-peg))
                       (&lt; disk (first (state to-peg)))))]
    (-&gt; state
        (update-in [from-peg] disj disk)
        (update-in [to-peg] conj disk))))
</pre></p>
<p>For each topmost disk, see if we can move it to another peg. To do that, the other peg has to have a bigger top disk, or no disks at all.</p>
<p>Run the same <code>find-path</code> function on our new inputs&#8230;</p>
<p><pre class="brush: clojure;">
(let [start [(sorted-set 1 2 3) (sorted-set) (sorted-set)]
      end [(sorted-set) (sorted-set) (sorted-set 1 2 3)]]
  (find-path moves start end))
=&gt; ([#{1 2 3} #{} #{}] [#{2 3} #{} #{1}] [#{3} #{2} #{1}] [#{3} #{1 2} #{}] [#{} #{1 2} #{3}] [#{1} #{2} #{3}] [#{1} #{} #{2 3}] [#{} #{} #{1 2 3}])
</pre></p>
<p>And voilà. We have&#8230;something not so pretty. <a href="http://github.com/jkk/loom">Loom</a>, <a href="http://graphviz.org/">GraphViz</a>, and <a href="http://ubietylab.net/ubigraph/">Ubigraph</a> to the rescue:</p>
<div class='embed-vimeo' style='text-align:center;'><iframe src='http://player.vimeo.com/video/15117130' width='600' height='450' frameborder='0'></iframe></div>
<p>Here are renderings of solutions to Towers of Hanoi with three pegs and 3, 4, 5, 6, 7, and 8 disks (the last pushed the limits of GraphViz):</p>

<a href='http://jkkramer.wordpress.com/2010/08/27/fun-with-clojure%c2%a0turning-cats-into-dogs-in-hanoi/hanoi-3-3/' title='hanoi-3-3'><img data-attachment-id='57' data-orig-size='752,785' data-liked='0'width="143" height="150" src="http://jkkramer.files.wordpress.com/2010/08/hanoi-3-3.png?w=143&#038;h=150" class="attachment-thumbnail" alt="Towers of Hanoi, 3 disks 3 pegs" title="hanoi-3-3" /></a>
<a href='http://jkkramer.wordpress.com/2010/08/27/fun-with-clojure%c2%a0turning-cats-into-dogs-in-hanoi/hanoi-4-3/' title='hanoi-4-3'><img data-attachment-id='60' data-orig-size='841,782' data-liked='0'width="150" height="139" src="http://jkkramer.files.wordpress.com/2010/08/hanoi-4-3.png?w=150&#038;h=139" class="attachment-thumbnail" alt="hanoi-4-3" title="hanoi-4-3" /></a>
<a href='http://jkkramer.wordpress.com/2010/08/27/fun-with-clojure%c2%a0turning-cats-into-dogs-in-hanoi/hanoi-5-3/' title='hanoi-5-3'><img data-attachment-id='61' data-orig-size='824,831' data-liked='0'width="148" height="150" src="http://jkkramer.files.wordpress.com/2010/08/hanoi-5-3.png?w=148&#038;h=150" class="attachment-thumbnail" alt="hanoi-5-3" title="hanoi-5-3" /></a>
<a href='http://jkkramer.wordpress.com/2010/08/27/fun-with-clojure%c2%a0turning-cats-into-dogs-in-hanoi/hanoi-6-3/' title='hanoi-6-3'><img data-attachment-id='62' data-orig-size='1590,1717' data-liked='0'width="138" height="150" src="http://jkkramer.files.wordpress.com/2010/08/hanoi-6-3.png?w=138&#038;h=150" class="attachment-thumbnail" alt="hanoi-6-3" title="hanoi-6-3" /></a>
<a href='http://jkkramer.wordpress.com/2010/08/27/fun-with-clojure%c2%a0turning-cats-into-dogs-in-hanoi/hanoi-7-3/' title='hanoi-7-3'><img data-attachment-id='63' data-orig-size='3208,3452' data-liked='0'width="139" height="150" src="http://jkkramer.files.wordpress.com/2010/08/hanoi-7-3.png?w=139&#038;h=150" class="attachment-thumbnail" alt="hanoi-7-3" title="hanoi-7-3" /></a>
<a href='http://jkkramer.wordpress.com/2010/08/27/fun-with-clojure%c2%a0turning-cats-into-dogs-in-hanoi/hanoi-8-3/' title='hanoi-8-3'><img data-attachment-id='70' data-orig-size='2640,2769' data-liked='0'width="143" height="150" src="http://jkkramer.files.wordpress.com/2010/08/hanoi-8-31.png?w=143&#038;h=150" class="attachment-thumbnail" alt="hanoi-8-3" title="hanoi-8-3" /></a>
<a href='http://jkkramer.wordpress.com/2010/08/27/fun-with-clojure%c2%a0turning-cats-into-dogs-in-hanoi/cat-cot-dot-dog/' title='cat-cot-dot-dog'><img data-attachment-id='73' data-orig-size='1195,567' data-liked='0'width="150" height="71" src="http://jkkramer.files.wordpress.com/2010/09/cat-cot-dot-dog.png?w=150&#038;h=71" class="attachment-thumbnail" alt="cat-cot-dot-dog" title="cat-cot-dot-dog" /></a>

<p>(<a href="http://en.wikipedia.org/wiki/Sierpi%C5%84ski_triangle">Look familiar?</a>)</p>
<h3>Code</h3>
<p><a href="http://gist.github.com/608728">Click here for all the code used to create this post (plus some extra bits)</a></p>
<h3>To Be Continued</h3>
<p>Next time we&#8217;ll play with bigger graphs and leverage Clojure&#8217;s state-management tools to create parallel search algorithms.</p>
<h3>Footnotes</h3>
<ol>
<li id="footnote1">
<p>This version of <code>find-path</code> was used for blog simplicity. For a version that takes advantage of lazy sequences, see <a href="http://gist.github.com/608728">the gist</a> for this post or <a href="http://github.com/jkk/loom/blob/master/src/loom/alg_generic.clj">the Loom source</a>.</p>
</li>
</ol>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jkkramer.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jkkramer.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jkkramer.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jkkramer.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jkkramer.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jkkramer.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jkkramer.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jkkramer.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jkkramer.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jkkramer.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jkkramer.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jkkramer.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jkkramer.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jkkramer.wordpress.com/3/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jkkramer.wordpress.com&amp;blog=15411386&amp;post=3&amp;subd=jkkramer&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jkkramer.wordpress.com/2010/08/27/fun-with-clojure%c2%a0turning-cats-into-dogs-in-hanoi/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/693b9bfd287e55741c2a4af6f7de0d72?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jkkramer</media:title>
		</media:content>

		<media:content url="http://jkkramer.files.wordpress.com/2010/09/cat-cot-dot-dog.png" medium="image">
			<media:title type="html">cat-cot-dot-dog</media:title>
		</media:content>

		<media:content url="http://jkkramer.files.wordpress.com/2010/08/hanoi-3-3.png?w=450" medium="image">
			<media:title type="html">hanoi-3-3</media:title>
		</media:content>

		<media:content url="http://jkkramer.files.wordpress.com/2010/08/hanoi-3-3.png?w=143" medium="image">
			<media:title type="html">hanoi-3-3</media:title>
		</media:content>

		<media:content url="http://jkkramer.files.wordpress.com/2010/08/hanoi-4-3.png?w=150" medium="image">
			<media:title type="html">hanoi-4-3</media:title>
		</media:content>

		<media:content url="http://jkkramer.files.wordpress.com/2010/08/hanoi-5-3.png?w=148" medium="image">
			<media:title type="html">hanoi-5-3</media:title>
		</media:content>

		<media:content url="http://jkkramer.files.wordpress.com/2010/08/hanoi-6-3.png?w=138" medium="image">
			<media:title type="html">hanoi-6-3</media:title>
		</media:content>

		<media:content url="http://jkkramer.files.wordpress.com/2010/08/hanoi-7-3.png?w=139" medium="image">
			<media:title type="html">hanoi-7-3</media:title>
		</media:content>

		<media:content url="http://jkkramer.files.wordpress.com/2010/08/hanoi-8-31.png?w=143" medium="image">
			<media:title type="html">hanoi-8-3</media:title>
		</media:content>

		<media:content url="http://jkkramer.files.wordpress.com/2010/09/cat-cot-dot-dog.png?w=150" medium="image">
			<media:title type="html">cat-cot-dot-dog</media:title>
		</media:content>
	</item>
	</channel>
</rss>
