## Math

#### approximatelyEqual

Checks if two numbers are approximately equal to each other.

Use `Math.abs()` to compare the absolute difference of the two values to `epsilon`. Omit the third parameter, `epsilon`, to use a default value of `0.001`.

    const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;

examples

    approximatelyEqual(Math.PI / 2.0, 1.5708); // true

#### average

Returns the average of two or more numbers.

Use `Array.reduce()` to add each value to an accumulator, initialized with a value of `0`, divide by the `length` of the array.

    const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;

examples

    average(...[1, 2, 3]); // 2
    average(1, 2, 3); // 2

#### averageBy

Returns the average of an array, after mapping each element to a value using the provided function.

Use `Array.map()` to map each element to the value returned by `fn`, `Array.reduce()` to add each value to an accumulator, initialized with a value of `0`, divide by the `length` of the array.

    const averageBy = (arr, fn) =>
      arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) /
      arr.length;

examples

    averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 5
    averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 5

#### binomialCoefficient

Evaluates the binomial coefficient of two integers `n` and `k`.

Use `Number.isNaN()` to check if any of the two values is `NaN`. Check if `k` is less than `0`, greater than or equal to `n`, equal to `1` or `n - 1` and return the appropriate result. Check if `n - k` is less than `k` and switch their values accordingly. Loop from `2` through `k` and calculate the binomial coefficient. Use `Math.round()` to account for rounding errors in the calculation.

    const binomialCoefficient = (n, k) => {
      if (Number.isNaN(n) || Number.isNaN(k)) return NaN;
      if (k < 0 || k > n) return 0;
      if (k === 0 || k === n) return 1;
      if (k === 1 || k === n - 1) return n;
      if (n - k < k) k = n - k;
      let res = n;
      for (let j = 2; j <= k; j++) res *= (n - j + 1) / j;
      return Math.round(res);
    };

examples

    binomialCoefficient(8, 2); // 28

#### clampNumber

Clamps `num` within the inclusive range specified by the boundary values `a` and `b`.

If `num` falls within the range, return `num`. Otherwise, return the nearest number in the range.

    const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));

examples

    clampNumber(2, 3, 5); // 3
    clampNumber(1, -1, -5); // -1

#### degreesToRads

Converts an angle from degrees to radians.

Use `Math.PI` and the degree to radian formula to convert the angle from degrees to radians.

    const degreesToRads = deg => (deg * Math.PI) / 180.0;

examples

    degreesToRads(90.0); // ~1.5708

#### digitize

Converts a number to an array of digits.

Convert the number to a string, using the spread operator (`...`) to build an array. Use `Array.map()` and `parseInt()` to transform each value to an integer.

    const digitize = n => [...`${n}`].map(i => parseInt(i));

examples

    digitize(123); // [1, 2, 3]

#### distance

Returns the distance between two points.

Use `Math.hypot()` to calculate the Euclidean distance between two points.

    const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);

examples

    distance(1, 1, 2, 3); // 2.23606797749979

#### elo

Computes the new ratings between two or more opponents using the Elo rating system. It takes an array of pre-ratings and returns an array containing post-ratings. The array should be ordered from best performer to worst performer (winner -> loser).

Use the exponent `**` operator and math operators to compute the expected score (chance of winning). of each opponent and compute the new rating for each. Loop through the ratings, using each permutation to compute the post-Elo rating for each player in a pairwise fashion. Omit the second argument to use the default `kFactor` of 32.

    const elo = ([...ratings], kFactor = 32, selfRating) => {
      const [a, b] = ratings;
      const expectedScore = (self, opponent) => 1 / (1 + 10 ** ((opponent - self) / 400));
      const newRating = (rating, i) =>
        (selfRating || rating) + kFactor * (i - expectedScore(i ? a : b, i ? b : a));
      if (ratings.length === 2) {
        return [newRating(a, 1), newRating(b, 0)];
      }
      for (let i = 0, len = ratings.length; i < len; i++) {
        let j = i;
        while (j < len - 1) {
          j++;
          [ratings[i], ratings[j]] = elo([ratings[i], ratings[j]], kFactor);
        }
      }
      return ratings;
    };

