From 13a5d57be02e350b08ce3718a31ece44bfdd1e71 Mon Sep 17 00:00:00 2001 From: Piyush Katyal <109459034+piyushk77@users.noreply.github.com> Date: Thu, 5 Oct 2023 01:13:34 +0530 Subject: [PATCH 1/8] feat: add determinant calculating algorithm --- Maths/Determinant.js | 77 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 Maths/Determinant.js diff --git a/Maths/Determinant.js b/Maths/Determinant.js new file mode 100644 index 0000000000..3c1a88e4cd --- /dev/null +++ b/Maths/Determinant.js @@ -0,0 +1,77 @@ +/** + * Given a square matrix, find its determinant. + * + * @param {number[[]]} matrix - Two dimensional array of integers. + * @returns {number} - An integer equal to the determinant. + * + * @example + * const squareMatrix = [ + * [2,3,4,6], + * [5,8,9,0], + * [7,4,3,9], + * [4,0,2,1] + * ]; + * + * const result = determinant(squareMatrix); + * // The function should return 858 as the resultant determinant. + */ + +const subMatrix = (matrix, i, j) => { + let matrixSize = matrix[0].length + if (matrixSize === 1) { + return matrix[0][0] + } + let subMatrix = [] + for (let x = 0; x < matrixSize; x++) { + if (x === i) { + continue + } else { + subMatrix.push([]) + for (let y = 0; y < matrixSize; y++) { + if (y === j) { + continue + } else { + subMatrix[subMatrix.length - 1].push(matrix[x][y]) + } + } + } + } + return subMatrix +} + +const isMatrixSquare = (matrix) => { + let numRows = matrix.length + for (let i = 0; i < numRows; i++) { + if (numRows !== matrix[i].length) { + return false + } + } + return true +} + +const determinant = (matrix) => { + if ( + !Array.isArray(matrix) || + matrix.length === 0 || + !Array.isArray(matrix[0]) + ) { + return 'Input is not a valid 2D matrix.' + } + if (isMatrixSquare(matrix) === false) { + return 'Square matrix is required.' + } + let numCols = matrix[0].length + if (numCols === 1) { + return matrix[0][0] + } + let result = null + let setIndex = 0 + for (let i = 0; i < numCols; i++) { + result += + Math.pow(-1, i) * + matrix[setIndex][i] * + determinant(subMatrix(matrix, setIndex, i)) + } + return result +} +export { determinant } From 7c5e6fb11407dfa137d58fa454d5319478d8d852 Mon Sep 17 00:00:00 2001 From: Piyush Katyal <109459034+piyushk77@users.noreply.github.com> Date: Thu, 5 Oct 2023 01:15:34 +0530 Subject: [PATCH 2/8] test: add self-tests for determinant algorithm --- Maths/test/Determinant.test.js | 56 ++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Maths/test/Determinant.test.js diff --git a/Maths/test/Determinant.test.js b/Maths/test/Determinant.test.js new file mode 100644 index 0000000000..e145e2c737 --- /dev/null +++ b/Maths/test/Determinant.test.js @@ -0,0 +1,56 @@ +import { determinant } from '../Determinant' +describe('Determinant', () => { + const testCases = [ + [ + [ + [8, 1, 6], + [1, 2, 3], + [4, 7, 5] + ], + -87 + ], + [ + [ + [2, 1, 0, 2], + [1, 2, 4, 3], + [0, 4, 7, 5], + [4, 7, 9, 8] + ], + 25 + ], + [ + [ + [5, 9], + [3, 7] + ], + 8 + ], + [ + [ + [7, 5, 1, 4, 3], + [6, 8, 7, 9, 6], + [9, 8, 0, 4, 7], + [0, 3, 4, 7, 9], + [3, 6, 2, 8, 8] + ], + 2476 + ], + [[[23]], 23], + [ + [ + [1, 6], + [1, 2, 3], + [4, 7, 5] + ], + 'Square matrix is required.' + ], + [[1, 3, 2, [5, 8, 6], 3], 'Input is not a valid 2D matrix.'] + ] + + test.each(testCases)( + 'Should return the determinant of the square matrix.', + (matrix, expected) => { + expect(determinant(matrix)).toEqual(expected) + } + ) +}) From 4284d3b9fd6759acdc06f4b108ff6c6290480703 Mon Sep 17 00:00:00 2001 From: Piyush Katyal <109459034+piyushk77@users.noreply.github.com> Date: Thu, 5 Oct 2023 01:28:15 +0530 Subject: [PATCH 3/8] chore: add wikipedia info link --- Maths/Determinant.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Maths/Determinant.js b/Maths/Determinant.js index 3c1a88e4cd..ecbac2955c 100644 --- a/Maths/Determinant.js +++ b/Maths/Determinant.js @@ -1,6 +1,8 @@ /** * Given a square matrix, find its determinant. * + * For more info: https://en.wikipedia.org/wiki/Determinant + * * @param {number[[]]} matrix - Two dimensional array of integers. * @returns {number} - An integer equal to the determinant. * From a94b419e464da09fce84e9bc978f28a7b2e8ae93 Mon Sep 17 00:00:00 2001 From: Piyush Katyal <109459034+piyushk77@users.noreply.github.com> Date: Thu, 5 Oct 2023 13:55:45 +0530 Subject: [PATCH 4/8] fix: change initialization to zero --- Maths/Determinant.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Maths/Determinant.js b/Maths/Determinant.js index ecbac2955c..6c3458a05b 100644 --- a/Maths/Determinant.js +++ b/Maths/Determinant.js @@ -66,7 +66,7 @@ const determinant = (matrix) => { if (numCols === 1) { return matrix[0][0] } - let result = null + let result = 0 let setIndex = 0 for (let i = 0; i < numCols; i++) { result += From 7f6a7b6492c9d519e64b1ee168390bfbd504d78e Mon Sep 17 00:00:00 2001 From: Piyush Katyal <109459034+piyushk77@users.noreply.github.com> Date: Sun, 8 Oct 2023 23:29:07 +0530 Subject: [PATCH 5/8] fix: add error throw and general code improvements --- Maths/Determinant.js | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Maths/Determinant.js b/Maths/Determinant.js index 6c3458a05b..d218a6ee98 100644 --- a/Maths/Determinant.js +++ b/Maths/Determinant.js @@ -1,5 +1,6 @@ /** - * Given a square matrix, find its determinant. + * Given a square matrix, find its determinant using Laplace Expansion. + * Time Complexity : O(n!) * * For more info: https://en.wikipedia.org/wiki/Determinant * @@ -27,15 +28,13 @@ const subMatrix = (matrix, i, j) => { for (let x = 0; x < matrixSize; x++) { if (x === i) { continue - } else { - subMatrix.push([]) - for (let y = 0; y < matrixSize; y++) { - if (y === j) { - continue - } else { - subMatrix[subMatrix.length - 1].push(matrix[x][y]) - } + } + subMatrix.push([]) + for (let y = 0; y < matrixSize; y++) { + if (y === j) { + continue } + subMatrix[subMatrix.length - 1].push(matrix[x][y]) } } return subMatrix @@ -57,10 +56,10 @@ const determinant = (matrix) => { matrix.length === 0 || !Array.isArray(matrix[0]) ) { - return 'Input is not a valid 2D matrix.' + throw new Error('Input is not a valid 2D matrix.') } - if (isMatrixSquare(matrix) === false) { - return 'Square matrix is required.' + if (!isMatrixSquare(matrix)) { + throw new Error('Square matrix is required.') } let numCols = matrix[0].length if (numCols === 1) { From 55a04d31f705f5a6f771d21835f46a61b9cbe5a2 Mon Sep 17 00:00:00 2001 From: Piyush Katyal <109459034+piyushk77@users.noreply.github.com> Date: Sun, 8 Oct 2023 23:32:53 +0530 Subject: [PATCH 6/8] fix: add error try and catch --- Maths/test/Determinant.test.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Maths/test/Determinant.test.js b/Maths/test/Determinant.test.js index e145e2c737..cfb3de41b4 100644 --- a/Maths/test/Determinant.test.js +++ b/Maths/test/Determinant.test.js @@ -1,3 +1,4 @@ +import { expect } from 'vitest' import { determinant } from '../Determinant' describe('Determinant', () => { const testCases = [ @@ -50,7 +51,11 @@ describe('Determinant', () => { test.each(testCases)( 'Should return the determinant of the square matrix.', (matrix, expected) => { - expect(determinant(matrix)).toEqual(expected) + try { + expect(determinant(matrix)).toEqual(expected) + } catch (err) { + expect(err.message).toEqual(expected) + } } ) }) From 95062050b487962ae45bbe183ae403fa7393ac78 Mon Sep 17 00:00:00 2001 From: Piyush Katyal <109459034+piyushk77@users.noreply.github.com> Date: Mon, 9 Oct 2023 12:46:44 +0530 Subject: [PATCH 7/8] fix: seperate the test loops of error cases --- Maths/test/Determinant.test.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Maths/test/Determinant.test.js b/Maths/test/Determinant.test.js index cfb3de41b4..4ad3874e5c 100644 --- a/Maths/test/Determinant.test.js +++ b/Maths/test/Determinant.test.js @@ -1,7 +1,7 @@ import { expect } from 'vitest' import { determinant } from '../Determinant' describe('Determinant', () => { - const testCases = [ + const validTestCases = [ [ [ [8, 1, 6], @@ -36,7 +36,10 @@ describe('Determinant', () => { ], 2476 ], - [[[23]], 23], + [[[23]], 23] + ] + + const errorTestCases = [ [ [ [1, 6], @@ -48,7 +51,7 @@ describe('Determinant', () => { [[1, 3, 2, [5, 8, 6], 3], 'Input is not a valid 2D matrix.'] ] - test.each(testCases)( + test.each(validTestCases)( 'Should return the determinant of the square matrix.', (matrix, expected) => { try { @@ -58,4 +61,15 @@ describe('Determinant', () => { } } ) + + test.each(errorTestCases)( + 'Should return the error message.', + (matrix, expected) => { + try { + expect(determinant(matrix)).toEqual(expected) + } catch (err) { + expect(err.message).toEqual(expected) + } + } + ) }) From dd43ae4d30b828b590b506f7662d6c3696c7f929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20M=C3=BCller?= <34514239+appgurueu@users.noreply.github.com> Date: Mon, 9 Oct 2023 16:44:38 +0200 Subject: [PATCH 8/8] clean up a bit --- Maths/test/Determinant.test.js | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/Maths/test/Determinant.test.js b/Maths/test/Determinant.test.js index 4ad3874e5c..df9d34df83 100644 --- a/Maths/test/Determinant.test.js +++ b/Maths/test/Determinant.test.js @@ -1,7 +1,7 @@ import { expect } from 'vitest' import { determinant } from '../Determinant' describe('Determinant', () => { - const validTestCases = [ + test.each([ [ [ [8, 1, 6], @@ -37,9 +37,14 @@ describe('Determinant', () => { 2476 ], [[[23]], 23] - ] + ])( + 'Should return the determinant of the square matrix.', + (matrix, expected) => { + expect(determinant(matrix)).toEqual(expected) + } + ) - const errorTestCases = [ + test.each([ [ [ [1, 6], @@ -49,27 +54,10 @@ describe('Determinant', () => { 'Square matrix is required.' ], [[1, 3, 2, [5, 8, 6], 3], 'Input is not a valid 2D matrix.'] - ] - - test.each(validTestCases)( - 'Should return the determinant of the square matrix.', - (matrix, expected) => { - try { - expect(determinant(matrix)).toEqual(expected) - } catch (err) { - expect(err.message).toEqual(expected) - } - } - ) - - test.each(errorTestCases)( + ])( 'Should return the error message.', (matrix, expected) => { - try { - expect(determinant(matrix)).toEqual(expected) - } catch (err) { - expect(err.message).toEqual(expected) - } + expect(() => determinant(matrix)).toThrowError(expected) } ) })