Advanced Counting

CSE 16: Applied Discrete Mathematics

Instructor: Owen Arden

Winter 2023

Generating permutations and combinations

Often in addition to counting the number of permutations or combinations (subsets), we also want to generate them.

For example, we could try finding all the anagrams of “triangle” by generating the permutations of the letters and looking them up in a dictionary.

  • For example, here are some permutations of “triangle” that are words in English:
    • (a,l,e,r,t,i,n,g)
    • (a,l,t,e,r,i,n,g)
    • (i,n,t,e,g,r,a,l)
    • (r,e,l,a,t,i,n,g)
    • (t,a,n,g,l,i,e,r)
    • (t,r,i,a,n,g,l,e)

Generating in permutations in order

If we sort permutations according to a well-defined order, then we can ensure we generate each permutation exactly once.

Lexicographic order
Lexicographic order of a collection of n-tuples compares each position of the n-tuple using a well-defined order. Two n-tuples are ordered relative to each other based on the order of the first non-equal position.

Example: (a,l,e,r,t,i,n,g) is sorted before (a,l,t,e,r,i,n,g) since e comes before t.

Generation algorithm

For a given order (e.g., lexicographic), if we can generate the “next” permutation for any given permutation, then a simple algorithm for generating all permutations is:

let p = (1,2,...,n-1,n) in
  print p
  while (p != (n,n-1,...,2,1) do
    p := next_perm(p)
    print p
  end
  1. We initialize p with the “first” or “smallest” n-tuple (1,2,...,n-1,n).
  2. Then we generate the next smallest n-tuple with next_perm(p)
  3. We continue step 2 until we generate the “largest” n-tuple (n,n-1,...,2,1)

Ok, but what is this magical next_perm(p)??? (ZyBook animation)

Generating the next permutation

let next_perm(p) = 
  k := -1 
  for (i := len(p)-1; i > 0; p--)
    if (p[i] > p[i-1]) 
      k := i
      break
  if (k==-1) return p

  j:=0 
  for (i := len(p)-1; i > k; p--)
    if (p[i] > p[k] && p[i] < p[j])
      j := i
  pj := p[j]
  pk := p[k]
  p[j] := pk
  p[k] := pj

  pleft := p[..k]     
  pright := reverse(p[k+1..])

  return pleft ++ pright

Generating r-subsets

The order of elements in subsets doesn’t matter, but we can still sort subsets by using a well-defined order to put each subset in a canonical (or unique) form.

Example: As sets, {2,1,3} and {3,1,2} are equal. If we write all sets with their elements sorted lexicographically, it will be easier to define a lexicographic order on subsets. So, {2,1,3} < {1,4,2} since {1,2,3} < {1,2,4}.

Generating r-subsets

For a given \(n\) and \(r\), we can generate all r-subsets of {1,2,...,n-1,n} with an algorithm similar to the one for permutations:

let s = (1,2,...,r-1,r) in
  print s
  while (s != (n-r+1,...,n-1,n) do
    s := next_subset(n,s)
    print s
  end

Notice the different starting and ending n-tuples. Why are these the smallest/largest?

The next r-subset

(Zybook animation)

Combinatorial identies

Theorem: For any integers \(n\) and \(k\) where \(k \leq n\):

\[{n \choose k} = {n \choose {n-k} }\]

Algebraic proof:

\[\dfrac{n!}{k!(n-k)!} = \dfrac{n!}{(n-k)!(n-(n-k))!} = \dfrac{n!}{(n-k)!k!}\]

Combinatorial identies

Theorem: For any integers \(n\) and \(k\) where \(k \leq n\):

\[{n \choose k} = {n \choose {n-k} }\]

Combinatorial proof:

  • There are \({n \choose k}\) ways to select \(k\) items to include in a k-subset from a set of \(n\) items. Equivalently, there are \({n \choose {n-k} }\) ways to select \(n-k\) items to exclude from a k-subset from a set of \(n\) items. Therefore, \[{n \choose k} = {n \choose {n-k} }\]

Binomial coefficients

Multiplying out a binomial like \((a+b)^3\) results in some terms we can add together:

\[\begin{align} (a+b)^3 &= aaa + aab + aba + abb + baa + bab + bba + bbb \\ &= a^3 + 3a^2b + 3ab^2 + b^3 \end{align}\]

It turns out these binomial coefficients can be calculated using combinatorial techniques.

Binomial Theorem:
For any non-negative integer \(n\) and any real numbers \(a\) and \(b\)
\[(a+b)^n = \sum_{k=0}^n {n \choose k} a^{n-k}b^k = \sum_{k=0}^n {n \choose k} a^{k}b^{n-k}\]

Combinatorial identities

Theorem: \[2^n = \sum_{k=0}^n {n \choose k}\]

Proof: Applying the binomial theorem with \(a=1\) and \(b=1\), we have \[\begin{align} (1 + 1)^n &= \sum_{k=0}^n {n \choose k} 1^k 1^{n-k} \\ 2^n &= \sum_{k=0}^n {n \choose k} \end{align}\] \(\square\)

Combinatorial identities

Theorem: \[{n \choose 0} - {n \choose 1} + {n \choose 2} + ... + (-1)^n {n \choose n} = 0\]

Proof. Observe \[\sum_{k=0}^n (-1)^k {n \choose k} = {n \choose 0} - {n \choose 1} + {n \choose 2} + ... + (-1)^n {n \choose n}\]

By the binomial theorem with \(a=-1\) and \(b=1\),

\[\begin{align} $$\sum_{k=0}^n (-1)^k {n \choose k} &= \sum_{k=0}^n (-1)^k 1^{n-k}{n \choose k} \\ &= (-1+1)^n = 0^n = 0 \end{align}\] \(\square\)

Combinatorial identities

Pascal’s triangle

Combinatorial identities

Pascal’s identity
\[{n \choose k} = { {n-1} \choose {k-1} } + { {n-1} \choose k}\]

Proof. Suppose \({n \choose k}\) is the number of k-subsets of a set \(A=\{a_1,a_2, ...,a_n\}\). Each k-subset either contains \(a_n\) or does not contain \(a_n\).
The number of k-subsets that do not contain \(a_n\) is \({ {n-1} \choose k}\) since we choose from \(A - \{a_n\}\).
The number of k-subsets that do contain \(a_n\) is \({ {n-1} \choose {k-1} }\) since we choose \(k-1\) elements from \(A - \{a_n\}\). Therefore the total number of k-subsets of \(A\) is \[{ {n-1} \choose {k-1} } + { {n-1} \choose k}\]

\(\square\)

Pigeonhole principle

Theorem:
If a function \(f\) has domain of size at least \(n+1\), and a codomain of size at most \(n\), where \(n\) is a positive integer, then \(f\) is not injective (one-to-one).

Proof. }For contradiction, assume \(f\) is injective. Therefore each \(n+1\) element in the domain maps to one of \(n+1\) elements in the codomain. However, \(f\)’s codomain has size at most \(n\). Therefore \(f\) is not injective.