examples

    // Standard 1v1s
    elo([1200, 1200]); // [1216, 1184]
    elo([1200, 1200], 64); // [1232, 1168]
    // 4 player FFA, all same rank
    elo([1200, 1200, 1200, 1200]).map(Math.round); // [1246, 1215, 1185, 1154]
    /*
    For teams, each rating can adjusted based on own team's average rating vs.
    average rating of opposing team, with the score being added to their
    own individual rating by supplying it as the third argument.
    */

#### factorial

Calculates the factorial of a number.

Use recursion. If `n` is less than or equal to `1`, return `1`. Otherwise, return the product of `n` and the factorial of `n - 1`. Throws an exception if `n` is a negative number.

    const factorial = n =>
      n < 0
        ? (() => {
            throw new TypeError('Negative numbers are not allowed!');
          })()
        : n <= 1
          ? 1
          : n * factorial(n - 1);

examples

    factorial(6); // 720

#### fibonacci

Generates an array, containing the Fibonacci sequence, up until the nth term.

Create an empty array of the specific length, initializing the first two values (`0` and `1`). Use `Array.reduce()` to add values into the array, using the sum of the last two values, except for the first two.

    const fibonacci = n =>
      Array.from({ length: n }).reduce(
        (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
        []
      );

examples

    fibonacci(6); // [0, 1, 1, 2, 3, 5]

#### gcd

Calculates the greatest common divisor between two or more numbers/arrays.

The inner `_gcd` function uses recursion. Base case is when `y` equals `0`. In this case, return `x`. Otherwise, return the GCD of `y` and the remainder of the division `x/y`.

    const gcd = (...arr) => {
      const _gcd = (x, y) => (!y ? x : gcd(y, x % y));
      return [...arr].reduce((a, b) => _gcd(a, b));
    };

examples

    gcd(8, 36); // 4
    gcd(...[12, 8, 32]); // 4

#### geometricProgression

Initializes an array containing the numbers in the specified range where `start` and `end` are inclusive and the ratio between two terms is `step`. Returns an error if `step` equals `1`.

Use `Array.from()`, `Math.log()` and `Math.floor()` to create an array of the desired length, `Array.map()` to fill with the desired values in a range. Omit the second argument, `start`, to use a default value of `1`. Omit the third argument, `step`, to use a default value of `2`.

    const geometricProgression = (end, start = 1, step = 2) =>
      Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map(
        (v, i) => start * step ** i
      );

examples

    geometricProgression(256); // [1, 2, 4, 8, 16, 32, 64, 128, 256]
    geometricProgression(256, 3); // [3, 6, 12, 24, 48, 96, 192]
    geometricProgression(256, 1, 4); // [1, 4, 16, 64, 256]

#### hammingDistance

Calculates the Hamming distance between two values.

Use XOR operator (`^`) to find the bit difference between the two numbers, convert to a binary string using `toString(2)`. Count and return the number of `1`s in the string, using `match(/1/g)`.

    const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length;

examples

    hammingDistance(2, 3); // 1

#### inRange

Checks if the given number falls within the given range.

Use arithmetic comparison to check if the given number is in the specified range. If the second parameter, `end`, is not specified, the range is considered to be from `0` to `start`.

    const inRange = (n, start, end = null) => {
      if (end && start > end) [end, start] = [start, end];
      return end == null ? n >= 0 && n < start : n >= start && n < end;
    };

examples

    inRange(3, 2, 5); // true
    inRange(3, 4); // true
    inRange(2, 3, 5); // false
    inRange(3, 2); // false

#### isDivisible

Checks if the first numeric argument is divisible by the second one.

Use the modulo operator (`%`) to check if the remainder is equal to `0`.

    const isDivisible = (dividend, divisor) => dividend % divisor === 0;

examples

    isDivisible(6, 3); // true

#### isEven

Returns `true` if the given number is even, `false` otherwise.

Checks whether a number is odd or even using the modulo (`%`) operator. Returns `true` if the number is even, `false` if the number is odd.

    const isEven = num => num % 2 === 0;

examples

    isEven(3); // false

#### isPrime

Checks if the provided integer is a prime number.

Check numbers from `2` to the square root of the given number. Return `false` if any of them divides the given number, else return `true`, unless the number is less than `2`.

    const isPrime = num => {
      const boundary = Math.floor(Math.sqrt(num));
      for (var i = 2; i <= boundary; i++) if (num % i === 0) return false;
      return num >= 2;
    };

examples

    isPrime(11); // true

#### lcm

Returns the least common multiple of two or more numbers.

Use the greatest common divisor (GCD) formula and the fact that `lcm(x,y) = x * y / gcd(x,y)` to determine the least common multiple. The GCD formula uses recursion.

    const lcm = (...arr) => {
      const gcd = (x, y) => (!y ? x : gcd(y, x % y));
      const _lcm = (x, y) => (x * y) / gcd(x, y);
      return [...arr].reduce((a, b) => _lcm(a, b));
    };

examples

    lcm(12, 7); // 84
    lcm(...[1, 3, 4, 5]); // 60

#### luhnCheck

Implementation of the Luhn Algorithm used to validate a variety of identification numbers, such as credit card numbers, IMEI numbers, National Provider Identifier numbers etc.

Use `String.split('')`, `Array.reverse()` and `Array.map()` in combination with `parseInt()` to obtain an array of digits. Use `Array.splice(0,1)` to obtain the last digit. Use `Array.reduce()` to implement the Luhn Algorithm. Return `true` if `sum` is divisible by `10`, `false` otherwise.

    const luhnCheck = num => {
      let arr = (num + '')
        .split('')
        .reverse()
        .map(x => parseInt(x));
      let lastDigit = arr.splice(0, 1)[0];
      let sum = arr.reduce((acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), 0);
      sum += lastDigit;
      return sum % 10 === 0;
    };

examples

    luhnCheck('4485275742308327'); // true
    luhnCheck(6011329933655299); //  false
    luhnCheck(123456789); // false

#### maxBy

Returns the maximum value of an array, after mapping each element to a value using the provided function.

Use `Array.map()` to map each element to the value returned by `fn`, `Math.max()` to get the maximum value.

    const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));

