You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Combinatorics/README.markdown
+18-18Lines changed: 18 additions & 18 deletions
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,7 @@
3
3
A *permutation* is a certain arrangement of the objects from a collection. For example, if we have the first five letters from the alphabet, then this is a permutation:
4
4
5
5
a, b, c, d, e
6
-
6
+
7
7
This is another permutation:
8
8
9
9
b, e, d, a, c
@@ -28,7 +28,7 @@ After picking the second letter, there are only three letters left to choose fro
28
28
To calculate the factorial in Swift:
29
29
30
30
```swift
31
-
funcfactorial(n: Int) ->Int {
31
+
funcfactorial(_n: Int) ->Int {
32
32
var n = n
33
33
var result =1
34
34
while n >1 {
@@ -62,7 +62,7 @@ You could implement this in terms of the `factorial()` function from earlier, bu
62
62
Here is an algorithm that can deal with larger numbers:
63
63
64
64
```swift
65
-
funcpermutations(n: Int, _k: Int) ->Int {
65
+
funcpermutations(_n: Int, _k: Int) ->Int {
66
66
var n = n
67
67
var answer = n
68
68
for_in1..<k {
@@ -98,7 +98,7 @@ So far we've counted how many permutations exist for a given collection, but how
98
98
Here's a recursive algorithm by Niklaus Wirth:
99
99
100
100
```swift
101
-
funcpermuteWirth<T>(a: [T], _n: Int) {
101
+
funcpermuteWirth<T>(_a: [T], _n: Int) {
102
102
if n ==0 {
103
103
print(a) // display the current permutation
104
104
} else {
@@ -216,7 +216,7 @@ If the above is still not entirely clear, then I suggest you give it a go in the
216
216
For fun, here is an alternative algorithm, by Robert Sedgewick:
As you can see, you can derive it from the formula for `P(n, k)`. There are always more permutations than combinations. You divide the number of permutations by `k!` because a total of `k!` of these permutations give the same combination.
284
284
285
-
Above I showed that the number of permutations of `k``l``m` is 6, but if you pick only two of those letters the number of combinations is 3. If we use the formula we should get the same answer. We want to calculate `C(3, 2)` because we choose 2 letters out of a collection of 3.
285
+
Above I showed that the number of permutations of `k``l``m` is 6, but if you pick only two of those letters the number of combinations is 3. If we use the formula we should get the same answer. We want to calculate `C(3, 2)` because we choose 2 letters out of a collection of 3.
286
286
287
287
3 * 2 * 1 6
288
288
C(3, 2) = --------- = --- = 3
@@ -291,15 +291,15 @@ Above I showed that the number of permutations of `k` `l` `m` is 6, but if you p
291
291
Here's a simple function to calculate `C(n, k)`:
292
292
293
293
```swift
294
-
funccombinations(n: Int, _k: Int) ->Int {
294
+
funccombinations(_n: Int, choosek: Int) ->Int {
295
295
returnpermutations(n, k) /factorial(k)
296
296
}
297
297
```
298
298
299
299
Use it like this:
300
300
301
301
```swift
302
-
combinations(28, 5) // prints 98280
302
+
combinations(28, choose: 5) // prints 98280
303
303
```
304
304
305
305
Because this uses the `permutations()` and `factorial()` functions under the hood, you're still limited by how large these numbers can get. For example, `combinations(30, 15)` is "only" `155,117,520` but because the intermediate results don't fit into a 64-bit integer, you can't calculate it with the given function.
@@ -319,7 +319,7 @@ After the reduction of fractions, we get the following formula:
@@ -334,8 +334,8 @@ This algorithm can create larger numbers than the previous method. Instead of ca
334
334
Here's how you can use this improved algorithm:
335
335
336
336
```swift
337
-
quickBinomialCoefficient(8, 2) // prints 28
338
-
quickBinomialCoefficient(30, 15) // prints 155117520
337
+
quickBinomialCoefficient(8, choose: 2) // prints 28
338
+
quickBinomialCoefficient(30, choose: 15) // prints 155117520
339
339
```
340
340
341
341
This new method is quite fast but you're still limited in how large the numbers can get. You can calculate `C(30, 15)` without any problems, but something like `C(66, 33)` will still cause integer overflow in the numerator.
@@ -345,10 +345,10 @@ Here is an algorithm that uses dynamic programming to overcome the need for calc
345
345
0: 1
346
346
1: 1 1
347
347
2: 1 2 1
348
-
3: 1 3 3 1
349
-
4: 1 4 6 4 1
350
-
5: 1 5 10 10 5 1
351
-
6: 1 6 15 20 15 6 1
348
+
3: 1 3 3 1
349
+
4: 1 4 6 4 1
350
+
5: 1 5 10 10 5 1
351
+
6: 1 6 15 20 15 6 1
352
352
353
353
Each number in the next row is made up by adding two numbers from the previous row. For example in row 6, the number 15 is made by adding the 5 and 10 from row 5. These numbers are called the binomial coefficients and as it happens they are the same as `C(n, k)`.
354
354
@@ -365,8 +365,8 @@ For example, for row 6:
365
365
The following code calculates Pascal's triangle in order to find the `C(n, k)` you're looking for:
366
366
367
367
```swift
368
-
funcbinomialCoefficient(n: Int, _k: Int) ->Int {
369
-
var bc =Array(count: n +1, repeatedValue: Array(count: n +1, repeatedValue: 0))
var bc =Array(repeating: Array(repeating: 0, count: n +1), count: n +1)
370
370
371
371
for i in0...n {
372
372
bc[i][0] =1
@@ -390,7 +390,7 @@ The algorithm itself is quite simple: the first loop fills in the 1s at the oute
390
390
Now you can calculate `C(66, 33)` without any problems:
391
391
392
392
```swift
393
-
binomialCoefficient(66, 33) // prints a very large number
393
+
binomialCoefficient(66, choose: 33) // prints a very large number
394
394
```
395
395
396
396
You may wonder what the point is in calculating these permutations and combinations, but many algorithm problems are really combinatorics problems in disguise. Often you may need to look at all possible combinations of your data to see which one gives the right solution. If that means you need to search through `n!` potential solutions, you may want to consider a different approach -- as you've seen, these numbers become huge very quickly!
0 commit comments