Comparing Poker Hands using Python/NumPy
Posted on by James Thomas.
Solving the Poker Hands Code Kata using a Matrix Representation with Python and NumPy.
The PyATL Jam Session is a meet-up every first Tuesday of the month where Python programmers of different skill sets - ranging from beginners to PhDs - get together and talk about solving code problems. The Jam Session is run by J.R. Rickerson who is an awesome guy and hosted by PinDrop Security which is an interesting and successful startup in Atlanta. At these Jam Sessions, we usually solve a Code Kata. While part of solving Code Katas involves thinking through and planning a solution, we sometimes actually code out the solutions as well. January's jam session used the poker hand comparison code kata, as its called. I highly suggest viewing the problem and reading it before continuing in order to get an idea of the problem more completely and understand the test cases.
Before I explain my solution to the code kata (or nearly completed solution that I have elected not to fix entirely), I would like to explain why I decided to make everything more painful than it needed to be. When introduced to the problem, I thought that it would definitely be more useful if I designed a program that would help me understand my chances of winning a round if I had a certain hand. For example, it is possible to calculate the odds of having a full house vs. a straight (hint: the straight is more likely to happen). However, you could extend this model to calculate the probability given knowledge of certain cards already played (basically, "counting cards"). The most important thing for me was to get the Poker hand into a form that could be analyzed and tracked easily. I didn’t code anything initially, I just thought through the process. I had several insufficient ideas of how to transform these test cases into a data representation at first. After thinking some more, I realized the obvious answer to any data analysis problem is to use matrices. I began to visualize the hand as a matrix with the card suits as the columns and the card face values as the rows. Each card could be placed in the matrix as a 1 value (and a 0 value if not present) and then information could be extracted from the matrix by summation across rows and summations across columns. These resulting arrays could then be compared and analyzed to provide insight into the hand of each player. Then the resulting hands could be stored in another matrix so that the remaining cards would have a 0 in their locations in order to track which cards have been drawn.
It took a little while for me to get the hand or test data into a matrix but the comparisons were very simple using NumPy. There was one problem I ran into though, but I found a solution. The problem was when comparing hands that were similar in type, such as straight flush to straight flush, it would be prudent to test for the highest card. Also in comparison of two pairs, in which both players had the same value pairs but a different low card. The solution involves taking the values array, converting it into a tuple and sorting it from lowest to highest and sorting it on mode from the greatest to the least occurring values. Suit doesn’t play an important role in this comparison because they will have both been established as flushes or not from the initial comparison of the hands and the suit adds no particular value to the card in regards to the comparison. The reason I did not finish this is because it occurred to me that I may not be solving my made up problem correctly. The value of the remaining cards has to be analyzed in order to predict whether the hand was above average for what the deck would allow. Mainly I ran out of time though.
I wanted to go ahead and post my thoughts on this and get some feedback as well. Check out my GitHub repo that has the code. Feel free to offer feedback or suggest alternative methods, and I will try not to be too defensive in my choice for a matrix for the data. I hope this stimulated you into thinking about how data can be best represented as much as it stimulated me.