examples

    maxBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 8
    maxBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 8

#### median

Returns the median of an array of numbers.

Find the middle of the array, use `Array.sort()` to sort the values. Return the number at the midpoint if `length` is odd, otherwise the average of the two middle numbers.

    const median = arr => {
      const mid = Math.floor(arr.length / 2),
        nums = [...arr].sort((a, b) => a - b);
      return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
    };

examples

    median([5, 6, 50, 1, -5]); // 5

#### minBy

Returns the minimum value of an array, after mapping each element to a value using the provided function.

Use `Array.map()` to map each element to the value returned by `fn`, `Math.min()` to get the maximum value.

    const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));

examples

    minBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 2
    minBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 2

#### percentile

Uses the percentile formula to calculate how many numbers in the given array are less or equal to the given value.

Use `Array.reduce()` to calculate how many numbers are below the value and how many are the same value and apply the percentile formula.

    const percentile = (arr, val) =>
      (100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length;

examples

    percentile([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 6); // 55

#### powerset

Returns the powerset of a given array of numbers.

Use `Array.reduce()` combined with `Array.map()` to iterate over elements and combine into an array containing all combinations.

    const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);

examples

    powerset([1, 2]); // [[], [1], [2], [2, 1]]

#### primes

Generates primes up to a given number, using the Sieve of Eratosthenes.

Generate an array from `2` to the given number. Use `Array.filter()` to filter out the values divisible by any number from `2` to the square root of the provided number.

    const primes = num => {
      let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2),
        sqroot = Math.floor(Math.sqrt(num)),
        numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2);
      numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x)));
      return arr;
    };

examples

    primes(10); // [2,3,5,7]

#### radsToDegrees

Converts an angle from radians to degrees.

