*Total work in progress; more than anything an early attempt at sorting it all out by myself. Code and derivations are my own and not necessarily bug-free (though about 80% of the equations here are standard results that are easy to find).*



# Combinatorics 

*If there are m ways to do one thing, and n ways to do another, then there are mn ways of doing both.* - Deepak Chopra


I am using the language convention that 'collections' are unordered and 'sequences' are ordered.


# Principles

### Product Principle
if we have a partition of a set S into m blocks, each of size n, then S has size mn.

### Quotient Principle
If we partition a set P into q blocks, each of size r, then q = p/r.

### Sum Principle
if we have a partition of a set S, then the size of S is the sum of the sizes
of the blocks of the partition.

### Bijection Principle
Two sets have the same size if and only if there is a bijection between them.



# Combinatorics Code

- factorial
- binomial coefficent
- subsets of size n (choices of n out of S)
- subsets of size n+m where n and m are drawn from different, possibly overlappingsets 
- multinomial
- permutations
- unordered multiplicities for all n-sized multisets with m classes (no permutations of multiplicities)
- multiplicities for all n-sized multisets with m classes


```python
import numpy as np

def factorial(x):
    if x == 0:
        return 1
    else:
        res = 1
        for i in range(1,x+1):
            res *= i
        return int(res)
    
    
def binomial(n,k):
    """
    binomial coefficients. convention is that it's 0 if k>n
    """
    if k <= n:
        return int(factorial(n)/(factorial(k)*factorial(n-k)))
    else:
        return 0
    
def multinomial(n,k):
    """
    multinomial coefficient. k is multiindex. Returns error if sum(k) != n
    """
    assert np.sum(k) == n
    return int(factorial(n)/np.product([factorial(x) for x in k]))


def unordered_multiplicities(n,m,k0_max=None):
    """
    Generator that yields all unordered multiplicities for multisets with n objects of m classes.
    
    The convention is that they are sorted:
    n_1 >= n_2 >= n_3 >= ... >= n_m
    
    Example: (n=3,m=3) returns [3,0,0],[2,1,0],[1,1,1] 
    
    
    I don't know what the proper math term for this is: If a set of n elements is partitioned into m subsets, 
    then these are the possible relative sizes of that partitions can have. 
    
    In a multiset of size n, so {1,1,2} = [2,0] is different from {1,2,2} = [0,2]. The multiplicities are ordered, 
    and so [0,2] and [2,0] are counted twice.
    
    The "unordered multiplicites" here treat [2,0] and [0,2] as identical.  
    
    As of now, I don't know how many there should be, but I think that she solution probably lies 
    in creating a bijection to lattice paths. For the case m = n, I think the count might be the Catalan number C_n.
    I haven't checked. 
    
    EDIT: These are called partitions and I am using the 'decreasing list' representation of partitions
    """
    
    if m == 0:
        yield []
        
    else:
        
        # define range of largest entry
        if not k0_max: 
            k0_max = n
            
        k0_min = int(np.ceil(n/m))
        
        # iterate over largest entry, add combinations of remaining entries recursively
        for k0 in range(k0_min,k0_max+1):
            
            # the remaining entries are distributed as n-k0 objects over m-1 buckets, including constraint on maximum amount
            k_rem = unordered_multiplicities(n-k0,m-1,k0_max=np.min([n-k0,k0])) 
            
            for k_n in k_rem:
                res = [k0] + k_n
            
                assert np.sum(res) == n

                yield res
                
            
            
def permutations(x):
    """
    generator that yields all permutations of an array x
    
    will be a total of factorial(len(x)) if all elements of x are distinguishable
    
    (you can just use itertools library)
    """
    
    pivots = set()

    if len(x) == 0 or len(x) == 1:
        yield x
        
    elif len(x) == 2:
        if x[0] == x[1]:
            yield x
        else:
            res = [x,x[::-1]]
            for i in range(2):
                yield res[i]
            
    else:
        for i in range(len(x)):
            p = x[i]
            if p in pivots:
                pass
            else:
                pivots.add(p)
                y = permutations(x[:i]+x[i+1:])

                for remainder in y:
                    yield [p] + remainder
                    

            
def subsets(n,S):
    """
    Return all choices n out of S
    
    assumes all elements of the set are distinguishable
    """
    S = list(S)
    
    assert len(S) >= n
    
    if n == 0:
        yield []
    
    else:
        for i in range(len(S)-n+1):
            p = [S[i]]
            
            rem = subsets(n-1,S[i+1:])
            
            for r in rem:
                yield p+r
                
                
                
def choose(n,m,A,B):
    """
    Returns all unordered collections where n are chosen from A and m are chosen from B, where A & B may overlap.
    """
    
    C = [x for x in A if x in set(B)]
    A_ = [x for x in A if x not in B]
    B_ = [x for x in B if x not in A]
    
    a_ = len(A_)
    b_ = len(B_)
    c = len(C)

    for i in range(np.max([n-a_,0]),np.min([c,n])+1):
        for j in range(np.max([m-b_,0]),np.min([c-i,m])+1):

            c_C = subsets(i+j,C)            
            for cc in c_C: # iterate over picks from intersection
                a_A = subsets(n-i,A_)
                for aa in a_A: # iterate over picks from A 
                    b_B = subsets(m-j,B_)
                    for bb in b_B: # iterate over picks from B
                        
                        yield aa+bb+cc
                
                
                
def multisets(n,m):
    """
    All multisets of n objects of m classes. All possible ways for n objects divided into m distinguishable classes.
    
    ex.: [1,0,0],[0,1,0],[0,0,1]
    
    Will be a total of (n multichoose m) 
    
    This could be huge.
    """
    
    distributions = unordered_multiplicities(n,m)
    for distribution in distributions:
        mindexes = permutations(distribution) 
        for mindex in mindexes:
            yield mindex
```

