<?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>LAMBDAPHONE &#187; recursion</title>
	<atom:link href="http://coder.bsimmons.name/blog/tag/recursion/feed/" rel="self" type="application/rss+xml" />
	<link>http://coder.bsimmons.name/blog</link>
	<description>fragmentary ideas  ䷿  intellectual what-nots  ䷷  and haskell programming  ䷴</description>
	<lastBuildDate>Tue, 27 Jul 2010 16:58:03 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>The Gift of Inconsistency</title>
		<link>http://coder.bsimmons.name/blog/2010/07/the-gift-of-inconsistency/</link>
		<comments>http://coder.bsimmons.name/blog/2010/07/the-gift-of-inconsistency/#comments</comments>
		<pubDate>Thu, 22 Jul 2010 23:35:23 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[EsotericLanguages]]></category>
		<category><![CDATA[LambdaCalculus]]></category>
		<category><![CDATA[laziness]]></category>
		<category><![CDATA[recursion]]></category>
		<category><![CDATA[theory]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=453</guid>
		<description><![CDATA[<p>Computer science is a fascinating and maddening thing. Even the most seemingly-esoteric topics turn out to be fundamental. Go out to the fringes of CS and you find yourself smack in the middle of <a href="http://en.wikipedia.org/wiki/G%C3%B6del%27s_incompleteness_theorems#Minds_and_machines">Philosophy</a>. You try to understand&#8230; <a href="http://coder.bsimmons.name/blog/2010/07/the-gift-of-inconsistency/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<p>Computer science is a fascinating and maddening thing. Even the most seemingly-esoteric topics turn out to be fundamental. Go out to the fringes of CS and you find yourself smack in the middle of <a href="http://en.wikipedia.org/wiki/G%C3%B6del%27s_incompleteness_theorems#Minds_and_machines">Philosophy</a>. You try to understand a single point and you suddenly find yourself embracing everything. </p>
<p>So this post comes from that infinitely-recursive rabbit hole of wikipedia topics I&#8217;ve been falling down for the last few weeks, and you can probably expect a few more like this one; I&#8217;ll try to keep focused.</p>
<p>We begin (as do All Good Things) with the <a href="http://en.wikipedia.org/wiki/Untyped_lambda_calculus">Untyped Lambda Calculus</a>:<br />
<span id="more-453"></span></p>
<h2>The System</h2>
<p>The lambda calculus, invented by <a href="http://en.wikipedia.org/wiki/Alonzo_Church">Alonzo Church</a>, is a formal system for modeling functional computation and logic. It has an extraordinarily simple set of semantics, has no notion of data as a separate idea, and yet (as was proven later) is Turing complete. It serves as the skeleton and sinew of the Lisp and Scheme programming languages.</p>
<p>At its invention it seems that the system sat right at the crossroads of formal logic, mathematics and computational theory and could embrace all three fields. But it quickly became apparent that there were apparent flaws with the Lambda Calculus as a universal system.</p>
<h2>The Paradox</h2>
<p>In 1935 it was shown that the lambda calculus was <em>logically inconsistent</em> by the <a href="http://en.wikipedia.org/wiki/Kleene%E2%80%93Rosser_paradox">Kleene–Rosser paradox</a>. The &#8220;paradox&#8221; is an apparently self-contradictory lambda expression, and goes like this:</p>
<p>We have a lambda calculus expression we will call <code>'k'</code>, which takes an argument, applies it to to itself, and negates (the ¬ symbol) the result (for some undefined, logical definition of &#8220;negate&#8221;). </p>
<blockquote><p>
k = λx.( ¬ (x x))
</p></blockquote>
<p>Okay, no problem. But look what happens when we apply the function <code>'k'</code> to itself:</p>
<blockquote><p>
k k = λx.( ¬ (x x)) k<br />
k k = ¬ (k k)
</p></blockquote>
<p>After we reduce the expression, we seem to be saying that <code>(k k)</code> is equal to the opposite of itself, a self-contradictory statement.</p>
<p>To address this apparent shortcoming of his system, Church went on to define a <a href="http://en.wikipedia.org/wiki/Simply_typed_lambda_calculus">typed lambda calculus</a>. This new system differentiated between function types and simple terms in order to disallow these kinds of problematic expressions.</p>
<p>But as with many paradoxes, this one was really an issue of perspective&#8230;</p>
<h2>The Foundation</h2>
<p>Church&#8217;s new &#8220;Simply Typed Lambda Calculus&#8221; had an interesting property that the untyped lambda calculus didn&#8217;t have: the <a href="http://en.wikipedia.org/wiki/Strongly_normalizing">normalization property</a>.</p>
<p>This more restricted version of the Lambda Calculus was &#8220;strongly normalizing&#8221;, meaning that any expression could be reduced to some <em>normal form</em> (i.e. a form that cannot be reduced further) through some sequence of rewrite/reduction steps. In programming terms, this means that every expression in the <em>typed</em> lambda calculus is <em>guaranteed to terminate</em>.</p>
<p>That sounds pretty damn useful until you realize that this interesting property also makes Church&#8217;s new typed version of his system <em>not Turing complete</em>! </p>
<p>To prove this is so, consider this: imagine you encoded a program in the typed lambda calculus; it searched for (and halted) when it found an integer that was greater than two, and was <em>not</em> the sum of two primes. </p>
<p>Merely being able to encode such a function would imply the function halted, thus disproving <a href="http://en.wikipedia.org/wiki/Goldbach%27s_conjecture">Goldbach&#8217;s conjecture</a>, one of the great open problems of mathematics. All without even needing to evaluate said expression! The function referred to is of course not expressible in the typed lambda calculus.</p>
<p>It turns out that an apparent logical contradiction was actual the essential secret to computation.</p>
<h3>Embracing Inconsistency</h3>
<p>When you think of the LC as a model of computation, rather than a framework for logical assertions, the Kleene–Rosser paradox becomes what we might call the &#8220;Kleene–Rosser useless function&#8221;. </p>
<p>Let&#8217;s go ahead and express a nearly identical paradox in <a href="http://en.wikipedia.org/wiki/Haskell_%28programming_language%29">haskell</a>:</p>
<blockquote><p>
k :: (Num a) => a<br />
k = negate k
</p></blockquote>
<p>Haskell has no notion of mutability, so what we are saying here is &#8220;k is the negation of itself&#8221;. No logical fallacies or great existential questions here, just an infinite loop (and not a very useful one)! </p>
<p>Let&#8217;s express another similar &#8220;paradox&#8221;, one we can actually <em>use</em>:</p>
<blockquote><p>
babble :: [ String ]<br />
babble = &#8220;blah&#8221; : babble
</p></blockquote>
<p>How can a list be equal to itself with an extra element added? Doesn&#8217;t that imply a paradox? Well I know the runtime isn&#8217;t swayed by that argument, producing an infinite stream of &#8220;blah&#8221;s. We can even <em>use</em> this stream because of haskell&#8217;s lazy evaluation strategy.</p>
<p>But note: it isn&#8217;t laziness that lets us get away with defining paradoxes; it just allows us to make use of some more blatant paradoxical expressions without them blowing up in our faces as soon as we call them.</p>
<h3>Conclusion and Further Thoughts</h3>
<p>Interestingly, there are quite a number of non-turing complete programming languages (or language subsets) that have been created both for theoretical purposes and for practical use. <a href="http://en.wikipedia.org/wiki/Charity_%28programming_language%29">Here</a> <a href="http://en.wikipedia.org/wiki/BlooP_and_FlooP">are</a> <a href="http://www-fp.cs.st-andrews.ac.uk/hume/index.shtml">a few</a>. They seem to owe their existence and usefulness to an environment of turing complete systems.</p>
<p>So does this mean that formal logic is Turing Incomplete? Let me know your thoughts, and please let me know if I harmed any knowledge in the making of this post.</p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2010/07/the-gift-of-inconsistency/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Code Jam 2010: Incrementing a Binary Counter</title>
		<link>http://coder.bsimmons.name/blog/2010/05/code-jam-2010-incrementing-a-binary-counter/</link>
		<comments>http://coder.bsimmons.name/blog/2010/05/code-jam-2010-incrementing-a-binary-counter/#comments</comments>
		<pubDate>Sun, 09 May 2010 21:36:44 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[cellularAutomata]]></category>
		<category><![CDATA[CodeJam]]></category>
		<category><![CDATA[recursion]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=406</guid>
		<description><![CDATA[<h3>The Problem</h3>
<p><a href="http://code.google.com/codejam/contest/dashboard?c=433101#s=p0">Problem A</a> in the qualifying round of this year&#8217;s Google CodeJam contest was really clever. The problem used a classic made-for-TV gadget from the 80s: <a href="http://www.youtube.com/watch?v=-XUOhjW2AXM">The Clapper™</a> (&#8220;snapper&#8221; in google&#8217;s version) and went like this:</p>
<blockquote><p>
The</p></blockquote><p>&#8230; <a href="http://coder.bsimmons.name/blog/2010/05/code-jam-2010-incrementing-a-binary-counter/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<h3>The Problem</h3>
<p><a href="http://code.google.com/codejam/contest/dashboard?c=433101#s=p0">Problem A</a> in the qualifying round of this year&#8217;s Google CodeJam contest was really clever. The problem used a classic made-for-TV gadget from the 80s: <a href="http://www.youtube.com/watch?v=-XUOhjW2AXM">The Clapper™</a> (&#8220;snapper&#8221; in google&#8217;s version) and went like this:</p>
<blockquote><p>
The Snapper is a clever little device that, on one side, plugs its input plug into an output socket, and, on the other side, exposes an output socket for plugging in a light or other device.</p>
<p>When a Snapper is in the ON state and is receiving power from its input plug, then the device connected to its output socket is receiving power as well. When you snap your fingers &#8212; making a clicking sound &#8212; any Snapper receiving power at the time of the snap toggles between the ON and OFF states.</p>
<p>In hopes of destroying the universe by means of a singularity, I have purchased N Snapper devices and chained them together by plugging the first one into a power socket, the second one into the first one, and so on. The light is plugged into the Nth Snapper.</p>
<p>Initially, all the Snappers are in the OFF state, so only the first one is receiving power from the socket, and the light is off. I snap my fingers once, which toggles the first Snapper into the ON state and gives power to the second one. I snap my fingers again, which toggles both Snappers and then promptly cuts power off from the second one, leaving it in the ON state, but with no power. I snap my fingers the third time, which toggles the first Snapper again and gives power to the second one. Now both Snappers are in the ON state, and if my light is plugged into the second Snapper it will be on. </p>
<p>I keep doing this for hours. Will the light be on or off after I have snapped my fingers K times? The light is on if and only if it&#8217;s receiving power from the Snapper it&#8217;s plugged into.
</p></blockquote>
<p><span id="more-406"></span><br />
It&#8217;s a great problem because we have a situation that is easily modeled with a computer program, and yet a naive solution will be far too inefficient to process the inputs that google provides (e.g. 10^8 claps).</p>
<p>Here is a direct-to-code translation of the functioning of a &#8220;chain of snappers&#8221; implemented in (very verbose) Haskell:</p>
<p><div class="vimblock"><br />
<span class="Comment">&gt;</span>&nbsp;<span class="Type">module</span>&nbsp;Main<br />
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Type">where</span><br />
<span class="Comment">&gt;</span><br />
<span class="Comment">&gt;</span>&nbsp;<span class="Type">type</span>&nbsp;ClapperChain&nbsp;<span class="Statement">=</span>&nbsp;[<span class="Type">Bool</span>]<br />
<span class="Comment">&gt;</span><br />
<span class="Comment">&gt;</span><br />
<span class="Comment">&gt;</span>&nbsp;clapOnOff&nbsp;<span class="Statement">::</span>&nbsp;ClapperChain&nbsp;<span class="Statement">-&gt;</span>&nbsp;ClapperChain<br />
<span class="Comment">&gt;</span>&nbsp;clapOnOff&nbsp;[]&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">=</span>&nbsp;[]<br />
<span class="Comment">&gt;</span>&nbsp;clapOnOff&nbsp;(c<span class="Statement">:</span>cs)&nbsp;<span class="Statement">=</span><br />
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">if</span>&nbsp;isPowered&nbsp;cs<br />
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">then</span>&nbsp;toggleState&nbsp;c&nbsp;<span class="Statement">:</span>&nbsp;clapOnOff&nbsp;cs<br />
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">else</span>&nbsp;c&nbsp;<span class="Statement">:</span>&nbsp;clapOnOff&nbsp;cs<br />
<span class="Comment">&gt;</span><br />
<span class="Comment">&gt;</span>&nbsp;isPowered&nbsp;<span class="Statement">::</span>&nbsp;ClapperChain&nbsp;<span class="Statement">-&gt;</span>&nbsp;<span class="Type">Bool</span><br />
<span class="Comment">&gt;</span>&nbsp;isPowered&nbsp;[]&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">=</span>&nbsp;<span class="Constant">True</span>&nbsp;<span class="Comment">-- at the outlet</span><br />
<span class="Comment">&gt;</span>&nbsp;isPowered&nbsp;(c<span class="Statement">:</span>cs)&nbsp;<span class="Statement">=</span>&nbsp;inOnState&nbsp;c&nbsp;<span class="Statement">&amp;&amp;</span>&nbsp;isPowered&nbsp;cs<br />
<span class="Comment">&gt;</span><br />
<span class="Comment">&gt;</span>&nbsp;inOnState&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">id</span><br />
<span class="Comment">&gt;</span>&nbsp;toggleState&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">not</span>&nbsp;<br />
<br /></div></p>
<p>We can then look at a few iterations (snaps) and see how the chain changes. <code>True</code> is a &#8220;snapper&#8221; in the ON state:</p>
<blockquote><pre>
*Main> take 4 $ iterate clapOnOff [False,False,False]
[[False,False,False],[False,False,True],[False,True,False],[False,True,True]]</pre>
</blockquote>
<h3>A Solution</h3>
<p>After working out a few iterations on paper I realized that the snappers follow the pattern of an ascending binary number count: <code>000, 001, 010, 011...</code></p>
<p>The lamp will be on when all of the snappers are <code>1s</code> (i.e. in the ON state) which will occur every (2^number_of_snappers) snaps. Thus my solution was simply the following:</p>
<p><blockquote class="vimblock"><br />
caseAlgorithm&nbsp;(n,k)&nbsp;<span class="Statement">=</span>&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">if</span>&nbsp;(((k<span class="Statement">+</span><span class="Constant">1</span>)&nbsp;<span class="Statement">`mod`</span>&nbsp;<span class="Constant">2</span><span class="Statement">^</span>n)&nbsp;<span class="Statement">==</span>&nbsp;<span class="Constant">0</span>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">then</span>&nbsp;ON<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">else</span>&nbsp;OFF<br />
<br /></blockquote></p>
<h3>More Code and Thoughts</h3>
<p>Here is a more terse and better version of the Snapper simulation code I posted above, now simply called <code>increment</code> for incrementing a binary number:</p>
<p><div class="vimblock"><br />
<span class="Comment">&gt;</span>&nbsp;increment&nbsp;<span class="Statement">::</span>&nbsp;ClapperChain&nbsp;<span class="Statement">-&gt;</span>&nbsp;ClapperChain<br />
<span class="Comment">&gt;</span>&nbsp;increment&nbsp;[]&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">=</span>&nbsp;[]&nbsp;&nbsp;<span class="Comment">-- [] is the outlet</span><br />
<span class="Comment">&gt;</span>&nbsp;increment&nbsp;chain<span class="Statement">@</span>(c<span class="Statement">:</span>cs)&nbsp;&nbsp;<br />
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">|</span>&nbsp;<span class="Identifier">and</span>&nbsp;cs&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">map</span>&nbsp;<span class="Identifier">not</span>&nbsp;chain<br />
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">|</span>&nbsp;<span class="Identifier">otherwise</span>&nbsp;<span class="Statement">=</span>&nbsp;c&nbsp;<span class="Statement">:</span>&nbsp;increment&nbsp;cs<br />
<br /></div></p>
<p>We can convert our lists into pretty strings with&#8230;</p>
<p><div class="vimblock"><br />
<span class="Comment">&gt;</span>&nbsp;showBinary&nbsp;<span class="Statement">::</span>&nbsp;ClapperChain&nbsp;<span class="Statement">-&gt;</span>&nbsp;<span class="Type">String</span><br />
<span class="Comment">&gt;</span>&nbsp;showBinary&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">map</span>&nbsp;(<span class="Statement">\</span>b<span class="Statement">-&gt;</span>&nbsp;<span class="Statement">if</span>&nbsp;b&nbsp;<span class="Statement">then</span>&nbsp;<span class="Constant">'1'</span>&nbsp;<span class="Statement">else</span>&nbsp;<span class="Constant">'0'</span>)<br />
<br /></div></p>
<p>And play with it like so:</p>
<blockquote><pre>
*Main> map showBinary $ take 9 $ iterate increment  [False,False,False]
["000","001","010","011","100","101","110","111","000"]</pre>
</blockquote>
<p>I liked realizing that a binary count could be represented recursively and <a href="http://en.wikipedia.org/wiki/Counter">mechanically</a>. It led me to look into how <a href="http://www.play-hookey.com/digital/ripple_counter.html">binary</a> <a href="http://www.play-hookey.com/digital/synchronous_counter.html">counter</a> <a href="http://hyperphysics.phy-astr.gsu.edu/hbase/electronic/bincount.html">circuits</a> are implemented in electronics (it turns out The Clapper™  is not generally involved), and got me thinking about <a href="http://en.wikipedia.org/wiki/Cellular_automaton">cellular automata</a>.</p>
<p>A binary counter could be implemented as Cellular Automata in which each bit is an Automaton with two states: an ON/OFF state and a POWERED/UNPOWERED state.</p>
<p>&#8230;although I think POWERED or UNPOWERED would have to be evaluated lazily, which might not fit the model.</p>
<p>Oh well, good luck to everyone doing the competition this year!</p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2010/05/code-jam-2010-incrementing-a-binary-counter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enumerating all n-integer Sets Which Sum to an Integer x</title>
		<link>http://coder.bsimmons.name/blog/2009/07/enumerating-all-n-integer-sets-which-sum-to-an-integer-x/</link>
		<comments>http://coder.bsimmons.name/blog/2009/07/enumerating-all-n-integer-sets-which-sum-to-an-integer-x/#comments</comments>
		<pubDate>Thu, 30 Jul 2009 01:27:34 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[monads]]></category>
		<category><![CDATA[recursion]]></category>
		<category><![CDATA[short]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=199</guid>
		<description><![CDATA[<p>I came up with what I think is an elegant use of monadic code, while working on a program to compute solutions to the <a href="http://en.wikipedia.org/wiki/Postage_stamp_problem">Postage Stamp Problem</a>. The problem asks: </p>
<blockquote><p><em>Consider that an envelope is able to hold</em></p></blockquote><p>&#8230; <a href="http://coder.bsimmons.name/blog/2009/07/enumerating-all-n-integer-sets-which-sum-to-an-integer-x/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<p>I came up with what I think is an elegant use of monadic code, while working on a program to compute solutions to the <a href="http://en.wikipedia.org/wiki/Postage_stamp_problem">Postage Stamp Problem</a>. The problem asks: </p>
<blockquote><p><em>Consider that an envelope is able to hold a limited number of postage stamps. Then, consider the set of the values of the stamps &#8212; positive integers only. Then, what is the smallest total postage which *cannot* be put onto the envelope?</em></p></blockquote>
<p>The algorithm below takes a <em>number of stamps that can fit</em> and a <em>total postage to apply</em> and returns a list of all the sets of different stamp values that can be combined to form the target postage sum:</p>
<p><div class="vimblock"><br>
<span class="Statement">&gt;</span>&nbsp;sumLists&nbsp;<span class="Statement">::</span>&nbsp;<span class="Type">Int</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;<span class="Type">Int</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;[[<span class="Type">Int</span>]]<br>
<span class="Statement">&gt;</span>&nbsp;sumLists&nbsp;<span class="Statement">=</span>&nbsp;f&nbsp;<span class="Constant">0</span>&nbsp;<span class="Type">where</span><br>
<span class="Statement">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; f&nbsp;_&nbsp;<span class="Constant">1</span>&nbsp;n&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">return</span>&nbsp;[n]&nbsp;&nbsp;<br>
<span class="Statement">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; f&nbsp;i&nbsp;c&nbsp;n&nbsp;<span class="Statement">=</span>&nbsp;<span class="Statement">do</span>&nbsp;a&nbsp;&nbsp;<span class="Statement">&lt;-</span>&nbsp;[i<span class="Statement">..</span>&nbsp;<span class="Identifier">div</span>&nbsp;n&nbsp;c]&nbsp;<br>
<span class="Statement">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;as&nbsp;<span class="Statement">&lt;-</span>&nbsp;f&nbsp;(i<span class="Statement">+</span>a)&nbsp;(c<span class="Statement">-</span><span class="Constant">1</span>)&nbsp;(n<span class="Statement">-</span>a)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
<span class="Statement">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Identifier">return</span>&nbsp;(a&nbsp;<span class="Statement">:</span>&nbsp;as)&nbsp;<br>
<br></div></p>
<p>Thus the potential stamp combinations for a letter which can hold three stamps and costing 5 cents to mail would be:</p>
<blockquote><p>*Main> sumLists 3 5<br />
[[0,0,5],[0,1,4],[0,2,3],[1,1,3],[1,2,2]]</p></blockquote>
<p>As you can see, the algorithm also produces ordered lists naturally! </p>
<p>But perhaps all we care about are unique stamp values that. If we want to adjust our goal such that the algorithm returns <em>a list of all sets of unique stamp values sufficient to create the target postage</em>, we need only adjust the <code>return</code> line:</p>
<p><blockquote class="vimblock"><br>
<span class="Statement">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Identifier">return</span>&nbsp;(a&nbsp;<span class="Statement">:</span>&nbsp;<span class="Identifier">dropWhile</span>&nbsp;(<span class="Statement">==</span>a)&nbsp;as)&nbsp;<br>
<br></blockquote></p>
<p>Similarly we could drop the zeros (which mean &#8220;no stamp&#8221; in our case) from the beginnings of each set if we desired. The above code have applications to many similar problems including <a href="http://en.wikipedia.org/wiki/Subset_sum">Subset Sum</a>, and <a href="http://en.wikipedia.org/wiki/Knapsack_problem">Knapsack</a> as well as other partitioning problems.</p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2009/07/enumerating-all-n-integer-sets-which-sum-to-an-integer-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fun with Lazy Arrays: the LZ77 Algorithm</title>
		<link>http://coder.bsimmons.name/blog/2009/06/fun-with-lazy-arrays-the-lz77-algorithm/</link>
		<comments>http://coder.bsimmons.name/blog/2009/06/fun-with-lazy-arrays-the-lz77-algorithm/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 17:30:29 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[Array]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[recursion]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=187</guid>
		<description><![CDATA[<p><em>This is my third post investigating compression techniques related to the DEFLATE algorithm: the first on <a href="http://coder.bsimmons.name/blog/2009/05/run-length-encoding/">run-length encoding</a>, and the second on simple <a href="http://coder.bsimmons.name/blog/2009/05/huffman-coding/">Huffman Coding</a>. This post models the <a href="http://www.zlib.net/feldspar.html">LZ77 algorithm, the second of the two compression</a></em>&#8230; <a href="http://coder.bsimmons.name/blog/2009/06/fun-with-lazy-arrays-the-lz77-algorithm/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<p><em>This is my third post investigating compression techniques related to the DEFLATE algorithm: the first on <a href="http://coder.bsimmons.name/blog/2009/05/run-length-encoding/">run-length encoding</a>, and the second on simple <a href="http://coder.bsimmons.name/blog/2009/05/huffman-coding/">Huffman Coding</a>. This post models the <a href="http://www.zlib.net/feldspar.html">LZ77 algorithm, the second of the two compression strategies used by DEFLATE</a>, and in the process explores some interesting properties of Haskell&#8217;s basic Arrays.</em></p>
<h5>IMPLEMENTATION:</h5>
<p><div class="vimblock"><br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">module</span>&nbsp;LZ77<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Type">where</span><br>
<br>
we will use GHC's &quot;basic non-strict arrays&quot; for this <br>
experiment:<br>
<br>
<span class="Comment">&gt;</span>&nbsp;<span class="PreProc">import</span>&nbsp;Data.Array<br>
<br>
<br>
and use Ints to store the length of the entire decoded<br>
message (needed to create our array):<br>
<br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">type</span>&nbsp;Length&nbsp;<span class="Statement">=</span>&nbsp;<span class="Type">Int</span><br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">type</span>&nbsp;Offset&nbsp;<span class="Statement">=</span>&nbsp;<span class="Type">Int</span><br>
<br>
in place of the length in the standard length-offset pair<br>
I've decided to use an Int representing the index of the <br>
last element in the span relative to the element at<br>
offset. Thus the pair encoding a span of only one element,<br>
two elements back would be (0,2), rather than the more <br>
traditional (1,2). <br>
<br>
This simply makes more sense to me, especially since I want<br>
to be able to encoded reversed sequences, as you will see.<br>
<br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">type</span>&nbsp;Index&nbsp;<span class="Statement">=</span>&nbsp;<span class="Type">Int</span><br>
<br>
and a few simple dataypes for our uncompressed and <br>
compressed data respectively:<br>
<br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">type</span>&nbsp;Decoded&nbsp;a&nbsp;<span class="Statement">=</span>&nbsp;Array&nbsp;Index&nbsp;a<br>
<span class="Comment">&gt;</span><br>
<span class="Comment">&gt;</span>&nbsp;<span class="Type">data</span>&nbsp;Encoded&nbsp;a&nbsp;<span class="Statement">=</span>&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; Enc&nbsp;Length&nbsp;[&nbsp;<span class="Type">Either</span>&nbsp;a&nbsp;(Index,Offset)&nbsp;]&nbsp;<br>
<br>
<br>
The decompress function works by traversing the encoded message,<br>
keeping track of our array index position (since offsets are <br>
relative to the current position), and building an Array lazily<br>
from a list which we generate, in part by referencing elements<br>
from the partially generated array itself. <br>
<br>
So when we see a Right value we look up in the Array the elements <br>
referenced by the length-offset, concat-ing that list with the<br>
result of processing the rest of the encoded message.<br>
<br>
If we hit [] in 'dec' we call an error because the stored value <br>
for the length of the uncompressed message in the Encoded type<br>
was longer than what the 'decompress' function could produce.<br>
<br>
It's diffficult to describe, but I hope the code is clear:<br>
<br>
<span class="Comment">&gt;</span>&nbsp;decompress&nbsp;<span class="Statement">::</span>&nbsp;Encoded&nbsp;a&nbsp;<span class="Statement">-&gt;</span>&nbsp;Decoded&nbsp;a<br>
<span class="Comment">&gt;</span>&nbsp;decompress&nbsp;(Enc&nbsp;el&nbsp;es)&nbsp;<span class="Statement">=</span>&nbsp;decoded<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp; <span class="Type">where</span>&nbsp;decoded&nbsp;<span class="Statement">=</span>&nbsp;listArray&nbsp;(<span class="Constant">0</span>,el&nbsp;<span class="Statement">-</span>&nbsp;<span class="Constant">1</span>)&nbsp;<span class="Statement">$</span>&nbsp;dec&nbsp;<span class="Constant">0</span>&nbsp;es<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dec&nbsp;&nbsp;_&nbsp;&nbsp;&nbsp;&nbsp; []&nbsp;<span class="Statement">=</span>&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Identifier">error</span>&nbsp;<span class="Constant">&quot;message is shorter than it should be&quot;</span>&nbsp;<br>
<span class="Comment">&gt;</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dec&nbsp;n&nbsp;(<span class="Constant">Left</span>&nbsp;x&nbsp;<span class="Statement">:</span>&nbsp;xs)&nbsp;<span class="Statement">=</span>&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x&nbsp;<span class="Statement">:</span>&nbsp;dec&nbsp;(n<span class="Statement">+</span><span class="Constant">1</span>)&nbsp;xs<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dec&nbsp;n&nbsp;(<span class="Constant">Right</span>&nbsp;(iRel,off)&nbsp;<span class="Statement">:</span>&nbsp;xs)&nbsp;<span class="Statement">=</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">let</span>&nbsp;i1&nbsp;<span class="Statement">=</span>&nbsp;n&nbsp;&nbsp;<span class="Statement">-</span>&nbsp;off<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i2&nbsp;<span class="Statement">=</span>&nbsp;(<span class="Statement">if</span>&nbsp;iN&nbsp;<span class="Statement">&gt;</span>&nbsp;i1&nbsp;<span class="Statement">then</span>&nbsp;<span class="Identifier">succ</span>&nbsp;<span class="Statement">else</span>&nbsp;<span class="Identifier">pred</span>)&nbsp;i1&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iN&nbsp;<span class="Statement">=</span>&nbsp;i1&nbsp;<span class="Statement">+</span>&nbsp;iRel<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">in</span>&nbsp;[&nbsp;decoded<span class="Statement">!</span>i&nbsp;<span class="Statement">|</span>&nbsp;i&nbsp;<span class="Statement">&lt;-</span>&nbsp;[i1,&nbsp;i2&nbsp;<span class="Statement">..</span>&nbsp;iN]&nbsp;]&nbsp;<span class="Statement">++</span>&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dec&nbsp;(n&nbsp;<span class="Statement">+</span>&nbsp;<span class="Constant">1</span>&nbsp;<span class="Statement">+</span>&nbsp;<span class="Identifier">abs</span>&nbsp;iRel)&nbsp;xs<br>
<br>
<br>
Some interesting things about the code above:<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;1) we create an array from a list, which we build,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in part, by looking up elements from the array<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; we are in the process of building. <br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;2) we can compress a sequence of symbols which were<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; seen previously but in reverse order, simply by <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; storing a negative relative index in the <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (relative_index,offset) tuple. So, the string... <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;her racecar returns to race&quot; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; might compress to: <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{her race(-5,2)turns to(4,19)}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I'm not sure if this is useful in real compression,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; especially when it comes down to the binary encoding.<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;3) even more interesting, we can use this same decoder<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function to decompress data that matches a sequence<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in parts of the array we haven't built yet! We simply <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; use a negative offset in our tuple. <br>
<br></div></p>
<h5>EXAMPLES AND CONCLUSION:</h5>
<p><div class="vimblock"><br>
point (3) may or may not be something like the LZ78 algorithm, <br>
which apparently works by encoding future data, but it is <br>
defintely a cool thing to be able to do with arrays:<br>
<br>
<span class="Comment">&gt;</span>&nbsp;coolArray&nbsp;<span class="Statement">=</span>&nbsp;listArray&nbsp;(<span class="Constant">0</span>,<span class="Constant">4</span>)&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[<span class="Constant">0</span>,&nbsp;&nbsp;coolArray<span class="Statement">!</span><span class="Constant">4</span>&nbsp;<span class="Statement">-</span>&nbsp;<span class="Constant">3</span>,&nbsp;&nbsp;<span class="Constant">2</span>,&nbsp;&nbsp;coolArray<span class="Statement">!</span><span class="Constant">1</span>&nbsp;<span class="Statement">+</span>&nbsp;<span class="Constant">2</span>,&nbsp;&nbsp;<span class="Constant">4</span>]<br>
<br>
<br>
Here's an example with great compression where the relative <br>
index exceeds the offset:<br>
<br>
<span class="Comment">&gt;</span>&nbsp;exceedsOffset&nbsp;<span class="Statement">=</span>&nbsp;elems&nbsp;<span class="Statement">$</span>&nbsp;decompress&nbsp;<span class="Statement">$</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Enc&nbsp;<span class="Constant">25</span>&nbsp;[<span class="Constant">Left</span>&nbsp;<span class="Constant">'B'</span>,&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">'l'</span>,&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">'a'</span>,&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">'h'</span>,&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">' '</span>,<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">Left</span>&nbsp;<span class="Constant">'b'</span>,&nbsp;<span class="Constant">Right</span>&nbsp;(<span class="Constant">17</span>,<span class="Constant">5</span>),&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">'!'</span>]<br>
<br>
<br>
...and a code example for (2) above:<br>
<br>
<span class="Comment">&gt;</span>&nbsp;reverseReference&nbsp;<span class="Statement">=</span>&nbsp;elems&nbsp;<span class="Statement">$</span>&nbsp;decompress&nbsp;<span class="Statement">$</span><br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Enc&nbsp;<span class="Constant">27</span>&nbsp;[<span class="Constant">Left</span>&nbsp;<span class="Constant">'h'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'e'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'r'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">' '</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'r'</span>,<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">Left</span>&nbsp;<span class="Constant">'a'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'c'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'e'</span>,<span class="Constant">Right</span>(<span class="Statement">-</span><span class="Constant">5</span>,<span class="Constant">2</span>),<span class="Constant">Left</span>&nbsp;<span class="Constant">'t'</span>,<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">Left</span>&nbsp;<span class="Constant">'u'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'r'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'n'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'s'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">' '</span>,<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">Left</span>&nbsp;<span class="Constant">'t'</span>,<span class="Constant">Left</span>&nbsp;<span class="Constant">'o'</span>,<span class="Constant">Right</span>(<span class="Constant">4</span>,<span class="Constant">19</span>)]<br>
<br>
...and finally an example combining (2) and (3):<br>
<br>
<span class="Comment">&gt;</span>&nbsp;reverseLookAhead&nbsp;<span class="Statement">=</span>&nbsp;elems&nbsp;<span class="Statement">$</span>&nbsp;decompress&nbsp;<span class="Statement">$</span>&nbsp;<br>
<span class="Comment">&gt;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Enc&nbsp;<span class="Constant">5</span>&nbsp;[<span class="Constant">Left</span>&nbsp;<span class="Constant">1</span>,&nbsp;<span class="Constant">Right</span>&nbsp;(<span class="Statement">-</span><span class="Constant">1</span>,<span class="Statement">-</span><span class="Constant">3</span>),&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">3</span>,&nbsp;<span class="Constant">Left</span>&nbsp;<span class="Constant">4</span>]<br>
<br>
<br>
I was surprised to discover these properties in Haskell's lazy<br>
Arrays. hope they came as a surprise to a few others.<br>
<br></div></p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2009/06/fun-with-lazy-arrays-the-lz77-algorithm/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Run-length Encoding</title>
		<link>http://coder.bsimmons.name/blog/2009/05/run-length-encoding/</link>
		<comments>http://coder.bsimmons.name/blog/2009/05/run-length-encoding/#comments</comments>
		<pubDate>Tue, 26 May 2009 23:27:03 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[recursion]]></category>
		<category><![CDATA[short]]></category>
		<category><![CDATA[sorting]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=168</guid>
		<description><![CDATA[<p>Just a quick implementation of a<a href="http://en.wikipedia.org/wiki/Run-length_encoding"> RLE algorithm</a> for lists in haskell. We compress a list by converting &#8220;runs&#8221; of consecutive elements into a tuple of the form: (run_length, element).</p>
<p><blockquote class="vimblock"><br />
<span class="PreProc">import</span>&#160;Data.List (group)<br />
<span class="PreProc">import</span>&#160;Control.Arrow<br />
<br />
<br />
runLengthEnc&#160;<span</blockquote>&#8230; <a href="http://coder.bsimmons.name/blog/2009/05/run-length-encoding/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<p>Just a quick implementation of a<a href="http://en.wikipedia.org/wiki/Run-length_encoding"> RLE algorithm</a> for lists in haskell. We compress a list by converting &#8220;runs&#8221; of consecutive elements into a tuple of the form: (run_length, element).</p>
<p><blockquote class="vimblock"><br>
<span class="PreProc">import</span>&nbsp;Data.List (group)<br>
<span class="PreProc">import</span>&nbsp;Control.Arrow<br>
<br>
<br>
runLengthEnc&nbsp;<span class="Statement">::</span>&nbsp;<span class="Type">Eq</span>&nbsp;a&nbsp;<span class="Statement">=&gt;</span>&nbsp;[a]&nbsp;<span class="Statement">-&gt;</span>&nbsp;[(<span class="Type">Int</span>,a)]<br>
runLengthEnc&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">map</span>&nbsp;(<span class="Identifier">length</span>&nbsp;<span class="Statement">&amp;&amp;&amp;</span>&nbsp;<span class="Identifier">head</span>)&nbsp;<span class="Statement">.</span>&nbsp;group<br>
<br>
decode&nbsp;<span class="Statement">::</span>&nbsp;[(<span class="Type">Int</span>,&nbsp;a)]&nbsp;<span class="Statement">-&gt;</span>&nbsp;[a]<br>
decode&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">concatMap</span>&nbsp;(<span class="Identifier">uncurry</span>&nbsp;<span class="Identifier">replicate</span>)<br>
<br></blockquote></p>
<p>If the <code>&#038;&#038;&</code> combinator looks foreign to you, check out David R. Maciver&#8217;s <a href="http://www.drmaciver.com/2007/08/playing-with-arrows/">very enlightening blog about Arrow functions</a>. </p>
<p>I&#8217;m always curious to see how naive-looking functions like the above compare in performance to a from-scratch implementation with explicit recursion, so I came up with the following:</p>
<p><blockquote class="vimblock"><br>
runLengthEnc' <span class="Statement">::</span>&nbsp;<span class="Type">Eq</span>&nbsp;a&nbsp;<span class="Statement">=&gt;</span>&nbsp;[a]&nbsp;<span class="Statement">-&gt;</span>&nbsp;[(<span class="Type">Int</span>,a)]<br>
runLengthEnc' []&nbsp;<span class="Statement">=</span>&nbsp;[]<br>
runLengthEnc' (a<span class="Statement">:</span>as)&nbsp;<span class="Statement">=</span>&nbsp;run&nbsp;<span class="Constant">1</span>&nbsp;a&nbsp;as<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Type">where</span>&nbsp;run&nbsp;n&nbsp;x&nbsp;[]&nbsp;<span class="Statement">=</span>&nbsp;[(n,x)]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;run&nbsp;n&nbsp;x&nbsp;(x2<span class="Statement">:</span>xss)&nbsp;<span class="Statement">|</span>&nbsp;x&nbsp;<span class="Statement">==</span>&nbsp;x2&nbsp;&nbsp; <span class="Statement">=</span>&nbsp;run&nbsp;(n<span class="Statement">+</span><span class="Constant">1</span>)&nbsp;x&nbsp;xss<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">|</span>&nbsp;<span class="Identifier">otherwise</span>&nbsp;<span class="Statement">=</span>&nbsp;(n,x)&nbsp;<span class="Statement">:</span>&nbsp;run&nbsp;<span class="Constant">1</span>&nbsp;x2&nbsp;xss<br>
<br></blockquote></p>
<p>I tested both functions on a list of 100,000 random 1s and 0s and found the explicit version to be only marginally better performing, completing the list in <code>49 ticks &#038; 130Mb</code>, compared to <code>54 ticks &#038; 139 Mb</code> for the one-liner!</p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2009/05/run-length-encoding/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
