n-choose-k.mjs

/**
 * Newton's formula (Binomial Coefficient) n choose k.
 * Evaluates the number of possible combinations.
 * Built strictly on BigInt and optimized iterative fraction reduction 
 * to prevent RAM and precision loss during massive factorial expansions.
 * 
 * @param {number|bigint|string} n Total elements
 * @param {number|bigint|string} k Elements to pick
 * @returns {bigint} Total possible subset combinations
 */
export const nChooseK = (n, k) => {
  const bigN = BigInt(n);
  const bigK = BigInt(k);
  
  if (bigK < 0n || bigK > bigN) return 0n;
  if (bigK === 0n || bigK === bigN) return 1n;

  // Optimization: dynamically reduce the factorial expansion
  // equivalent to (n! / (k! * (n-k)!)), shrinking the multiplication loops.
  const kMin = bigK > (bigN - bigK) ? (bigN - bigK) : bigK;

  let numerator = 1n;
  let denominator = 1n;

  for (let i = 1n; i <= kMin; ++i) {
    numerator *= (bigN - i + 1n);
    denominator *= i;
  }
  
  return numerator / denominator;
};