# Subsets and Permutations

### k-Element Permutations

A permutation is an ordered sequence of distinguishable elements drawn from some set without replacement.  Let $[S]$ be a set of $S$ distinguishable elements. A $k$-element permutation can be thought of as a injective function from $[k]=\{1,2,3,...,k\}$ to $[S]$. There are $S^{\underline{k}} = \frac{|S|!}{(|S|-k)!}$ different $k$-element permutations. 

The notation $S^\underline{k} = S(S-1)(S-2)...(S-k+1)$ is the "falling factorial". 


### Number of Subsets of Set with Size n

The number of subsets of a set $S$ with size $n$ is $2^n$. One way to calculate that:

\begin{equation}
n_{subsets} = \sum^n_{i=0} (\mathrm{ways\ of\ picking\ i\ out\ of\ n}) = \sum^n_{i=0}\left(\begin{array}{c}n\\i\end{array}\right) = 2^n
\end{equation}

There is a better way, though. A subset can be thought of as assigning a label to each element of $S$: it's in or out. That means that any possible subset cen be described by an $n$-element binary string and vice versa -- the subsets and the $n$-element strings can be linked by bijection. The number of subsets is therefore the number of $n$-element binary strings, which is:

\begin{equation}
n_{subsets} = 2^n
\end{equation}

### Number of ways to Divide a Set of size n into m Partitions

Equally well, one might ask: how many ways are there to partition $S$ into $k$ subsets? In that case there are $k$ labels, so there are $k^n$ ways. That means:

\begin{equation}
\sum_{\begin{array}{c}k_1,k_2,...,k_m\\ \sum_{k_i}=n\end{array}}\left(\begin{array}{c}n\\k_1 k_2 ... k_m \end{array}\right) = m^n
\end{equation}

Which is: (ways of taking $k_1$ out of $n$) x (ways of taking $k_2$ out of ($n-k_1$)) x (ways of ...). Progressively dividing the set into subsets, and adding up all ways of making the division.


# Sequences and Collections

### Sequences sampled with Replacement
Let [A] be a set of size $A$.

\begin{equation}
\begin{array}{c}
S = \left\{ (a_1,a_2,...,a_n) : a_1,a_2,...,a_n\in [A] \right\}\\
|S| = A^n
\end{array}
\end{equation}

The creation of n-tuples $(a_1,a_2,...,a_n)$ from elements of $A$ can be thought of in terms of functions that map each element of the tuple ($a_i$ for any choice of $i\in (1,n)$) to an element of $A$. For ordered tuples, these functions are always injective.

