Probability in a Weighted Coin-flip Game using Python and Numpy | by Michael Salmon | Towards Data Science

A short, fun one for this week:
Two players are playing a game where they flip a not necessarily fair coin, starting with Player 1. The first person to flip heads wins. The probability that a coin flipped lands on heads is p. What is the probability that Player 1 will win the game?
We can explore this problem with a simple function in python. Let’s write a function that takes in two arguments: 1.) the number of games to be played, and 2.) the probability that a coin flip will result in heads (set to a default of 0.5 or 50%).
Let’s call this function “P1_win_prob_weighted_coin_game”
We can simulate this game with the following code:
import numpy as npdef P1_win_prob_weighted_coin_game(num_games, prob_heads=.5):   player_one_wins = 0   for n in range(0,num_games):     num_flips = 0     win = 0    while win == 0:       turn = np.random.uniform(0,1)       num_flips += 1       if turn <= prob_heads:         if num_flips % 2 != 0:           player_one_wins += 1         win += 1   return float(player_one_wins)/float(num_games)
Now, let’s walk through this briefly step-by-step.
import numpy as npdef P1_win_prob_weighted_coin_game(num_games, prob_heads = 0.5):   player_one_wins = 0
We begin by importing numpy, as we can utilize its random choice functionality to simulate the coin-flipping mechanism for this game.
We define the name of our function, and specify our two arguments. We’ll set a default probability of heads to 0.5, in case we simply want to specify a number of games using a fair coin to see what results. Obviously, we can enter custom probabilities here as we like.
We also set a global counter for the number of games won by Player 1, to begin at 0 for each round of simulations.
  for n in range(0,num_games):       num_flips = 0       win = 0      while win == 0:         turn = np.random.uniform(0,1)         num_flips += 1
Now, for every game in the specified number of simulations (e.g., range(0, num_games), we will count the number of coin flips starting from zero. This both keeps track of how the long the game has gone on, and will help us to determine who the winner is once a heads has been flipped.
We also specify a win condition “win” that will help us know when a game has been completed. While win remains equal to zero, the players continue to flip the coin. Each “turn” constitutes a flip of the coin, which is a randomly selected decimal value between 0 and 1. Each time a turn is taken, we add one to our num_flips counter.
        if turn <= prob_heads:           if num_flips % 2 != 0:             player_one_wins += 1           win += 1
If the randomly chosen “turn” value is less than or equal to our set “prob_heads” value, we consider this a winning condition.
We can understand this in the following way: if the probability of flipping a heads is 0.6, than 60% of the values between 0 and 1 could be interpreted as a flip of heads (e.g., all of the values between 0.0 and 0.6).
Once the winning condition is met, we check how many times the coin has been flipped. Because player 1 always has the first flip, we know that an odd number of flips means that player 1 was the last player to go, and would therefore be the winner. If player 1 won the game, we add one to our player_one_wins counter at the top of the function. We also change the value of “win” to 1.0, which will break off the current game, and begin the next game in the preset number of simulations.
  return float(player_one_wins)/float(num_games)
Once all simulations have been run, the function returns the number of games won by player 1 divided by the total number of games played. This will be expressed as a decimal win percentage.
Okay! Now that we have written our function, let’s play 50,000 games with a fair coin and see what results:
P1_win_prob_weighted_coin_game(50000)0.66848
Over 50,000 games, we see that player 1 has a distinct advantage by going first. In fact, player 1 has about a 2/3 chance of winning the game as a result of flipping first, even when using a fair coin.
What if we adjust the probability of the coin turning up heads? What if the coin has a 75% chance of coming up heads?
P1_win_prob_weighted_coin_game(50000, .75)0.80066
With a weighted coin coming up heads 75% of flips, player 1 would be expected to win about 80% of the time.
What if we really scale back the likelihood of a head appearing? Say, if heads only came up 1% of the time?
P1_win_prob_weighted_coin_game(50000, .01)0.50498
It’s only when we drastically cut back the likelihood of a heads turning up that both players have approximately the same chances of winning.
Fun stuff! Play around with the function as you like to see how different numbers of simulations and probabilities for heads effect the likelihood of player 1 winning.
Thanks for reading!