Wednesday, April 13, 2011

Greed Kata–First attempt

I’ve had this on my TODO list since this year’s CodeMash conference. If you’re not already familiar with the Greed kata, or kata’s in general, take a moment and read the article on Steve Gentile’s site. You can also take a look at his solution.

For my first attempt, I made an effort to stay away from Linq. I had no specific reason for this additional constraint. I was really just curious how the solution would turn out. So with that lead-in, here’s my first attempt:

   1: public class Scorer
   2: {
   3:     public int Compute(int[] diceValues)
   4:     {
   5:         if (0 == diceValues.Length) return 0;
   6:  
   7:         Dictionary<int, int> valueGroups = GroupByDiceValue(diceValues);
   8:  
   9:         int totalScore = 0;
  10:         foreach (KeyValuePair<int, int> group in valueGroups)
  11:         {
  12:             totalScore += ScoreGroup(group.Value, group.Key);
  13:         }
  14:         
  15:         return totalScore;
  16:     }
  17:  
  18:     private int ScoreGroup(int count, int value)
  19:     {
  20:         int groupScore = 0;
  21:         if (count>=3)
  22:         {
  23:             if (value == 1) groupScore += 1000;
  24:             else groupScore += value * 100;
  25:  
  26:             count -= 3;
  27:         }
  28:             
  29:         if (1 == value)
  30:         {
  31:             groupScore += count * 100;
  32:         }
  33:             
  34:         if (5 == value)
  35:         {
  36:             groupScore += count * 50;
  37:         }
  38:         return groupScore;
  39:     }
  40:  
  41:     private Dictionary<int, int> GroupByDiceValue(int[] diceValues)
  42:     {
  43:         Array.Sort(diceValues);
  44:         var valueGroups = new Dictionary<int, int>();
  45:         foreach (int value in diceValues)
  46:         {
  47:             int count = 0;
  48:             valueGroups.TryGetValue(value, out count);
  49:             valueGroups[value] = ++count;
  50:         }
  51:         return valueGroups;
  52:     }
  53: }

And here are the tests:



   1: [TestFixture]
   2: public class ScorerTests
   3: {
   4:     
   5:     [Test]
   6:     public void Compute_WhenNoValues_Score_0()
   7:     {
   8:         var scorer = new Scorer();
   9:         Assert.That(scorer.Compute(new int[]{}), Is.EqualTo(0));
  10:     }
  11:  
  12:     [Test]
  13:     public void Compute_ThreeOnes_Score_1000()
  14:     {
  15:         var scorer = new Scorer();
  16:         Assert.That(scorer.Compute(new int[] {1,1,1,2,3}), Is.EqualTo(1000));
  17:     }
  18:  
  19:     [Test]
  20:     public void Compute_ThreeTwos_Score_200()
  21:     {
  22:         var scorer = new Scorer();
  23:         Assert.That(scorer.Compute(new int[] { 3, 2, 2, 2, 3 }), Is.EqualTo(200));
  24:     }
  25:  
  26:     [Test]
  27:     public void Compute_ThreeThreess_Score_300()
  28:     {
  29:         var scorer = new Scorer();
  30:         Assert.That(scorer.Compute(new int[] { 4, 4, 3, 3, 3 }), Is.EqualTo(300));
  31:     }
  32:  
  33:     [Test]
  34:     public void Compute_ASingleOne_Score_100()
  35:     {
  36:         var scorer = new Scorer();
  37:         Assert.That(scorer.Compute(new int[] { 4, 4, 1, 2, 2 }), Is.EqualTo(100));
  38:     }
  39:  
  40:     [Test]
  41:     public void Compute_ASingleFive_Score_50()
  42:     {
  43:         var scorer = new Scorer();
  44:         Assert.That(scorer.Compute(new int[] { 4, 4, 5, 2, 2 }), Is.EqualTo(50));
  45:     }
  46:  
  47:     [Test]
  48:     public void Compute_FourOnes_Score_1100()
  49:     {
  50:         var scorer = new Scorer();
  51:         Assert.That(scorer.Compute(new int[] { 1, 1, 1, 1, 2 }), Is.EqualTo(1100));
  52:     }
  53:  
  54:     [Test]
  55:     public void Compute_ThreeOnesAndTwoFives_Score_1100()
  56:     {
  57:         var scorer = new Scorer();
  58:         Assert.That(scorer.Compute(new int[] { 5, 5, 1, 1, 1 }), Is.EqualTo(1100));
  59:     }
  60:  
  61:     [Test]
  62:     public void Compute_ThreeThreesAndOneFives_Score_350()
  63:     {
  64:         var scorer = new Scorer();
  65:         Assert.That(scorer.Compute(new int[] { 4, 5, 3, 3, 3 }), Is.EqualTo(350));
  66:     }
  67:  
  68:     [Test]
  69:     public void Compute_NoValidScoringCombinations_Score_0()
  70:     {
  71:         var scorer = new Scorer();
  72:         Assert.That(scorer.Compute(new int[] { 2, 2, 4, 4, 3 }), Is.EqualTo(0));
  73:     }
  74:  
  75: }

I’m not unhappy with the solution but the voice in my head is nagging me that I’m missing something obvious.

1 comment:

  1. The interesting thing about katas is the path. All solutions are suitable and you shouldn't be concerned with /missing something/ just reflect on the activities lead to that end.

    For instance, what decision(s) led you to group all vs count explicitly those values that are important.

    Try to do the kata again and force yourself not to work in groups or only go through the list once or not use any ifs.

    ReplyDelete