*Example: bit strings of length $3$: [0,0,0],[0,0,1],[0,1,1],[1,0,1],...*



### Collections sampled with Replacement (Multisets)
Let [A] a set of size A.
\begin{equation}
S = \left\{ \{a_1,a_2,...,a_n\} : a_1,a_2,...,a_n \in [A] \right\}
\end{equation}

This can be thought of as picking a total of $n$ objects from a choice of $k$ classes. 

There are three entries, that can correspond to up to $\min(3,A)$ different elements of $[A]$.

For $n=3$, the options are: they are all the same, two are the same, or they're all different. There are $A$ ways for them to be all the same, $2*A*(A-1)$ ways for two of them to be the same (the factor 2 is because $(a,a,b) \neq (b,b,a)$) and $\left(\begin{array}{c}A\\3\end{array}\right)$ ways for them to all be different.  

Instead of expressing the elements of S in terms of the unordered multiset $\{a,b,c\}$, we can write them in terms of an ordered sequence that contains the multiplicity of the elements of the multisets. That is, if $[A] = \{1,2,3,4\}$, we write $\{1,1,2\} \in S$ as $[2_1|1_2|0_3|0_4]$. This is a bijection between elements of $S$ and the elements of $N = \{[i_1,i_2,...,i_k]: i_1,i_2,...,i_k \in \mathbb{N}_0^+ , \sum_{i_j} i_j = n\}$ (all length $k$ sequences of integers $[i_1,i_2,...,i_k]$ so that $\sum_{i_j} i_j = n$). The bijection implies that $S$ and $K$ have the same size.  

The amount of elements in $N$ is the Bose-Einstein Coefficient that is derived in the ``Bose Einstein Coefficients - Stars and Bars`` notebook. Therefore:

\begin{equation}
|S| = \left(\begin{array}{c}n+k-1\\n\end{array}\right)
\end{equation}

This is also known as *multichoose*. It is the number of $k$-element multisets on $n$ symbols.

*Example: You are 8 years old and you get to pick n pieces of candy from a candy store that has k different types of candy.*

*Example: Ways for n bosons to be distributed over k degenerate states.*

*Example: The number of ways to draw n elements from k equally likely classes, when the order does not matter.*

*Example: How many ways are there to partition a set with n elements (apart the empty set). (In this case k=n)* 

*Example: In a universe of k stocks, how many portfolios are possible that consist of n stocks?*


### Sequences sampled without Replacement
Assume $a,b,c$ are all drawn from a single set $[A]$ without replacement. Then $|S| = A*(A-1)*(A-2)$, i.e. $\frac{n!}{(n-k)!} = n^\underline{k}$ 

*Example: Possible ways of assigning first, second and third place in a competition.*

### Collections sampled without Replacement

This means, selecting $k$ out of $n$:

\begin{equation}
|S| = \frac{n^\underline{k}}{k!} = \left(\begin{array}{c}n\\k\end{array}\right)
\end{equation}

Which is the *binomial coefficient*.

That's the same as taking the number of ordered $k$-tuples and dividing by the number of internal orderings $k!$.

*Example: Possible ways that k fermions might be distributed over n degenerate states*

*Example: Possible groups of k people that can be formed out of a pool of n.*


### Collections sampled from several Disjoint Sets with or without Replacement
Let [A], [B] and [C] be disjoint subsets of size $A$, $B$ and $C$, respectively. 

\begin{equation}
\begin{array}{c}
S = \left\{ \{a,b,c\} : a\in [A], b\in [B], c\in[C] \right\}\\
|S| = ABC
\end{array}
\end{equation}

The mappings between the domain $S$ and co-domain are injective: each entry in the n-tuples is mapped to a disjoint subset of the co-domain. It is impossible for two tuples in $S$ to be permutations of each other, so that different permutations doesn't lead to overcounting.

*Example: Choose one drink $a$, one sandwich $b$ and one free T-shirt $c$. How many options are there?*


### Collections from several Overlapping Sets with Replacement
Let $[A]$ and $[B]$ be two sets of size $A$ and $B$ respectively, where $A$ and $B$ may or may not overlap. 

