<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Tom Moertel's Weblog: The Bowling Game Kata in Haskell</title>
    <link>http://blog.moertel.com/articles/2006/04/05/the-bowling-game-kata-in-haskell</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Quality rants on programming theory and stuff geeks like</description>
    <item>
      <title>The Bowling Game Kata in Haskell</title>
      <description>&lt;p&gt;On the &lt;a href="http://www.wplug.org/"&gt;&lt;span class="caps"&gt;WPLUG&lt;/span&gt;&lt;/a&gt; mailing list I came across a post
about the formation of a &lt;a href="http://www.insomnia-consulting.org/"&gt;Pittsburgh Coding
Dojo&lt;/a&gt;.  The idea is to get a bunch
of hackers together and have them work on solving a challenge
problem with the goal of sharpening their programming skills and
learning from each other.&lt;/p&gt;


	&lt;p&gt;There was a &lt;a href="http://www.jadetower.org/muses/archives/000491.html"&gt;trial meeting on 31 March&lt;/a&gt; that focused on &lt;a href="http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata"&gt;The Bowling Game
Kata&lt;/a&gt;.
The challenge was essentially to write some code that scores
a full (ten-frame) game of bowling.  A game is represented by a series
of &amp;#8220;rolls,&amp;#8221; each being the number of pins knocked down by a
roll of the bowling ball.  The scoring function must
determine frame boundaries from the sequence of rolls and score all
ten frames according to the rules of bowling, i.e., taking into account
spares and strikes and the final frame.&lt;/p&gt;


	&lt;p&gt;The challenge sounded like a fun lunch-break problem, and so I
whipped up the following solution in Haskell.  (You might find
it interesting to compare this solution to the Java-based
solutions on the web.)&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='comment'&gt;{-
   My solution to "The Bowling Game Kata" 
   Tom Moertel &amp;lt;tom@moertel.com&amp;gt;
   2006-04-05

   See &lt;a href="http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata"&gt;http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata&lt;/a&gt;
-}&lt;/span&gt;

&lt;span class='keyword'&gt;module&lt;/span&gt; &lt;span class='conid'&gt;Bowling&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;score&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyword'&gt;where&lt;/span&gt;

&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='conid'&gt;Test&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;HUnit&lt;/span&gt;

&lt;span class='comment'&gt;-- | Compute the score for the list of rolls 'rs'&lt;/span&gt;

&lt;span class='varid'&gt;score&lt;/span&gt; &lt;span class='varid'&gt;rs&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;sc&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='varid'&gt;rs&lt;/span&gt;

&lt;span class='comment'&gt;-- accumulate the score 's' and frame count 'f' while consuming a&lt;/span&gt;
&lt;span class='comment'&gt;-- list of rolls 'rs' one frame at a time&lt;/span&gt;

