Kata–Greed Kata

While at Codemash this year, I was introduced to ‘katas’.  It’s a great idea really – where you are given a problem to solve and you work through it using whatever language and technique you want.   Take a look at Ryan Cromwell’s post ‘The Purpose of Katas’ to learn more.

So, actually I went with Ryan to Codemash and instead of just going to a session the entire day, there were opportunities to try some new stuff.  Ryan and I took a session off, desiring to do some coding, and went to the Codemash ‘Coding Dojo’ where you could pair up or even solve the kata alone. 

I will admit, I was a bit bewildered, as I really didn’t quite get it at first, as I really didn’t know what a kata was!  I ended up closing my lid of my laptop and leaned over to watch the process Ryan was doing.   For experienced kata developers in the dojo, they were off and running and pounding out the code in the allotted 30 minute timeframe.  Honestly, I spent my whole time trying to figure out what the kata meant!

When I got home from Codemash, one of my goals was to work through some kata’s to gain some experience and not be such a newbie.  My first week home I went through the bowling kata, following along with Uncle Bob (Bob Martin) – I highly suggest following along his powerpoint presentation : http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata (check out this as well – adapted for C# 4 : http://www.slideshare.net/stewshack/bowling-game-kata-c ).  I went through this kata several times, attempting to grasp the flow and technique.  I don’t think kata’s are just meant to blindly work through and instead, start to develop an eye for when to refactor, how to use TDD, spotting patterns (ie. http://cleancoder.posterous.com/the-transformation-priority-premise) etc…  You don’t ‘have’ to use TDD to do a kata, but honestly, I am going to say that it would really defeat the purpose not too!

Ok, so all that aside, today I decided to re-try the Greed kata.   This time around, I didn’t want to follow along with any guide, just to try to solve it myself.  What I’m going to show is my ‘final product’ – although I think I need to figure out a way to do as Bob Martin did and go through my thought process – as this final product was not how I started.  I went through many iterations and steps (and although I can barely follow that link about transformation priority- I will say I think I saw that action – lol!).  I learned a few things going through this such as the TestCase concept – which I saw used at Codemash and thought was a clever way to test sets of data.   I am open to any feedback on my solution, as I don’t really like my ‘switch…case’ solution – so I will be looking to refine this the next time I run through the kata.   Kata’s are meant to be repeated over and over again.

Greed Kata

Greed is a simple dice game in which players roll a number of dice and determine their score based on combinations of dice rolled.  In an actual game, players would be allowed to re-roll unused dice until they arrived at their final score for one of their turns, and a game might be played up to a certain point total.  The game can be played with different numbers of dice.
For the purposes of this kata, the game will use 5 dice and will not allow any re-rolls.  A Game class with a Score method will return the player’s score for a given roll of the dice.  The following scoring rules will be used:

•    A set of 3 1’s [1,1,1] is worth 1000 points
•    A set of 3 of any other number is worth 100 * that number (e.g. [2,2,2] is worth 200 points)
•    A single 1 is worth 100 points
•    A single 5 is worth 50 points
•    Any other die or combination is worth 0 points

Requirements

•    Write a class named “Game” that has a public Score() method accepting a collection of dice values.
•    Implement the rules above however you like, so that the correct score is returned for a given roll of 5 dice

My solution:

First the test using NUnit – (if using Visual Studio with Nuget – you can do ‘Install-Package NUnit’) :

[TestFixture]
    public class GreedScoreTester
    {
        [TestCase(1, 1, 1, 2, 3, 1000)]
        [TestCase(1, 1, 1, 1, 5, 1150)]
        [TestCase(1, 1, 1, 1, 1, 1200)]
        [TestCase(2, 3, 4, 6, 2, 0)]
        [TestCase(3, 4, 5, 3, 3, 350)]
        [TestCase(1, 5, 1, 2, 4, 250)]
        public void GameScore(int die1, int die2,int die3, int die4, int die5, int expectedScore)
        {
            var values = new int[]{die1, die2, die3, die4, die5};
            var greed = new Greed();
            int score = greed.Score(values);
            Assert.That(score == expectedScore);
        }
    }

Basically, the TestCase allows me to pass different sets of data to my GameScore test.  Since there are 5 dice being rolled, I can control the values being passed in.  Additionally, I pass the expected value with the set to assert on.

Next is the Greed class:

public class Greed
    {
        public int Score(int[] ints)
        {
            IEnumerable<IGrouping<int, int>> groupedDieRolls = ints.GroupBy(c => c);
            return groupedDieRolls.Sum(g => ScoreSet(g.Key, g.ToList()));
        }

        private static int ScoreSet(int key, IList<int> values)
        {
            int score = 0;
            var count = values.Count;
            switch(key)
            {
                case 1:
                    if (count >= 3)
                    {
                        score += 1000;
                        int extraOnes = count - 3;
                        score += (extraOnes*100);
                    }
                    else
                    {
                        score += (count*100);
                    }
                    break;
                case 5:
                    if (count >= 3)
                    {
                        score += (key * 100);
                        int extraFives = count - 3;
                        score += (extraFives * 50);
                    }
                    else
                    {
                        score += (count * 50);
                    }
                    break;
                default:
                    if (count >= 3)
                        score += (key * 100);
                    break;
            }
            return score;
        }
    }

As I mentioned above, the only real issue I have with my solution is the switch…case – I would like to have a more robust solution.  Then again, this was my first attempt at the kata.

In my initial code experience I started with an array of ints.  Then I moved to a dictionary of ints – as I wanted to group my values.  My last refactor was to use the Linq ‘GroupBy’.

Well, it was fun, I plan now on going out and seeing other examples.  One thing I didn’t mention above is that some people like to use the kata’s to learn new skills, ie. do it with Vim, do it with Ruby, etc… since I’m very new, I stuck to C# but hope to expand!

Advertisements

Kata–Greed Kata

While at Codemash this year, I was introduced to ‘katas’.  It’s a great idea really – where you are given a problem to solve and you work through it using whatever language and technique you want.   Take a look at Ryan Cromwell’s post ‘The Purpose of Katas’ to learn more.

So, actually I went with Ryan to Codemash and instead of just going to a session the entire day, there were opportunities to try some new stuff.  Ryan and I took a session off, desiring to do some coding, and went to the Codemash ‘Coding Dojo’ where you could pair up or even solve the kata alone. 

I will admit, I was a bit bewildered, as I really didn’t quite get it at first, as I really didn’t know what a kata was!  I ended up closing my lid of my laptop and leaned over to watch the process Ryan was doing.   For experienced kata developers in the dojo, they were off and running and pounding out the code in the allotted 30 minute timeframe.  Honestly, I spent my whole time trying to figure out what the kata meant!

When I got home from Codemash, one of my goals was to work through some kata’s to gain some experience and not be such a newbie.  My first week home I went through the bowling kata, following along with Uncle Bob (Bob Martin) – I highly suggest following along his powerpoint presentation : http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata (check out this as well – adapted for C# 4 : http://www.slideshare.net/stewshack/bowling-game-kata-c ).  I went through this kata several times, attempting to grasp the flow and technique.  I don’t think kata’s are just meant to blindly work through and instead, start to develop an eye for when to refactor, how to use TDD, spotting patterns (ie. http://cleancoder.posterous.com/the-transformation-priority-premise) etc…  You don’t ‘have’ to use TDD to do a kata, but honestly, I am going to say that it would really defeat the purpose not too!

Ok, so all that aside, today I decided to re-try the Greed kata.   This time around, I didn’t want to follow along with any guide, just to try to solve it myself.  What I’m going to show is my ‘final product’ – although I think I need to figure out a way to do as Bob Martin did and go through my thought process – as this final product was not how I started.  I went through many iterations and steps (and although I can barely follow that link about transformation priority- I will say I think I saw that action – lol!).  I learned a few things going through this such as the TestCase concept – which I saw used at Codemash and thought was a clever way to test sets of data.   I am open to any feedback on my solution, as I don’t really like my ‘switch…case’ solution – so I will be looking to refine this the next time I run through the kata.   Kata’s are meant to be repeated over and over again.

Greed Kata

Greed is a simple dice game in which players roll a number of dice and determine their score based on combinations of dice rolled.  In an actual game, players would be allowed to re-roll unused dice until they arrived at their final score for one of their turns, and a game might be played up to a certain point total.  The game can be played with different numbers of dice.
For the purposes of this kata, the game will use 5 dice and will not allow any re-rolls.  A Game class with a Score method will return the player’s score for a given roll of the dice.  The following scoring rules will be used:

•    A set of 3 1’s [1,1,1] is worth 1000 points
•    A set of 3 of any other number is worth 100 * that number (e.g. [2,2,2] is worth 200 points)
•    A single 1 is worth 100 points
•    A single 5 is worth 50 points
•    Any other die or combination is worth 0 points

Requirements

•    Write a class named “Game” that has a public Score() method accepting a collection of dice values.
•    Implement the rules above however you like, so that the correct score is returned for a given roll of 5 dice

My solution:

First the test using NUnit – (if using Visual Studio with Nuget – you can do ‘Install-Package NUnit’) :

[TestFixture]
    public class GreedScoreTester
    {
        [TestCase(1, 1, 1, 2, 3, 1000)]
        [TestCase(1, 1, 1, 1, 5, 1150)]
        [TestCase(1, 1, 1, 1, 1, 1200)]
        [TestCase(2, 3, 4, 6, 2, 0)]
        [TestCase(3, 4, 5, 3, 3, 350)]
        [TestCase(1, 5, 1, 2, 4, 250)]
        public void GameScore(int die1, int die2,int die3, int die4, int die5, int expectedScore)
        {
            var values = new int[]{die1, die2, die3, die4, die5};
            var greed = new Greed();
            int score = greed.Score(values);
            Assert.That(score == expectedScore);
        }
    }

Basically, the TestCase allows me to pass different sets of data to my GameScore test.  Since there are 5 dice being rolled, I can control the values being passed in.  Additionally, I pass the expected value with the set to assert on.

Next is the Greed class:

public class Greed
    {
        public int Score(int[] ints)
        {
            IEnumerable<IGrouping<int, int>> groupedDieRolls = ints.GroupBy(c => c);
            return groupedDieRolls.Sum(g => ScoreSet(g.Key, g.ToList()));
        }

        private static int ScoreSet(int key, IList<int> values)
        {
            int score = 0;
            var count = values.Count;
            switch(key)
            {
                case 1:
                    if (count >= 3)
                    {
                        score += 1000;
                        int extraOnes = count - 3;
                        score += (extraOnes*100);
                    }
                    else
                    {
                        score += (count*100);
                    }
                    break;
                case 5:
                    if (count >= 3)
                    {
                        score += (key * 100);
                        int extraFives = count - 3;
                        score += (extraFives * 50);
                    }
                    else
                    {
                        score += (count * 50);
                    }
                    break;
                default:
                    if (count >= 3)
                        score += (key * 100);
                    break;
            }
            return score;
        }
    }

As I mentioned above, the only real issue I have with my solution is the switch…case – I would like to have a more robust solution.  Then again, this was my first attempt at the kata.

In my initial code experience I started with an array of ints.  Then I moved to a dictionary of ints – as I wanted to group my values.  My last refactor was to use the Linq ‘GroupBy’.

Well, it was fun, I plan now on going out and seeing other examples.  One thing I didn’t mention above is that some people like to use the kata’s to learn new skills, ie. do it with Vim, do it with Ruby, etc… since I’m very new, I stuck to C# but hope to expand!

New Opportunity!

I’ll be shifting gears as I am departing the best consulting company in southwest Ohio (Strategic Data Systems) !  I will certainly miss the great developers that work there. 

That said, I’m excited to announce that I’ll be taking on a new position with Applied Information Sciences (AIS) as a Principle Software Engineer in Beavercreek, OH.  AIS is a Microsoft Managed Gold Partner, based out of Reston, Virginia and has offices in Maryland, Texas, and Ohio.

Just recently (September 2010) AIS setup an office in the Dayton area and they are expanding to grow a great team of developers interested in building products and solutions for our customers with the latest and greatest .net technologies.

I’m off to an exciting start of a new year !  One of my new personal objectives and goals will be to help grow and support the Dayton .NET area, in particular and to start with the Dayton .NET User group – to be more active and involved there.  Several of my SDS co-workers are heavily involved in the Cincinnati .NET user group and I watched that grow over time and produce some good speakers and community.

So – here is to 2011 – let’s hope it brings new and exciting challenges!