Let:

\begin{equation}
S = \{\{a_1,a_2,...,a_n,b_1,b_2,...,b_m\}: a\in[A],b\in[B]\}
\end{equation}

Then, I *think*, but haven't checked:

\begin{equation}
|S| = \left( \begin{array}{c}n+a-1\\n \end{array}\right)\left( \begin{array}{c}n+b-1\\m \end{array}\right)
\end{equation}


### Collections from several Overlapping Sets without Replacement

Let $[A]$ and $[B]$ be two sets of size $A$ and $B$ respectively, so that $[A] \neq [B]$ but $[A]\cap[B]=[C]$, with the $C$ the size of $[C]$. The set $S$ consists of all collections of $n$ items from $[A]$ and $m$ items of $[B]$.

Let:

\begin{equation}
S = \{\{a_1,a_2,...,a_n,b_1,b_2,...,b_m\}: a\in[A],b\in[B]\}
\end{equation}

Then the size of $|S|$:

\begin{equation}
|S| = \sum_{\max(n-A+C,0)\leq i \leq \min(C,n)\\\max(m-B+C,0)\leq j \leq \min(C,m) \\i+j\leq C} \left(\begin{array}{c}C\\i+j\end{array}\right)\left(\begin{array}{c}A-C\\n-i\end{array}\right)\left(\begin{array}{c}B-C\\m-j\end{array}\right)
\end{equation}

This can be thought of choosing unordered collections from the 3 disjoint sets $[C]$,$[A]\setminus[C]$ and $[B]\setminus[C]$ and summing over the ways in which $[A]$ and $[B]$-assigned elements can be drawn from $[C]$. 

TO DO: Generalize this to more than two sets. The key will be to reduce the problem to sampling from disjoint sets again.
 
*Example: You want to travel to 6 countries, of which at least 3 are Spanish speaking and at least 3 are in Europe.* 


## Experiments

Testing almost everything.