&lt;span class='varid'&gt;sc&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='num'&gt;11&lt;/span&gt; &lt;span class='keyword'&gt;_&lt;/span&gt;  &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt;           &lt;span class='comment'&gt;-- frame 11 means all done; return score&lt;/span&gt;
&lt;span class='varid'&gt;sc&lt;/span&gt; &lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='varid'&gt;f&lt;/span&gt; &lt;span class='varid'&gt;rs&lt;/span&gt;  &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;case&lt;/span&gt; &lt;span class='varid'&gt;rs&lt;/span&gt; &lt;span class='keyword'&gt;of&lt;/span&gt;  &lt;span class='comment'&gt;-- otherwise, consume the frame &amp;amp; recurse&lt;/span&gt;
    &lt;span class='num'&gt;10&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;rs'&lt;/span&gt;                &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;sc'&lt;/span&gt; &lt;span class='num'&gt;3&lt;/span&gt; &lt;span class='varid'&gt;rs'&lt;/span&gt;  &lt;span class='comment'&gt;-- strike&lt;/span&gt;
    &lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;rs'&lt;/span&gt; &lt;span class='keyglyph'&gt;|&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varop'&gt;+&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='varop'&gt;==&lt;/span&gt; &lt;span class='num'&gt;10&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;sc'&lt;/span&gt; &lt;span class='num'&gt;3&lt;/span&gt; &lt;span class='varid'&gt;rs'&lt;/span&gt;  &lt;span class='comment'&gt;-- spare&lt;/span&gt;
            &lt;span class='keyglyph'&gt;|&lt;/span&gt; &lt;span class='varid'&gt;otherwise&lt;/span&gt;   &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;sc'&lt;/span&gt; &lt;span class='num'&gt;2&lt;/span&gt; &lt;span class='varid'&gt;rs'&lt;/span&gt;  &lt;span class='comment'&gt;-- normal&lt;/span&gt;
    &lt;span class='keyword'&gt;_&lt;/span&gt;                     &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;error&lt;/span&gt; &lt;span class='str'&gt;"ill-formed sequence of rolls"&lt;/span&gt;
  &lt;span class='keyword'&gt;where&lt;/span&gt;
    &lt;span class='comment'&gt;-- accumulate the next 'n' rolls into the score and recurse&lt;/span&gt;
    &lt;span class='varid'&gt;sc'&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;rs'&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;sc&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;s&lt;/span&gt; &lt;span class='varop'&gt;+&lt;/span&gt; &lt;span class='varid'&gt;sum&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;take&lt;/span&gt; &lt;span class='varid'&gt;n&lt;/span&gt; &lt;span class='varid'&gt;rs&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;f&lt;/span&gt; &lt;span class='varop'&gt;+&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;rs'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Here are my unit tests:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='comment'&gt;{-
                      *** Unit tests ***

             *Bowling&amp;gt; runTestTT tests
             Cases: 9  Tried: 9  Errors: 0  Failures: 0
-}&lt;/span&gt;

