<?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; Array</title>
	<atom:link href="http://coder.bsimmons.name/blog/tag/array/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>17&#215;17: A Simulated Annealing approach using thresholds</title>
		<link>http://coder.bsimmons.name/blog/2010/07/17x17-a-simulated-annealing-approach-using-thresholds/</link>
		<comments>http://coder.bsimmons.name/blog/2010/07/17x17-a-simulated-annealing-approach-using-thresholds/#comments</comments>
		<pubDate>Sat, 10 Jul 2010 17:05:07 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[17x17]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[Array]]></category>
		<category><![CDATA[heuristics]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=443</guid>
		<description><![CDATA[<blockquote><p><em>Note: this is part of a <a href="http://coder.bsimmons.name/blog/tag/17x17/">series of posts</a> is related to the &#8220;<a href="http://blog.computationalcomplexity.org/2009/11/17x17-challenge-worth-28900-this-is-not.html">17&#215;17 Challenge</a>&#8221; posted by Bill Gasarch. The goal is to color cells of a 17 by 17 grid, using only four colors, such that no</em></p></blockquote><p>&#8230; <a href="http://coder.bsimmons.name/blog/2010/07/17x17-a-simulated-annealing-approach-using-thresholds/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<blockquote><p><em>Note: this is part of a <a href="http://coder.bsimmons.name/blog/tag/17x17/">series of posts</a> is related to the &#8220;<a href="http://blog.computationalcomplexity.org/2009/11/17x17-challenge-worth-28900-this-is-not.html">17&#215;17 Challenge</a>&#8221; posted by Bill Gasarch. The goal is to color cells of a 17 by 17 grid, using only four colors, such that no rectangle is formed from four cells of the same color.</em></p></blockquote>
<p>This is something I&#8217;ve been wanting to play with for months now, but haven&#8217;t made the time to implement: I wondered if <a href="http://en.wikipedia.org/wiki/Simulated_annealing">simulated annealing</a> techniques could be effective in finding a complete grid covering. </p>
<p>We would simply start with four copies of the 74-color grid and swap their rows and columns around, within each color set, trying to cover all of the cells by the union of the four subsets. So all of the sets of cells of a single color are fundamentally simply different permutations of the same 74-cell rectangle-free Graph. </p>
<p>Here is an illustration of the concept. Our algorithm starts with all four colored sets of cell overlapping (the red cells are on top, covering the other three colors):</p>
<p><a href="http://coder.bsimmons.name/blog/wp-content/uploads/Screenshot-74-coloring.png"><img src="http://coder.bsimmons.name/blog/wp-content/uploads/Screenshot-74-coloring-285x300.png" alt="Illustration showing four sets of colored cells, all overlapping in every cell" title="Screenshot - 74-coloring" width="285" height="300" class="aligncenter size-medium wp-image-446" /></a></p>
<p>&#8230;then we swap two rows or two columns from a colored subset of cells, until the four colored subsets spread out covering as much of the grid as possible. Here we cover all but 21 cells:</p>
<p><a href="http://coder.bsimmons.name/blog/wp-content/uploads/Screenshot-20-free.png"><img src="http://coder.bsimmons.name/blog/wp-content/uploads/Screenshot-20-free-300x291.png" alt="Four layers of cells of colors RGBY, spread out to cover most of the grid" title="Screenshot - 20 free" width="300" height="291" class="aligncenter size-medium wp-image-447" /></a></p>
<p><span id="more-443"></span></p>
<h2>A Brief Intro to Simulated Annealing</h2>
<p>Simulated Annealing is a bit of an intimidating term (has its origins in <a href="http://en.wikipedia.org/wiki/Annealing_%28metallurgy%29">metallurgy</a> of all things), but the idea is simple: you start off with an initial solution (in my case, four sets of cells, all of which overlap) and then you mutate it randomly by choosing a random &#8220;neighbor&#8221; solution (in my case, a grid in which two rows or two columns of the same color are swapped).</p>
<p>You score these solutions so that you can compare a current solution with a proposed mutated solution, and here&#8217;s the key: </p>
<blockquote><p>
You begin by accepting nearly every mutation, whether it improves your solution or not. But as the procedure progresses you become more picky about &#8220;how much worse&#8221; a new solution can be from the previous one.
</p></blockquote>
<p>So in the classic <a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem">Traveling Salesman Problem</a> a neighbor solution would be a new route that goes from city C to city E, where in the last solution we went from city E to city C.</p>
<h3>Threshold Acceptance</h3>
<p>There are various ways of accomplishing the task of &#8220;ratcheting down&#8221; the computation over time. The traditional method (the method most matching the metallurgical metaphor, if you will) is to have a function that computes the probability of a proposed change being accepted. This probability function changes over time, such that as we progress it becomes more and more unlikely that a solution worse than the previous will be accepted.</p>
<p>Another method, and the one I chose to implement, seems to be referred to as <a href="http://comisef.wikidot.com/concept:thresholdaccepting">Threshold Accepting</a>; instead of having a probability function, you accept all mutations that are below a certain threshold of change from the previous solution. The threshold becomes more strict over time.</p>
<p>So in our case we might start off with a threshold of five, meaning that we will accept all changes that give us a <em>worse</em> solution of no more than 5 new un-colored cells. So for example: if swapping blue rows 5 and 12 create a new solution with 6 fewer colored (covered) cells from the previous solution (i.e. a worse solution by six), then it won&#8217;t be accepted by our meta-algorithm at this stage.</p>
<h2>Notes on the implementation</h2>
<p>The approach I tried to describe above was really attractive to me because it short-circuits the whole complex &#8220;rectangle-free&#8221; constraint entirely. We simply start with a known rectangle-free subset and see if we can make four copies fit together. </p>
<p>Also, because we swap two rows or columns at a time, we need only look at the local change of score produced by the swap and then add it to the global score to obtain the new global score.</p>
<p>The astronomical number (<code>17!^2</code>) of possible permutations of a single rectangle-free subset give me hope that this approach could work, but that is an open question as far as I know. </p>
<p>I wrote this first draft of the script in haskell (as usual), and was happy with how fast it is, thanks in large part to the <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/vector">vector library</a>, which was a pleasure to work with. The code uses 4 pairs of <code>Vector</code>s (arrays of Ints), 8 in total, each of which represent a row or column ordering of one of the four colors. </p>
<p>We store the original 74-cell rectangle-free subset as a 2D <code>Array (Int,Int) Bool</code>. The pairs of Vectors act as references to row or column slices of this 2D array.</p>
<p>When we want to score a swap, we have to &#8220;render&#8221; all four colors of the pair of rows/columns in question using our 2D reference array. Then a swap consists of swapping two Ints in a single Vector. This is much more friendly on more poor laptop than if we were to try storing all four color subsets as 2D arrays and swapping them around!</p>
<p>You can <a href="http://coder.bsimmons.name/code/simulatedAnnealing.lhs">download the code here</a>, but mind it isn&#8217;t incredibly pretty.</p>
<h2>Initial findings</h2>
<p>The best I&#8217;ve done with this initial version is a grid with 19 empty cells:</p>
<p><a href="http://coder.bsimmons.name/blog/wp-content/uploads/Screenshot-19-free.png"><img src="http://coder.bsimmons.name/blog/wp-content/uploads/Screenshot-19-free-283x300.png" alt="A 17 by 17 grid showing all but 19 cells colored" title="Screenshot - 19 free" width="283" height="300" class="aligncenter size-medium wp-image-448" /></a></p>
<p>It is obvious though that the heuristic needs a lot of tuning, and that in my case the &#8220;Threshold Accepting&#8221; approach isn&#8217;t working well. That is because it is far too granular: we get from complete disorder to a minimum in just a handful of threshold rounds.</p>
<p>Here is a quick graph overlaying two runs, one of which starts with a threshold (each threshold round bracketed in black) of 5, the other (in blue) starts with a threshold of 2. The Y-axis is the number of uncolored cells in the grid at the current solution:</p>
<p><a href="http://coder.bsimmons.name/blog/wp-content/uploads/5-2.combined-annotated.png"><img src="http://coder.bsimmons.name/blog/wp-content/uploads/5-2.combined-annotated-300x136.png" alt="" title="5-2.combined-annotated" width="300" height="136" class="aligncenter size-medium wp-image-449" /></a></p>
<p>You can see that both basically look like <a href="http://en.wikipedia.org/wiki/Brownian_motion">random Brownian walks</a> during the course of a threshold round, and quickly drop to a lower energy level (better solution) as soon as the threshold is tightened. Most dramatic is the jump when we go from 2 to 1.</p>
<p>This looks like we&#8217;re being thrust into a local minima, which is the opposite of what we want here. But whether a more finely-tuned annealing schedule can do better is anyone&#8217;s guess.</p>
<h2>What&#8217;s next?</h2>
<p>It should be very simple to implement a more traditional annealing procedure that would ease us into lower &#8220;energy levels&#8221; without the harsh dives we get from using only a handful of threshold levels. So that is what is next on the agenda for this problem.</p>
<p>If this annealing business looks promising after I master the black art of &#8220;tuning the meta-heuristic&#8221;, it would be cool to come up with a single-coloring algorithm, capable of generating rectangle free colorings of 72,73, or 74 cells. We would then feed those solutions into our annealing framework, finding the best combinations of colorings via a genetic algorithm or the like.</p>
<p>But that leads to the question I&#8217;ve posed earlier: it is sometimes trivial to determine if two colorings are &#8220;unique&#8221; (i.e. by counting colored cells in rows and columns); but when it isn&#8217;t trivial, determining whether two colorings are <em>&#8220;equivalent&#8221;</em> seems to be a very difficult problem. </p>
<p>What a hole I&#8217;ve fallen into&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2010/07/17x17-a-simulated-annealing-approach-using-thresholds/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Befunge-93 Interpreter</title>
		<link>http://coder.bsimmons.name/blog/2010/01/a-befunge-93-interpreter/</link>
		<comments>http://coder.bsimmons.name/blog/2010/01/a-befunge-93-interpreter/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 21:13:50 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[Array]]></category>
		<category><![CDATA[EsotericLanguages]]></category>
		<category><![CDATA[MonadTransformers]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[state]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=302</guid>
		<description><![CDATA[<p><em>I just finished an initial release of an interpreter for the <a href="http://en.wikipedia.org/wiki/Befunge">befunge</a> programming language, based on the <a href="http://catseye.tc/projects/befunge93/">&#8216;93 spec</a>. The project was quite fun! My goal was to produce a well-designed program with performance that didn&#8217;t suck too</em>&#8230; <a href="http://coder.bsimmons.name/blog/2010/01/a-befunge-93-interpreter/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<p><em>I just finished an initial release of an interpreter for the <a href="http://en.wikipedia.org/wiki/Befunge">befunge</a> programming language, based on the <a href="http://catseye.tc/projects/befunge93/">&#8216;93 spec</a>. The project was quite fun! My goal was to produce a well-designed program with performance that didn&#8217;t suck too bad. Here are some highlights:</em></p>
<h2>Design</h2>
<p>I found that writing the core functionality of the interpreter took almost no time, once I settled on the approach I would take. I used a monad transformer for the first time, <code>StateT</code>: </p>
<p><blockquote class="vimblock"><br />
<span class="Type">type</span>&nbsp;REPL&nbsp;a&nbsp;<span class="Statement">=</span>&nbsp;StateT&nbsp;ProgramState&nbsp;<span class="Type">IO</span>&nbsp;a<br />
<br /></blockquote></p>
<p>This let me pass around the state of the computation in the <code>State</code> monad while doing IO actions. This made some potentially-awkward befunge commands really easy to implement.<br />
<span id="more-302"></span><br />
Here is an excerpt from the function <code>execute :: Char -> REPL ()</code> which reads the befunge character at our position and returns the code to execute:</p>
<p><blockquote class="vimblock"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- Pop value and output as an integer. funge-98 spec calls for</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- integer to be followed by a space, so we'll do that too:</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">'.'</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;<span class="Statement">do</span>&nbsp;i&nbsp;<span class="Statement">&lt;-</span>&nbsp;pop<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; liftIO&nbsp;<span class="Statement">$</span>&nbsp;<span class="Identifier">putStr</span>&nbsp;<span class="Statement">$</span>&nbsp;<span class="Identifier">show</span>&nbsp;i&nbsp;<span class="Statement">++</span><span class="Constant">&quot; &quot;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- Pop value and output as ASCII character</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">','</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;<span class="Statement">do</span>&nbsp;i&nbsp;<span class="Statement">&lt;-</span>&nbsp;pop<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; liftIO&nbsp;<span class="Statement">$</span>&nbsp;<span class="Identifier">putChar</span>&nbsp;<span class="Statement">$</span>&nbsp;chr&nbsp;i<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">'</span><span class="Special">\\</span><span class="Constant">'</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;<span class="Statement">do</span>&nbsp;(a,b)&nbsp;<span class="Statement">&lt;-</span>&nbsp;pop2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;a<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;b<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">':'</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;<span class="Statement">do</span>&nbsp;a&nbsp;<span class="Statement">&lt;-</span>&nbsp;pop<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; replicateM_&nbsp;<span class="Constant">2</span>&nbsp;(push&nbsp;a)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- program flow commands: --</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">' '</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;<span class="Identifier">return</span>&nbsp;()&nbsp;&nbsp;&nbsp;&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">'&gt;'</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;setDirection&nbsp;right<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">'&lt;'</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;setDirection&nbsp;left&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">'^'</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;setDirection&nbsp;up<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">'v'</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;setDirection&nbsp;down<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Constant">'?'</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;getRandomDirection&nbsp;<span class="Statement">&gt;&gt;=</span>&nbsp;setDirection&nbsp;<br />
<br /></blockquote></p>
<p>And here is the program state that gets passed in the monad:</p>
<p><blockquote class="vimblock"><br />
<span class="Type">data</span>&nbsp;ProgramState&nbsp;<span class="Statement">=</span>&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;ES&nbsp;{&nbsp;<span class="Comment">-- state of the code and stack:</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; code&nbsp;<span class="Statement">::</span>&nbsp;Code,&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stack&nbsp;<span class="Statement">::</span>&nbsp;Stack,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- state of program flow:</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; position&nbsp;<span class="Statement">::</span>&nbsp;Position,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; direction&nbsp;<span class="Statement">::</span>&nbsp;Direction,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; haltBit&nbsp;<span class="Statement">::</span>&nbsp;<span class="Type">Bool</span>,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- random generator:</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; randGen&nbsp;<span class="Statement">::</span>&nbsp;StdGen,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- errors or other messages we collect:</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; messages&nbsp;<span class="Statement">::</span>&nbsp;[<span class="Type">String</span>],<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- should we announce messages and warnings?:</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; verbose&nbsp;<span class="Statement">::</span>&nbsp;<span class="Type">Bool</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />
<br /></blockquote></p>
<p>I only use the accessor functions (as opposed to pattern matching) to reach into the state in my code, so it was easy to add another state parameter if I wanted to extend the functionality somewhere.</p>
<p>Finally here is the evaluation loop that ties the core of the interpreter together:</p>
<p><blockquote class="vimblock"><br />
evalLoop&nbsp;<span class="Statement">::</span>&nbsp;REPL&nbsp;()<br />
evalLoop&nbsp;<span class="Statement">=</span>&nbsp;<span class="Statement">do</span><br />
&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- extract the command at our position &amp; execute it:</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;getCmd&nbsp;<span class="Statement">&gt;&gt;=</span>&nbsp;execute<br />
&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- print messages in the queue (unless quiet), and clear it:</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;printMessages<br />
&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- halt if @ command issued, else move and recurse:</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;halting&nbsp;<span class="Statement">&lt;-</span>&nbsp;gets&nbsp;haltBit<br />
&nbsp;&nbsp;&nbsp;&nbsp;unless&nbsp;halting&nbsp;(move&nbsp;<span class="Statement">&gt;&gt;</span>&nbsp;evalLoop)&nbsp;<br />
<br /></blockquote></p>
<p>I found the most time-consuming parts of this project were in the design decisions and behaviour tweaks related to holes in the &#8216;93 spec, and tracking down a few silly bugs that came from wrong assumptions about the spec. </p>
<p>Vital in debugging were the <a href="http://users.tkk.fi/~mniemenm/befunge/ccbi.html">CCBI interpreter</a> as well as the <a href="http://mearie.org/projects/pyfunge/">pyfunge interpreter.</a> It&#8217;s difficult to debug an interpreter when you don&#8217;t whether the befunge code you are testing on is buggy or whether your interpreter is!</p>
<p>One last detail that I am proud of is the test suite that I have integrated into my darcs repo. Darcs automatically runs the befunge-93 portion of the amazing <a href="http://iki.fi/matti.niemenmaa/befunge/mycology.html">mycology test suite</a> by Matti Niemenmaa on each commit, as well as two smaller <a href="http://www.phlamethrower.co.uk/befunge/#files">test befunge programs</a> from phlamethrower, testing that the interpreter hasn&#8217;t changed behavior.</p>
<h2>Play With It</h2>
<p>You can check out the full source for the program <a href="http://coder.bsimmons.name/code/Befunge/Befunge.hs">here</a>, or get my whole darcs repository with:</p>
<blockquote><p>
<code>$ darcs get --tag=v0.2 http://coder.bsimmons.name/code/Befunge</code>
</p></blockquote>
<p>And here are a few nice programs to try out, written by folks cleverer than I, and stolen from vsync&#8217;s funge stuff <a href="http://quadium.net/funge/downloads/bef93src/">here</a>.</p>
<p><em>aturley.bf</em> by Andrew Turley:</p>
<blockquote><pre>
>84*>:#v_55+"ude.ub@yelruta">:#,_@>188*+>\02p\12p\:22p#v_$    55+,1-         v
    ^  0 v +1\                   _^#-+*<>22g02g*"_@"*-!1- #v_v>
       >:>::3g: ,\188                  ^^               -1\g21\g22
<p3 \"_":<
________________________________@_________________________________^  p3\"@":<
</pre>
</p3></pre>
</blockquote>
<p><em>life.bf</em> by Dmitry M Litvinov:</p>
<blockquote><pre>
v>>31g> ::51gg:2v++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9p BXY|-+<v3 *89<%+ *                                                      *   +
21 >98 *7^>+\-0|< + *                                                     *    +
*5 ^:+ 1pg15\,:< + *                                                     ***  +
10^  <>$25*,51g1v+                                                            +
-^ p< | -*46p15:+<+                                                            +
> 31^> 151p>92*4v+                                                            +
 ^_ ".",   ^ vp1< +                                                            +
>v >41p      >0 v+                                                            +
:5! vg-1g15-1g14< +                                                            +
+1-+>+41g1-51gg+v+                                                            +
1p-1vg+1g15-1g14< +                                                            +
g61g>+41g51g1-g+v+                                                            +
14*1v4+g+1g15g14< +                           * *                              +
5>^4>1g1+51g1-g+v+                           * *                              +
^ _^v4+gg15+1g14< +                           ***                              +
>v! >1g1+51g1+g+v+                                                            +
g8-v14/*25-*4*88< +                                                            +
19+>g51gg" "- v  +                                                            +
4*5  v< v-2:_3v+                                                            +
 >^   |!-3_$  v< -+                                                            +
^    < <      <|<+                                                         ***+
>g51gp ^ >51gp^>v+                                                            +
^14"+"< ^g14"!"<++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
</pre>
<p></v3></pre>
</blockquote>
<p><em>prime.bf</em> by Kalyna Zazelenchuk:</p>
<blockquote><pre>
222p35*89+*11p>133p                   >33g1+33p   22g33g- v>22g33g%#v_v
 o                                                        >|
  2                             v,,,,, ,,,,,.g22"is prime."< 1                            >    v^                             < ^_@#-g11g22p22+1g22,*25<,,,,,,,,,,,,,.g22"is not prime."<
</pre>
</pre>
</blockquote>
<p>There is still a lot that could be done, but I think I&#8217;m done with it for now. Thanks for looking!</p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2010/01/a-befunge-93-interpreter/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Cracking a Lock in Haskell with the De Bruijn sequence, pt. 1</title>
		<link>http://coder.bsimmons.name/blog/2009/09/cracking-a-lock-in-haskell-with-the-de-bruijn-sequence-pt-1/</link>
		<comments>http://coder.bsimmons.name/blog/2009/09/cracking-a-lock-in-haskell-with-the-de-bruijn-sequence-pt-1/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 04:14:59 +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[security]]></category>
		<category><![CDATA[sequences]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=215</guid>
		<description><![CDATA[<p><em>Update: a more efficient variation is implemented in <a href="http://coder.bsimmons.name/blog/2009/09/cracking-a-lock-in-haskell-with-the-de-bruijn-sequence-pt-2/">Part 2</a>.</em></p>
<p>A <a href="http://en.wikipedia.org/wiki/De_Bruijn_sequence">De Bruijn sequence</a> is (for example) a cyclical list of characters such that every word of a given length appears once and only once in the sequence.&#8230; <a href="http://coder.bsimmons.name/blog/2009/09/cracking-a-lock-in-haskell-with-the-de-bruijn-sequence-pt-1/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<p><em>Update: a more efficient variation is implemented in <a href="http://coder.bsimmons.name/blog/2009/09/cracking-a-lock-in-haskell-with-the-de-bruijn-sequence-pt-2/">Part 2</a>.</em></p>
<p>A <a href="http://en.wikipedia.org/wiki/De_Bruijn_sequence">De Bruijn sequence</a> is (for example) a cyclical list of characters such that every word of a given length appears once and only once in the sequence. Instead of using letters, you can have a De Bruijn sequence of bits. For example here is one possibility for a sequence in which every 3-bit word appears somewhere (you have to wrap around from the end for the final &#8220;words&#8221;):</p>
<blockquote><p>00011101</p></blockquote>
<p>In a sense we compress a dictionary of 2^3 = 8 3-bit words (or 24 bits) to a sequence of only 2^3 = 8 bits. There are some very simple algorithms for generating these kinds of sequences of bits, and I will implement two here: the &#8220;<strong>prefer one</strong>&#8221; algorithm and a subtle variation called &#8220;<strong><a href="http://people.clarkson.edu/~aalhakim/Mypapers/PreferOpposite.pdf">prefer opposite</a>[PDF] by Alhakim</strong>&#8220;. Here is the author&#8217;s excellent description of the traditional Prefer One algorithm from the linked paper:</p>
<blockquote><p>&#8221; The prefer-one algorithm is a very simple method amazingly capable of generating a full cycle. For any positive integer n ≥ 1, the algorithm puts n zeroes, and proceeds after this by proposing 1 for the next bit and accepting it when the word formed by the last n bits has not been encountered previously in the sequence, otherwise 0 is placed. The algorithm stops when both 0 and 1 do not bring a new word.&#8221;</p></blockquote>
<p>And here is my haskell implementation. It works by creating a lazy array which we build from a list being generated by searching the earlier portions of the array that already have been defined. It&#8217;s very similar to the method I used in modeling the <a href="http://coder.bsimmons.name/blog/2009/06/fun-with-lazy-arrays-the-lz77-algorithm/">LZ77 algorithm</a>.:</p>
<p><blockquote class="vimblock"><br>
<span class="Type">module</span>&nbsp;Main<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Type">where</span><br>
<br>
<span class="PreProc">import</span>&nbsp;Data.Array<br>
<span class="PreProc">import</span>&nbsp;Data.List(isInfixOf)<br>
<br>
<br>
<span class="Type">type</span>&nbsp;Bit&nbsp;<span class="Statement">=</span>&nbsp;<span class="Type">Bool</span><br>
<br>
preferOne&nbsp;<span class="Statement">::</span>&nbsp;<span class="Type">Int</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;[&nbsp;Bit&nbsp;]<br>
preferOne&nbsp;n&nbsp;<span class="Statement">=</span>&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">let</span>&nbsp;upB&nbsp;<span class="Statement">=</span>&nbsp;<span class="Constant">2</span><span class="Statement">^</span>n<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr&nbsp;<span class="Statement">=</span>&nbsp;&nbsp;listArray&nbsp;(<span class="Constant">1</span>,&nbsp;upB)&nbsp;(<span class="Identifier">replicate</span>&nbsp;n&nbsp;<span class="Constant">False</span>&nbsp;<span class="Statement">++</span>&nbsp;rest)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- since we use Bool for bits, we can say (not.alreadySeen):</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rest&nbsp;&nbsp;<span class="Statement">=</span>&nbsp;&nbsp;<span class="Identifier">map</span>&nbsp;(<span class="Identifier">not</span>&nbsp;<span class="Statement">.</span>&nbsp;alreadySeen)&nbsp;[n<span class="Statement">+</span><span class="Constant">1</span>&nbsp;<span class="Statement">..</span>&nbsp;upB]<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alreadySeen&nbsp;i&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">or</span>&nbsp;<span class="Statement">$</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">do</span>&nbsp;<span class="Statement">let</span>&nbsp;range&nbsp;<span class="Statement">=</span>&nbsp;[&nbsp;arr<span class="Statement">!</span>i' <span class="Statement">|</span>&nbsp;i' <span class="Statement">&lt;-</span>&nbsp;[i<span class="Statement">-</span>n<span class="Statement">+</span><span class="Constant">1</span>&nbsp;<span class="Statement">..</span>&nbsp;i<span class="Statement">-</span><span class="Constant">1</span>]]&nbsp;<span class="Statement">++</span>&nbsp;[<span class="Constant">True</span>]&nbsp;<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;&nbsp;&nbsp;&nbsp;&nbsp; i1&nbsp;<span class="Statement">&lt;-</span>&nbsp;[<span class="Constant">1</span><span class="Statement">..</span>i<span class="Statement">-</span>n]&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">let</span>&nbsp;rangeP&nbsp;<span class="Statement">=</span>&nbsp;[&nbsp;arr<span class="Statement">!</span>i' <span class="Statement">|</span>&nbsp;i' <span class="Statement">&lt;-</span>&nbsp;[i1&nbsp;<span class="Statement">..</span>&nbsp;i1<span class="Statement">+</span>n<span class="Statement">-</span><span class="Constant">1</span>]&nbsp;]<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;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Identifier">return</span>&nbsp;(range&nbsp;<span class="Statement">==</span>&nbsp;rangeP)<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- an infinite stream is returned... because I can:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">in</span>&nbsp;<span class="Identifier">cycle</span>&nbsp;(elems&nbsp;arr)<br>
<br></blockquote></p>
<p>The Prefer Opposite algorithm works on the same principle, but with a couple twists. In my words it is as follows:</p>
<blockquote><p>Start with n zeros. Search for successive bits as follows:</p>
<p>propose to place the bit that is different from the previous bit: if the word formed by this bit has not been seen already, then choose it, else choose the same bit as the last. When 2^3-1 bit have been written, write a 1 for the final bit. and you&#8217;re done. (you can also keep track of how long a string of ones has been written; the sequence will always end with <code>n</code> ones)</p></blockquote>
<p>Here is my implementation:</p>
<p><blockquote class="vimblock"><br>
preferOpposite&nbsp;<span class="Statement">::</span>&nbsp;<span class="Type">Int</span>&nbsp;<span class="Statement">-&gt;</span>&nbsp;[&nbsp;Bit&nbsp;]<br>
preferOpposite&nbsp;n&nbsp;<span class="Statement">=</span>&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">let</span>&nbsp;upB&nbsp;<span class="Statement">=</span>&nbsp;<span class="Constant">2</span><span class="Statement">^</span>n<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr&nbsp;<span class="Statement">=</span>&nbsp;&nbsp;array&nbsp;(<span class="Constant">1</span>,&nbsp;upB)&nbsp;(final&nbsp;<span class="Statement">:</span>&nbsp;inits&nbsp;<span class="Statement">++</span>&nbsp;rest)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- we must specify the very last element of the sequence</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- which will always be a One:</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;<span class="Statement">=</span>&nbsp;(upB,<span class="Constant">True</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inits&nbsp;<span class="Statement">=</span>&nbsp;[&nbsp;(i,<span class="Constant">False</span>)&nbsp;<span class="Statement">|</span>&nbsp;i<span class="Statement">&lt;-</span>[<span class="Constant">1</span><span class="Statement">..</span>n]&nbsp;]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rest&nbsp;&nbsp;<span class="Statement">=</span>&nbsp;&nbsp;<span class="Identifier">map</span>&nbsp;seqBit&nbsp;[n<span class="Statement">+</span><span class="Constant">1</span>&nbsp;<span class="Statement">..</span>&nbsp;upB<span class="Statement">-</span><span class="Constant">1</span>]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- if the word generated by making the current bit the opposite</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- of the previous has already been seen, we make the bit the</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- same as the previous:</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;seqBit&nbsp;i&nbsp;<span class="Statement">=</span>&nbsp;&nbsp;(i,&nbsp;nextB)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Type">where</span>&nbsp;bP&nbsp;<span class="Statement">=</span>&nbsp;arr<span class="Statement">!</span>(i<span class="Statement">-</span><span class="Constant">1</span>)&nbsp;&nbsp;<span class="Comment">--previous bit</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nextB&nbsp;<span class="Statement">|</span>&nbsp;<span class="Identifier">or</span>&nbsp;(alreadySeen&nbsp;i&nbsp;bP)&nbsp;<span class="Statement">=</span>&nbsp;bP&nbsp;<span class="Comment">--same as previous</span><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;<span class="Statement">|</span>&nbsp;<span class="Identifier">otherwise</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">=</span>&nbsp;<span class="Identifier">not</span>&nbsp;bP&nbsp;<span class="Comment">--choose opposite </span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">--checks if the n-length string we would form by choosing the</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">--opposite for the next bit is already present in the array:</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alreadySeen&nbsp;i&nbsp;bP&nbsp;<span class="Statement">=</span>&nbsp;<span class="Statement">do</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">let</span>&nbsp;range&nbsp;<span class="Statement">=</span>&nbsp;[&nbsp;arr<span class="Statement">!</span>i' <span class="Statement">|</span>&nbsp;i' <span class="Statement">&lt;-</span>&nbsp;[i<span class="Statement">-</span>n<span class="Statement">+</span><span class="Constant">1</span>&nbsp;<span class="Statement">..</span>&nbsp;i<span class="Statement">-</span><span class="Constant">1</span>]]&nbsp;<span class="Statement">++</span>&nbsp;[<span class="Identifier">not</span>&nbsp;bP]&nbsp;<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; i1&nbsp;<span class="Statement">&lt;-</span>&nbsp;[<span class="Constant">1</span><span class="Statement">..</span>i<span class="Statement">-</span>n]&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">let</span>&nbsp;rangeP&nbsp;<span class="Statement">=</span>&nbsp;[&nbsp;arr<span class="Statement">!</span>i' <span class="Statement">|</span>&nbsp;i' <span class="Statement">&lt;-</span>&nbsp;[i1&nbsp;<span class="Statement">..</span>&nbsp;i1<span class="Statement">+</span>n<span class="Statement">-</span><span class="Constant">1</span>]&nbsp;]<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; <span class="Identifier">return</span>&nbsp;(range&nbsp;<span class="Statement">==</span>&nbsp;rangeP)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">in</span>&nbsp;<span class="Identifier">cycle</span>&nbsp;(elems&nbsp;arr)<br>
<br></blockquote></p>
<p>Enough code for now, let&#8217;s talk about applications of the sequence. The most easily-approachable and interesting application to me applies to those keyed entry systems, such as electronic door locks, which accept a stream of keys (i.e. they unlock as soon as the correct key sequence is input, without any need to press an &#8220;enter&#8221; key). These mechanisms are very susceptible to attack with a De Bruijn sequence of key presses.</p>
<p>Since the above algorithms use a binary alphabet, as opposed to say a decimal one found on electronic keypads (check out <a href="http://alicebobandmallory.com/articles/2009/09/23/why-you-should-use-four-different-digits-for-keypad-locks">Jonas Elfström&#8217;s blog post</a> dealing with keypads with worn out letters for more on that), I will choose as my target an old-fashined garage door opener.</p>
<p>An old-style garage door opener remote has 8 binary <a href="http://en.wikipedia.org/wiki/Dip_switch">DIP switches</a> allowing 256 different code combinations. We will imagine the garage door is susceptible to a stream-based attack like the electronic lock we described.</p>
<p>We can model the garage door receiver as follows:</p>
<p><blockquote class="vimblock"><br>
<span class="Type">type</span>&nbsp;Combo&nbsp;<span class="Statement">=</span>&nbsp;[&nbsp;Bit&nbsp;]<br>
<span class="Type">type</span>&nbsp;Receiver&nbsp;<span class="Statement">=</span>&nbsp;Combo&nbsp;<span class="Statement">-&gt;</span>&nbsp;<span class="Type">Bool</span><br>
<br>
<span class="Comment">-- True means access granted</span><br>
programReceiver&nbsp;<span class="Statement">::</span>&nbsp;Combo&nbsp;<span class="Statement">-&gt;</span>&nbsp;Receiver<br>
programReceiver&nbsp;<span class="Statement">=</span>&nbsp;isInfixOf&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
<br></blockquote></p>
<p>Now let&#8217;s test out our model with this <code>main</code> function:</p>
<p><blockquote class="vimblock"><br>
main&nbsp;<span class="Statement">=</span>&nbsp;&nbsp;<span class="Statement">let</span>&nbsp;secretCode&nbsp;<span class="Statement">=</span>&nbsp;[<span class="Constant">False</span>,<span class="Constant">False</span>,<span class="Constant">True</span>,<span class="Constant">False</span>,<span class="Constant">True</span>,<span class="Constant">False</span>,<span class="Constant">True</span>,<span class="Constant">True</span>]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;receiver&nbsp;<span class="Statement">=</span>&nbsp;programReceiver&nbsp;secretCode<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;crackingStream&nbsp;<span class="Statement">=</span>&nbsp;preferOne&nbsp;<span class="Constant">8</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="Statement">in</span>&nbsp;<span class="Statement">if</span>&nbsp;receiver&nbsp;crackingStream<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">then</span>&nbsp;<span class="Identifier">print</span>&nbsp;<span class="Constant">&quot;WE'RE IN!&quot;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">else</span>&nbsp;<span class="Identifier">print</span>&nbsp;<span class="Constant">&quot;...bugs&quot;</span><br>
<br></blockquote></p>
<p>Looks good!:</p>
<blockquote><p>
*Main> :main<br />
&#8220;WE&#8217;RE IN!&#8221;</p></blockquote>
<p>In the next couple posts I&#8217;ll explore improvements to the performance of these algorithms and maybe a few other things. </p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2009/09/cracking-a-lock-in-haskell-with-the-de-bruijn-sequence-pt-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Proposed modification to &#8216;array&#8217; function in Data.Array</title>
		<link>http://coder.bsimmons.name/blog/2009/09/proposed-modification-to-array-function-in-dataarray/</link>
		<comments>http://coder.bsimmons.name/blog/2009/09/proposed-modification-to-array-function-in-dataarray/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 03:09:33 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[Array]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[library]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=211</guid>
		<description><![CDATA[<p>In Data.Array the function <code>array :: (IArray a e, Ix i) => (i, i) -> [(i, e)] -> a i e</code> takes the array bounds and an association list, and it produces an <code>Array</code>. The function allows you to build&#8230; <a href="http://coder.bsimmons.name/blog/2009/09/proposed-modification-to-array-function-in-dataarray/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<p>In Data.Array the function <code>array :: (IArray a e, Ix i) => (i, i) -> [(i, e)] -> a i e</code> takes the array bounds and an association list, and it produces an <code>Array</code>. The function allows you to build an Array by providing the elements in whatever order you choose, rather than from the first index to the last.</p>
<p>The function <code>listArray</code> is similar except that it assumes that the list is already ordered by index so there is no need to provide tuples of (index, value). Becase <code>listArray</code> actually uses <code>zip</code> internally to produce the tupled list, so the programmer can pass a list to <code>listArray</code> which <em>exceeds the declared bounds of the array</em> and the function will quietly drop the extra list tail:</p>
<blockquote><p>
<strong>Prelude Data.Array></strong> listArray (1,3) ['a','b','c',undefined]<br />
array (1,3) [(1,'a'),(2,'b'),(3,'c')]</p></blockquote>
<p>But when a list that exceeds the specified bound is passed to <code>array</code>, it dies a horrible death:</p>
<blockquote><p>
<strong>Prelude Data.Array></strong> array (1,3) [(1,'a'),(2,'b'),(3,'c'),(4,'d')]<br />
array *** Exception: Error in array index</p></blockquote>
<p>I think the <code>array</code> function should be modified by adding a simple <code>take</code> to automatically drop any excess list elements:</p>
<p><blockquote class="vimblock"><br>
array&nbsp;(l,u)&nbsp;ies<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">=</span>&nbsp;<span class="Statement">let</span>&nbsp;n&nbsp;<span class="Statement">=</span>&nbsp;safeRangeSize&nbsp;(l,u)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">in</span>&nbsp;unsafeArray&nbsp;(l,u)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [(safeIndex&nbsp;(l,u)&nbsp;n&nbsp;i,&nbsp;e)&nbsp;<span class="Statement">|</span>&nbsp;(i,&nbsp;e)&nbsp;<span class="Statement">&lt;-</span>&nbsp;<span class="Identifier">take</span>&nbsp;n&nbsp;ies]<br>
<br></blockquote></p>
<p>This change would bring the function into better alignment with other prelude functions which expect infinite lists and drop tails as needed. It can be argued that the programmer might want to know that he is passing too long a list to his function, in which case I think the <code>safeRangeSize</code> function, etc. should be eliminated.</p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2009/09/proposed-modification-to-array-function-in-dataarray/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>
	</channel>
</rss>
