Solution to: [Day 2: Basic Probability](https://www.hackerrank.com/challenges/s10-mcq-1/tutorial)

<h1 id="tocheading">Table of Contents</h1>
<div id="toc"></div>

- Table of Contents
- Probability Notes
    - Event, Sample Space, and Probability
    - Fundamental probability rules
    - Sample question
    - Sample question 2
- Math Solution
    - Information
    - Formula:
    - Implementation
- Solution
    - Imports
    - Process
    - Probability of dice rolls at target
    - Main


```javascript
%%javascript
$.getScript('https://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')
```


    <IPython.core.display.Javascript object>


# Probability Notes

## Event, Sample Space, and Probability
In probability theory, an **experiment** is any procedure that can be infinitely repeated and has a well-defined set of possible outcomes, known as the sample space, **S**. We define an event to be a set of outcomes of an experiment (also known as a subset of **S**) to which a probability (numerical value) is assigned.

The probability of the occurrence of an event, A, is:

\begin{equation}
\large
\mathrm{P}(A) = 
\frac
{\text{Number of favorable outcomes}}
{\text{Total number of outcomes}}
$$


### Fundamental probability rules
Here are the first two fundamental rules of probability:
1. Any probability, **P(A)** , is a number between 0 and 1 *(0 <= P(A) <= 1)*.
2. The probability of the sample space, **S**, is 1 *(P(S) = 1)*.

So how do we bridge the gap between the value of **P(A)** and the sample space **P(S)**? 
We know that **P(A)** is the probability that event will occur, then we define $P(A^{c})$ - the complement of **P(A)** to be the probability that event **P(A)** will not occur. 


If our sample space is composed of the probabilities of P(A)'s occurrence and non-occurrence, we can then say:


\begin{equation}
\large
P(A) + P(A^{c}) = 1
\end{equation}


or, that the sum of all possible outcomes of A in the sample space is equal to 1. 

This is the third fundamental rule of probability:

\begin{equation}
\large
\text{P}(A^{c}) = 1 - \text{P(A)}
\end{equation}

### Sample question
Find the probability of getting an odd number when rolling a 6-sided fair die.

Given the above question, we can extract the following:
- Experiment: rolling a 6-sided die.
- Sample space (1): .
- Event (3): that the number rolled is odd (i.e., 1, 3, 5).

P(A) = (number of favorable outcomes) / (total number of outcomes) = P(A) / P(S) = 3/6 = 1/2

\begin{equation}
\normalsize
P(A) = \frac
{\text{number of favorable outcomes}}
{\text{total number of outcomes}}
\end{equation}

\begin{equation}
\normalsize
= \frac
{P(A)}{P(S)}
\end{equation}

\begin{equation}
\normalsize
= \frac{3}{6}
= \frac{1}{2}
\end{equation}

### Sample question 2

Let A and B be two events such that P(A) = 2/5 and P(B) = 4/5. If the probability of the occurrence of either A or B is 3/5, find the probability of the occurrence of both A and B together (i.e., P(A n B)).

We can use our fundamental rules of probability to solve this problem:


\begin{equation}
\large
|A \cup B| = |A| + |B| - |A \cap B|
\end{equation}

\begin{equation}
\large
P(A \cup B) = P(A) + P(B) - P(A \cap B)
\end{equation}

\begin{equation}
\large
P(A \cap B) = P(A) + P(B) - P(A \cup B)
\end{equation}

\begin{equation}
\large
P(A \cap B) = \frac{2}{5} + \frac{4}{5} - \frac{3}{5}
\end{equation}

\begin{equation}
\large
= \frac{3}{5}
\end{equation}


# Math Solution

## Information
In a single roll of 2 fair (evenly-weighted) six-sided dice, find the probability that their sum will be at most 9.
- Experiment: rolling 2 dice
- Sample space(S) = possible outcomes = 6 * 6 = 36
- Event P(A + B) <= 9


## Formula:

\begin{equation}
\large
P(A) = \frac{\text{Number of favorable events}}{\text{Probability Space}}
\end{equation}

\begin{equation}
\large
P(A) = \frac{P(A)}{P(S)}
\end{equation}

\begin{equation}
\large
P(A) = P(S) - P(A^{c})
\end{equation}

We can also find $P(A^{C})$, which is easier to calculate given the experiment context.


## Implementation
*Determine the probability of rolling 10+*

\begin{equation}
\large
P(A) = P(S) - P(A^{C})
\end{equation}

\begin{equation}
\large
P(A^{C}) = P( (4, 6)) + P( (5, 5), (5, 6)) + P( (6, 4), (6, 5), (6, 6))
\end{equation}

\begin{equation}
\large
= \frac{1 + 2 + 3}{36}
\end{equation}

\begin{equation}
\large
= 1 - \frac{6}{36}
\end{equation}

\begin{equation}
\large
= \frac{30}{36}
= \frac{5}{6}
\end{equation}

\begin{equation}
\large
= 0.833
\end{equation}

# Python Solution

## Imports



```python
from typing import List
```

## Process
- Iterate through all possible rolling combinations and create list of values <= 9
- Divide by number of total events

## Probability of dice rolls at target


```python
def get_possible_combinations(num_dice: int, dice_face: int, target: int) -> List[List[int]]:
	"""Returns Cartesian product of all possible dice rolls.
	
	Uses two helper functions:
		- get_possible_rolls, generator func to yield all die rolls.
		- recurse_roll_combos, helper recursion to create combinations for `num_dice`
	"""
	def get_possible_rolls(dice_face: int) -> int:
		"""Generator funct to yield possible rolls."""
		for i in range(1, dice_face + 1): yield i
	

	def recurse_roll_combos(processed_dice: int, all_roll_combos: list) -> List[List[int]]:
		"""Helper func to recurse through all dice."""
		if processed_dice == num_dice:		## Base case
			return all_roll_combos
		
		new_roll_combos = []
		for roll in all_roll_combos:
			roll_combo = [roll + [val] for val in get_possible_rolls(dice_face)]
			new_roll_combos += (roll_combo)
		
		processed_dice += 1
		return recurse_roll_combos(processed_dice= processed_dice, all_roll_combos = new_roll_combos)

	
	first_rolls = [[val] for val in get_possible_rolls(dice_face)]
	roll_combinations = recurse_roll_combos( 1, first_rolls)


	assert (len(roll_combinations) == dice_face ** num_dice)
	return roll_combinations
```

## Main


```python
def main():
	num_dice = 2
	dice_face = 6
	target = 9

	## Get Combinations
	roll_combos = get_possible_combinations(num_dice, dice_face, target)

	## Count combos at target
	num_under_target = 0
	for combo in roll_combos:
		if sum(combo) <= target:
			num_under_target += 1
	
	## Return P(A) / P(S)
	prob = num_under_target / len(roll_combos)
	print( round(prob, 3))
```


```python
if __name__ == "__main__":
	main()
```

    0.833


27d78dccdec7d0915abc13a3ef1d9869a750fb5c
ipynb
Jupyter Notebook
statistics/10_days/06_day2basicprobability.ipynb
jaimiles23/hacker_rank
0580eac82e5d0989afabb5c2e66faf09713f891b
Apache-2.0
statistics/10_days/06_day2basicprobability.ipynb
jaimiles23/hacker_rank
0580eac82e5d0989afabb5c2e66faf09713f891b
Apache-2.0
statistics/10_days/06_day2basicprobability.ipynb
jaimiles23/hacker_rank
0580eac82e5d0989afabb5c2e66faf09713f891b
Apache-2.0
2021-09-22T11:06:58.000Z
2022-01-25T09:29:24.000Z
Qwen/Qwen-72B
1. YES
2. YES