&lt;span class='varid'&gt;tests&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;test&lt;/span&gt;
    &lt;span class='keyglyph'&gt;[&lt;/span&gt; &lt;span class='str'&gt;"gutters"&lt;/span&gt;       &lt;span class='varop'&gt;~:&lt;/span&gt; &lt;span class='varid'&gt;score&lt;/span&gt;  &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;rep&lt;/span&gt; &lt;span class='num'&gt;20&lt;/span&gt;  &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;          &lt;span class='varop'&gt;~?=&lt;/span&gt;   &lt;span class='num'&gt;0&lt;/span&gt;
    &lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='str'&gt;"ones"&lt;/span&gt;          &lt;span class='varop'&gt;~:&lt;/span&gt; &lt;span class='varid'&gt;score&lt;/span&gt;  &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;rep&lt;/span&gt; &lt;span class='num'&gt;20&lt;/span&gt;  &lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;          &lt;span class='varop'&gt;~?=&lt;/span&gt;  &lt;span class='num'&gt;20&lt;/span&gt;
    &lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='str'&gt;"fives"&lt;/span&gt;         &lt;span class='varop'&gt;~:&lt;/span&gt; &lt;span class='varid'&gt;score&lt;/span&gt;  &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;rep&lt;/span&gt; &lt;span class='num'&gt;22&lt;/span&gt;  &lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;          &lt;span class='varop'&gt;~?=&lt;/span&gt; &lt;span class='num'&gt;150&lt;/span&gt;
    &lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='str'&gt;"strikes"&lt;/span&gt;       &lt;span class='varop'&gt;~:&lt;/span&gt; &lt;span class='varid'&gt;score&lt;/span&gt;  &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;rep&lt;/span&gt; &lt;span class='num'&gt;12&lt;/span&gt; &lt;span class='num'&gt;10&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;          &lt;span class='varop'&gt;~?=&lt;/span&gt; &lt;span class='num'&gt;300&lt;/span&gt;
    &lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='str'&gt;"1 + gutters"&lt;/span&gt;   &lt;span class='varop'&gt;~:&lt;/span&gt; &lt;span class='varid'&gt;score&lt;/span&gt;  &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='conop'&gt;:&lt;/span&gt; &lt;span class='varid'&gt;rep&lt;/span&gt; &lt;span class='num'&gt;19&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;       &lt;span class='varop'&gt;~?=&lt;/span&gt;   &lt;span class='num'&gt;1&lt;/span&gt;
    &lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='str'&gt;"first spare"&lt;/span&gt;   &lt;span class='varop'&gt;~:&lt;/span&gt; &lt;span class='varid'&gt;score&lt;/span&gt;  &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt; &lt;span class='conop'&gt;:&lt;/span&gt; &lt;span class='varid'&gt;rep&lt;/span&gt; &lt;span class='num'&gt;17&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;   &lt;span class='varop'&gt;~?=&lt;/span&gt;  &lt;span class='num'&gt;20&lt;/span&gt;
    &lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='str'&gt;"first strike"&lt;/span&gt;  &lt;span class='varop'&gt;~:&lt;/span&gt; &lt;span class='varid'&gt;score&lt;/span&gt;  &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='num'&gt;10&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt; &lt;span class='conop'&gt;:&lt;/span&gt; &lt;span class='varid'&gt;rep&lt;/span&gt; &lt;span class='num'&gt;17&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;  &lt;span class='varop'&gt;~?=&lt;/span&gt;  &lt;span class='num'&gt;30&lt;/span&gt;
    &lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='str'&gt;"last spare"&lt;/span&gt;    &lt;span class='varop'&gt;~:&lt;/span&gt; &lt;span class='varid'&gt;rscore&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt; &lt;span class='conop'&gt;:&lt;/span&gt; &lt;span class='varid'&gt;rep&lt;/span&gt; &lt;span class='num'&gt;18&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;   &lt;span class='varop'&gt;~?=&lt;/span&gt;  &lt;span class='num'&gt;15&lt;/span&gt;
    &lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='str'&gt;"last strike"&lt;/span&gt;   &lt;span class='varop'&gt;~:&lt;/span&gt; &lt;span class='varid'&gt;rscore&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='num'&gt;10&lt;/span&gt; &lt;span class='conop'&gt;:&lt;/span&gt; &lt;span class='varid'&gt;rep&lt;/span&gt; &lt;span class='num'&gt;18&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;  &lt;span class='varop'&gt;~?=&lt;/span&gt;  &lt;span class='num'&gt;20&lt;/span&gt;
    &lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='keyword'&gt;where&lt;/span&gt;
    &lt;span class='varid'&gt;rep&lt;/span&gt;    &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;replicate&lt;/span&gt;
    &lt;span class='varid'&gt;rscore&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;score&lt;/span&gt; &lt;span class='varop'&gt;.&lt;/span&gt; &lt;span class='varid'&gt;reverse&lt;/span&gt;  &lt;span class='comment'&gt;-- reverse list and then score it&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;If you have a little free time, code up a solution in your
favorite language.&lt;/p&gt;</description>
      <pubDate>Wed, 05 Apr 2006 15:18:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:ccebf69a709784ea7b53ff76c77008be</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2006/04/05/the-bowling-game-kata-in-haskell</link>
      <category>programming</category>
      <category>haskell</category>
      <category>pittsburgh</category>
      <category>haskell</category>
      <category>kata</category>
      <category>bowling</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/61</trackback:ping>
    </item>
    <item>
      <title>"The Bowling Game Kata in Haskell" by Isaac Gouy</title>
      <description>&lt;p&gt;Long ago I had some fun with &amp;#8220;The Bowling Game&amp;#8221; including &lt;a href="http://groups.google.com/group/comp.object/msg/45ed159928b69648"&gt;one &lt;/a&gt; or &lt;a href="http://groups.google.com/group/comp.object/msg/6f308490740ff11a"&gt;two&lt;/a&gt; Clean implementations.&lt;/p&gt;</description>
      <pubDate>Wed, 12 Apr 2006 19:43:22 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:</guid>
      <link>http://blog.moertel.com/articles/2006/04/05/the-bowling-game-kata-in-haskell#comment-124</link>
    </item>
  </channel>
</rss>
