 So some of you are looking at trying to see how whether we are writing a poker bot or something it might come as a little bit of disappointment to some of you. So the idea of this talk is actually how do you run random simulations and how how Python really helps you do those things effectively. Okay so that's the basic idea of this talk. So let's get started. Okay a little bit about me so I work as independent consultant mostly do my consultancy in Python but I do in other languages also. So I have run a consultancy company called Hypnoes Software Labs and Python is my go-to language for trying out new ideas and this talk is about one of such ideas that I wanted to try about to go to try. Okay so before we go through the talk so let me try to explain what is the motivation for this particular talk. So sometime back I was thinking what if we could simulate a large number of poker games can that help us define or develop some strategies that you want to that you could use to play a poker game. Okay so how many of you know about poker first of all right. Okay so it's an interesting multiplayer card game I'll be speaking a little I'll be giving a quick introduction of that. So this started with a question basically can we can we can we come out with some strategies if we can simulate a large number of games and then I started kind of working backwards okay so how do you simulate one single game and if you have to simulate one single game how do you basically what are the challenges involved and this talk is basically going to be talking about all of that. Okay so we'll be talking about why this particular problem so just be with me then I'll give a quick introduction about game of poker and what are poker hands etc. How are you how are we going to rank them by that there's going to be a lot of Python code here not a lot about different packages but just Python built-ins and Python standard library okay then we'll see how we can simulate one single poker game and then we are going to look at some results of I ran some of those simulations myself and then we are going to look at some of the results of simulations of those games okay so let's see I mean why this particular problem okay so one of the reasons I chose this problem is because as I said like I really like Python for trying out answers to some some questions that I have and this is one of such questions also it turns out this is a very good candidate for one to actually be able to think in Python what do I mean by thinking in a particular language okay so what do I mean by thinking in a particular language is every language has got certain built-ins certain constructs okay that are available with every language so C has got like a very very basic which is like very core to our very close to machine kind of language Python is like a reasonably high level but let's you do a lot of things so basically thinking in a language means you need to be able to think in terms of the constructs standard library and built-ins of the language so and I thought this is a pretty good interesting candidate problem for being able to think like that as we'll see soon Python has got some built-ins like less dictionary sets and ranking poker hands is a very interesting challenging problem and in the absence of something like a set abstraction it becomes a very hard problem to solve so I think one key take away from this talk if any should be like there's a lot of power in Python's built-in and standard library alone and we should be and we should be able to appreciate that okay so I'll give a quick introduction about a game of poker so that people who don't know about the game of poker will have some idea so it's basically a multiplayer card game and as any multiplayer card game will involve some kind of randomness some kind of luck okay so the way this game is played is each player is dead to have two cars initially and then there are total of five cards which are called as community cards which are basically dealt as three first then one more and then one more so basically what I say is these are the different stages of a game okay and at each of these rounds there is basically betting that happens okay and the betting happens in a round robin manner and whenever a player has bet you can actually match that player's bait or you can bet higher than what the player is bet which is in poker terminology called as raise or use you decide your hand is not good enough to continue and you simply fold it okay so this is a very common poker terminology and at each state all the bets of all the players should be equal if the bet is not equal the player with the highest bet or the best hand wins okay so that's quickly about what is there in the game of poker okay so how many of you know project Euler so this is one of the interesting problems on project Euler if you see how do you compare poker hands okay and we are going to look at Python code to do that so before we let's look at what are typical poker hands okay so in a card game right so the way poker hands are defined or the way the hand is ranked higher is based on how low the probability of that particular hand is okay so at the top you have something called as a royal flush which is basically sequence of cards of the same suite okay after that it's basically the sequence of card of the same suite but as you see ace to ten is higher than eight to four and then you have different kind of cards different kind of hands depending upon what are the odds against those kind of hands okay so I'll show so this is from Wikipedia I don't know how visible it is but this should give you a sum overview about how a rank how how a particular hand is ranked higher okay so one which has got the lowest probability or the lowest number of possible hand is a simple maths okay or the one which has got the odd the highest number of odds against a particular hand is ranked higher okay so as you see that basically this is how hands are ranked in a game of poker so the first one that you see has got a very high almost half more than half a million odds against it whereas if you love if you see the last one which is basically one of two ones so pretty much about 50% of the hands are like the last kind of hands okay so coming back so we will look at how actually we are going to be able to rank the hands like this okay okay so enough about poker so let's let's speak some Python now so to be able to simulate games let's let's see how are we going to basically represent a card then we are going to represent a deck and then we are going to represent poker hands okay so each card has got basically a rank and a suit okay so rank is basically 1 to 13 so one is for ace but we will use actually different ranks which is called 2 to 14 the reason being ace is actually ranked higher than king and queen okay so these are the reasons you are using a different numerical numbers okay and then there are then there are four suites in a card deck which is paired heart diamond and club so simply we can represent a card by the rank and the rank and the suit okay and for every rank we will have some notion of value which will which will which will which will indicate the score of that particular hand and this will come handy when we are going to be comparing the hands okay so again some simple Python that shows how that shows how a poker deck a deck of card is going to look like so we have a list of hands and then a dictionary where keys are the keys are the ranks and the values are their particular score and then you can simply do quickly you can have a deck of the card is going to look something like this simple Python all built-ins we have not used we're not using anything more than Python built-ins and then let's look at different kind of poker hands so it's basically a poker hand then is simply just a list of five cards and that can be represented as follows so the first hand is a flush which is basically all cards are of the same suite which is ace jack nine six and two of spade the second card is a full house where you have two SS and three kings and third card is basically a high card which means which is not a particular type of hand which is like 50% of the card hands are like this okay so you have these are different kinds of poker hands okay so well so now we'll look at how are we going to compare these hands okay so one way of going about it is we are going to define a class called as poker hand okay and basically we will be writing comparator operator for that particular class okay magic functions in Python if you if you guys know okay strictly speaking there's really no reason that you should be using class or something but when we simulate a game we will see why this this becomes very handy so we are basically going to be using the class okay so this is what we are going to be doing okay so the hand is going to look something like this it's a class and then has got these different attributes which says which are the cards a sweets ranks and then there is in the end you have something called as an order so we'll come to it when when we are basically comparing two hands right the two hands could actually have same score and then when they have a same score how are you going to do a tiebreaker so this is where this ordered is going to come is going to come into play so we'll look at little detail about implementation of some of this okay so before we actually so this is going to be our broad strategy okay first given a poker hand see if you can identify the type of a hand okay if you can identify the type of a hand see if you can actually assign some score or value to the hand so that's roughly going to be our strategy okay so if you want to find out whether whether a hand is a flush that means all the cards have the same sweet and this is something you can do in Python using length of set of so it's equal to one so if this condition is true that means it's a flush okay similarly if if there are only two ranks if a if the set of ranks is only two then it's going to be either a four of a kind and a one and or three of a kind and two of a kind so this is basically this gives us some idea about how we can go about finding the hands of the finding the type of a hand okay and a straight is basically is a sequence so basically a max of the ranks and minimum of the ranks the difference is going to be four there's one more condition actually here that all of them have to be distinct hand distinct cards which I have not mentioned here but this gives us some idea about how we can broadly try to solve the problem of identifying the type of a hand okay so having said that let's look at some actual code that does that we discussed something like this some of this code might look a little complicated but it's not really one so if you look at the straight it's basically basically all the ranks are unique which basically says that length of set of ranks is five and max minus minus four but also we need to take care of one more I mean some of the corner cases need to be taken care of for example ace two three four five is also a straight so we need to take care of that and so the second condition is taking care of that so basically you can simply say this is how a straight is look like and then a straight flush is basically it's a self it's a flush and a straight so this is this is how we can actually determine the different kinds of what are going to be the different kinds of hand type of a particular hand okay and like there are about seven types of hand and this is what we are going to be determined okay so now once we have identified the type of a hand the next step is going to be how are we going to assign a score to that particular hand okay so we start with a basic score of one which is which is what every card gets and if a card is of a particular type we kind of double the score and if you look at the if you remember the original probability okay at the lowest level there is a pair which is basically the score is twice the score of the original hand and we simply keep on multiplying the score by two left shift by two is basically multiplying by two and if you see if you have a straight and a flush you will have a score which is multiplied by two rest to five times two rest to four which is basically two rest to nine okay so that's basically how you can see that a particular hand you will have a score of a particular hand okay so so we have done two steps here first identified the type of the hand then we actually assign some kind of a score to a hand okay so if we can now compare the scores of two hand we are pretty much there to solving this particular problem okay there's one more thing though it's quite likely that two hands do have the same score and in that case how are we going to be doing a tiebreaker okay so this ordered is actually doing that okay it's actually doing that so if you look at it it's basically a list of tuples okay I think my next slide is going to explain what the order is look like so the core might look a little difficult little ugly but it's actually a list of tuples basically okay which is of the form the first is the rank and the second that's the second element of the tuple is basically the count of the rank okay so the way you are going to be comparing this is first you will be comparing the first you will be comparing the count if the count is higher than the hand then hand is higher if the counts are equal then you are basically going to be comparing the rank okay and now if we look at this it is this is basically what the sorted is doing it's first looking at the key one which is the second key of the tuple if that is if those are equal then it is going to look at key 0 of the tuple okay so this is this is this is going to be serving as a tiebreaker when we are so this is going to be serving as a tiebreaker when we are basically going to be comparing the hands okay so when trivia is this hand is from the movie casino royale so if you've seen this movie you will probably remember this hand is from that movie okay and once we have done something like this the next step is basically we are going to be defining what is what is called as a comparator operator okay so we are we are defining only a less than comparator operator we are not defining others because if a hand is not less than other way we don't basically care because there are occasionally scenarios in poker games where the two hands are equal indeed equal that happens sometimes don't know rarely and in that case in the poker terminology that is called as basically a split pot so both the players who are in the game till the end are actually going to be the winner in this particular case okay so basically what we have looked at is okay so we we had like three steps in solving this problem the first step was basically comparing the hands so we are kind of basically solve that okay so the next step is a step is going to be trying to see how we are going to be able to simulate one particular poker game and once we are able to simulate one particular poker game we will the next one we will see is how we can simulate a large number of such games and once we have that we will look at some of the results from a large number of such games and try to find out are there some interesting strategies I mean we originally started with that question and we are actually arriving at arriving at that answer okay so basically this is this is this is how we are trying to arrive at that answer okay okay so basically what what does a poker game consists of it's basically a table that contains a given number of player then there are different actions like you have the first deal where each player is dealt two cards and then there are different actions when the first three community cards are revealed it is called as flop and then there is a turn and river so basically when when we want to simulate a poker game we need to be able to simulate some of these actions okay and that is what we will be doing when simulating a poker game okay so basically what do we need to simulate a poker game we need a shuffle deck then we need a number of players okay and we need each player's initial hand because each player will be initially dealt two cards and we need to know about what that player's initial hand is going to look like which we call it as a mini poker hand so if you look at it if if you look at it this mini poker hand also derives from the same called class called as base poker hand the reason being there is an overlap in most of the functionality between a poker hand of five cards versus poker hand of just two cards and we just wanted to abstract out that functionality and this is where it actually helps in using that object oriented feature otherwise strictly speaking there's no need to simply you know force object oriented behavior on that okay so we now know what is it required to actually simulate a card so we will actually start with a class called as poker table so it's it's kind of a bad name that I initially started with and then I had to stick with it so if you look at the code you will come to know why but it's okay it could have been called as a poker game rather than calling it as a poker table but that's what it is okay and when we are going to be simulating poker game we are again going to look at some of the batons and some functions from ita tools from standard library a combinations functions from ita to standard library how it is going to be used so I mean as you would have seen so far I mean everything just from the standard library in fact so far we have not used anything from standard library other than the random now we'll be using some other function some method from ita tools okay so this is so what we discussed so far is actually enough to actually simulate a game okay but we do want to simulate a large number of such games okay and when we want to simulate a large number of such games we want to keep some additional state also in the particular class so ideally this is a state that you would keep outside the class depending upon what kind of questions you want to answer but that's fine I'm for our example this is good enough okay and some of the questions that we want to answer is which player had the best hand in the initial so initially when two cards added which player had indeed the best hand okay and then also we want to look at which player had the best hand at the end of flop at the end of the turn or at the end eventually okay we also like to answer some questions like how many pair how many hands had initially pairs in line okay I mean the question would come why those okay because this is something that if you are actually a player a statistics like this could actually help you strategize how you are going to be betting okay and we want to see we will look at some results from statistics at the end but that this is an additional state that we are keeping in the keeping in this particular poker table class ideally this can be kept separate but this is basically how it is and then we need some we need some functionality to rank players at different stages okay so so basically this is this is what the code is going to look like so so this is a function in the class in the poker table class okay so basically this function will be called either pre-flop before the initial before the three community cards are revealed or post-flop initially you want to if you see this this is where we are basically maintaining the state that number of ace high players number of pair players or the number of many flush players so this is a state that we are keeping in the this is the state that we are keeping in the keeping for the game this is basically this is a simulation state that we are keeping okay and here basically when we have the community cards so the way we want to go about is we want to be able to rank the players right so the way we want to go about doing that is first we will actually make the best hand for a given player and then compare the best hands are gay across the player so for a given player using the community cards you could actually have multiple hands that are possible okay so this is what you actually do in those combinations so use the community cards plus players hand and you get the players hands I mean possible hands that a player can make and then you make the best hand for a player so sorted and reverse to and zero is going to be basically the players best hand and once we have the best hand for each player we are actually going to be able to compare them across the player so basically the second one is exactly doing that and this is the sorted that uses custom function and the second sorted here which is comparing across players is actually using the comparator operator we had in the in the poker hand right so this is where and then simply we have a very simple state basically for every state the table rank zero player ideas is going to be the winner of this particular hand okay and then running one particular game is basically performing these actions okay and all of these actions are part of all of these actions are part of a part of the poker table class which is basically deal is an action okay then you rank players and then you say who's the deal winner then the in poker there is a concept called as a burn card which is basically setting aside a one card from the deck if you look at it in python terms it's simply list dot pop okay and which is actually what that code does just to make poker friendly and so these are all actions and after every action we perform ranking of the player and we keep the state corresponding to that particular ranking in our game state okay similarly we can do it for the turn river and eventually what is going to be our game winner okay so basically this is this is how you can actually simulate a game and collect all the state corresponding to particular game okay now we want to actually see what if we actually simulate a large number of such games are there any interesting statistics that are coming to so this part is actually very simple you just need a kind of a driver for the book code and the driver is simply going to be like it's going to take two variables one is the number of players okay and two is basically the number of games that you want to simulate and it's simply going to run in a for loop this is it's going to simply be running in this particular for right so this is how you are actually going to be simulating a large number of such games okay so in the next few slides I have collected some statistics from simulating some simulating some large about 5000 games okay and these are the couple of questions that I wanted to ask answer okay do the statistics show some interesting patterns are they a function of number of players because this is how you are going to be developing strategies when you are going to be playing okay so that's the idea okay so here I'm going to show statistics for simulation of two players and all of this code is available so something like this you can also run yourself so so what did what did I do is basically I simulated a game for two players okay so the number of players is two and simulated 5000 of such games and the kind of statistics that I'm trying to find out are as follows right so of the 5000 games about 21st 20% of the time which is basically about 1000 games okay is high I mean if a player had an ace high in the initial deal was actually eventually winner in the game so what does that basically means is assuming that every player plays to the end at the end of the game the winner whoever was after we do did a rank players was the player who had initially an ace high okay so this is about 20% of the time I'll explain a bit what is a conditional probability in about 30% of the time a mini flush or a player who had both the cards are of the same suit was actually eventually a winner okay and only in about 10% of the 10% of the games the player who had the player who had a pair initially was actually a winner okay so these if you look at it these look like some kind of let me put it this way this look like some kind of an absolute statistics okay but we need to also look at what do we mean by conditional probability right so let's look at the let's look at the first results okay so of the 5000 play games about 1000 games the ace high player was winner but there were only about 3900 games where actually in the initial deal there was an ace high okay so given now now think about how conditional probability helps you right let's say you are a player and you know you have an ace high hand right that means given you have an ace high hand your conditional probability of eventually winning a game based on based purely on statistics of large number of games is about 25% surprisingly which is not substantially better in fact it is actually comparable with respect to somebody who has a pair hand so basically this is how conditional probability actually helps you so the conditional probability is going to help you when you are as a player you want to actually be developing some strategies okay I'm going to quickly run through the results but you should you can note that the probabilities both absolute and conditional don't change substantially for three players and we have actually very similar players for very similar results for four number of players five players six players and seven players so all of these are pretty pretty similar results right about 25% of the time you have a conditional probability if you had an initial ace had or if you had an initial pair hand that you will win and about 33% of the time if you had both the cards of the same suite that you will actually win okay so these are basically what I say is absolute and conditional probability that you will see in this okay a couple of observations that one can be made okay a flush in the in the initial deal is actually winner we discussed this in the both absolute and conditional terms okay so the number of hands that will win if you if you had a flush and in absolute terms are also likely going to be higher and also as a conditional problem this is okay the pair winners appear to be just half the number of ace high winners but if you actually see the conditional probability they are comparable okay we have seen this then you can actually use this so this is this is these are the probabilities that are talking about initial deal then you can actually do this along with some other statistics okay I don't I have I had this results but I don't have it here so it's in about 75% of the times a player who's a winner at the flop is also an eventual winner and in about almost 85% of the time a player who's winner at the turn is also eventually a winner this is not very unintuitive because you know only if you if you're really winning in the turn are really really bad luck can actually make you lose this okay and a lot of the drama that you see about poker games is usually is a function of pure luck more than a statistics okay a couple of observations that I have about this is my original intuition was these statistics should actually be different for different users but it did it did turn out they don't come they don't substantially change across the number of across the number of players okay that was kind of a surprise and I don't have a very good intuitive answer as to why this is so okay and conditional probability will actually help you devise your strategies okay so how you can use it at each stage you can actually see so let's say you have a conditional probability of 30% of winning a particular hand okay that means if you are risking less than 30% of your capital statistically you have an age over the others right so that's how you can actually use this conditional probability to strategize this and then you can actually refine this because you had an initial conditional probability of winning 30% and then it appears that you are also a flop winner of course it doesn't mean that it appears mean doesn't mean that you will be winning okay so that's basically how you can refine the strategies okay so here are some references okay and then there is this code I have written so I think the links will be available that's that's pretty much what I have