simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

combinationsWithRep.js (2810B)


      1 import { factory } from '../../utils/factory.js';
      2 import { isInteger } from '../../utils/number.js';
      3 import { product } from '../../utils/product.js';
      4 var name = 'combinationsWithRep';
      5 var dependencies = ['typed'];
      6 export var createCombinationsWithRep = /* #__PURE__ */factory(name, dependencies, _ref => {
      7   var {
      8     typed
      9   } = _ref;
     10 
     11   /**
     12    * Compute the number of ways of picking `k` unordered outcomes from `n`
     13    * possibilities, allowing individual outcomes to be repeated more than once.
     14    *
     15    * CombinationsWithRep only takes integer arguments.
     16    * The following condition must be enforced: k <= n + k -1.
     17    *
     18    * Syntax:
     19    *
     20    *     math.combinationsWithRep(n, k)
     21    *
     22    * Examples:
     23    *
     24    *    math.combinationsWithRep(7, 5) // returns 462
     25    *
     26    * See also:
     27    *
     28    *    combinations, permutations, factorial
     29    *
     30    * @param {number | BigNumber} n    Total number of objects in the set
     31    * @param {number | BigNumber} k    Number of objects in the subset
     32    * @return {number | BigNumber}     Number of possible combinations with replacement.
     33    */
     34   return typed(name, {
     35     'number, number': function numberNumber(n, k) {
     36       if (!isInteger(n) || n < 0) {
     37         throw new TypeError('Positive integer value expected in function combinationsWithRep');
     38       }
     39 
     40       if (!isInteger(k) || k < 0) {
     41         throw new TypeError('Positive integer value expected in function combinationsWithRep');
     42       }
     43 
     44       if (n < 1) {
     45         throw new TypeError('k must be less than or equal to n + k - 1');
     46       }
     47 
     48       if (k < n - 1) {
     49         var _prodrange = product(n, n + k - 1);
     50 
     51         return _prodrange / product(1, k);
     52       }
     53 
     54       var prodrange = product(k + 1, n + k - 1);
     55       return prodrange / product(1, n - 1);
     56     },
     57     'BigNumber, BigNumber': function BigNumberBigNumber(n, k) {
     58       var BigNumber = n.constructor;
     59       var result, i;
     60       var one = new BigNumber(1);
     61       var nMinusOne = n.minus(one);
     62 
     63       if (!isPositiveInteger(n) || !isPositiveInteger(k)) {
     64         throw new TypeError('Positive integer value expected in function combinationsWithRep');
     65       }
     66 
     67       if (n.lt(one)) {
     68         throw new TypeError('k must be less than or equal to n + k - 1 in function combinationsWithRep');
     69       }
     70 
     71       result = one;
     72 
     73       if (k.lt(nMinusOne)) {
     74         for (i = one; i.lte(nMinusOne); i = i.plus(one)) {
     75           result = result.times(k.plus(i)).dividedBy(i);
     76         }
     77       } else {
     78         for (i = one; i.lte(k); i = i.plus(one)) {
     79           result = result.times(nMinusOne.plus(i)).dividedBy(i);
     80         }
     81       }
     82 
     83       return result;
     84     }
     85   });
     86 });
     87 /**
     88  * Test whether BigNumber n is a positive integer
     89  * @param {BigNumber} n
     90  * @returns {boolean} isPositiveInteger
     91  */
     92 
     93 function isPositiveInteger(n) {
     94   return n.isInteger() && n.gte(0);
     95 }