My unfair coin flipping code is giving conflicting results with theory

Question:

I was reading the wikipedia page for the Gambler’s ruin concept, and I decided to quickly code it myself as a quick challenge. Just like the example in the "Unfair coin flipping" part on the right, I created an unfair coin with a 0.6 probability for heads and 0.4 probability for tails. Player 1 wins if heads, player 2 wins if tails. Finally, player 1 starts with 5 pennies and player 2 with 10 pennies. If one player wins, they win a penny and the other player loses one penny.

Here’s my code:

import random as rd

def unfair_flip(sc1, sc2):  # function takes scores of player 1 and player 2
    coin = ['heads'] * 6 + ['tails'] * 4  # P = 0.6 for player 1
    flip1, flip2 = rd.choice(coin), rd.choice(coin)
    if flip1 == 'heads':  # if player 1 wins...
        sc1 += 1
        sc2 -= 1
    if flip2 == 'tails':  # if player 2 wins...
        sc1 -= 1
        sc2 += 1
    return sc1, sc2


def proba_check(it):  # function takes the nb of iterations
    wins_p1 = 0
    for _ in range(it):
        player1, player2 = 5, 10  # player 1 starts with 5 pennies, player 2 with 10
        while 0 < player1 < 15:
            player1, player2 = unfair_flip(player1, player2)
        if player1 == 15:
            wins_p1 += 1
    return round(wins_p1/it, 3)


print(f"Probability of winning for Player 1: {proba_check(10000)}")

Here’s the weird thing: using the formula from the wiki page, the win probability for player 1 should be ~0.8703. But when I run my program with a decent number of iterations, say 10 000, I usually get a win probability of around 0.98 for player 1. I’ve reviewed my code several times and I can’t find where I’m wrong. I’ve been coding from time to time for the last 4 years so I consider this an easy challenge haha, but somehow I can’t get it to work… Also, is there a quicker way to code an unfair coin flip than how I did it?
Thanks

Asked By: yasper99

||

Answers:

The example of the "Unfair coin flipping" is based on flipping one coin. In this code you are flipping two coins and checking their value independently, which changes the probabilities.

To get the expected result of ~0.8703, you should flip one coin and attribute the results of the penny exchange accordingly, like so:

def unfair_flip(sc1, sc2):  # function takes scores of player 1 and player 2
    coin = ['heads'] * 6 + ['tails'] * 4  # P = 0.6 for player 1
    flip = rd.choice(coin) # 1 flip for both players, instead of 1 flip for each
    if flip == 'heads':  # if player 1 wins...
        sc1 += 1
        sc2 -= 1
    else:  # if player 2 wins...
        sc1 -= 1
        sc2 += 1
    return sc1, sc2
Answered By: sauro

To answer to your last question, yes there is a quicker way to code it by using a bernouilli generator from scipy:

from scipy.stats import bernoulli


def unfair_flip(player1_account):
    coin = bernoulli.rvs(0.6)  # 1 means 'heads' with p=0.6, 0 means 'tails'
    return player1_account + 2 * (coin-0.5)  # +1 if heads and -1 if tails

def proba_check(it):
    wins_p1 = 0
    for _ in range(it):
        player1, total = 5, 15  # total = player1 + player2
        while 0 < player1 < total:
            player1 = unfair_flip(player1)
        if player1 == 15:
            wins_p1 += 1
    return round(wins_p1/it, 3)
Answered By: Jonathan Dauwe
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.