Use `Math.PI` and the radian to degree formula to convert the angle from radians to degrees.

    const radsToDegrees = rad => (rad * 180.0) / Math.PI;

examples

    radsToDegrees(Math.PI / 2); // 90

#### randomIntArrayInRange

Returns an array of n random integers in the specified range.

Use `Array.from()` to create an empty array of the specific length, `Math.random()` to generate a random number and map it to the desired range, using `Math.floor()` to make it an integer.

    const randomIntArrayInRange = (min, max, n = 1) =>
      Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min);

examples

    randomIntArrayInRange(12, 35, 10); // [ 34, 14, 27, 17, 30, 27, 20, 26, 21, 14 ]

#### randomIntegerInRange

Returns a random integer in the specified range.

Use `Math.random()` to generate a random number and map it to the desired range, using `Math.floor()` to make it an integer.

    const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;

examples

    randomIntegerInRange(0, 5); // 2

#### randomNumberInRange

Returns a random number in the specified range.

Use `Math.random()` to generate a random value, map it to the desired range using multiplication.

    const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;

examples

    randomNumberInRange(2, 10); // 6.0211363285087005

#### round

Rounds a number to a specified amount of digits.

Use `Math.round()` and template literals to round the number to the specified number of digits. Omit the second argument, `decimals` to round to an integer.

    const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);

examples

    round(1.005, 2); // 1.01

#### sdbm

Hashes the input string into a whole number.

Use `String.split('')` and `Array.reduce()` to create a hash of the input string, utilizing bit shifting.

    const sdbm = str => {
      let arr = str.split('');
      return arr.reduce(
        (hashCode, currentVal) =>
          (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode),
        0
      );
    };

examples

    sdbm('name'); // -3521204949

#### standardDeviation

Returns the standard deviation of an array of numbers.

Use `Array.reduce()` to calculate the mean, variance and the sum of the variance of the values, the variance of the values, then determine the standard deviation. You can omit the second argument to get the sample standard deviation or set it to `true` to get the population standard deviation.

    const standardDeviation = (arr, usePopulation = false) => {
      const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
      return Math.sqrt(
        arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) /
          (arr.length - (usePopulation ? 0 : 1))
      );
    };

examples

    standardDeviation([10, 2, 38, 23, 38, 23, 21]); // 13.284434142114991 (sample)
    standardDeviation([10, 2, 38, 23, 38, 23, 21], true); // 12.29899614287479 (population)

#### sum

Returns the sum of two or more numbers/arrays.

Use `Array.reduce()` to add each value to an accumulator, initialized with a value of `0`.

    const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);

examples

    sum(...[1, 2, 3, 4]); // 10

#### sumBy

Returns the sum of an array, after mapping each element to a value using the provided function.

Use `Array.map()` to map each element to the value returned by `fn`, `Array.reduce()` to add each value to an accumulator, initialized with a value of `0`.

    const sumBy = (arr, fn) =>
      arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0);

examples

    sumBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 20
    sumBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 20

#### sumPower

Returns the sum of the powers of all the numbers from `start` to `end` (both inclusive).

Use `Array.fill()` to create an array of all the numbers in the target range, `Array.map()` and the exponent operator (`**`) to raise them to `power` and `Array.reduce()` to add them together. Omit the second argument, `power`, to use a default power of `2`. Omit the third argument, `start`, to use a default starting value of `1`.

    const sumPower = (end, power = 2, start = 1) =>
      Array(end + 1 - start)
        .fill(0)
        .map((x, i) => (i + start) ** power)
        .reduce((a, b) => a + b, 0);

examples

    sumPower(10); // 385
    sumPower(10, 3); //3025
    sumPower(10, 3, 5); //2925

#### toSafeInteger

Converts a value to a safe integer.

Use `Math.max()` and `Math.min()` to find the closest safe value. Use `Math.round()` to convert to an integer.

    const toSafeInteger = num =>
      Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER));

examples

    toSafeInteger('3.2'); // 3
    toSafeInteger(Infinity); // 9007199254740991