<jupyter_start><jupyter_text>Chapter 1: Combinatorial AnalysisCombinatorics is an area of mathematics primarily concerned with counting  Setup- Customizing Jupyter Notebook CSS: https://stackoverflow.com/questions/32156248/how-do-i-set-custom-css-for-my-ipython-ihaskell-jupyter-notebook- Using Mathjax on Jupyter: http://jupyter-notebook.readthedocs.io/en/stable/examples/Notebook/Typesetting%20Equations.htmlInline-Typesetting-(Mixing-Markdown-and-TeX)<jupyter_code>%%html
<style>
.tableHeader{
    font-size:16px;
}

.eqn{
    font-size:16px;
    color:blue;
}
</style>
import math
import itertools
import pprint
def get_details_and_length_of_outcomes(outcomes):
    print('All possible outcomes:')
    pprint.pprint(outcomes)
    print('\n')
    print('Number of outcomes =', len(outcomes), '\n')

def nCr(n, r):
    f = math.factorial
    return f(n) // f(r) // f(n-r)<jupyter_output><empty_output><jupyter_text>---  1.2 The basic principle of countingSuppose that two experiments are to be performed. Then if experiment 1 can result in any one of **m** possible outcomes and if, for each outcome of experiment 1, there are **n** possible outcomes of experiment 2, then together there are **mn** possible outcomes of the two experimentsCartesian product: https://en.wikipedia.org/wiki/Cartesian_product **Example 2a**A small community consists of 10 women, each of whom has 3 children. If 1 woman and 1 of her children are to be chosen as mother and child of the year, how many different choices are possible?<jupyter_code># Generate lists of women and children
women = ['Woman'+str(i) for i in range(1,11)]
children = ['Child'+str(i) for i in range(1,4)]
print('List of women:', women, '\n')
print('List of children:', children, '\n')

# Generate the possible outcomes
outcomes = list(itertools.product(women, children))
get_details_and_length_of_outcomes(outcomes)
print('Number of outcomes based on the formula: mn =',
      len(women)*len(children), '\n')<jupyter_output>List of women: ['Woman1', 'Woman2', 'Woman3', 'Woman4', 'Woman5', 'Woman6', 'Woman7', 'Woman8', 'Woman9', 'Woman10'] 

List of children: ['Child1', 'Child2', 'Child3'] 

All possible outcomes:
[('Woman1', 'Child1'),
 ('Woman1', 'Child2'),
 ('Woman1', 'Child3'),
 ('Woman2', 'Child1'),
 ('Woman2', 'Child2'),
 ('Woman2', 'Child3'),
 ('Woman3', 'Child1'),
 ('Woman3', 'Child2'),
 ('Woman3', 'Child3'),
 ('Woman4', 'Child1'),
 ('Woman4', 'Child2'),
 ('Woman4', 'Child3'),
 ('Woman5', 'Child1'),
 ('Woman5', 'Child2'),
 ('Woman5', 'Child3'),
 ('Woman6', 'Child1'),
 ('Woman6', 'Child2'),
 ('Woman6', 'Child3'),
 ('Woman7', 'Child1'),
 ('Woman7', 'Child2'),
 ('Woman7', 'Child3'),
 ('Woman8', 'Child1'),
 ('Woman8', 'Child2'),
 ('Woman8', 'Child3'),
 ('Woman9', 'Child1'),
 ('Woman9', 'Child2'),
 ('Woman9', 'Child3'),
 ('Woman10', 'Child1'),
 ('Woman10', 'Child2'),
 ('Woman10', 'Child3')]


Number of outcomes = 30 

Number of outcomes based on the formula: mn = 30<jupyter_text>---  1.3 Permutations: Permutation is an order arrangement of objects.Given that there are $n$ objects for permutations:| With repetition | r or n where r  | Statistical formula || :------: | :------: | ------ || Yes | r | $n^r$ || No | n | $P(n,n) = n!$ || No | r | $P(n,r) = \frac{n!}{(n-r)!}$ | Multisets permutationIf $n_1+n_2+\cdots+n_r=n$, we define $\binom{n}{n_1,n_2,\cdots,n_r}$ by$$\binom{n}{n_1, n_2, \cdots ,n_r} = \frac{n!}{ (n_1!n_2! \cdots n_r!)}$$Thus $\binom{n}{n_1,n_2,\cdots,n_r}$ represents the number of possible divisions of $n$ distinct objects into $r$ distinct groups of respective sizes $n_1,n_2,\cdots,n_r$. **Without repetition**. Circular permutationCircular permutation of set $S$ with $n$ elements is: $$P_n = (n-1)!$$  Example 3aGiven 'ABC', show all the possible arrangements when repetitions are allowed<jupyter_code>x = list('ABC')
outcomes = [letter for letter in itertools.product(x, repeat=len(x))]
get_details_and_length_of_outcomes(outcomes)
print('Number of outcomes based on the formula: n^r =',
      math.pow(3, 3), '\n')<jupyter_output>All possible outcomes:
[('A', 'A', 'A'),
 ('A', 'A', 'B'),
 ('A', 'A', 'C'),
 ('A', 'B', 'A'),
 ('A', 'B', 'B'),
 ('A', 'B', 'C'),
 ('A', 'C', 'A'),
 ('A', 'C', 'B'),
 ('A', 'C', 'C'),
 ('B', 'A', 'A'),
 ('B', 'A', 'B'),
 ('B', 'A', 'C'),
 ('B', 'B', 'A'),
 ('B', 'B', 'B'),
 ('B', 'B', 'C'),
 ('B', 'C', 'A'),
 ('B', 'C', 'B'),
 ('B', 'C', 'C'),
 ('C', 'A', 'A'),
 ('C', 'A', 'B'),
 ('C', 'A', 'C'),
 ('C', 'B', 'A'),
 ('C', 'B', 'B'),
 ('C', 'B', 'C'),
 ('C', 'C', 'A'),
 ('C', 'C', 'B'),
 ('C', 'C', 'C')]


Number of outcomes = 27 

Number of outcomes based on the formula: n^r = 27.0<jupyter_text>Example 3bGiven 'ABC', show all the possible arrangements when repetitions are not allowed<jupyter_code>outcomes = list(itertools.permutations('ABC', 3))
get_details_and_length_of_outcomes(outcomes)
print('Number of outcomes based on the formula: n! =',
      math.factorial(3), '\n')<jupyter_output>All possible outcomes:
[('A', 'B', 'C'),
 ('A', 'C', 'B'),
 ('B', 'A', 'C'),
 ('B', 'C', 'A'),
 ('C', 'A', 'B'),
 ('C', 'B', 'A')]


Number of outcomes = 6 

Number of outcomes based on the formula: n! = 6<jupyter_text>---  1.4 Combination$\binom{n}{r}$ represents the number of different groups of size $r$ that could be formed from a total of $n$ objects. **Without repetition**:$$C(n,r) = \binom{n}{r} = \frac{n(n-1) \cdots (n-r+1)}{r!} = \frac{n!}{(n-r)!r!}; \;\; \text{for}\; r \le n \\\binom{n}{r} = \binom{n-1}{r-1} + \binom{n-1}{r}; \;\; 1 \le r \le n \\C(n,r) = \frac{P(n,r)}{P(r,r)}$$**With repetition**:$$C(n+r-1, r) = \binom{n+r-1}{r} = \frac{(n+r-1)!}{r!(n-1)!}$$  When to use permutation and combination<jupyter_code>def choose_permutation_or_combination(order):
    if order == True:
        return "Permutation"
    else:
        return "Combination"<jupyter_output><empty_output><jupyter_text>Example 4aGiven 'ABC', show all the possible combinations, without repetition<jupyter_code>outcomes = list(itertools.combinations('ABC', 3))
get_details_and_length_of_outcomes(outcomes)
print('Number of outcomes based on the formula: C(n,r) =',
      nCr(3,3), '\n')<jupyter_output>All possible outcomes:
[('A', 'B', 'C')]


Number of outcomes = 1 

Number of outcomes based on the formula: C(n,r) = 1<jupyter_text>Example 4bGiven 'ABC', show all the possible combinations, with repetition<jupyter_code>outcomes = list(itertools.combinations_with_replacement('ABC', 3))
get_details_and_length_of_outcomes(outcomes)
print('Number of outcomes based on the formula: C(n+r-1,r) =',
      nCr(3+3-1,3), '\n')<jupyter_output>All possible outcomes:
[('A', 'A', 'A'),
 ('A', 'A', 'B'),
 ('A', 'A', 'C'),
 ('A', 'B', 'B'),
 ('A', 'B', 'C'),
 ('A', 'C', 'C'),
 ('B', 'B', 'B'),
 ('B', 'B', 'C'),
 ('B', 'C', 'C'),
 ('C', 'C', 'C')]


Number of outcomes = 10 

Number of outcomes based on the formula: C(n+r-1,r) = 10
{'fraction_non_alphanumeric': 0.22290299051787016, 'fraction_numerical': 0.024799416484318017, 'mean_word_length': 5.0087642418930765, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 26, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '554157', 'license': 'BSD-2-Clause', 'n_tokens_mistral': 2719, 'n_tokens_neox': 2589, 'n_words': 729, 'path': 'a-first-course-in-probability/01-combinatorial-analysis.ipynb', 'repo_name': 'Shawn-Ng/statistics', 'size': '6855'}