UNPKG

quarkle

Version:

quarkle is the JavaScript util library providing support of all data types and data structures.

522 lines (521 loc) 16.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.matrixFlatten = exports.matrixInverse = exports.matrixAdjoint = exports.matrixDeterminant = exports.matrixTranspose = exports.scalarMatrixMultiplication = exports.matrixMultiplication = exports.matrixSubtraction = exports.matrixAddition = exports.lcm = exports.gcd = exports.histogram = exports.removeDuplicates = exports.standardDeviation = exports.variance = exports.rootMeanSquare = exports.mode = exports.median = exports.mean = exports.rotateArray = exports.arrayProduct = exports.maxArray = exports.minArray = void 0; const utils_1 = require("../../utils"); /** * Returns the `k`'th minimum element of the given array. `k` is 1-indexed variable with default value as 1. * @param list * @param k * @returns The `k`'th minimum element af the given array. */ const minArray = (list, k) => { (0, utils_1.sort)(list); return list[(k !== null && k !== void 0 ? k : 1) - 1]; }; exports.minArray = minArray; /** * Returns the `k`'th maximum element of the given array. `k` is 1-indexed variable with default value as 1. * @param list * @param k * @returns The `k`'th maximum element of the given array. */ const maxArray = (list, k) => { (0, utils_1.sort)(list, true); return list[(k !== null && k !== void 0 ? k : 1) - 1]; }; exports.maxArray = maxArray; /** * Returns the product of all items in the list. * @param list * @returns The product of the list. */ const arrayProduct = (list) => { let product = 1; for (const item of list) { product *= item; } if (product !== 0) return product; else if (product.toLocaleString()[0] === "-") return 0; else return 0; }; exports.arrayProduct = arrayProduct; /** * Rotate the given array to the `left` or `right` direction by given `position`. If the position is negative, the given (or default) direction is switched. * @param list * @param position * @param direction Optional with the possible values `left` and 'right`. Default direction is `right`. * @returns void. This will perform rotate in place. */ const rotateArray = (list, position, direction = "right") => { const length = list.length; position = position % length; if (position < 0) { position = -position; direction = direction === "left" ? "right" : "left"; } if (direction === "left") { position = length - position; } const reverse = (left, right) => { while (left < right) { [list[left], list[right]] = [list[right], list[left]]; left++; right--; } }; reverse(0, list.length - 1); reverse(0, position - 1); reverse(position, length - 1); }; exports.rotateArray = rotateArray; /** * Returns the mean or average of the list. * @param list The list of numbers. * @param type The type of the mean `arithmetic`, `geometric`, `harmonic` and `rms`. The default value is `arithmetic`. * @returns The mean of the list. */ const mean = (list, type) => { let meanValue = 0; const length = list.length; const selectedType = type !== null && type !== void 0 ? type : "arithmetic"; switch (selectedType) { case "arithmetic": { const sum = list.reduce((prev, curr) => prev + curr, 0); meanValue = sum / length; break; } case "geometric": { const mul = list.reduce((prev, curr) => prev * curr, 1); meanValue = Math.pow(mul, 1 / length); break; } case "harmonic": { const reciprocalSum = list.reduce((prev, curr) => prev + 1 / curr, 0); meanValue = length / reciprocalSum; break; } case "rms": { const squareSum = list.reduce((prev, curr) => prev + curr * curr, 0); const meanRms = squareSum / length; meanValue = Math.pow(meanRms, 0.5); break; } } return Math.round(meanValue * 100) / 100; }; exports.mean = mean; /** * Calculates the median of the list. * @param list list of numbers. * @returns The median of the list. */ const median = (list) => { const listClone = (0, utils_1.clone)(list); (0, utils_1.sort)(listClone); let medianValue; const length = listClone.length; const midValue = Math.floor(length / 2); if (length % 2 === 0) { medianValue = (0, exports.mean)([listClone[midValue - 1], listClone[midValue]]); } else { medianValue = listClone[midValue]; } return medianValue; }; exports.median = median; /** * Calculates the mode of the list. * @param list list of numbers * @returns mode of the list. If multiple numbers have the same highest frequency, it will return an array of mode values. */ const mode = (list) => { const freq = {}; for (const item of list) { if (freq[item] == null) { freq[item] = 1; } else { freq[item]++; } } const keys = Object.keys(freq); const sortedFreq = keys .map((key) => [key, freq[key]]) .sort((a, b) => b[1] - a[1]); const max = sortedFreq[0]; const modeValue = sortedFreq.filter((a) => a[1] === max[1]); return modeValue.length === 1 ? Number(modeValue[0][0]) : modeValue.map((a) => Number(a[0])); }; exports.mode = mode; /** * Calculate the RMS(Root Mean Square) of the list. * @param list * @returns RMS(Root Mean Square) value of the list. */ const rootMeanSquare = (list) => { const square = list.reduce((prev, curr) => prev + curr * curr, 0); const mean = square / list.length; const root = Math.sqrt(mean); return Math.round(root * 100) / 100; }; exports.rootMeanSquare = rootMeanSquare; /** * Calculates the variance of the list. * @param list * @returns Returns the variance. */ const variance = (list) => { const listMean = (0, exports.mean)(list); const squares = list.map((item) => (item - listMean) * (item - listMean)); const sum = squares.reduce((prev, curr) => prev + curr, 0); return Math.round((sum / (list.length - 1)) * 100) / 100; }; exports.variance = variance; /** * Calculates the standard deviation of the list. * @param list * @returns Standard deviation of the list. */ const standardDeviation = (list) => { return Math.round(Math.sqrt((0, exports.variance)(list)) * 100) / 100; }; exports.standardDeviation = standardDeviation; /** * Removes duplicates from the list and return the same list. * @param list List of numbers or strings. * @returns Same list with duplicates removed. */ const removeDuplicates = (list) => { const freq = {}; let i = 0; let j = 0; const length = list.length; while (j < length) { if (freq[list[j]] == null) { freq[list[j]] = 1; list[i] = list[j]; i++; } j++; } list.length = i; return list; }; exports.removeDuplicates = removeDuplicates; /** * Returns the histogram map for each item occurrence in a given list. * @param list List of numbers or strings. * @returns Histogram map for a given list. */ const histogram = (list) => { const map = {}; for (const item of list) { if (map[item]) { map[item]++; } else { map[item] = 1; } } return map; }; exports.histogram = histogram; /** * Returns the Greatest Common Divisor (GCD) of the list. * @param list List of numbers * @returns Greatest Common Divisor (GCD) of the list. */ const gcd = (list) => { if (list.length === 0) { return 0; } const recursiveGcd = (i, j) => { while (j !== 0) { const temp = j; j = i % j; i = temp; } return i; }; let result = list[0]; for (const item of list) { result = recursiveGcd(result, item); } return result; }; exports.gcd = gcd; /** * Returns the Least Common Multiple (LCM) of the list. * @param list List of numbers. * @returns Least Common Multiple (LCM) of the list */ const lcm = (list) => { if (list.length === 0) { return 0; } let lcm = list[0]; for (const item of list) { lcm = (lcm * item) / (0, exports.gcd)([lcm, item]); } return lcm; }; exports.lcm = lcm; /** * Adds two matrices and will return the result. * @param matrix1 First matrix * @param matrix2 Second matrix * @returns Addition of two matrices. */ const matrixAddition = (matrix1, matrix2) => { const m1 = matrix1.length; const n1 = matrix1[0].length; const m2 = matrix2.length; const n2 = matrix2[0].length; if (m1 === m2 && n1 === n2) { const result = new Array(m1); for (let index = 0; index < m1; index++) { result[index] = []; for (let index2 = 0; index2 < m2; index2++) { result[index][index2] = matrix1[index][index2] + matrix2[index][index2]; } } return result; } else { throw new Error("Order of both matrix are not same."); } }; exports.matrixAddition = matrixAddition; /** * Subtracts second matrix from first and will return the result. * @param matrix1 First matrix. * @param matrix2 Second matrix. * @returns Subtraction of two matrices. */ const matrixSubtraction = (matrix1, matrix2) => { const m1 = matrix1.length; const n1 = matrix1[0].length; const m2 = matrix2.length; const n2 = matrix2[0].length; if (m1 === m2 && n1 === n2) { const result = new Array(m1); for (let index = 0; index < m1; index++) { result[index] = []; for (let index2 = 0; index2 < m2; index2++) { result[index][index2] = matrix1[index][index2] - matrix2[index][index2]; } } return result; } else { throw new Error("Order of both matrix are not same."); } }; exports.matrixSubtraction = matrixSubtraction; /** * Multiplies both matrices and will return the result. * @param matrix1 First matrix * @param matrix2 Second matrix * @returns Multiplication of two matrices. */ const matrixMultiplication = (matrix1, matrix2) => { const m1 = matrix1.length; const n1 = matrix1[0].length; const m2 = matrix2.length; const n2 = matrix2[0].length; if (n1 === m2) { const result = new Array(m1); for (let index = 0; index < m1; index++) { result[index] = []; for (let index2 = 0; index2 < n2; index2++) { result[index][index2] = 0; for (let index3 = 0; index3 < n1; index3++) { result[index][index2] += matrix1[index][index3] * matrix2[index3][index2]; } } } return result; } else { throw new Error("Number of columns in first matrix should be same as number of rows in second matrix"); } }; exports.matrixMultiplication = matrixMultiplication; /** * Multiplies the given matrix with the scalar value and return the result. * @param matrix * @param scalar Scalar value to be multiplied. * @returns The multiplication of matrix with the scalar value. */ const scalarMatrixMultiplication = (matrix, scalar) => { const m = matrix.length; const n = matrix[0].length; const result = new Array(m); for (let i = 0; i < m; i++) { result[i] = new Array(n); } for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { let multiplication = scalar * matrix[i][j]; if (multiplication === 0 && multiplication.toLocaleString()[0] === "-") { multiplication = 0; } result[i][j] = multiplication; } } return result; }; exports.scalarMatrixMultiplication = scalarMatrixMultiplication; /** * Converts rows into columns and columns into rows and returns result. This will return a new matrix as transpose. * @param matrix * @returns The transpose of the given matrix. */ const matrixTranspose = (matrix) => { const m = matrix.length; const n = matrix[0].length; const result = new Array(n); for (let i = 0; i < n; i++) { result[i] = new Array(m); } for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { result[j][i] = matrix[i][j]; } } return result; }; exports.matrixTranspose = matrixTranspose; const cofactor = (matrix, i, j) => { const n = matrix.length; let currentI = 0; let currentJ = 0; const result = new Array(n - 1); for (let index = 0; index < n - 1; index++) { result[index] = new Array(n - 1).fill(0); } for (let row = 0; row < n; row++) { for (let column = 0; column < n; column++) { if (row !== i && column !== j) { result[currentI][currentJ] = matrix[row][column]; currentJ++; if (currentJ >= n - 1) { currentJ = 0; currentI++; } } } } return result; }; /** * Returns the determinant of the given matrix. * @param matrix * @returns The determinant of the matrix. */ const matrixDeterminant = (matrix) => { const n = matrix.length; const m = matrix[0].length; if (n !== m) { throw new Error("Given matrix is not a square matrix, determinant cannot be calculated."); } if (n === 1) { return matrix[0][0]; } let determinant = 0; let sign = 1; for (let i = 0; i < n; i++) { const cofactorMatrix = cofactor(matrix, 0, i); determinant += sign * matrix[0][i] * (0, exports.matrixDeterminant)(cofactorMatrix); sign = -sign; } return determinant; }; exports.matrixDeterminant = matrixDeterminant; /** * Returns the adjoint of the given matrix. * @param matrix * @returns The adjoint of the matrix. */ const matrixAdjoint = (matrix) => { const m = matrix.length; const n = matrix[0].length; if (m !== n) { throw new Error("Given matrix is not a square matrix, adjoint cannot be calculated."); } const adjoint = new Array(m); for (let i = 0; i < m; i++) { adjoint[i] = new Array(m).fill(0); } if (m === 1) { adjoint[0][0] = 1; } else { let sign = 1; for (let i = 0; i < n; i++) { for (let j = 0; j < n; j++) { const cofactorArray = cofactor(matrix, i, j); sign = (i + j) % 2 === 0 ? 1 : -1; adjoint[j][i] = sign * (0, exports.matrixDeterminant)(cofactorArray); } } } return adjoint; }; exports.matrixAdjoint = matrixAdjoint; /** * Returns the inverse of the given matrix. When matrix is multiplied with its reverse, it gives an identity matrix. * @param matrix * @returns The inverse of the matrix. */ const matrixInverse = (matrix) => { const m = matrix.length; const n = matrix[0].length; if (m !== n) { throw new Error("Given matrix is not a square matrix, inverse cannot be calculated."); } const determinant = (0, exports.matrixDeterminant)(matrix); if (determinant === 0) { throw new Error("This is a singular matrix, cannot find its inverse!!"); } const adjointArray = (0, exports.matrixAdjoint)(matrix); const inverseArray = new Array(m); for (let i = 0; i < m; i++) { inverseArray[i] = new Array(m).fill(0); } for (let i = 0; i < m; i++) { for (let j = 0; j < m; j++) { inverseArray[i][j] = parseFloat((adjointArray[i][j] / determinant).toFixed(6)); } } return inverseArray; }; exports.matrixInverse = matrixInverse; /** * Flatten the multidimensional matrix into 1-D array. * @param matrix * @returns The flattened array. */ const matrixFlatten = (matrix) => { const flatMatrix = []; const flatten = (matrix, flatMatrix) => { for (let i = 0; i < matrix.length; i++) { if (Array.isArray(matrix[i])) { flatten(matrix[i], flatMatrix); } else { flatMatrix.push(matrix[i]); } } }; flatten(matrix, flatMatrix); return flatMatrix; }; exports.matrixFlatten = matrixFlatten;