Tuesday, May 10, 2011

New laptop–update

In my previous post I discussed my new laptop. In that post I mentioned that my only disappointment was the discovery that the wifi card, a Atheros AR9285, was a single-band card. I’ve recently replaced it with an Intel 622AN.HMWWB Mini PCI Express 6200 Centrino Advanced-N Wireless Adapter. The card is working great and the installation was about 10 minutes.

Hopefully some other Asus G73SW owner will find this information useful.

Wednesday, May 4, 2011

New laptop

I recently purchased a new laptop I’ve had the previous one for a couple of years now so when an opportunity to purchase a new one presented itself,  who am I to pass on it!

I had been thinking about the features for a new laptop for a while. It had to be capable of 8GB of ram, 16 would be even better. I also wanted a quad-core processor.

When the time came to start looking around, I was able to narrow the field quite quickly. I’ve been a Dell user for quite a number of years. Every computer in the house, except for one, was purchased from Dell. It was then that I hit a snag. It seems that the laptop vendors are now doing displays using the HD resolutions: 720p, 900p and 1080p.

Sadly, there is no way that I can do a 1080p screen on a 15” laptop. My eyes just aren’t what they used to be. I was hesitant to go with 720p. It would be a lot of real estate to give up from the current laptop. 900p seemed to be a good compromise but there aren’t a lot of 15" laptops that have a 900p screen.

I decided that 720p was probably the way to go but, just to make sure, I visited the local Microcenter to see what 720p looked like on a 15” laptop.

And that’s where I found the new laptop. The Asus G73sw. Everything that I wanted but with a 17” screen. A 17” screen wasn’t in the original plans but I can read 1080p on a 17” screen!

Enough with the narrative. Here’s the specs on the (now) old laptop:

Dell Vostro 1500
4GB RAM
Core 2 Duo T9300 @ 2.5GHz
NVIDIA GeForce 8600M GT

image

The (now) current laptop:gallery_left

Asus G73sw
8GB RAM (capable of 16)
Core i7-2630QM @ 2GHz (boosts to 2.9Ghz)
NVIDIA GeForce GTX 460M
Dual hard-drive capable

The ‘Q’ in the processor name stands for Quad-Core!

image

The performance boost is quite nice.

The only aspect of the Asus that I’m disappointed with is the WLAN card. It’s an Atheros AR9285. While the card does do 802.11n, it only does so at 2.4GHz. It’s not a dual-band card. I can only use one of the bands that my dual-band DLink DIR-825 supports. Luckily the Atheros is just a PCIe card so I’m hoping to replace it at some point.

Also, the wife get a “new” laptop for her birthday

Sunday, April 24, 2011

Workout Update

Back on 8 Jan, I had finished up a workout cycle and posted my lifts at that time. Since then I’ve completed four more cycles. Here are the current numbers:

Life Weight (lbs) Reps Theoretical Max (lbs)
Military Press 140 1 145
Deadlift 300 3 329
Bench Press 240 5 330
Squat 230 4 260

Just looking at the weight, you would think that I’ve gotten stronger. In fact, I feel stronger. Yet, when comparing the theoretical max between 8 Jan and now, I have dropped in all the lifts except the bench.

My guess is that I underestimated my one-rep max (ORM) for all but the bench when I started the workout. Now the reps that I’m getting are closer to those on the workout. The third week of the cycle calls for three sets at 5,3 and 1 reps respectively. Previously I was getting 10s and 12s. Now the reps are closer to schedule.

The Bench Press results are most interesting. This is the lift that I was disappointed with the most since I wasn’t seeing the gains that I was seeing with the others. In fact, I was really considering changing this part of the workout. In reality, a 60lb increase in four months is probably pretty good.

Based on the two sets of results, I think I’ll stay on the workout, unchanged, for another three or four cycles.

Sunday, April 17, 2011

Greed Kata–Second attempt

When I wrote the post on my first attempt, I mentioned that I thought I was “missing something obvious.” It occurred to me after I put up that post.

A die can only be used in one scoring combination

This is probably obvious to everyone else but I’m only responsible for what goes on in my head.

This realization push me to think that calculating the score using the Pipes and Filters pattern would probably be a good fit. I started with the data that each scorer, the filter, would operate on:

   1: public class GameContext
   2:  {
   3:      public int Score;
   4:      public int[] DiceValues;
   5:  }

Each filter would use the die values stored in the DiceValues field and update the Score field.


For the scorers, I started with the single value rules:



A single one (1) is worth 100 points.
A single five (5) is worth 50 points.


Working through lead to the following:



   1: public class ValueScorer
   2: {
   3:     private readonly int _die;
   4:     private readonly int _value;
   5:  
   6:     public ValueScorer(int die, int value)
   7:     {
   8:         _die = die;
   9:         _value = value;
  10:     }
  11:  
  12:     public GameContext Compute(GameContext context)
  13:     {
  14:         if (0 == context.DiceValues.Length) return context;
  15:         var occurances = Array.FindAll(context.DiceValues, v => v== this._die).Length;
  16:         context.Score += occurances * this._value;
  17:  
  18:         List<int> diceValues = RemoveValuesUsedInAScoringCombination(context.DiceValues, occurances);
  19:         context.DiceValues = diceValues.ToArray();
  20:  
  21:         return context;
  22:     }
  23:  
  24:     private List<int> RemoveValuesUsedInAScoringCombination(int[] currentDiceValues, int occurances)
  25:     {
  26:         var diceValues = new List<int>(currentDiceValues);
  27:         foreach (var ii in Enumerable.Range(1, occurances))
  28:         {
  29:             diceValues.Remove(this._die);
  30:         }
  31:         return diceValues;
  32:     }
  33: }


