- Combinatorial generation
- Permutations
- Combinations
- Subsets

- “Combinatorics is the study of the ways in which discrete objects can be arranged into various kinds of patterns.” wrote Donald Knuth in
*The Art of Computer Programming, Vol 4A, Combinatorial Algorithms, Part 1.* - In this lecture note we will touch on the fascinating subject of
*Combinatorial Generation*. - Generating a combinatorial object is the basis of various algorithms.
- Backtracking can be viewed as a modification of the regular algorithm for generating combinatorial objects. Backtracking takes an algorithm for generating a certain type of combinatorial objects and modifies it so that only objects satisfying certain constraints are generated.

- Let \(S\) be a finite set. A permutation on \(S\) is a 1-1 and onto function from \(S\) into itself. Put simply, it’s an arrangement of all the elements of \(S\) in a line, taking order into consideration. E.g. if \(S = \{ a, b, c \}\) then \(bca\) is a permutation of \(S\) and \(cab\) is another. In fact, these are all the permutations of \(S\)
- \(abc\)
- \(acb\)
- \(bac\)
- \(bca\)
- \(cab\)
- \(cba\)

- E.g., in the \(n\)-queen puzzle every valid placement of \(n\) queens on the \(n\times n\) chessboard can be described as “
*a permutation \(pi\) of the set \(\{ 0, 1, \ldots, n-1 \}\) such that placing queen \(i\) at position \(pi(i)\) for all \(0\le i<n\), does not put any two queens on mutually-attacking squares*.” The program`nQueensRandomized.kt`

demonstrated in class uses backtracking for the n-queen puzzle in this way. It takes the basic algorithm for generating the permutations on \(\{0,1,\ldots, n-1\}\) and modifies it so that any branch of the permutation generation algorithm that will generate a mutually-attacking queen pair is abandoned.

Here is an algorithm to generate all the permutations on the set \(\{ 0, 1, \dots, n-1 \}\).

`fun main(args: Array<String>) { val n = args[0].toInt() val a = IntArray(n) { it } fun swap(i: Int, k: Int) { val temp = a[i] a[i] = a[k] a[k] = temp } fun perm(k: Int) { if (k == n) println(a.joinToString(separator=" ")) else for (i in k until n) { swap(i, k) perm(k+1) swap(i, k) } } perm(0) }`

- Let \(S\) be a finite set. A \(k\)-combination of \(S\) is a subset of \(S\) of size \(k\).
- E.g., if \(S = \{a, b, c, d\}\), then all the 2-combinations of \(S\) are
- \(ab\)
- \(ac\)
- \(ad\)
- \(bc\)
- \(bd\)
- \(cd\)

Note that order of symbols does not matter in the above listing: \(ab\) or \(ba\) means the same subset.

Here is an algorithm to generate all the \(k\)-combinations of the set \(\{ 0, 1, \dots, n-1 \}\).

`fun main(args: Array<String>) { val n = args[0].toInt() val k = args[1].toInt() val b = BooleanArray(n) fun comb(start: Int, i: Int) { if (i == k+1) { for (j in b.indices) if (b[j]) print(" $j") println() } else for (j in start until (n-k+i)) { b[j] = true comb(j+1, i+1) b[j] = false } } comb(0, 1) }`

- Let \(S\) be a finite set. A subset of \(S\) is any set \(T\) such that every member of \(T\) is also a member of \(S\).
- E.g., if \(S = \{ 0, 1, 2 \}\) then the subsets of \(S\) are
- \(\emptyset\)
- \(0\)
- \(1\)
- \(2\)
- \(0 1\)
- \(0 2\)
- \(1 2\)
- \(0 1 2\)

where order does not matter in the above listing.

Here is an algorithm to generate all the subsets of the set \(\{ 0, 1, \dots, n-1 \}\).

`fun main(args: Array<String>) { val n = args[0].toInt() val b = BooleanArray(n) fun subsets(i: Int) { if (i == n) { for (j in b.indices) if (b[j]) print(" $j") println() } else { b[i] = false subsets(i+1) b[i] = true subsets(i+1) } } subsets(0) }`