Things I learned about comparing two poker hands in C#

I’ve been going through Visual C# 2005: How to Program, 2/e and I recently got stuck on problem 30 in chapter 8. Chapter 8 deals with arrays and problem 30 is an innocent thing asking you to compare 2 hands of poker. Well, I spend a good month fucking around with this problem thinking to myself, there is NO WAY it should be this convoluted and hard. After finishing it yesterday, it turns out it is. The Coding the Wheel site has an entire page devoted to poker hand evaluations and my code looks remarkably like the naive implementation. My implementation is more difficult because beyond the initial hand evaluation, it tries to compare the hands and account for ties all the way down to a perfect tie, which in poker results in a pot split. I always thought suits would be used to break ties, but that isn’t an official rule according to Wikipedia. I found a few things significantly hampered me in my particular implementation.

  1. I should have developed using TDD. I developed the test code below AFTER I had written a significant portion of code, which killed me since I had to scrap a lot of that poorly tested code and rewrite my algorithms. I’ve posted a portion of the test code below. The only thing of note here is that I created an Enumeration called Hands which contained all of all the poker hands which I passed into this method.

    BuildHand method of DeckOfCardsTest class

     private void BuildHand(Card[] pokerHand, Hands typeOfHand) {
                int counter;
    
                string[] suits = { "Hearts", "Diamonds", "Clubs", "Spades" };
                string[] faces = { "Ace", "Deuce", "Three", "Four", "Five", "Six",
     "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" };
    
                // designate default suit 
    for cards as Hearts and default face as deuce
                string testSuit = suits[0];
                string testFace = faces[1];
    
                Card card;
    
                switch (Convert.ToInt32(typeOfHand)) {
                    // Create high card hand
                    case 0:
                        testSuit = suits[0];
                        for (counter = 0; counter < pokerHand.Length; ++counter) {
                            switch (counter) {
                                case 0:
                                    testFace = faces[2];
                                    testSuit = suits[3];
                                    break;
                                case 1:
                                    testFace = faces[9];
                                    testSuit = suits[1];
                                    break;
                                case 2:
                                    testFace = faces[12];
                                    testSuit = suits[2];
                                    break;
                                case 3:
                                    testFace = faces[4];
                                    testSuit = suits[3];
                                    break;
                                case 4:
                                    testFace = faces[random.Next(4,9)];
                                    testSuit = suits[1];
                                    break;
                            }
                            card = new Card(testFace, testSuit);
                            pokerHand[counter] = card;
                        }
                        break;
                    // Create pair hand
                    case 1:
                        int pair = random.Next(0, 7);
                        for (counter = 0; counter < pokerHand.Length; ++counter) {
                            switch (counter) {
                                case 0:
                                    testFace = faces[pair];
                                    testSuit = suits[0];
                                    break;
                                case 1:
                                    testFace = faces[pair];
                                    testSuit = suits[1];
                                    break;
                                case 2:
                                    testFace = faces[7];
                                    testSuit = suits[2];
                                    break;
                                case 3:
                                    testFace = faces[9];
                                    testSuit = suits[3];
                                    break;
                                case 4:
                                    testFace = faces[10];
                                    testSuit = suits[1];
                                    break;
                            }
                            card = new Card(testFace, testSuit);
                            pokerHand[counter] = card;
                        }
                        break;                
  2. I REALLY should have implemented a HandOfPoker class instead of using a Card array directly. This would have cleaned up my code quite a bit because each HandOfPoker object could have contained the frequency arrays I was using to store my face and suit counts. I also could have stored the hand results directly as properties instead of having to immediately compare after evaluation. See some of my ugly code below. Notice the massive redundancy as I compare the two hands. Sorry about some of the code getting cut off, but I can’t make it appear without ruining the formatting which will make it impossible to read. It’s not really for analysis, but to demonstrate what I could have improved.
    CompareTwoHands method from DeckOfCards class
    public void CompareTwoHands(Card[] firstHand, Card[] secondHand) {
                Hands firstHandResult;
                Hands secondHandResult;
    
                int counter;
                int cardCounter;
                int highestCardCount;
    
                int firstHandHighCard = faceValues.Length;
                int secondHandHighCard = faceValues.Length;
    
                // for each hand we will create 
    a frequency array for the faces (13) and suits (4)
                int[] faceCountsFirstHand;
                int[] suitCountsFirstHand;
    
                int[] faceCountsSecondHand;
                int[] suitCountsSecondHand;
    
                faceCountsFirstHand = CountFaceCards(firstHand);
                suitCountsFirstHand = CountSuitCards(firstHand);
    
                faceCountsSecondHand = CountFaceCards(secondHand);
                suitCountsSecondHand = CountSuitCards(secondHand);
    
                firstHandResult = 
    		AssessHand(faceCountsFirstHand, suitCountsFirstHand);
                secondHandResult = 
    		AssessHand(faceCountsSecondHand, suitCountsSecondHand);
    
                if (firstHandResult > secondHandResult) {
                    Console.WriteLine("The first hand won with "
     + DisplayHand(firstHandResult,faceCountsFirstHand,suitCountsFirstHand) + 
    " beating " +
     DisplayHand(secondHandResult,faceCountsSecondHand,suitCountsSecondHand));
                }
                else if (firstHandResult < secondHandResult) {
                    Console.WriteLine("The second hand won with " + 
    DisplayHand(secondHandResult,faceCountsSecondHand,suitCountsSecondHand) + " beating " +
     DisplayHand(firstHandResult,faceCountsFirstHand,suitCountsFirstHand));
                }
                else if (firstHandResult == secondHandResult) {
                    switch (Convert.ToInt32(firstHandResult)) {
                        case 1:
                            highestCardCount = 2;
                            for (cardCounter = highestCardCount; cardCounter > 0; --cardCounter) {
                                for (counter = faceCountsFirstHand.Length - 1; counter > 0; --counter) {
                                    if (faceCountsFirstHand[0] == highestCardCount || faceCountsSecondHand[0] == highestCardCount) {
                                        if (faceCountsFirstHand[counter] != faceCountsSecondHand[counter]) {
                                            firstHandHighCard = faceCountsFirstHand[counter];
                                            secondHandHighCard = faceCountsSecondHand[counter];
                                            cardCounter = 0;
                                            break;
                                        }
                                    }
                                    else if (faceCountsFirstHand[counter] == highestCardCount || faceCountsSecondHand[counter] == highestCardCount) {
                                        if (faceCountsFirstHand[counter] != faceCountsSecondHand[counter]) {
                                            firstHandHighCard = faceCountsFirstHand[counter];
                                            secondHandHighCard = faceCountsSecondHand[counter];
                                            cardCounter = 0;
                                            break;
                                        }
                                    }
                                }
                                if (counter == 1 && firstHandHighCard == secondHandHighCard) {
                                    highestCardCount = highestCardCount - 1;
                                }
                            }
                            break;

 

But you  know what? After doing all this, I’m pretty content with finishing it. I’m really fired up about what I learned, and after looking over some of the better solutions on Coding the Wheel, I realize that my solution is hampered by my tools, in this case my tool being the data structure Array which I’m being asked to use exclusively ( and I don’t really know anything else either. 🙂 ).

Hope this helps someone else trying to learn about this problem!

Advertisements

How long will it take for the Washington State Department of Licensing to renew my expired tabs?

20 days.

I have been driving around in mortal fear of the police since April 1st. In all the hustle and bustle of getting laid off, I totally forgot to renew my tabs on time. I sent in the payment on the 6th by mail and I just got them today ( the 25th ). So if you let your tabs expire, drive slow, don’t run any lights, and watch out for cops because you’ll have to wait 20 days to get your new tabs. It might be faster doing it online, but you have to pay a surcharge, and I was trying to save some dollars. Was it worth it? I dunno, but I got real good at identifying cop cars. 🙂

Signing up for COBRA: Yes! ( or Thank you Obama and the Country for passing the American Recovery and Reinvestment Act (ARRA) 2009 )

Since my last day at Microsoft was the 23rd of March, one important decision I had to make was signing up for COBRA. If you don’t know, COBRA stands for Consolidated Omnibus Budget Reconciliation Act. There is lots of information available, but in summary, it’s a temporary form of health coverage that you can elect to have until you are able to obtain insurance again through your employer or through an individual plan. In the past, it was difficult to choose to select since even for a single guy like myself, COBRA normally would have cost $323.00/month. That’s right, for a single month’s of health coverage for a single, healthy male, it would cost over three hundred dollars! That’s not even including dental which will add between $20-50 to the final price. Of course, you could always try to get an individual plan, but the coverage is usually pretty terrible, and of course you have to submit to a test for pre-existing conditions. Hopefully you’ve never had a lapse in coverage, but if you have, then you’ll probably be rendered ineligible or priced out of reason.

Let’s assume you qualify, here are the rates for a single, non-smoking male around 30 years of age through Group Health Cooperative:

Plan Name and Deductable Coinsurance % Office Visit Monthly Cost
Balance 5000 Catastrophic Plan 50 $30 $62
HSA 2000 Catastrophic Plan 10 10% $71
Welcome 3500 Plan 50 50% $73
Balance 2500 Catastrophic Plan 40 $30 $75
Welcome 1750 Plan 40 40% $89
Balance 1500 Plan 30 $30 $192
Balance 1000 Plan 20 $30 $228
Welcome 500 Plan 20 $30 $262

As you can see, there are certainly much cheaper plans, but you’ll also notice that the coverage is sketchy at best. Although you have health insurance, having a $2500 deductable on top of $30 co-pays and a $75 per month fee isn’t exactly reassuring. It make sure you have coverage for a single catastrophic event, but you’ll be buried in debt after 2 years of this. And you can see that the better plans have monthly costs that rise sharply – the first plan to hit a $1500 deductable is almost two hundred a month. Still cheaper than COBRA, but the coverage and overall costs with Coinsurance and deductable is much worse than most employer plans.

Well, what to do? Well Hallelujah! In 2009, President Obama and the American People passed the American Recovery and Reinvestment Act (ARRA). The long and the short of it means that if you are an eligible worker ( getting laid off from Microsoft counts ), you are on the hook for 35% of your COBRA premium for 9 months. Through a combination of government dollars and whatever else, the other 65% is paid for. This means that the $323.00 per month a single male like myself would normally pay gets a subsidy of $209.95 bringing the total cost down to $113.05!!! That’s lower than the Balance 1500 plan and offers significantly better benefits! On top of that, it’s now SUPER easy to sign up for COBRA benefits. Just head on over to http://cobra.ehr.com. Your separation paperwork from MS should have your User ID. To create a new user id, just click on the link above the login text boxes:

image

Here is the tricky part. During your user creation, there will be a screen asking you to accept the ARRA money. DO IT!!! It’s your ONLY chance to accept it. Once you waive it, you are done! I’m sure there is a way in case you accidentally click no, but don’t cause yourself pain. Getting laid off is hard enough already. Just be careful and select the right option!

Once you are logged in, you’ve only got 1 option:

image

Just proceed and setup your COBRA enrollment. The only other tricky part is your subsidized cost won’t show up until you enter in all your information. So don’t get freaked out by the high cost, it will show your actual cost in the final screen. One more word of advice, when you print the summary for your records, select Landscape otherwise part of the data will get cutoff.

So there you go! Your government dollars at work! I hope this helps someone get the health coverage they need at a price they can afford until they get a job. I know I am really thankful for this.

Persepolis (2007) Film review

Last night my fiance and I watched Persepolis, an autobiographical film by Marjane Satrapi based on her graphic novels. I had heard about this film on the New York Times when it had been released and was intrigued by the story, but I never had a chance to see it. Enter the Netflix, and we had it delivered to our doorstep. My short take on it would be that I really liked the film, but it was really sad.

I was really shocked that I probably learned more about Iran’s history in the movie than I had in my entire U.S. education. I’m a little ashamed about it, and I went to Wikipedia to verify some of the larger details. From what I can gather, its a mostly accurate depiction of the history of Iran during that time period. It’s pretty sobering stuff, with the ultimate kicker being that even though our country has an IMMENSE dependence upon this nation, and has participated in major political events, it is nothing more than a footnote in our history books, if that. I don’t ever recall learning about the Middle East during any of my school classes or at University. I think that it is remarkable that we should know so little about this nation, and continually wonder at our continued inability to understand them, or even interact with them in a reliable manner. Look at how well we understand Canadian or British history and we still have issues understanding them.

That other thing that really stood out to me was the similarities in the revolution with Vietnams. Reading some more about it, I know that some of the fundamental reasons were different, but in essence I believe that the people rebelled in the hopes of something better and were only given an even worse country for their efforts. In a way, I felt a kinship with the Iranian people I don’t think I would have felt without watching the movie. If you aren’t from a country that was torn by revolution and clouded over by disappointment, I think it’s hard to have that same feeling, but if you are, then this movie will really speak to you.

Two thumbs up.

A Tale of 2 Batteries

If you read my HTC Vox S710 review, you may remember that one of my major gripes with the phone was the terrible battery life. Being the enterprising individual I am, I started checking out alternatives to getting a new phone since I wanted to save money. If you check out the official HTC replacement battery options, you’ll see that they cost around $40.00 USD. Now, considering you can pick up some cheap dumb phone for that much, it’s not a very appealing option. If you dig deeper you’ll find a whole mess of battery options for dirt cheap. I mostly looked on eBay, but you can find similar items online.

I chose eBay because the prices are even cheaper than online, more like 8 dollars. I won my auction for $7.90 USD and free shipping! I admit, I was trepidatious about the whole thing, but reasoning if it was totally bogus, the worst off I’d be was 8 dollars poorer, I pulled the trigger.

It arrived in a non-descript manila envelope in some bubble wrap and that’s about it. Looking at it for the first time did not leave a good impression. Janky as hell is about the best way to describe what I felt.  I mean, look at these 2 shots comparing the new (left) and old (right) batteries:

 

HTC S710 old and new batteries 1

HTC S710 old and new batteries 2

I mean, jeez! The new battery was about as stiff as a wet piece of paper and looked like its contents were about ready to come out if I looked at it wrong. To top it off, its poor construction made its shape slightly larger than the actual battery opening, and in trying to force it in, I just about tore off the plastic end cap on one end. Take a look!

HTC S710 old and new batteries 3

At this point I was scared that if I put the battery into my phone it would spontaneously combust, sending me to an ignoble end to save a measly 30 dollars. Never being one to be accused of too much caution, I stuffed the battery in and hit the power button.

It turned on and buzzed in my hands, going through its normal boot up without any issues.  I sighed with relief and once the phone was done with its ( painfully slow ) startup, the phone was sitting there with 3 bars of juice. Nothing to get too excited about, because my other battery said that too, only to fuck me right in the ass as soon as I tried to do anything such as place a call, check e-mail, look of the time, etc. Relieved that the phone simply didn’t blow up, I got ready for bed and set the phone down next to my bed. Here was the true test. After sitting around all night, if I could get up and check Microsoft’s stock and the New York Times from bed, then the battery would be declared a success. Sleep….

Next morning I checked the phone. 2 bars! Let’s see what it had. At this point, the phone floored me. It took everything I had and laughed. Gmail, Wall Street Journal, New York Times, stocks, I even turned on the Wi-Fi and browsed some sites. The battery life hardly budged! Not believing it I carried the phone with me all day and evening and charged it over night to 100%. Damn! The phone was AMAZING! I had long phone calls, walks in the park, internet, e-mail, everything! The phone would even safely go for 2 days on a single charge! In fact, the battery life was so good that its made my happy with my phone again.

So many of the weaknesses of the phone become more tolerable with good battery life, or conversely they become worse with poor battery life. Think about it, if loading a web page too a long time AND sucked your battery dry, would you get pissed? But in the same scenario, if it took a long time, but didn’t drain any life, sure it would be annoying, but not a killer in the same way as the former scenario. I would recommend ANY Windows Mobile user to consider getting a new battery if they are unhappy with the phone. You can thank me later. 🙂 In case anyone is interested, I used this seller on eBay: http://myworld.ebay.com/centexwireless.

Floods and The Great Seattle Move of ‘05

More photos from my past. These are from my move to Seattle. Check out the album!

1) Flooded house

2005 was a CRAZY year for me. I had just quit my job at Lockheed Martin and was getting ready to move to Seattle. I had flown my friend Sean Fitzgerald out to help me move and drive cross country when just before leaving, one of the worst floods to hit Upstate New York in over 10 years. My friends put us up until the waters receded, but in spite of our preparations, the flooding in the house hit all but the highest floor. You can see some pictures of the house, but here is the basement afterwards:

Post Flood Basement

The mud was an inch think and was infested with sewage and whatever else you can think of. My friends later told me the entire house was condemned and torn down. I suppose its hard to imagine if you haven’t gone through it, but a flood is probably one of the worst things you can experience. The worst part about the flood is what it does to things after the waters recede. Anything touched by the water will be damaged and it leaves behind a horrible stench as the nutrient rich mud deposited by the flood waters coat everything in sight.

2) KPOF Catholic Radio in Denver

So after leaving Upstate New York, Sean and I have an uneventful drive to my mom’s place in Michigan. After a few days of R&R, we head off to our next destination: Denver. The purpose of this visit is mainly to meet a girl my mom was trying to set me up with. That is a story for another day, but to get to the point, right before we head into Denver proper, we spy a MASSIVE red building. I head off the freeway to check it out. Apparently its called “The Big Red Castle” and it runs a radio station. We didn’t know that at the time, but the building is absolutely gorgeous and in the middle of nowhere. Totally awesome.

The Big Red Castle KPOF Radio Studios

3) Denver Proper

We stayed with my mom’s good friend in Seattle. During the evening I was suppose to hang out with the girl, but during the day, she was busy at school, so Sean and I took a tour of the town. Did you know Denver has a Mint? Sorry, no pictures inside the mint, it’s not allowed for security purposes. And a pretty awesome Capitol building if I may say so myself. My friend’s mom has a super nice place and treated us like son’s coming home from war. A bit out of the way if you ever drive across the U.S., but I liked Denver.

The Capitol Building:

Capitol Dome

Denver’s Public Library:

Me at the Denver LIbrary

Denver has a GIANT amphitheatre in the center of the downtown:

Top of the world ma!

4) The Flaming Gorge and The Craters of the Moon

I’ll never know how we ended up in Flaming Gorge. I guess from what Sean and I can remember, we were at a gas station or an Arby’s or something, when this older guy, maybe early 40’s spins us a yarn about this gorge in the West that’s so fucking beautiful, at sunset it looks like its on fire. So it gets the name Flaming Gorge and done deal, right? Well, apparently the Flaming Gorge we went to was a desolate wasteland populated by dead cows, and crows. Maybe we weren’t suppose to come in the winter time, or maybe we went to the wrong Flaming Gorge? I dunno. But in the end, it was a good time.

Flaming Gorge

The Crater’s of the Moon was Sean’s idea. Apparently he and Sarah had wanted to see it on their road trip into Seattle, but had missed it. I think it probably would have been a great idea, but when Sean and I went, the park was completely deserted. In fact, in retrospect, I think the park was probably closed to the public entirely and somehow we just waltzed into the place. It was pretty eerie, the place had not a single other visitor and we just had free reign of the place. It got boring in the sameness, but a strange sight to behold at first glance.

Craters of the Moon

One final thing. In my photos I found an old picture of my beloved CRX. 1989 Honda CRX Si with 5-speed transmission. I learned so much about cars on that thing. I’m glad there was an old shot of the car in its glory. I sold it to some boy racer kids later on and they turned it into some The Fast and the Furious looking thing, but here she is in her stock glory.

Farewell CRX

We totally took the shot as a total fluke. We were talking about stuff when Sean mentioned his brother always took a picture of his car wherever he went. I did NOT do this, but this one shot was taken on that note.