<?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; parsing</title>
	<atom:link href="http://coder.bsimmons.name/blog/tag/parsing/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>Some Haskell Boilerplate For Google CodeJam</title>
		<link>http://coder.bsimmons.name/blog/2009/08/haskell-boilerplate-for-google-codejam/</link>
		<comments>http://coder.bsimmons.name/blog/2009/08/haskell-boilerplate-for-google-codejam/#comments</comments>
		<pubDate>Sat, 22 Aug 2009 07:37:16 +0000</pubDate>
		<dc:creator>jberryman</dc:creator>
				<category><![CDATA[haskell]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[CodeJam]]></category>
		<category><![CDATA[IO]]></category>
		<category><![CDATA[parsing]]></category>
		<category><![CDATA[release]]></category>

		<guid isPermaLink="false">http://coder.bsimmons.name/blog/?p=207</guid>
		<description><![CDATA[<p>I put together a skeleton module which should be usable for any of the problems in this year&#8217;s <a href="http://code.google.com/codejam/">Google CodeJam Programming Contest</a> (as long as they don&#8217;t adopt a new format/pattern for the problems this year). The module includes&#8230; <a href="http://coder.bsimmons.name/blog/2009/08/haskell-boilerplate-for-google-codejam/" class="read_more">   [ R E A D &#124; M O R E ]</a></p>]]></description>
			<content:encoded><![CDATA[<p>I put together a skeleton module which should be usable for any of the problems in this year&#8217;s <a href="http://code.google.com/codejam/">Google CodeJam Programming Contest</a> (as long as they don&#8217;t adopt a new format/pattern for the problems this year). The module includes some useful parsing functions which should in the worst case be useful as a cheatsheet for those not too experienced with <a href="http://legacy.cs.uu.nl/daan/download/parsec/parsec.html">Parsec</a> (*cough me). I hope it will encourage people to <a href="http://code.google.com/codejam/contest/registration">sign up</a> and use Haskell in the contest!</p>
<p>To adapt the module to a problem, one defines the following:</p>
<ol>
<li>a type <code>Case</code> into which we will parse a test case (i.e. problem)</li>
<li>a type <code>SolvedCase</code>, representing a solution to a test case</li>
<li>our <code>algorithm :: Case -> SolvedCase</code></li>
<li>a Parser <code>caseParser</code> which can parse a <em>single test case</em> (n.b. not the whole file) into the <code>Case</code> type</li>
<li>a function <code>formatCase :: SolvedCase -> String</code> which brings the solution to the state where it can be prepended with the standard &#8220;Case #1: &#8221; string</li>
</ol>
<p>Here is the module, filled in to solve the Minimum Scalar Product practice problem. You can download the code <a href="http://coder.bsimmons.name/code/Boiler.hs">here</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;Text.ParserCombinators.Parsec<br>
<span class="PreProc">import</span>&nbsp;IO <span class="PreProc">hiding</span>&nbsp;(try)<br>
<span class="PreProc">import</span>&nbsp;System.Environment<br>
<br>
<span class="Comment">-- PROBLEM-SPECIFIC IMPORTS --</span><br>
<span class="PreProc">import</span>&nbsp;Data.List (sort)<br>
<span class="PreProc">import</span>&nbsp;Control.Arrow<br>
<span class="Comment">------------------------------</span><br>
<br>
<br>
<span class="Comment">-- the input file will be parsed into a list of some type representing</span><br>
<span class="Comment">-- individual cases to be solved by our algorithm:</span><br>
<span class="Type">type</span>&nbsp;Input&nbsp;<span class="Statement">=</span>&nbsp;[Case]&nbsp;<br>
<br>
<span class="Comment">-- our algorithms will produce a list of some type SolutionCase:</span><br>
<span class="Type">type</span>&nbsp;Solution&nbsp;<span class="Statement">=</span>&nbsp;[SolvedCase]&nbsp;<br>
<br>
<span class="Comment">-- we convert each solved case into a String, which is zipped with</span><br>
<span class="Comment">--&nbsp;&nbsp;the standard &quot;Case #x: &quot; strings for the final output</span><br>
<span class="Type">type</span>&nbsp;Output&nbsp;<span class="Statement">=</span>&nbsp;[<span class="Type">String</span>]<br>
<br>
<br>
<br>
<br>
<br>
<span class="Comment">-- --------------- BEGIN EDITING --------------- --</span><br>
<br>
<br>
<br>
<span class="Comment">-- DEFINE A TYPE TO REPRESENT A SINGLE UNSOLVED TEST CASE: --</span><br>
<span class="Type">type</span>&nbsp;Case&nbsp;<span class="Statement">=</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- EXAMPLE: a pair of lists of Ints (our &quot;vectors&quot;):</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;([<span class="Type">Int</span>],[<span class="Type">Int</span>])<br>
<br>
<br>
<span class="Comment">-- DEFINE A TYPE TO REPRESENT A SINGLE SOLVED TEST CASE: --</span><br>
<span class="Type">type</span>&nbsp;SolvedCase&nbsp;<span class="Statement">=</span>&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- EXAMPLE: our Minimum Scalar Product as an Int:</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Type">Int</span><br>
<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- -- -- ALGORITHMS -- -- --</span><br>
<br>
<br>
<span class="Comment">-- SOLVE A TEST CASE HERE:</span><br>
algorithm&nbsp;<span class="Statement">::</span>&nbsp;Case&nbsp;<span class="Statement">-&gt;</span>&nbsp;SolvedCase<br>
algorithm&nbsp;<span class="Statement">=</span>&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- EXAMPLE: simply sort both lists, reverse one, and combine:</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Identifier">sum</span>&nbsp;<span class="Statement">.</span>&nbsp;<span class="Identifier">uncurry</span>&nbsp;(<span class="Identifier">zipWith</span>&nbsp;(<span class="Statement">*</span>))&nbsp;<span class="Statement">.</span>&nbsp;(<span class="Identifier">reverse</span>&nbsp;<span class="Statement">.</span>&nbsp;sort&nbsp;<span class="Statement">***</span>&nbsp;sort)<br>
<br>
<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- -- -- PARSING INPUT -- -- --</span><br>
<br>
<br>
<span class="Comment">-- DEFINE PARSER FOR A TEST CASE: --</span><br>
caseParser&nbsp;<span class="Statement">::</span>&nbsp;Parser&nbsp;Case<br>
caseParser&nbsp;<span class="Statement">=</span>&nbsp;<span class="Statement">do</span><br>
&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- EXAMPLE: parses a case consisting of 3 lines: the first describes the </span><br>
&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">--&nbsp;&nbsp;number n of elements in the following two lines, the next two lines </span><br>
&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- have n space-separated elements:</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;w&nbsp;<span class="Statement">&lt;-</span>&nbsp;word<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">let</span>&nbsp;n&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">read</span>&nbsp;w<br>
&nbsp;&nbsp;&nbsp;&nbsp;as&nbsp;<span class="Statement">&lt;-</span>&nbsp;count&nbsp;n&nbsp;word<br>
&nbsp;&nbsp;&nbsp;&nbsp;bs&nbsp;<span class="Statement">&lt;-</span>&nbsp;count&nbsp;n&nbsp;word<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Identifier">return</span>&nbsp;&nbsp;(<span class="Identifier">map</span>&nbsp;<span class="Identifier">read</span>&nbsp;as,&nbsp;<span class="Identifier">map</span>&nbsp;<span class="Identifier">read</span>&nbsp;bs)<br>
<br>
<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- -- -- FORMAT OUTPUT -- -- --</span><br>
<br>
<br>
<span class="Comment">-- DEFINE A FUNCTION FROM AN INDIVIDUAL SolvedCase -&gt; String. </span><br>
formatCase&nbsp;<span class="Statement">::</span>&nbsp;SolvedCase&nbsp;<span class="Statement">-&gt;</span>&nbsp;<span class="Type">String</span><br>
formatCase&nbsp;sol&nbsp;<span class="Statement">=</span>&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- EXAMPLE: nothing to speak of here:</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Identifier">show</span>&nbsp;sol<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp; <br>
<br>
<span class="Comment">-- --------------- STOP EDITING --------------- --</span><br>
<br>
<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">--------------------</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- IO BOILERPLATE --</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">--------------------</span><br>
<br>
<br>
main&nbsp;<span class="Statement">=</span>&nbsp;<span class="Statement">do</span><br>
&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- pass the input file name to our program:</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;(f<span class="Statement">:</span>_)&nbsp;<span class="Statement">&lt;-</span>&nbsp;getArgs<br>
&nbsp;&nbsp;&nbsp;&nbsp;file&nbsp;&nbsp;<span class="Statement">&lt;-</span>&nbsp;<span class="Identifier">readFile</span>&nbsp;f<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- start parsing, solve problem, and prepare output: </span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">let</span>&nbsp;inp&nbsp;&nbsp;<span class="Statement">=</span>&nbsp;parseWith&nbsp;mainParser&nbsp;file<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;solution&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">map</span>&nbsp;algorithm&nbsp;inp<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;solutionStrings&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">map</span>&nbsp;formatCase&nbsp;solution<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;outp&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">zipWith</span>&nbsp;(<span class="Statement">++</span>)&nbsp;prefixes&nbsp;solutionStrings<br>
&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp; <span class="Comment">-- write the prepared output to screen:</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Identifier">putStr</span>&nbsp;<span class="Statement">$</span>&nbsp;<span class="Identifier">unlines</span>&nbsp;outp<br>
<br>
<br>
<span class="Comment">-- dies with error, or returns some datatype with our parsed data:</span><br>
parseWith&nbsp;p&nbsp;<span class="Statement">=</span>&nbsp;<span class="Identifier">either</span>&nbsp;(<span class="Identifier">error</span>&nbsp;<span class="Statement">.</span>&nbsp;<span class="Identifier">show</span>)&nbsp;<span class="Identifier">id</span>&nbsp;<span class="Statement">.</span>&nbsp;parse&nbsp;p&nbsp;<span class="Constant">&quot;&quot;</span>&nbsp;<br>
<br>
<span class="Comment">-- to begin parsing, we read in a line containing the number of test cases </span><br>
<span class="Comment">-- to follow. We parse them with caseParser, returning a list:</span><br>
mainParser&nbsp;<span class="Statement">::</span>&nbsp;Parser&nbsp;Input<br>
mainParser&nbsp;<span class="Statement">=</span>&nbsp;<span class="Statement">do</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;n&nbsp;&nbsp;<span class="Statement">&lt;-</span>&nbsp;word<br>
&nbsp;&nbsp;&nbsp;&nbsp;ms&nbsp;<span class="Statement">&lt;-</span>&nbsp;count&nbsp;(<span class="Identifier">read</span>&nbsp;n)&nbsp;caseParser&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Identifier">return</span>&nbsp;ms<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">&lt;?&gt;</span>&nbsp;<span class="Constant">&quot;mainParser&quot;</span><br>
<br>
<span class="Comment">-- strings to prepend to output:</span><br>
prefixes&nbsp;<span class="Statement">=</span>&nbsp;[&nbsp;<span class="Constant">&quot;Case #&quot;</span>&nbsp;<span class="Statement">++</span>&nbsp;<span class="Identifier">show</span>&nbsp;n&nbsp;<span class="Statement">++</span>&nbsp;<span class="Constant">&quot;: &quot;</span>&nbsp;<span class="Statement">|</span>&nbsp;n&nbsp;<span class="Statement">&lt;-</span>&nbsp;[<span class="Constant">1</span><span class="Statement">..</span>]]<br>
<br>
<br>
<br>
<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">---------------------</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">-- VARIOUS PARSERS --</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Comment">---------------------</span><br>
<br>
<br>
<span class="Comment">-- -- LINE PARSERS -- --</span><br>
<br>
<br>
<span class="Comment">-- a single line String, up to the newline:</span><br>
wholeLine&nbsp;<span class="Statement">::</span>&nbsp;Parser&nbsp;<span class="Type">String</span><br>
wholeLine&nbsp;<span class="Statement">=</span>&nbsp;manyTill&nbsp;anyChar&nbsp;(try&nbsp;newline)&nbsp;<span class="Statement">&lt;?&gt;</span>&nbsp;<span class="Constant">&quot;wholeLine&quot;</span><br>
<br>
<span class="Comment">-- parse a String with whitespace-separated values into [String]</span><br>
whiteSepLine&nbsp;<span class="Statement">=</span>&nbsp;manyTill&nbsp;spaceSepWord&nbsp;newline&nbsp;<span class="Statement">&lt;?&gt;</span>&nbsp;<span class="Constant">&quot;whiteSepLine&quot;</span><br>
<br>
<br>
<span class="Comment">-- -- WORD PARSERS -- -- </span><br>
<br>
<br>
<span class="Comment">-- a single word followed by whitespace (space, newline, etc.):</span><br>
word&nbsp;<span class="Statement">=</span>&nbsp;<span class="Statement">do</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;w&nbsp;<span class="Statement">&lt;-</span>&nbsp;many1&nbsp;nonWhite<br>
&nbsp;&nbsp;&nbsp;&nbsp;spaces<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Identifier">return</span>&nbsp;w<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">&lt;?&gt;</span>&nbsp;<span class="Constant">&quot;word&quot;</span><br>
<br>
<span class="Comment">-- a single word followed by one or more ' ' characters (won't consume '\n')</span><br>
spaceSepWord&nbsp;<span class="Statement">=</span>&nbsp;<span class="Statement">do</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;w&nbsp;<span class="Statement">&lt;-</span>&nbsp;many1&nbsp;nonWhite<br>
&nbsp;&nbsp;&nbsp;&nbsp;many&nbsp;(char&nbsp;<span class="Constant">' '</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Identifier">return</span>&nbsp;w<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">&lt;?&gt;</span>&nbsp;<span class="Constant">&quot;spaceSepWord&quot;</span><br>
<br>
<span class="Comment">-- e.g. &quot;hello:world&quot; ---&gt; (&quot;hello&quot;,&quot;world&quot;)</span><br>
<span class="Comment">-- won't consume newlines</span><br>
twoWordsSepBy&nbsp;c&nbsp;<span class="Statement">=</span>&nbsp;<span class="Statement">do</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;<span class="Statement">&lt;-</span>&nbsp;manyTill&nbsp;nonWhite&nbsp;(try<span class="Statement">$</span>&nbsp;char&nbsp;c)<br>
&nbsp;&nbsp;&nbsp;&nbsp;y&nbsp;<span class="Statement">&lt;-</span>&nbsp;many1&nbsp;nonWhite<br>
&nbsp;&nbsp;&nbsp;&nbsp;many&nbsp;(char&nbsp;<span class="Constant">' '</span>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Identifier">return</span>&nbsp;(x,y)<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="Statement">&lt;?&gt;</span>&nbsp;<span class="Constant">&quot;twoWordsSepBy&quot;</span><br>
<br>
<br>
<span class="Comment">-- -- CHARACTER PARSERS -- --</span><br>
<br>
<br>
<span class="Comment">-- nonWhitespace character:</span><br>
nonWhite&nbsp;<span class="Statement">=</span>&nbsp;noneOf&nbsp;<span class="Constant">&quot; </span><span class="Special">\v\f\t\r\n</span><span class="Constant">&quot;</span>&nbsp;<span class="Statement">&lt;?&gt;</span>&nbsp;<span class="Constant">&quot;nonWhite&quot;</span><br>
<br>
<br>
<br></blockquote></p>
]]></content:encoded>
			<wfw:commentRss>http://coder.bsimmons.name/blog/2009/08/haskell-boilerplate-for-google-codejam/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