```python
# Permutations

print("Permutations:")
for n in range(10):
    x = list(range(n))
    print('objects: %i\t permutations: %i %i' % (n,len(list(permutations(x))),factorial(n)))
    
    
#Subsets
nn = [2,5,10]
mm = [2,5,10]

print("\nTotal number of subsets of an n-sized set")
for n in nn:
    n_subsets = 0
    
    for i in range(n+1):
        n_subsets += binomial(n,i) # choose i out of n
    print("n: %i\t %i %i" % (n,n_subsets,2**n))

   

#Number of Partitionings into m Partitions
print("\nTotal number of partitionings of an n-sized set into m")
for n in nn:
    for m in mm:
        n_partitions = 0
        for mindex in multisets(n,m):
            n_partitions += multinomial(n,mindex)

        print("n: %i m: %i\t %i %i" % (n,m,n_partitions,m**n))

        
print("\nSubsets Generator:")
S = 'A,B,C,D,E'.split(',')
for n in range(6):
    print('choose %i out of %i\t size: %i %i' % (n,len(S),len(list(subsets(n,S))),binomial(len(S),n)))
    print([''.join(x) for x in subsets(n,S)])

# Class balances when choosing n from k classes
print("\nMultiplicities:")
print("Class balances when choosing n from k classes")
m = 4
for n in range(10):
    x = list(range(n))
    print('objects: %i classes: %i\t size: %i %i' % (n,m,len(list(unordered_multiplicities(n,m))),0))
    print(list(unordered_multiplicities(n,m)))


# Collections of n objects from k classes with replacement
print("\nMultisets:")
print("(Collections of n objects from k classes with replacement)")
m = 4
for n in range(7):
    x = list(range(n))
    print('objects: %i classes: %i\t size: %i %i' % (n,m,len(list(multisets(n,m))),
                                                      factorial(n+m-1)/(factorial(n)*factorial(m-1))))
    print(list(multisets(n,m)))
    


A = list('1234')
ordered_pairs = np.vstack(np.vstack(np.vstack([[[[(a,b,c) for a in A ] for b in A]] for c in A])))
print('\nOrdered Sequences with Replacement %i %i' % (len(ordered_pairs),len(A)**3))
print([''.join(x) for x in ordered_pairs])

unordered_pairs = {tuple(sorted(pair)) for pair in ordered_pairs}
print('\nUnordered Collections with Replacement %i %i' % (len(unordered_pairs),factorial(3+len(A)-1)/(factorial(3)*factorial(len(A)-1))))
print([''.join(x) for x in sorted(list(unordered_pairs))])
    
unordered_pairs_without_replacement = []
for i in range(len(A)):
    for j in range(i+1,len(A)):
        for k in range(j+1,len(A)):
            unordered_pairs_without_replacement+=[(A[i],A[j],A[k])]
        
print('\nUnordered Collections without Replacement %i %i' % (len(unordered_pairs_without_replacement),
                                                  factorial(len(A))/(factorial(3)*factorial(len(A)-3))))
print([''.join(x) for x in sorted(unordered_pairs_without_replacement)])
    
    
                        
                        

def count_choices(n,m,A,B):
    """
    Count choices for drawing n from A and m from B without replacement, where A and B may overlap.
    """
    C = [x for x in A if x in B]
    a = len(A)
    b = len(B)
    c = len(C)
    
    i_min = np.max([n-a+c,0])
    j_min = np.max([m-b+c,0])
    
    s = 0
    for i in range(i_min,np.min([c,n])+1):
        for j in range(j_min,np.min([c-i,m])+1):
            s += binomial(c,i+j)*binomial(a-c,n-i)*binomial(b-c,m-j)
    
    return s
            
            

A = 'Spain,Mexico,Cuba'.split(',') # spanish speaking countries
B = 'Spain,France,Germany'.split(',') # countries in Europe
 

print("\nChoose from Overlapping Sets")
for n in range(len(A)):
    for m in range(len(B)):
        S = list(choose(n,m,A,B))
        print("Spanish speaking: %i European: %i \t %i %i" % (n,m,len(S),count_choices(n,m,A,B)))
        print(['-'.join(x) for x in S])
```

    Permutations:
    objects: 0	 permutations: 1 1
    objects: 1	 permutations: 1 1
    objects: 2	 permutations: 2 2
    objects: 3	 permutations: 6 6
    objects: 4	 permutations: 24 24
    objects: 5	 permutations: 120 120
    objects: 6	 permutations: 720 720
    objects: 7	 permutations: 5040 5040
    objects: 8	 permutations: 40320 40320
    objects: 9	 permutations: 362880 362880
    
    Total number of subsets of an n-sized set
    n: 2	 4 4
    n: 5	 32 32
    n: 10	 1024 1024
    
    Total number of partitionings of an n-sized set into m
    n: 2 m: 2	 4 4
    n: 2 m: 5	 25 25
    n: 2 m: 10	 100 100
    n: 5 m: 2	 32 32
    n: 5 m: 5	 3125 3125
    n: 5 m: 10	 100000 100000
    n: 10 m: 2	 1024 1024
    n: 10 m: 5	 9765625 9765625
    n: 10 m: 10	 10000000000 10000000000
    
    Subsets Generator:
    choose 0 out of 5	 size: 1 1
    ['']
    choose 1 out of 5	 size: 5 5
    ['A', 'B', 'C', 'D', 'E']
    choose 2 out of 5	 size: 10 10
    ['AB', 'AC', 'AD', 'AE', 'BC', 'BD', 'BE', 'CD', 'CE', 'DE']
    choose 3 out of 5	 size: 10 10
    ['ABC', 'ABD', 'ABE', 'ACD', 'ACE', 'ADE', 'BCD', 'BCE', 'BDE', 'CDE']
    choose 4 out of 5	 size: 5 5
    ['ABCD', 'ABCE', 'ABDE', 'ACDE', 'BCDE']
    choose 5 out of 5	 size: 1 1
    ['ABCDE']
    
    Multiplicities:
    Class balances when choosing n from k classes
    objects: 0 classes: 4	 size: 1 0
    [[0, 0, 0, 0]]
    objects: 1 classes: 4	 size: 1 0
    [[1, 0, 0, 0]]
    objects: 2 classes: 4	 size: 2 0
    [[1, 1, 0, 0], [2, 0, 0, 0]]
    objects: 3 classes: 4	 size: 3 0
    [[1, 1, 1, 0], [2, 1, 0, 0], [3, 0, 0, 0]]
    objects: 4 classes: 4	 size: 5 0
    [[1, 1, 1, 1], [2, 1, 1, 0], [2, 2, 0, 0], [3, 1, 0, 0], [4, 0, 0, 0]]
    objects: 5 classes: 4	 size: 6 0
    [[2, 1, 1, 1], [2, 2, 1, 0], [3, 1, 1, 0], [3, 2, 0, 0], [4, 1, 0, 0], [5, 0, 0, 0]]
    objects: 6 classes: 4	 size: 9 0
    [[2, 2, 1, 1], [2, 2, 2, 0], [3, 1, 1, 1], [3, 2, 1, 0], [3, 3, 0, 0], [4, 1, 1, 0], [4, 2, 0, 0], [5, 1, 0, 0], [6, 0, 0, 0]]
    objects: 7 classes: 4	 size: 11 0
    [[2, 2, 2, 1], [3, 2, 1, 1], [3, 2, 2, 0], [3, 3, 1, 0], [4, 1, 1, 1], [4, 2, 1, 0], [4, 3, 0, 0], [5, 1, 1, 0], [5, 2, 0, 0], [6, 1, 0, 0], [7, 0, 0, 0]]
    objects: 8 classes: 4	 size: 15 0
    [[2, 2, 2, 2], [3, 2, 2, 1], [3, 3, 1, 1], [3, 3, 2, 0], [4, 2, 1, 1], [4, 2, 2, 0], [4, 3, 1, 0], [4, 4, 0, 0], [5, 1, 1, 1], [5, 2, 1, 0], [5, 3, 0, 0], [6, 1, 1, 0], [6, 2, 0, 0], [7, 1, 0, 0], [8, 0, 0, 0]]
    objects: 9 classes: 4	 size: 18 0
    [[3, 2, 2, 2], [3, 3, 2, 1], [3, 3, 3, 0], [4, 2, 2, 1], [4, 3, 1, 1], [4, 3, 2, 0], [4, 4, 1, 0], [5, 2, 1, 1], [5, 2, 2, 0], [5, 3, 1, 0], [5, 4, 0, 0], [6, 1, 1, 1], [6, 2, 1, 0], [6, 3, 0, 0], [7, 1, 1, 0], [7, 2, 0, 0], [8, 1, 0, 0], [9, 0, 0, 0]]
    
    Multisets:
    (Collections of n objects from k classes with replacement)
    objects: 0 classes: 4	 size: 1 1
    [[0, 0, 0, 0]]
    objects: 1 classes: 4	 size: 4 4
    [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
    objects: 2 classes: 4	 size: 10 10
    [[1, 1, 0, 0], [1, 0, 1, 0], [1, 0, 0, 1], [0, 1, 1, 0], [0, 1, 0, 1], [0, 0, 1, 1], [2, 0, 0, 0], [0, 2, 0, 0], [0, 0, 2, 0], [0, 0, 0, 2]]
    objects: 3 classes: 4	 size: 20 20
    [[1, 1, 1, 0], [1, 1, 0, 1], [1, 0, 1, 1], [0, 1, 1, 1], [2, 1, 0, 0], [2, 0, 1, 0], [2, 0, 0, 1], [1, 2, 0, 0], [1, 0, 2, 0], [1, 0, 0, 2], [0, 2, 1, 0], [0, 2, 0, 1], [0, 1, 2, 0], [0, 1, 0, 2], [0, 0, 2, 1], [0, 0, 1, 2], [3, 0, 0, 0], [0, 3, 0, 0], [0, 0, 3, 0], [0, 0, 0, 3]]
    objects: 4 classes: 4	 size: 35 35
    [[1, 1, 1, 1], [2, 1, 1, 0], [2, 1, 0, 1], [2, 0, 1, 1], [1, 2, 1, 0], [1, 2, 0, 1], [1, 1, 2, 0], [1, 1, 0, 2], [1, 0, 2, 1], [1, 0, 1, 2], [0, 2, 1, 1], [0, 1, 2, 1], [0, 1, 1, 2], [2, 2, 0, 0], [2, 0, 2, 0], [2, 0, 0, 2], [0, 2, 2, 0], [0, 2, 0, 2], [0, 0, 2, 2], [3, 1, 0, 0], [3, 0, 1, 0], [3, 0, 0, 1], [1, 3, 0, 0], [1, 0, 3, 0], [1, 0, 0, 3], [0, 3, 1, 0], [0, 3, 0, 1], [0, 1, 3, 0], [0, 1, 0, 3], [0, 0, 3, 1], [0, 0, 1, 3], [4, 0, 0, 0], [0, 4, 0, 0], [0, 0, 4, 0], [0, 0, 0, 4]]
    objects: 5 classes: 4	 size: 56 56
    [[2, 1, 1, 1], [1, 2, 1, 1], [1, 1, 2, 1], [1, 1, 1, 2], [2, 2, 1, 0], [2, 2, 0, 1], [2, 1, 2, 0], [2, 1, 0, 2], [2, 0, 2, 1], [2, 0, 1, 2], [1, 2, 2, 0], [1, 2, 0, 2], [1, 0, 2, 2], [0, 2, 2, 1], [0, 2, 1, 2], [0, 1, 2, 2], [3, 1, 1, 0], [3, 1, 0, 1], [3, 0, 1, 1], [1, 3, 1, 0], [1, 3, 0, 1], [1, 1, 3, 0], [1, 1, 0, 3], [1, 0, 3, 1], [1, 0, 1, 3], [0, 3, 1, 1], [0, 1, 3, 1], [0, 1, 1, 3], [3, 2, 0, 0], [3, 0, 2, 0], [3, 0, 0, 2], [2, 3, 0, 0], [2, 0, 3, 0], [2, 0, 0, 3], [0, 3, 2, 0], [0, 3, 0, 2], [0, 2, 3, 0], [0, 2, 0, 3], [0, 0, 3, 2], [0, 0, 2, 3], [4, 1, 0, 0], [4, 0, 1, 0], [4, 0, 0, 1], [1, 4, 0, 0], [1, 0, 4, 0], [1, 0, 0, 4], [0, 4, 1, 0], [0, 4, 0, 1], [0, 1, 4, 0], [0, 1, 0, 4], [0, 0, 4, 1], [0, 0, 1, 4], [5, 0, 0, 0], [0, 5, 0, 0], [0, 0, 5, 0], [0, 0, 0, 5]]
    objects: 6 classes: 4	 size: 84 84
    [[2, 2, 1, 1], [2, 1, 2, 1], [2, 1, 1, 2], [1, 2, 2, 1], [1, 2, 1, 2], [1, 1, 2, 2], [2, 2, 2, 0], [2, 2, 0, 2], [2, 0, 2, 2], [0, 2, 2, 2], [3, 1, 1, 1], [1, 3, 1, 1], [1, 1, 3, 1], [1, 1, 1, 3], [3, 2, 1, 0], [3, 2, 0, 1], [3, 1, 2, 0], [3, 1, 0, 2], [3, 0, 2, 1], [3, 0, 1, 2], [2, 3, 1, 0], [2, 3, 0, 1], [2, 1, 3, 0], [2, 1, 0, 3], [2, 0, 3, 1], [2, 0, 1, 3], [1, 3, 2, 0], [1, 3, 0, 2], [1, 2, 3, 0], [1, 2, 0, 3], [1, 0, 3, 2], [1, 0, 2, 3], [0, 3, 2, 1], [0, 3, 1, 2], [0, 2, 3, 1], [0, 2, 1, 3], [0, 1, 3, 2], [0, 1, 2, 3], [3, 3, 0, 0], [3, 0, 3, 0], [3, 0, 0, 3], [0, 3, 3, 0], [0, 3, 0, 3], [0, 0, 3, 3], [4, 1, 1, 0], [4, 1, 0, 1], [4, 0, 1, 1], [1, 4, 1, 0], [1, 4, 0, 1], [1, 1, 4, 0], [1, 1, 0, 4], [1, 0, 4, 1], [1, 0, 1, 4], [0, 4, 1, 1], [0, 1, 4, 1], [0, 1, 1, 4], [4, 2, 0, 0], [4, 0, 2, 0], [4, 0, 0, 2], [2, 4, 0, 0], [2, 0, 4, 0], [2, 0, 0, 4], [0, 4, 2, 0], [0, 4, 0, 2], [0, 2, 4, 0], [0, 2, 0, 4], [0, 0, 4, 2], [0, 0, 2, 4], [5, 1, 0, 0], [5, 0, 1, 0], [5, 0, 0, 1], [1, 5, 0, 0], [1, 0, 5, 0], [1, 0, 0, 5], [0, 5, 1, 0], [0, 5, 0, 1], [0, 1, 5, 0], [0, 1, 0, 5], [0, 0, 5, 1], [0, 0, 1, 5], [6, 0, 0, 0], [0, 6, 0, 0], [0, 0, 6, 0], [0, 0, 0, 6]]
    
    Ordered Sequences with Replacement 64 64
    ['111', '211', '311', '411', '121', '221', '321', '421', '131', '231', '331', '431', '141', '241', '341', '441', '112', '212', '312', '412', '122', '222', '322', '422', '132', '232', '332', '432', '142', '242', '342', '442', '113', '213', '313', '413', '123', '223', '323', '423', '133', '233', '333', '433', '143', '243', '343', '443', '114', '214', '314', '414', '124', '224', '324', '424', '134', '234', '334', '434', '144', '244', '344', '444']
    
    Unordered Collections with Replacement 20 20
    ['111', '112', '113', '114', '122', '123', '124', '133', '134', '144', '222', '223', '224', '233', '234', '244', '333', '334', '344', '444']
    
    Unordered Collections without Replacement 4 4
    ['123', '124', '134', '234']
    
    Choose from Overlapping Sets
    Spanish speaking: 0 European: 0 	 1 1
    ['']
    Spanish speaking: 0 European: 1 	 3 3
    ['France', 'Germany', 'Spain']
    Spanish speaking: 0 European: 2 	 3 3
    ['France-Germany', 'France-Spain', 'Germany-Spain']
    Spanish speaking: 1 European: 0 	 3 3
    ['Mexico', 'Cuba', 'Spain']
    Spanish speaking: 1 European: 1 	 8 8
    ['Mexico-France', 'Mexico-Germany', 'Cuba-France', 'Cuba-Germany', 'Mexico-Spain', 'Cuba-Spain', 'France-Spain', 'Germany-Spain']
    Spanish speaking: 1 European: 2 	 7 7
    ['Mexico-France-Germany', 'Cuba-France-Germany', 'Mexico-France-Spain', 'Mexico-Germany-Spain', 'Cuba-France-Spain', 'Cuba-Germany-Spain', 'France-Germany-Spain']
    Spanish speaking: 2 European: 0 	 3 3
    ['Mexico-Cuba', 'Mexico-Spain', 'Cuba-Spain']
    Spanish speaking: 2 European: 1 	 7 7
    ['Mexico-Cuba-France', 'Mexico-Cuba-Germany', 'Mexico-Cuba-Spain', 'Mexico-France-Spain', 'Mexico-Germany-Spain', 'Cuba-France-Spain', 'Cuba-Germany-Spain']
    Spanish speaking: 2 European: 2 	 5 5
    ['Mexico-Cuba-France-Germany', 'Mexico-Cuba-France-Spain', 'Mexico-Cuba-Germany-Spain', 'Mexico-France-Germany-Spain', 'Cuba-France-Germany-Spain']


933a5cec8aa066d116dce844199a90ae232db01b
ipynb
Jupyter Notebook
Combinatorics - Basics & Code.ipynb
jpbm/probabilism
a2f5c1595aed616236b2b889195604f365175899
MIT
Combinatorics - Basics & Code.ipynb
jpbm/probabilism
a2f5c1595aed616236b2b889195604f365175899
MIT
Combinatorics - Basics & Code.ipynb
jpbm/probabilism
a2f5c1595aed616236b2b889195604f365175899
MIT
Qwen/Qwen-72B
1. YES
2. YES