 
 /* Supporting code because Swift doesn't have a built-in 2D array. */
 struct Array2D<T> {
-  let columns: Int
-  let rows: Int
-  private var array: [T]
-  
-  init(columns: Int, rows: Int, initialValue: T) {
-    self.columns = columns
-    self.rows = rows
-    array = .init(count: rows*columns, repeatedValue: initialValue)
-  }
-  
-  subscript(column: Int, row: Int) -> T {
-    get { return array[row*columns + column] }
-    set { array[row*columns + column] = newValue }
-  }
+    let columns: Int
+    let rows: Int
+    private var array: [T]
+    
+    init(columns: Int, rows: Int, initialValue: T) {
+        self.columns = columns
+        self.rows = rows
+        array = .init(count: rows*columns, repeatedValue: initialValue)
+    }
+    
+    subscript(column: Int, row: Int) -> T {
+        get { return array[row*columns + column] }
+        set { array[row*columns + column] = newValue }
+    }
 }
 
 /*
-  Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose
-  k things out of n possibilities.
+ Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose
+ k things out of n possibilities.
+ 
+ Thanks to the dynamic programming, this algorithm from Skiena allows for
+ the calculation of much larger numbers, at the cost of temporary storage
+ space for the cached values.
+ */
 
-  Thanks to the dynamic programming, this algorithm from Skiena allows for
-  the calculation of much larger numbers, at the cost of temporary storage
-  space for the cached values.
-*/
 func binomialCoefficient(n: Int, _ k: Int) -> Int {
-  var bc = Array2D(columns: n + 1, rows: n + 1, initialValue: 0)
-  
-  for i in 0...n {
-    bc[i, 0] = 1
-    bc[i, i] = 1
-  }
-  
-  if n > 0 {
-    for i in 1...n {
-      for j in 1..<i {
-        bc[i, j] = bc[i - 1, j - 1] + bc[i - 1, j]
-      }
+    var bc = Array(count: n + 1, repeatedValue: Array(count: n + 1, repeatedValue: 0))
+    
+    for i in 0...n {
+        bc[i][0] = 1
+        bc[i][i] = 1
     }
-  }
-  
-  return bc[n, k]
+    
+    if n > 0 {
+        for i in 1...n {
+            for j in 1..<i {
+                bc[i][j] = bc[i - 1][j - 1] + bc[i - 1][j]
+            }
+        }
+    }
+    
+    return bc[n][k]
 }
 
 binomialCoefficient(30, 15)



/*
  Prints out all the permutations of an n-element collection.

  The initial array must be initialized with all zeros. The algorithm
  uses 0 as a flag that indicates more work to be done on each level
  of the recursion.

  Original algorithm by Robert Sedgewick.
  See also Dr.Dobb's Magazine June 1993, Algorithm Alley
*/
func permuteSedgewick(a: [Int], _ n: Int, inout _ pos: Int) {
  var a = a
  pos += 1
  a[n] = pos
  if pos == a.count - 1 {
    print(a)              // display the current permutation
  } else {
    for i in 0..<a.count {
      if a[i] == 0 {
        permuteSedgewick(a, i, &pos)
      }
    }
  }
  pos -= 1
  a[n] = 0
}

print("\nSedgewick permutations:")


print("\nCombinations:")
for i in 1...20 {
    print("\(20)-choose-\(i) = \(combinations(20, i))")
}



/*
 Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose
 k things out of n possibilities.
 */
func quickBinomialCoefficient(n: Int, _ k: Int) -> Int {
    var result = 1
    
    for i in 0..<k {
        result *= (n - i)
        result /= (i + 1)
    }
    return result
}

quickBinomialCoefficient(8, 2)
