UNPKG

2.5 kBJavaScriptView Raw
1'use strict'
2
3const isInteger = require('../../utils/number').isInteger
4const product = require('./product')
5function factory (type, config, load, typed) {
6 /**
7 * Compute the number of ways of picking `k` unordered outcomes from `n`
8 * possibilities.
9 *
10 * Combinations only takes integer arguments.
11 * The following condition must be enforced: k <= n.
12 *
13 * Syntax:
14 *
15 * math.combinations(n, k)
16 *
17 * Examples:
18 *
19 * math.combinations(7, 5) // returns 21
20 *
21 * See also:
22 *
23 * permutations, factorial
24 *
25 * @param {number | BigNumber} n Total number of objects in the set
26 * @param {number | BigNumber} k Number of objects in the subset
27 * @return {number | BigNumber} Number of possible combinations.
28 */
29
30 const combinations = typed('combinations', {
31 'number, number': function (n, k) {
32 let prodrange, nMinusk
33
34 if (!isInteger(n) || n < 0) {
35 throw new TypeError('Positive integer value expected in function combinations')
36 }
37 if (!isInteger(k) || k < 0) {
38 throw new TypeError('Positive integer value expected in function combinations')
39 }
40 if (k > n) {
41 throw new TypeError('k must be less than or equal to n')
42 }
43
44 nMinusk = n - k
45
46 if (k < nMinusk) {
47 prodrange = product(nMinusk + 1, n)
48 return prodrange / product(1, k)
49 }
50 prodrange = product(k + 1, n)
51 return prodrange / product(1, nMinusk)
52 },
53
54 'BigNumber, BigNumber': function (n, k) {
55 let max, result, i, ii
56 const one = new type.BigNumber(1)
57
58 if (!isPositiveInteger(n) || !isPositiveInteger(k)) {
59 throw new TypeError('Positive integer value expected in function combinations')
60 }
61 if (k.gt(n)) {
62 throw new TypeError('k must be less than n in function combinations')
63 }
64
65 max = n.minus(k)
66 if (k.lt(max)) max = k
67 result = one
68 for (i = one, ii = n.minus(max); i.lte(ii); i = i.plus(1)) {
69 result = result.times(max.plus(i)).dividedBy(i)
70 }
71
72 return result
73 }
74
75 // TODO: implement support for collection in combinations
76 })
77
78 combinations.toTex = { 2: `\\binom{\${args[0]}}{\${args[1]}}` }
79
80 return combinations
81}
82
83/**
84 * Test whether BigNumber n is a positive integer
85 * @param {BigNumber} n
86 * @returns {boolean} isPositiveInteger
87 */
88function isPositiveInteger (n) {
89 return n.isInteger() && n.gte(0)
90}
91
92exports.name = 'combinations'
93exports.factory = factory