{"id":962,"date":"2010-04-24T19:04:36","date_gmt":"2010-04-24T19:04:36","guid":{"rendered":"http:\/\/www.navision-blog.de\/2010\/04\/24\/solving-kata-yahtzee-with-fsharp-and-naturalspec\/"},"modified":"2010-04-24T19:04:36","modified_gmt":"2010-04-24T19:04:36","slug":"solving-kata-yahtzee-with-fsharp-and-naturalspec","status":"publish","type":"post","link":"http:\/\/www.navision-blog.de\/blog\/2010\/04\/24\/solving-kata-yahtzee-with-fsharp-and-naturalspec\/","title":{"rendered":"Solving KataYahtzee with F# and NaturalSpec"},"content":{"rendered":"<p>Today I\u2019m starting a new blog post series about solving code katas in <a href=\"http:\/\/msdn.microsoft.com\/en-us\/fsharp\/default.aspx\">F#<\/a> and with the help of my <a href=\"http:\/\/bitbucket.org\/forki\/naturalspec\/wiki\/Home\">NaturalSpec<\/a> project. A code kata is a programming exercise which helps to improve your skills through practice and repetition. In this series we want to use the <a href=\"http:\/\/en.wikipedia.org\/wiki\/Test-driven_development\">Test Driven Development TDD<\/a> approach which means in the context of NaturalSpec that we have to write our specs before we implement the algorithm.<\/p>\n<h4>Problem Description<\/h4>\n<blockquote>\n<p>\u201cThe game of yahtzee is a simple dice game. Each round, each player rolls five six sided dice. The player may choose to reroll some or all of the dice up to three times (including the original roll). The player then places the roll at a category, such as ones, twos, sixes, pair, two pairs etc. If the roll is compatible with the score, the player gets a score for this roll according to the rules. If the roll is not compatible, the player gets a score of zero for this roll. <\/p>\n<p>The kata consists of creating the rules to score a roll in any of a predefined category. Given a roll and a category, the final solution should output the score for this roll placed in this category.\u201d<\/p>\n<p align=\"right\">[<a href=\"http:\/\/www.codingdojo.org\/cgi-bin\/wiki.pl?KataYahtzee\">codingdojo.org<\/a>]<\/p>\n<\/blockquote>\n<h5>Category 1 \u2013 Ones, Twos, Threes, Fours, Fives, Sixes<\/h5>\n<blockquote>\n<p>\u201cOnes, Twos, Threes, Fours, Fives, Sixes: The player scores the sum of the dice that reads one, two, three, four, five or six, respectively. For example, 1, 1, 2, 4, 4 placed on &quot;fours&quot; gives 8 points.\u201d<\/p>\n<\/blockquote>\n<p>After reading this category description we could come up with the following spec:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">module<\/span> Yahtzee.Specs<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">open<\/span> NaturalSpec<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> placed_on category list =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; printMethod category<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; calcValue category list<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,1,2,4,4 placed on &quot;fours&quot; gives 8 points.&#8220; () =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1, 1, 2, 4, 4)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on Fours)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 8<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<\/p><\/div>\n<p>Since we really want to implement six different categories we should also add some more scenarios like this one:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,1,6,4,6 placed on &quot;sixes&quot; gives 12 points.&#8220; ()=&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1, 1, 6, 4, 6)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on Sixes)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 12<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">\/\/ &#8230;<\/p>\n<\/p><\/div>\n<p>Now we have some specs but they will all fail since we don\u2019t have anything implemented yet. So we have to come up with a model of dice rolls and categories. As the specs suggests we model the dice roll as a tuple of ints and the category as a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd233226.aspx\">discriminated union<\/a>:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">module<\/span> Yahtzee.Model<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">type<\/span> Roll = int * int * int * int * int<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">type<\/span> Category =<\/p>\n<p style=\"margin: 0px\">| Ones<\/p>\n<p style=\"margin: 0px\">| Twos<\/p>\n<p style=\"margin: 0px\">| Threes<\/p>\n<p style=\"margin: 0px\">| Fours<\/p>\n<p style=\"margin: 0px\">| Fives<\/p>\n<p style=\"margin: 0px\">| Sixes&#160;&#160; <\/p>\n<\/p><\/div>\n<p>The tuple is a natural choice for the dice roll, but for easier calculation we add a helper function which converts it into a list. This allows use to use the standard list functions and therefore summing the values becomes trivial:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> toList (roll:Roll) =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> a,b,c,d,e = roll<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; [a;b;c;d;e]<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> sumNumber number =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Seq.filter ((=) number)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; &gt;&gt; Seq.sum<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> calcValue category roll =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> list = toList roll<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">match<\/span> category <span style=\"color: blue\">with<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | Ones&#160;&#160; <span style=\"color: blue\">-&gt;<\/span> sumNumber 1 list<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | Twos&#160;&#160; <span style=\"color: blue\">-&gt;<\/span> sumNumber 2 list<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | Threes <span style=\"color: blue\">-&gt;<\/span> sumNumber 3 list<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | Fours&#160; <span style=\"color: blue\">-&gt;<\/span> sumNumber 4 list<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | Fives&#160; <span style=\"color: blue\">-&gt;<\/span> sumNumber 5 list<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | Sixes&#160; <span style=\"color: blue\">-&gt;<\/span> sumNumber 6 list<\/p>\n<\/p><\/div>\n<p>Now we can run our scenarios with any NUnit runner. I\u2019m using the default <a href=\"http:\/\/www.nunit.org\/\">NUnit<\/a> GUI runner here, which gives me a picture like this:<\/p>\n<p><img loading=\"lazy\" class=\"bordered\" title=\"Both specs in NUnit\" border=\"0\" alt=\"Both specs in NUnit\" src=\"http:\/\/www.navision-blog.de\/images\/SolvingKataYahtzeewithFandNaturalSpec_11049\/image_thumb.png\" width=\"500\" height=\"342\" \/><\/p>\n<h5>Category 2 \u2013 Pair<\/h5>\n<blockquote>\n<p>\u201cPair: The player scores the sum of the two highest matching dice. For example, 3, 3, 3, 4, 4 placed on &quot;pair&quot; gives 8.\u201d<\/p>\n<\/blockquote>\n<p>The kata description gives us some new scenarios. As seen above we should specify them before writing the code.<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 3,3,3,4,4 placed on &quot;pair&quot; gives 8.&#8220; () =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (3, 3, 3, 4, 4)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on Pair)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 8<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 5,3,5,4,4 placed on &quot;pair&quot; gives 10.&#8220; () =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (5, 3, 5, 4, 4)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on Pair)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 10<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,2,3,4,5 placed on &quot;pair&quot; gives 0.&#8220; () =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1, 2, 3, 4, 5)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on Pair)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 0<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify&#160;&#160;&#160;&#160;&#160; <\/p>\n<\/p><\/div>\n<p>Since we use a new category we now have to extend our model and the <strong>calcValue<\/strong> function:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">type<\/span> Category =<\/p>\n<p style=\"margin: 0px\">| Ones<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">| Sixes<\/p>\n<p style=\"margin: 0px\">| Pair<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\"><\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> sumAsPair list number =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> numberCount = <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; list <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.filter ((=) number) <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.length<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> numberCount &gt;= 2 <span style=\"color: blue\">then<\/span> 2 * number <span style=\"color: blue\">else<\/span> 0<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> calcValue category roll =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> list = toList roll<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">match<\/span> category <span style=\"color: blue\">with<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | Ones&#160;&#160; <span style=\"color: blue\">-&gt;<\/span> sumNumber 1 list<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | Sixes&#160; <span style=\"color: blue\">-&gt;<\/span> sumNumber 6 list<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | Pair&#160;&#160; <span style=\"color: blue\">-&gt;<\/span> <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; [1..6]<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.map (sumAsPair list)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.max&#160;&#160; <\/p>\n<\/p><\/div>\n<h5>Category 3 &#8211; Two pairs<\/h5>\n<blockquote>\n<p>\u201cTwo pairs: If there are two pairs of dice with the same number, the player scores the sum of these dice. If not, the player scores 0. For example, 1, 1, 2, 3, 3 placed on &quot;two pairs&quot; gives 8.\u201d<\/p>\n<\/blockquote>\n<p> <strong><\/strong>  <\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,1,2,3,3 placed on &quot;two pair&quot; gives 8.&#8220; () =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1, 1, 2, 3, 3)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on TwoPair)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 8<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,6,6,3,3 placed on &quot;two pair&quot; gives 18.&#8220; () =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1, 6, 6, 3, 3)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on TwoPair)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 18<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,1,2,4,3 placed on &quot;two pair&quot; gives 0.&#8220; () =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1, 1, 2, 4, 3)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on TwoPair)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 0<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify&#160; <\/p>\n<\/p><\/div>\n<p>Implementing this category is a little bit tricky but with the help of our Pair function and some more standard sequence combinators we can get our spec green:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">type<\/span> Category =<\/p>\n<p style=\"margin: 0px\">| Ones<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">| TwoPair<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> allPairs =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; [<span style=\"color: blue\">for<\/span> i <span style=\"color: blue\">in<\/span> 1..6 <span style=\"color: blue\">do<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">for<\/span> j <span style=\"color: blue\">in<\/span> 1..6 <span style=\"color: blue\">-&gt;<\/span> i,j]<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> calcValue category roll =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | TwoPair&#160;&#160; <span style=\"color: blue\">-&gt;<\/span> <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; allPairs<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.filter (<span style=\"color: blue\">fun<\/span> (a,b) <span style=\"color: blue\">-&gt;<\/span> a &lt;&gt; b)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.map (<span style=\"color: blue\">fun<\/span> (a,b) <span style=\"color: blue\">-&gt;<\/span> <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> a&#8217; = sumAsPair list a<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> b&#8217; = sumAsPair list b<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> a&#8217; = 0 || b&#8217; = 0 <span style=\"color: blue\">then<\/span> 0 <span style=\"color: blue\">else<\/span> a&#8217; + b&#8217;)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.max&#160;&#160;&#160;&#160; <\/p>\n<\/p><\/div>\n<h5>Category 4 &#8211; Three of a kind<\/h5>\n<blockquote>\n<p>\u201cThree of a kind: If there are three dice with the same number, the player scores the sum of these dice. Otherwise, the player scores 0. For example, 3, 3, 3, 4, 5 places on &quot;three of a kind&quot; gives 9.\u201d<\/p>\n<\/blockquote>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 3,3,3,4,5 placed on &quot;three of a kind&quot; gives 9&#8220;()=&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (3, 3, 3, 4, 5)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on ThreeOfAKind)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 9<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 3,4,3,4,5 placed on &quot;three of a kind&quot; gives 0&#8220;()=&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (3, 4, 3, 4, 5)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on ThreeOfAKind)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 0<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify <\/p>\n<\/p><\/div>\n<p>Now it is time to refactor our code. The <b>sumAsPair<\/b> function should be extended to a sumAsTuple function:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">type<\/span> Category =<\/p>\n<p style=\"margin: 0px\">| Ones<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">| ThreeOfAKind<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> sumAsTuple value list number =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> numberCount = <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; list <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.filter ((=) number) <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.length<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> takeBestTuple value list =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; [1..6]<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.map (sumAsTuple value list)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.max&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> numberCount &gt;= value <span style=\"color: blue\">then<\/span> value * number <span style=\"color: blue\">else<\/span> 0<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> calcValue category roll =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | Pair&#160;&#160; <span style=\"color: blue\">-&gt;<\/span> takeBestTuple 2 list<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | TwoPair&#160;&#160; <span style=\"color: blue\">-&gt;<\/span> <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; allPairs<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.filter (<span style=\"color: blue\">fun<\/span> (a,b) <span style=\"color: blue\">-&gt;<\/span> a &lt;&gt; b)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.map (<span style=\"color: blue\">fun<\/span> (a,b) <span style=\"color: blue\">-&gt;<\/span> <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> a&#8217; = sumAsTuple 2 list a<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> b&#8217; = sumAsTuple 2 list b<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> a&#8217; = 0 || b&#8217; = 0 <span style=\"color: blue\">then<\/span> 0 <span style=\"color: blue\">else<\/span> a&#8217; + b&#8217;)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.max<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | ThreeOfAKind \u2013<span style=\"color: blue\">&gt;<\/span> takeBestTuple 3 list<\/p>\n<\/p><\/div>\n<h5>Category 5 &#8211; Four of a kind<\/h5>\n<blockquote>\n<p>\u201cFour of a kind: If there are four dice with the same number, the player scores the sum of these dice. Otherwise, the player scores 0. For example, 2, 2, 2, 2, 5 places on &quot;four of a kind&quot; gives 8.\u201d<\/p>\n<\/blockquote>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 2,2,2,2,5 placed on &quot;four of a kind&quot; gives 8&#8220; ()=&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (2, 2, 2, 2, 5)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on FourOfAKind)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 8<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 2,6,2,2,5 placed on &quot;four of a kind&quot; gives 0&#8220; ()=&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (2, 6, 2, 2, 5)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on FourOfAKind)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 0<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify&#160;&#160; <\/p>\n<\/p><\/div>\n<p>With the help of the takeBestTuple function this becomes trivial:<\/p>\n<p style=\"margin: 0px; font-family: courier new; background: white; color: black; font-size: 10pt\"><span style=\"color: blue\">type<\/span> Category =<\/p>\n<p style=\"margin: 0px; font-family: courier new; background: white; color: black; font-size: 10pt\">| Ones<\/p>\n<p style=\"margin: 0px; font-family: courier new; background: white; color: black; font-size: 10pt\">&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px; font-family: courier new; background: white; color: black; font-size: 10pt\">| FourOfAKind<\/p>\n<p style=\"margin: 0px; font-family: courier new; background: white; color: black; font-size: 10pt\">&#160;<\/p>\n<p style=\"margin: 0px; font-family: courier new; background: white; color: black; font-size: 10pt\"><span style=\"color: blue\">let<\/span> calcValue category roll =<\/p>\n<p style=\"margin: 0px; font-family: courier new; background: white; color: black; font-size: 10pt\">&#160;&#160;&#160;&#160;&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px; font-family: courier new; background: white; color: black; font-size: 10pt\">&#160;&#160;&#160; | FourOfAKind&#160; <span style=\"color: blue\">-&gt;<\/span> takeBestTuple 4 list<\/p>\n<p style=\"margin: 0px; font-family: courier new; background: white; color: black; font-size: 10pt\">&#160;<\/p>\n<h5>Category 6 \u2013 Small straight<\/h5>\n<blockquote>\n<p style=\"margin: 0px\">\u201cSmall straight: If the dice read 1,2,3,4,5, the player scores 15 (the sum of all the dice), otherwise 0.\u201d<\/p>\n<\/blockquote>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,2,3,4,5 placed on &quot;Small Straight&quot; gives 15&#8220;()=&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1,2,3,4,5)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on SmallStraight)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 15<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,2,5,4,3 placed on &quot;Small Straight&quot; gives 15&#8220;()=&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1,2,5,4,3)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on SmallStraight)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 15<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,2,6,4,3 placed on &quot;Small Straight&quot; gives 0&#8220;()=&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1,2,6,4,3)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on SmallStraight)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 0<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify&#160; <\/p>\n<\/p><\/div>\n<p>As in all the above scenarios we don\u2019t assume any specific order in our rolls but for this category it is easier to test if the data is sorted:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">type<\/span> Category =<\/p>\n<p style=\"margin: 0px\">| Ones<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">| SmallStraight<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> calcValue category roll =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | SmallStraight <span style=\"color: blue\">-&gt;<\/span> <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">match<\/span> list |&gt; List.sort <span style=\"color: blue\">with<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; | [1;2;3;4;5] <span style=\"color: blue\">-&gt;<\/span> 15<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; | _ <span style=\"color: blue\">-&gt;<\/span> 0<\/p>\n<\/p><\/div>\n<h5>Category 7 \u2013 Large straight<\/h5>\n<blockquote>\n<p>\u201cLarge straight: If the dice read 2,3,4,5,6, the player scores 20 (the sum of all the dice), otherwise 0.\u201d<\/p>\n<\/blockquote>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 2,3,4,5,6 placed on &quot;Large Straight&quot; gives 20&#8220;()=&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (2,3,4,5,6)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on LargeStraight)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 20<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 6,2,5,4,3 placed on &quot;Large Straight&quot; gives 20&#8220;()=&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (6,2,5,4,3)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on LargeStraight)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 20<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,2,6,4,3 placed on &quot;Large Straight&quot; gives 0&#8220;()=&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1,2,6,4,3)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on LargeStraight)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 0<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify&#160; <\/p>\n<\/p><\/div>\n<p>Of course the implementation is exactly the same as for the small straight:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">type<\/span> Category =<\/p>\n<p style=\"margin: 0px\">| Ones<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">| LargeStraight<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> calcValue category roll =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | LargeStraight <span style=\"color: blue\">-&gt;<\/span> <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">match<\/span> list |&gt; List.sort <span style=\"color: blue\">with<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; | [2;3;4;5;6] <span style=\"color: blue\">-&gt;<\/span> 20<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; | _ <span style=\"color: blue\">-&gt;<\/span> 0<\/p>\n<\/p><\/div>\n<h5>Category 8 \u2013 Full house<\/h5>\n<blockquote>\n<p>\u201cFull house: If the dice are two of a kind and three of a kind, the player scores the sum of all the dice. For example, 1,1,2,2,2 placed on &quot;full house&quot; gives 8. 4,4,4,4,4 is not &quot;full house&quot;.\u201d<\/p>\n<\/blockquote>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,1,2,2,2 placed on &quot;full house&quot; gives 8.&#8220; () =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1,1,2,2,2)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on FullHouse)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 8<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 4,4,4,4,4 placed on &quot;full house&quot; gives 0.&#8220; () =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (4,4,4,4,4)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on FullHouse)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 0<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,1,2,3,2 placed on &quot;full house&quot; gives 0.&#8220; () =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1,1,2,3,2)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on FullHouse)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 0<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify <\/p>\n<\/p><\/div>\n<p>Implementing the FullHouse category is easy if we reuse our solutions to the Two pairs category:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">type<\/span> Category =<\/p>\n<p style=\"margin: 0px\">| Ones<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">| FullHouse<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> takeBestCombo value1 value2 list =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; allPairs<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.filter (<span style=\"color: blue\">fun<\/span> (a,b) <span style=\"color: blue\">-&gt;<\/span> a &lt;&gt; b)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.map (<span style=\"color: blue\">fun<\/span> (a,b) <span style=\"color: blue\">-&gt;<\/span> <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> a&#8217; = sumAsTuple value1 list a<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> b&#8217; = sumAsTuple value2 list b<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> a&#8217; = 0 || b&#8217; = 0 <span style=\"color: blue\">then<\/span> 0 <span style=\"color: blue\">else<\/span> a&#8217; + b&#8217;)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&gt; Seq.max<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> calcValue category roll =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | TwoPair&#160;&#160; <span style=\"color: blue\">-&gt;<\/span> takeBestCombo 2 2 list<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | FullHouse&#160;&#160; <span style=\"color: blue\">-&gt;<\/span> takeBestCombo 2 3 list<\/p>\n<\/p><\/div>\n<h5>Category 9 \u2013 Yahtzee<\/h5>\n<blockquote>\n<p>\u201cYahtzee: If all dice are the have the same number, the player scores 50 points, otherwise 0.\u201d<\/p>\n<\/blockquote>\n<p>Here we can use NaturalSpec&#8217;s ScenarioTemplates in order to specify all Yahtzees:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\">[&lt;ScenarioTemplate(1)&gt;]<\/p>\n<p style=\"margin: 0px\">[&lt;ScenarioTemplate(2)&gt;]<\/p>\n<p style=\"margin: 0px\">[&lt;ScenarioTemplate(3)&gt;]<\/p>\n<p style=\"margin: 0px\">[&lt;ScenarioTemplate(4)&gt;]<\/p>\n<p style=\"margin: 0px\">[&lt;ScenarioTemplate(5)&gt;]<\/p>\n<p style=\"margin: 0px\">[&lt;ScenarioTemplate(6)&gt;]<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given n,n,n,n,n placed on &quot;Yahtzee&quot; gives 50.&#8220; n =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (n,n,n,n,n)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on Yahtzee)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 50<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,1,1,2,1 placed on &quot;Yahtzee&quot; gives 50.&#8220; () =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1,1,1,2,1)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on Yahtzee)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 0<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<\/p><\/div>\n<p>The implementation is pretty easy:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">type<\/span> Category =<\/p>\n<p style=\"margin: 0px\">| Ones<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">| Yahtzee<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> calcValue category roll =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | Yahtzee <span style=\"color: blue\">-&gt;<\/span> <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> a,b,c,d,e = roll<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> a = b &amp;&amp; a = c &amp;&amp; a = d &amp;&amp; a = e <span style=\"color: blue\">then<\/span> 50 <span style=\"color: blue\">else<\/span> 0 <\/p>\n<\/p><\/div>\n<h5>Category 10 \u2013 Chance<\/h5>\n<blockquote>\n<p>\u201cChance: The player gets the sum of all dice, no matter what they read.\u201d<\/p>\n<\/blockquote>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,1,1,2,1 placed on &quot;Chance&quot; gives 6.&#8220; () =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1,1,1,2,1)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on Chance)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 6<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">[&lt;Scenario&gt;]&#160;&#160;&#160;&#160; <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> &#8220;Given 1,6,1,2,1 placed on &quot;Chance&quot; gives 11.&#8220; () =&#160;&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Given (1,6,1,2,1)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; When (placed_on Chance)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; It should equal 11<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Verify<\/p>\n<\/p><\/div>\n<p>This seems to be the easiest category as we only have to sum the values:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">type<\/span> Category =<\/p>\n<p style=\"margin: 0px\">| Ones<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">| Chance<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> calcValue category roll =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; <span style=\"color: green\">\/\/ &#8230;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; | Chance <span style=\"color: blue\">-&gt;<\/span> List.sum list<\/p>\n<\/p><\/div>\n<h5>Conclusion<\/h5>\n<p>We used a lot of F#\u2019s sequence combinators, pattern matching and discriminated unions in this kata. I think this shows that F# is very well suited for such a problem and with NaturalSpec we can easily use a TDD\/BDD approach.<\/p>\n<p>The complete source code can be found in the <a href=\"http:\/\/github.com\/forki\/NaturalSpec\/tree\/master\/src\/test\/Spec.KataYahtzee\/\">NaturalSpec repository<\/a>.<\/p>\n<p>If you want to know more about a specific part of the kata or NaturalSpec feel free to contact me.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today I\u2019m starting a new blog post series about solving code katas in F# and with the help of my NaturalSpec project. A code kata is a programming exercise which helps to improve your skills through practice and repetition. In this series we want to use the Test Driven Development TDD approach which means in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[448,8,586],"tags":[533,548,664,667,587,666,219,531],"_links":{"self":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/962"}],"collection":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/comments?post=962"}],"version-history":[{"count":0,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/962\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/media?parent=962"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/categories?post=962"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/tags?post=962"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}