# Count your probabilities using Python

Everyone familiar with probabilities knows that they can be tricky. And when solving even really simple problems an answer might be unituitive (as in famous Linda problem). The simplest way to count your probability is by using straightforward formula `P = (number of successful outcomes) / (number of all outcomes)`

. There is one issue with this approach though: we need to know the size for the space of the events in order to calculate the result. That’s why there is a number of other helpful formulae allowing to make shortcut calculation. With a help of a computer we can easily generate vast amount of possible outcomes and verify that we have applied correct equation for the particular problem. In this article I’ll show couple of examples that will make us sure the solution is correct for some unintuitive examples.

### Example 1

There are 10 white beads and 6 black beads in your pocket. You pull 2 of those beads out of your pocket at random, without replacement. What is the probability that both beads are the same color?

**Solution**

With a help of combinatorics we can calculate number of possible arrangements of two beads from 16 total items.

`C(16 2) = 16! / (2! 14!) = 120`

. Now we need to count the number of positive outcomes.

It’s the same formula for white `C(10 2) = 10! / (2! 8!) = 45`

and for black `C(6 2) = 6! / (2! 4!) = 15`

. Using sum rule for independent events

we have `45/120 + 15/120 = 60/120 = 1/2`

which is the final answer.

**Confirmation**

We’ll start with generating all possible outcomes for an action. Let’s represent our beads with numbers. Each unique number represents one bead and we use *even* numbers for *black* beads and *odd* numbers for *white* beads. These helper functions will tell them apart.

1 | def is_white(num): |

Next we generate all possible outcomes (taking two beads from our initial bag) with a help of permutation function. We’ll heavily rely on itertools module later, so make sure you’ve imported required functions to follow examples below like this

1 | from itertools import count, permutations, islice, product |

This will help us quickly initialize input sequences in a functional programming manner.

1 | black_beads = list(islice(filter(is_black, count()), 6)) |

Inspecting the whole list of outcomes shows us that we have exactly the half of the pairs with matching color which is the same as calculated by a formula.

1 | successful_outcomes = list(filter(same_color_pair, outcomes)) |

Confirmed! `0.5`

is our `1/2`

probability. You may notice that we have `240`

outcomes in our space but `120`

when calculating via equation. That’s because an order doesn’t matter for us, so taking `4`

and then `11`

is the same as taking `11`

and then `4`

because we consider only matching of their colors.

### Example 2

There are 5 black beads and 5 white beads in your pocket. You pull the beads out of your pocket one at a time, at random and without replacement. What is the probability that the third bead drawn from your pocket is the same color as the first?

**Solution**

In my opinion this is very unintuitive problem. After pulling first bead we have only 9 of them left in the bag. Also we have no information about second bead at all. Suppose we pulled out black bead then we still have equal probability for each of the 9 beads. Since only 4 of them are black we have `4/9`

probability of matching color. Probability wouldn’t change for the white bead too as we follow the same logic.

**Confirmation**

First we define a function for comparing color of first and third bead drawn

1 | def same_first_and_third(triple): |

and then follow usual procedure of generating space of possible events

1 | beads = list(islice(count(), 10)) |

This gives us expected `320/720 = 4/9`

resulting probability.

### Example 3

You flip a fair coin 10 times. What is the probability that there are exactly 8 heads in those 10 flips?

**Solution**

For each coin we have two possible states so there are `2x2x...x2`

(ten times) `2^10`

total states. We need to pick eight heads from these arrangements so we need to count combinations of 8 elements from 10 total

In our case `n=10`

and `k=8`

, so calculation gives us `10! / (8! 2!) = 45`

. Using our base formula we can infer `45/2^10 = 45/1024`

probability of having exactly 8 heads for our 10 flips.

**Confirmation**

Let `1`

represent a head and `0`

represent a tail. We need to generate all possible arrangements of zeros and ones with a length of 10 and then count how many outcomes contain exactly 8 entires of heads. This simple function will do that for us

1 | def eight_heads(flips): |

As before we output the ration between successful events and number of total events

1 | outcomes = list(product([1, 0], repeat=10)) |

Correct answer `45/1024`

is confirmed.

### Example 4

There are 10 blue marbles and 7 red marbles in a bag. What is the probability that three marbles drawn from the bag (without replacement) are all red?

**Solution**

There are `C(17 3) = 17! / (3! 14!) = 680`

possible ways to draw three marbles. There are only `C(7 3) = 7! / (3! 4!) = 35`

distinct combinations for three red marbles. So our probability is `35/680 = 7/136`

.

**Confirmation**

We begin by defining helper function which will tell us whether all the marbles in our sample are red.

1 | def all_red_marbles(triple): |

We will map *blue* color to *black* and *red* color to *white* not to introduce new functions and reuse existing ones.

1 | blue_marbles = list(islice(filter(is_black, count()), 10)) |

This gives us `210/4080`

probability which is the same as ours `7/136`

final result.

### Conclusion

When in doubt verify your solution with a help of a code. That will make you double think on a problem and spot any flaws in your conclusions. In the next article I will show you how similar technique to the problems where you cannot generate whole space of possible events with a help of LLN (law of large numbers) and Monte Carlo method. Leave your comments and questions below and see you soon.