The next set of rules:


A set of three ones (1) is worth 1000 points
A set of three of any other number is worth 100 time that number (ex. {2,2,2} = 200 points}.

For which I ended up with:

 


   1: public class TripleScorer
   2: {
   3:     public GameContext Compute(GameContext context)
   4:     {
   5:         if (0 == context.DiceValues.Length) return context;
   6:  
   7:         var triples = context.DiceValues.GroupBy(d => d).Where(g => g.Count() >= 3);
   8:  
   9:         context.Score += triples.Sum(g => (g.Count() / 3) * ((1 == g.Key) ? 1000 : g.Key * 100));
  10:  
  11:         List<int> diceValues = RemoveValuesUsedInAScoringCombination(context.DiceValues, triples);
  12:         context.DiceValues = diceValues.ToArray();
  13:  
  14:         return context;
  15:     }
  16:  
  17:     private List<int> RemoveValuesUsedInAScoringCombination(int[] currentDiceValues, IEnumerable<IGrouping<int, int>> triples)
  18:     {
  19:         var diceValues = new List<int>(currentDiceValues);
  20:         foreach (var tripleGroup in triples)
  21:         {
  22:             int digitsToRemove = (tripleGroup.Count()/3)*3;
  23:             foreach (var ii in Enumerable.Range(1,digitsToRemove))
  24:             {
  25:                 diceValues.Remove(tripleGroup.Key);
  26:             }
  27:         }
  28:         return diceValues;
  29:     }
  30: }


The method RemoveValuesUsedInAScoringCombination() is key to making this approach work. This method updates the DiceValues array in the context to remove the values that were used. This piece enforces the constraint that a die is only used once in a scoring combination.


The driver is really straight forward and look like:



   1: public class Scorer
   2: {
   3:     public int Computer(int[] diceValues)
   4:     {
   5:         if (0 == diceValues.Length) return 0;
   6:  
   7:         var tripleScorer = new TripleScorer();
   8:         var oneScorer = new ValueScorer(1,100);
   9:         var fiveScorer = new ValueScorer(5,50);
  10:  
  11:         var context = new GameContext() {DiceValues = diceValues, Score = 0};
  12:  
  13:         context = tripleScorer.Compute(context);
  14:         context = oneScorer.Compute(context);
  15:         context = fiveScorer.Compute(context);
  16:  
  17:         return context.Score;
  18:     }
  19: }

What I find really nice about this approach is that adding additional scoring combinations is just a matter of creating another scorer. For example, say that the ruling body for the game Greed introduces the following rule:



A set of five consecutive numbers (ex. {1,2,3,4,5} or {2,3,4,5,6}) is called a Straight and is worth 2000 points.


This is easily implemented with a Scorer such as:



   1: public class StraightScorer
   2: {
   3:     public GameContext Compute(GameContext context)
   4:     {
   5:         if (0 == context.DiceValues.Length) return context;
   6:  
   7:         foreach (int startingAt in Enumerable.Range(1,2))
   8:         {
   9:             if (this.DiceValuesContainStraight(startingAt, context.DiceValues))
  10:             {
  11:                 context.Score += 2000;
  12:                 context.DiceValues = this.RemoveValuesUsedInAScoringCombination(context.DiceValues, startingAt).ToArray();
  13:             }
  14:         }
  15:  
  16:         return context;
  17:     }
  18:  
  19:     private bool DiceValuesContainStraight(int straightStartsAt, int[] diceValues)
  20:     {
  21:         foreach (var n in Enumerable.Range(straightStartsAt,5))
  22:         {
  23:             if (!diceValues.Contains(n)) return false;
  24:         }
  25:         return true;
  26:     }
  27:  
  28:     private List<int> RemoveValuesUsedInAScoringCombination(int[] currentDiceValues, int startingAt)
  29:     {
  30:         var diceValues = new List<int>(currentDiceValues);
  31:         foreach (var n in Enumerable.Range(startingAt, 5))
  32:         {
  33:             diceValues.Remove(n);
  34:         }
  35:         return diceValues;
  36:     }
  37:  
  38: }

The driver gets modified as:



   1: public class Scorer
   2: {
   3:     public int Computer(int[] diceValues)
   4:     {
   5:         if (0 == diceValues.Length) return 0;
   6:  
   7:         var straightScorer = new StraightScorer();
   8:         var tripleScorer = new TripleScorer();
   9:         var oneScorer = new ValueScorer(1,100);
  10:         var fiveScorer = new ValueScorer(5,50);
  11:  
  12:         var context = new GameContext() {DiceValues = diceValues, Score = 0};
  13:  
  14:         context = straightScorer.Compute(context);
  15:         context = tripleScorer.Compute(context);
  16:         context = oneScorer.Compute(context);
  17:         context = fiveScorer.Compute(context);
  18:  
  19:         return context.Score;
  20:     }
  21: }

Modifying the previous version would not have been nearly as simple.

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.