quarkle
Version:
quarkle is the JavaScript util library providing support of all data types and data structures.
522 lines (521 loc) • 16.4 kB
JavaScript
"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;