From ad0bde6ddb46fed08e96b94b14f57e12557e23de Mon Sep 17 00:00:00 2001
From: Rahul Bhandari <90493221+imrahulkb@users.noreply.github.com>
Date: Sun, 15 Oct 2023 20:42:09 +0530
Subject: [PATCH 01/73] Update Problem006.js (#1537)

---
 Project-Euler/Problem006.js | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/Project-Euler/Problem006.js b/Project-Euler/Problem006.js
index 58f5e2fbc1..474de2ae96 100644
--- a/Project-Euler/Problem006.js
+++ b/Project-Euler/Problem006.js
@@ -1,11 +1,8 @@
 // https://projecteuler.net/problem=6
 
 export const squareDifference = (num = 100) => {
-  let sumOfSquares = 0
-  let sums = 0
-  for (let i = 1; i <= num; i++) {
-    sumOfSquares += i ** 2 // add squares to the sum of squares
-    sums += i // add number to sum to square later
-  }
+  let sumOfSquares = (num)*(num+1)*(2*num+1)/6
+  let sums = (num*(num+1))/2
+  
   return sums ** 2 - sumOfSquares // difference of square of the total sum and sum of squares
 }

From 0315c8a5387a26fdb54ad5809927a47f24d54c0b Mon Sep 17 00:00:00 2001
From: Manpreet Singh <63737630+ManpreetSingh2004@users.noreply.github.com>
Date: Sun, 15 Oct 2023 22:31:55 +0530
Subject: [PATCH 02/73] docs: fix typo in rotateRight's docstring (#1527)

---
 Hashes/SHA256.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Hashes/SHA256.js b/Hashes/SHA256.js
index d046b9966e..25e1a865c9 100644
--- a/Hashes/SHA256.js
+++ b/Hashes/SHA256.js
@@ -59,14 +59,14 @@ function chunkify(str, size) {
 }
 
 /**
- * Rotates string representation of bits to th left
+ * Rotates string representation of bits to the right
  *
  * @param {string} bits - string representation of bits
  * @param {int} turns - number of rotations to make
  * @return {string} - string representation of bits after rotation
  *
  * @example
- *      rotateLeft("1011", 3); // "1101"
+ *      rotateRight("1011", 3); // "1101"
  */
 function rotateRight(bits, turns) {
   return bits.substr(bits.length - turns) + bits.substr(0, bits.length - turns)

From 60443c7effe51b6a677d8383a7e4896eff14aa3b Mon Sep 17 00:00:00 2001
From: malpotra <56645001+malpotra@users.noreply.github.com>
Date: Sun, 22 Oct 2023 23:10:53 +0530
Subject: [PATCH 03/73] test: add tests for Binary Equivalent Algorithm (#1560)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* test: add tests for Binary Equivalent Algorithm

* test: Refactored tests using .each()

* Update BinaryEquivalent.test.js

---------

Co-authored-by: {Harshit Malpotra} <{malpotra.harshit@gmail.com}>
Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>
---
 Recursive/test/BinaryEquivalent.test.js | 29 +++++++++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 Recursive/test/BinaryEquivalent.test.js

diff --git a/Recursive/test/BinaryEquivalent.test.js b/Recursive/test/BinaryEquivalent.test.js
new file mode 100644
index 0000000000..b79a455eed
--- /dev/null
+++ b/Recursive/test/BinaryEquivalent.test.js
@@ -0,0 +1,29 @@
+import { binaryEquivalent } from "../BinaryEquivalent";
+
+const tests = [
+    {
+        test: 2,
+        expectedValue: "10"
+    },
+    {       
+        test: 0,
+        expectedValue: "0"
+    },
+    {
+        test: 543,
+        expectedValue: "1000011111"
+    },
+    {
+        test: 4697621023,
+        expectedValue: "100011000000000000000001000011111"
+    }
+]
+
+describe("Binary Equivalent", () => {
+    test.each(tests)(
+        "of $test should be $expectedValue",
+        ({test, expectedValue}) => {
+            expect(binaryEquivalent(test)).toBe(expectedValue);
+        }
+    )
+})

From 7d7f109e6fe36e901aff06750d89788ee7be5f3a Mon Sep 17 00:00:00 2001
From: Hardik Pawar <97388607+Hardvan@users.noreply.github.com>
Date: Tue, 24 Oct 2023 12:18:13 +0530
Subject: [PATCH 04/73] Enhance readability of KnightTour (#1572)

---
 Backtracking/KnightTour.js | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/Backtracking/KnightTour.js b/Backtracking/KnightTour.js
index 36f400160d..5f81ca345a 100644
--- a/Backtracking/KnightTour.js
+++ b/Backtracking/KnightTour.js
@@ -2,12 +2,13 @@
 
 class OpenKnightTour {
   constructor(size) {
+    // Constructor to initialize the chessboard and size
     this.board = new Array(size).fill(0).map(() => new Array(size).fill(0))
     this.size = size
   }
 
   getMoves([i, j]) {
-    // helper function to get the valid moves of the knight from the current position
+    // Helper function to get the valid moves of the knight from the current position
     const moves = [
       [i + 2, j - 1],
       [i + 2, j + 1],
@@ -19,18 +20,19 @@ class OpenKnightTour {
       [i - 1, j + 2]
     ]
 
+    // Filter out moves that are within the board boundaries
     return moves.filter(
       ([y, x]) => y >= 0 && y < this.size && x >= 0 && x < this.size
     )
   }
 
   isComplete() {
-    // helper function to check if the board is complete
+    // Helper function to check if the board is complete
     return !this.board.map((row) => row.includes(0)).includes(true)
   }
 
   solve() {
-    // function to find the solution for the given board
+    // Function to find the solution for the given board
     for (let i = 0; i < this.size; i++) {
       for (let j = 0; j < this.size; j++) {
         if (this.solveHelper([i, j], 0)) return true
@@ -40,14 +42,15 @@ class OpenKnightTour {
   }
 
   solveHelper([i, j], curr) {
-    // helper function for the main computation
+    // Helper function for the main computation
     if (this.isComplete()) return true
 
+    // Iterate through possible moves and attempt to fill the board
     for (const [y, x] of this.getMoves([i, j])) {
       if (this.board[y][x] === 0) {
         this.board[y][x] = curr + 1
         if (this.solveHelper([y, x], curr + 1)) return true
-        // backtracking
+        // Backtracking: If the solution is not found, reset the cell to 0
         this.board[y][x] = 0
       }
     }
@@ -55,7 +58,7 @@ class OpenKnightTour {
   }
 
   printBoard(output = (value) => console.log(value)) {
-    // utility function to display the board
+    // Utility function to display the board
     for (const row of this.board) {
       let string = ''
       for (const elem of row) {

From fb134b10b0521d01ade8da215803d34d9fafd8e8 Mon Sep 17 00:00:00 2001
From: Vedas Dixit <111585043+vedas-dixit@users.noreply.github.com>
Date: Tue, 24 Oct 2023 12:18:59 +0530
Subject: [PATCH 05/73] Implemented M Coloring Problem (#1562)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Implemented M Coloring Problem

* Implemented M Coloring Problem

* Switch to a functional approach instead of class-based.
Use proper JSDoc comments.
Refine the comments and remove redundancies.

* Updated Documentation in README.md

* Proper JSDoc comment

---------

Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>
---
 Backtracking/MColoringProblem.js            | 49 +++++++++++++++++++++
 Backtracking/tests/MColoringProblem.test.js | 23 ++++++++++
 DIRECTORY.md                                |  2 +
 3 files changed, 74 insertions(+)
 create mode 100644 Backtracking/MColoringProblem.js
 create mode 100644 Backtracking/tests/MColoringProblem.test.js

diff --git a/Backtracking/MColoringProblem.js b/Backtracking/MColoringProblem.js
new file mode 100644
index 0000000000..c89f30e043
--- /dev/null
+++ b/Backtracking/MColoringProblem.js
@@ -0,0 +1,49 @@
+/**
+ * Colors a graph using up to m colors such that no two adjacent vertices share the same color.
+ * @param {number[][]} graph - Adjacency matrix of the graph, using 0 for no edge.
+ * @param {number} m - The number of colors to use.
+ * @returns {?Array.<number>} A valid M-coloring of the graph using colors 1 to m, or null if none exists.
+ * @see https://en.wikipedia.org/wiki/Graph_coloring
+ */
+function mColoring(graph, m) {
+  const colors = new Array(graph.length).fill(0);
+
+  // Check if it's safe to color a vertex with a given color.
+  function isSafe(vertex, color) {
+    for (let i = 0; i < graph.length; i++) {
+      if (graph[vertex][i] && colors[i] === color) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  // Use backtracking to try and color the graph.
+  function solveColoring(vertex = 0) {
+    if (vertex === graph.length) {
+      return true;
+    }
+
+    for (let color = 1; color <= m; color++) {
+      if (isSafe(vertex, color)) {
+        colors[vertex] = color;
+        
+        if (solveColoring(vertex + 1)) {
+          return true;
+        }
+
+        // If no solution, backtrack.
+        colors[vertex] = 0;
+      }
+    }
+    return false;
+  }
+
+  // If coloring is possible, return the colors.
+  if (solveColoring()) {
+    return colors;
+  }
+  return null;
+}
+
+export { mColoring };
diff --git a/Backtracking/tests/MColoringProblem.test.js b/Backtracking/tests/MColoringProblem.test.js
new file mode 100644
index 0000000000..d98134b62a
--- /dev/null
+++ b/Backtracking/tests/MColoringProblem.test.js
@@ -0,0 +1,23 @@
+import { mColoring } from '../MColoringProblem';
+
+describe('MColoringProblem', () => {
+  it('should color a triangle with 3 colors', () => {
+    const graph = [
+      [0, 1, 1],
+      [1, 0, 1],
+      [1, 1, 0]
+    ];
+    const solution = mColoring(graph, 3);
+    expect(solution).not.toBeNull();
+  });
+
+  it('should not color a triangle with 2 colors', () => {
+    const graph = [
+      [0, 1, 1],
+      [1, 0, 1],
+      [1, 1, 0]
+    ];
+    const solution = mColoring(graph, 2);
+    expect(solution).toBeNull();
+  });
+});
diff --git a/DIRECTORY.md b/DIRECTORY.md
index aea7b1548f..61fa501119 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -3,6 +3,7 @@
   * [generateParentheses](Backtracking/generateParentheses.js)
   * [GeneratePermutations](Backtracking/GeneratePermutations.js)
   * [KnightTour](Backtracking/KnightTour.js)
+  * [MColoringProblem](Backtracking/MColoringProblem.js)
   * [NQueens](Backtracking/NQueens.js)
   * [RatInAMaze](Backtracking/RatInAMaze.js)
   * [Sudoku](Backtracking/Sudoku.js)
@@ -166,6 +167,7 @@
   * [Area](Maths/Area.js)
   * [ArithmeticGeometricMean](Maths/ArithmeticGeometricMean.js)
   * [ArmstrongNumber](Maths/ArmstrongNumber.js)
+  * [AutomorphicNumber](Maths/AutomorphicNumber.js)
   * [AverageMean](Maths/AverageMean.js)
   * [AverageMedian](Maths/AverageMedian.js)
   * [BinaryConvert](Maths/BinaryConvert.js)

From 9a875264cc526a874defd09544a8bcfd7d3f6212 Mon Sep 17 00:00:00 2001
From: Omkarnath Parida <pomkarnath98@gmail.com>
Date: Tue, 24 Oct 2023 22:49:37 +0530
Subject: [PATCH 06/73] prettier fixes & added test cases for Project Euler
 problem 4 (#1566)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* 📦 NEW: Added solution for ProjectEuler-007

* 🐛 FIX: Spelling mistake fixes

* 👌 IMPROVE: changed variable name from `inc` to `candidateValue` and thrown error in case of invalid input

* 👌 IMPROVE: Modified the code

* 👌 IMPROVE: Added test case for ProjectEuler Problem001

* 👌 IMPROVE: Added test cases for Project Euler Problem 4

* 👌 IMPROVE: auto prettier fixes

---------

Co-authored-by: Omkarnath Parida <omkarnath.parida@yocket.in>
---
 Bit-Manipulation/BinaryCountSetBits.js  |  2 +-
 Maths/AutomorphicNumber.js              |  2 +-
 Maths/test/AutomorphicNumber.test.js    | 16 ++++-----
 Project-Euler/Problem006.js             |  6 ++--
 Project-Euler/test/Problem004.test.js   | 11 ++++++
 Recursive/test/BinaryEquivalent.test.js | 48 ++++++++++++-------------
 Search/InterpolationSearch.js           |  2 +-
 7 files changed, 49 insertions(+), 38 deletions(-)
 create mode 100644 Project-Euler/test/Problem004.test.js

diff --git a/Bit-Manipulation/BinaryCountSetBits.js b/Bit-Manipulation/BinaryCountSetBits.js
index b879f3bd67..b959caf062 100644
--- a/Bit-Manipulation/BinaryCountSetBits.js
+++ b/Bit-Manipulation/BinaryCountSetBits.js
@@ -16,7 +16,7 @@ function BinaryCountSetBits(a) {
 
   let count = 0
   while (a) {
-    a &= (a - 1)
+    a &= a - 1
     count++
   }
 
diff --git a/Maths/AutomorphicNumber.js b/Maths/AutomorphicNumber.js
index d1b6608316..ba008271fc 100644
--- a/Maths/AutomorphicNumber.js
+++ b/Maths/AutomorphicNumber.js
@@ -35,6 +35,6 @@ export const isAutomorphic = (n) => {
     n = Math.floor(n / 10)
     n_sq = Math.floor(n_sq / 10)
   }
-  
+
   return true
 }
diff --git a/Maths/test/AutomorphicNumber.test.js b/Maths/test/AutomorphicNumber.test.js
index 19b963388c..57f40d27ee 100644
--- a/Maths/test/AutomorphicNumber.test.js
+++ b/Maths/test/AutomorphicNumber.test.js
@@ -9,19 +9,19 @@ describe('AutomorphicNumber', () => {
   })
 
   test.each([
-    { n: -3 , expected: false },
-    { n: -25 , expected: false },
+    { n: -3, expected: false },
+    { n: -25, expected: false }
   ])('should return false when n is negetive', ({ n, expected }) => {
     expect(isAutomorphic(n)).toBe(false)
   })
 
   test.each([
-    { n: 7 , expected: false },
-    { n: 83 , expected: false },
-    { n: 0 , expected: true },
-    { n: 1 , expected: true },
-    { n: 376 , expected: true },
-    { n: 90625 , expected: true },
+    { n: 7, expected: false },
+    { n: 83, expected: false },
+    { n: 0, expected: true },
+    { n: 1, expected: true },
+    { n: 376, expected: true },
+    { n: 90625, expected: true }
   ])('should return $expected when n is $n', ({ n, expected }) => {
     expect(isAutomorphic(n)).toBe(expected)
   })
diff --git a/Project-Euler/Problem006.js b/Project-Euler/Problem006.js
index 474de2ae96..804b165558 100644
--- a/Project-Euler/Problem006.js
+++ b/Project-Euler/Problem006.js
@@ -1,8 +1,8 @@
 // https://projecteuler.net/problem=6
 
 export const squareDifference = (num = 100) => {
-  let sumOfSquares = (num)*(num+1)*(2*num+1)/6
-  let sums = (num*(num+1))/2
-  
+  let sumOfSquares = (num * (num + 1) * (2 * num + 1)) / 6
+  let sums = (num * (num + 1)) / 2
+
   return sums ** 2 - sumOfSquares // difference of square of the total sum and sum of squares
 }
diff --git a/Project-Euler/test/Problem004.test.js b/Project-Euler/test/Problem004.test.js
new file mode 100644
index 0000000000..cd6a55ac98
--- /dev/null
+++ b/Project-Euler/test/Problem004.test.js
@@ -0,0 +1,11 @@
+import { largestPalindromic } from '../Problem004.js'
+
+describe('Largest Palindromic Number', () => {
+  test('if digit is 2', () => {
+    expect(largestPalindromic(2)).toBe(9009)
+  })
+  // Project Euler Condition Check
+  test('if digit is 3', () => {
+    expect(largestPalindromic(3)).toBe(906609)
+  })
+})
diff --git a/Recursive/test/BinaryEquivalent.test.js b/Recursive/test/BinaryEquivalent.test.js
index b79a455eed..ddabb7d477 100644
--- a/Recursive/test/BinaryEquivalent.test.js
+++ b/Recursive/test/BinaryEquivalent.test.js
@@ -1,29 +1,29 @@
-import { binaryEquivalent } from "../BinaryEquivalent";
+import { binaryEquivalent } from '../BinaryEquivalent'
 
 const tests = [
-    {
-        test: 2,
-        expectedValue: "10"
-    },
-    {       
-        test: 0,
-        expectedValue: "0"
-    },
-    {
-        test: 543,
-        expectedValue: "1000011111"
-    },
-    {
-        test: 4697621023,
-        expectedValue: "100011000000000000000001000011111"
-    }
+  {
+    test: 2,
+    expectedValue: '10'
+  },
+  {
+    test: 0,
+    expectedValue: '0'
+  },
+  {
+    test: 543,
+    expectedValue: '1000011111'
+  },
+  {
+    test: 4697621023,
+    expectedValue: '100011000000000000000001000011111'
+  }
 ]
 
-describe("Binary Equivalent", () => {
-    test.each(tests)(
-        "of $test should be $expectedValue",
-        ({test, expectedValue}) => {
-            expect(binaryEquivalent(test)).toBe(expectedValue);
-        }
-    )
+describe('Binary Equivalent', () => {
+  test.each(tests)(
+    'of $test should be $expectedValue',
+    ({ test, expectedValue }) => {
+      expect(binaryEquivalent(test)).toBe(expectedValue)
+    }
+  )
 })
diff --git a/Search/InterpolationSearch.js b/Search/InterpolationSearch.js
index e6deae496f..93f3b78b0e 100644
--- a/Search/InterpolationSearch.js
+++ b/Search/InterpolationSearch.js
@@ -36,4 +36,4 @@ export function interpolationSearch(arr, key) {
   }
 
   return -1
-}
\ No newline at end of file
+}

From 9c07bb110758aae6316385c966b42add948b0586 Mon Sep 17 00:00:00 2001
From: Omkarnath Parida <pomkarnath98@gmail.com>
Date: Thu, 26 Oct 2023 19:04:20 +0530
Subject: [PATCH 07/73] Test cases project euler 9 (#1571)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* 📦 NEW: Added solution for ProjectEuler-007

* 🐛 FIX: Spelling mistake fixes

* 👌 IMPROVE: changed variable name from `inc` to `candidateValue` and thrown error in case of invalid input

* 👌 IMPROVE: Modified the code

* 👌 IMPROVE: Added test case for ProjectEuler Problem001

* 👌 IMPROVE: Added test cases for Project Euler Problem 4

* 👌 IMPROVE: auto prettier fixes

* 👌 IMPROVE: Added test cases for project euler problem 9

* Updated Documentation in README.md

* Updated Documentation in README.md

---------

Co-authored-by: Omkarnath Parida <omkarnath.parida@yocket.in>
Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
---
 Project-Euler/test/Problem009.test.js | 8 ++++++++
 1 file changed, 8 insertions(+)
 create mode 100644 Project-Euler/test/Problem009.test.js

diff --git a/Project-Euler/test/Problem009.test.js b/Project-Euler/test/Problem009.test.js
new file mode 100644
index 0000000000..3919fa2833
--- /dev/null
+++ b/Project-Euler/test/Problem009.test.js
@@ -0,0 +1,8 @@
+import { findSpecialPythagoreanTriplet } from '../Problem009.js'
+
+describe('Pythagorean Triplet', () => {
+  // Project Euler Condition Check
+  test('the multiplication of the pythagorean triplet where a + b + c = 1000', () => {
+    expect(findSpecialPythagoreanTriplet()).toBe(31875000)
+  })
+})

From f67cdc3cad62924de6c29083b7d2776f90655cbe Mon Sep 17 00:00:00 2001
From: Omkarnath Parida <pomkarnath98@gmail.com>
Date: Thu, 26 Oct 2023 19:05:34 +0530
Subject: [PATCH 08/73] Test cases project euler 6 (#1570)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* 📦 NEW: Added solution for ProjectEuler-007

* 🐛 FIX: Spelling mistake fixes

* 👌 IMPROVE: changed variable name from `inc` to `candidateValue` and thrown error in case of invalid input

* 👌 IMPROVE: Modified the code

* 👌 IMPROVE: Added test case for ProjectEuler Problem001

* 👌 IMPROVE: Added test cases for Project Euler Problem 4

* 👌 IMPROVE: auto prettier fixes

* 👌 IMPROVE: added test cases for project euler problem 6

* Updated Documentation in README.md

* Updated Documentation in README.md

---------

Co-authored-by: Omkarnath Parida <omkarnath.parida@yocket.in>
Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
---
 Project-Euler/test/Problem006.test.js | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 Project-Euler/test/Problem006.test.js

diff --git a/Project-Euler/test/Problem006.test.js b/Project-Euler/test/Problem006.test.js
new file mode 100644
index 0000000000..1323a34ac2
--- /dev/null
+++ b/Project-Euler/test/Problem006.test.js
@@ -0,0 +1,11 @@
+import { squareDifference } from '../Problem006.js'
+
+describe('Square Difference', () => {
+  test('difference between the sum of the squares of the first ten natural numbers and the square of the sum', () => {
+    expect(squareDifference(10)).toBe(2640)
+  })
+  // Project Euler Condition Check
+  test('difference between the sum of the squares of the first one hundred natural numbers and the square of the sum', () => {
+    expect(squareDifference()).toBe(25164150)
+  })
+})

From d671327ebe63832434285ef96cabf255e11bf2cd Mon Sep 17 00:00:00 2001
From: Nikunj Bisht <52692588+Nikunj-bisht@users.noreply.github.com>
Date: Thu, 26 Oct 2023 19:08:19 +0530
Subject: [PATCH 09/73] feat: added find subsets algorithm using
 bitmanipulation (#1514)

* feat: added find subsets algorithm using bitmanipulation

* file name fix

* test file name fix

* fix: codespell fix

* error handled

* added test cases for error
---
 Bit-Manipulation/GenerateSubSets.js           | 34 ++++++++++++++++++
 Bit-Manipulation/test/GenerateSubSets.test.js | 36 +++++++++++++++++++
 2 files changed, 70 insertions(+)
 create mode 100644 Bit-Manipulation/GenerateSubSets.js
 create mode 100644 Bit-Manipulation/test/GenerateSubSets.test.js

diff --git a/Bit-Manipulation/GenerateSubSets.js b/Bit-Manipulation/GenerateSubSets.js
new file mode 100644
index 0000000000..9ee131d757
--- /dev/null
+++ b/Bit-Manipulation/GenerateSubSets.js
@@ -0,0 +1,34 @@
+/**
+ * @function generateSubSets
+ * @param {Array} inputArray
+ * @returns {Array}
+ * @example [1,2] -> [[],[1],[2],[1,2]]
+ */
+
+// The time complexity of this algorithm is BigO(2^n) where n is the length of array
+function generateSubSets(inputArray) {
+  if (!Array.isArray(inputArray)) {
+    throw new Error('Provided input is not an array')
+  }
+  if (inputArray.length > 32) {
+    throw new RangeError('Error size should be less than equal to 32')
+  }
+  let arrayLength = inputArray.length
+  let subSets = []
+  // loop till (2^n) - 1
+  for (let i = 0; i < 1 << arrayLength; i++) {
+    let subSet = []
+    for (let j = 0; j < arrayLength; j++) {
+      // 1 << j it shifts binary digit 1 by j positions and then we perform
+      // and by AND operation we are checking whetheer jth bit
+      // in i is set to 1 if result is non zero just add into set
+      if (i & (1 << j)) {
+        subSet.push(inputArray[j])
+      }
+    }
+    subSets.push(subSet)
+  }
+  return subSets
+}
+
+export { generateSubSets }
diff --git a/Bit-Manipulation/test/GenerateSubSets.test.js b/Bit-Manipulation/test/GenerateSubSets.test.js
new file mode 100644
index 0000000000..2e3b90ba71
--- /dev/null
+++ b/Bit-Manipulation/test/GenerateSubSets.test.js
@@ -0,0 +1,36 @@
+import { generateSubSets } from '../GenerateSubSets'
+
+describe('subSets', () => {
+  it('find the subsets', () => {
+    expect(generateSubSets([1, 2, 3])).toEqual([
+      [],
+      [1],
+      [2],
+      [1, 2],
+      [3],
+      [1, 3],
+      [2, 3],
+      [1, 2, 3]
+    ])
+    expect(generateSubSets([1, 2])).toEqual([[], [1], [2], [1, 2]])
+    expect(generateSubSets([1, 2, 3])).toEqual([
+      [],
+      [1],
+      [2],
+      [1, 2],
+      [3],
+      [1, 3],
+      [2, 3],
+      [1, 2, 3]
+    ])
+    expect(() => generateSubSets('invalid')).toThrow(
+      'Provided input is not an array'
+    )
+    expect(() =>
+      generateSubSets([
+        1, 2, 2, 1, 2, 3, 4, 3, 2, 3, 4, 3, 2, 2, 2, 3, 12, 11, 4, 2, 2, 2, 2,
+        1, 2, 3, 5, 6, 7, 7, 8, 6, 5, 6, 7, 8, 9, 8, 0, 6
+      ])
+    ).toThrow('Error size should be less than equal to 32')
+  })
+})

From 0b9fad86ba60b4f76e4d68a27fa222e55ca65fdb Mon Sep 17 00:00:00 2001
From: Lars Mueller <appgurulars@gmx.de>
Date: Sat, 28 Oct 2023 00:50:16 +0200
Subject: [PATCH 10/73] fix: CI code style checking

---
 .github/workflows/Ci.yml | 2 +-
 package.json             | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/Ci.yml b/.github/workflows/Ci.yml
index e08dcdb446..12093c2738 100644
--- a/.github/workflows/Ci.yml
+++ b/.github/workflows/Ci.yml
@@ -25,7 +25,7 @@ jobs:
         run: npm run test
 
       - name: 💄 Code style
-        run: npm run style
+        run: npm run check-style
 
   codespell:
     name: Check for spelling errors
diff --git a/package.json b/package.json
index 2dd45beac9..9ce6f3cb0f 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
     "test": "vitest run",
     "test-watch": "vitest",
     "style": "npx prettier . --write",
+    "check-style": "npx prettier . --check",
     "prepare": "husky install"
   },
   "author": "TheAlgorithms",

From 28c27d9474043b7fb9b6b3b4aa3cca015db2a090 Mon Sep 17 00:00:00 2001
From: Lars Mueller <appgurulars@gmx.de>
Date: Sat, 28 Oct 2023 00:56:39 +0200
Subject: [PATCH 11/73] chore: format using prettier

---
 Backtracking/MColoringProblem.js            | 24 ++++++++++-----------
 Backtracking/tests/MColoringProblem.test.js | 20 ++++++++---------
 2 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/Backtracking/MColoringProblem.js b/Backtracking/MColoringProblem.js
index c89f30e043..d625b34a45 100644
--- a/Backtracking/MColoringProblem.js
+++ b/Backtracking/MColoringProblem.js
@@ -6,44 +6,44 @@
  * @see https://en.wikipedia.org/wiki/Graph_coloring
  */
 function mColoring(graph, m) {
-  const colors = new Array(graph.length).fill(0);
+  const colors = new Array(graph.length).fill(0)
 
   // Check if it's safe to color a vertex with a given color.
   function isSafe(vertex, color) {
     for (let i = 0; i < graph.length; i++) {
       if (graph[vertex][i] && colors[i] === color) {
-        return false;
+        return false
       }
     }
-    return true;
+    return true
   }
 
   // Use backtracking to try and color the graph.
   function solveColoring(vertex = 0) {
     if (vertex === graph.length) {
-      return true;
+      return true
     }
 
     for (let color = 1; color <= m; color++) {
       if (isSafe(vertex, color)) {
-        colors[vertex] = color;
-        
+        colors[vertex] = color
+
         if (solveColoring(vertex + 1)) {
-          return true;
+          return true
         }
 
         // If no solution, backtrack.
-        colors[vertex] = 0;
+        colors[vertex] = 0
       }
     }
-    return false;
+    return false
   }
 
   // If coloring is possible, return the colors.
   if (solveColoring()) {
-    return colors;
+    return colors
   }
-  return null;
+  return null
 }
 
-export { mColoring };
+export { mColoring }
diff --git a/Backtracking/tests/MColoringProblem.test.js b/Backtracking/tests/MColoringProblem.test.js
index d98134b62a..759a328aae 100644
--- a/Backtracking/tests/MColoringProblem.test.js
+++ b/Backtracking/tests/MColoringProblem.test.js
@@ -1,4 +1,4 @@
-import { mColoring } from '../MColoringProblem';
+import { mColoring } from '../MColoringProblem'
 
 describe('MColoringProblem', () => {
   it('should color a triangle with 3 colors', () => {
@@ -6,18 +6,18 @@ describe('MColoringProblem', () => {
       [0, 1, 1],
       [1, 0, 1],
       [1, 1, 0]
-    ];
-    const solution = mColoring(graph, 3);
-    expect(solution).not.toBeNull();
-  });
+    ]
+    const solution = mColoring(graph, 3)
+    expect(solution).not.toBeNull()
+  })
 
   it('should not color a triangle with 2 colors', () => {
     const graph = [
       [0, 1, 1],
       [1, 0, 1],
       [1, 1, 0]
-    ];
-    const solution = mColoring(graph, 2);
-    expect(solution).toBeNull();
-  });
-});
+    ]
+    const solution = mColoring(graph, 2)
+    expect(solution).toBeNull()
+  })
+})

From aebd52f39f80a46c4f698fae16a553496f5ec4e8 Mon Sep 17 00:00:00 2001
From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
Date: Fri, 27 Oct 2023 22:57:25 +0000
Subject: [PATCH 12/73] chore: update readme

---
 DIRECTORY.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/DIRECTORY.md b/DIRECTORY.md
index 61fa501119..730df9cdf9 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -10,6 +10,7 @@
   * [SumOfSubset](Backtracking/SumOfSubset.js)
 * **Bit-Manipulation**
   * [BinaryCountSetBits](Bit-Manipulation/BinaryCountSetBits.js)
+  * [GenerateSubSets](Bit-Manipulation/GenerateSubSets.js)
   * [GrayCodes](Bit-Manipulation/GrayCodes.js)
   * [IsPowerofFour](Bit-Manipulation/IsPowerofFour.js)
   * [IsPowerOfTwo](Bit-Manipulation/IsPowerOfTwo.js)

From 889d9c361df169e9a01d32295cb02f8eb0372a08 Mon Sep 17 00:00:00 2001
From: Manpreet Singh <63737630+ManpreetSingh2004@users.noreply.github.com>
Date: Mon, 30 Oct 2023 10:54:35 +0530
Subject: [PATCH 13/73] feat: Added MD5 hashing algorithm (#1519)

* feat: Added MD5 hashing algorithm

* Added wiki link

* Remove spam?

* Fix extend towards end

* Return Uint32Array in MD5 function

* Preprocess function now works on uint arrays

* chunkify U32Array instead of string

* Remove all string related functions

* Replace typed arrays with named variables

* Fix "Replace typed arrays with named variables"

* Return Uint8 Array in MD5 function

The MD5 function now returns a uint8 array with the correct endianness.

* Add tests

* Fix docstrings

* Introduce hexMD5 function

* Change test string

* Format test file
---
 Hashes/MD5.js            | 205 +++++++++++++++++++++++++++++++++++++++
 Hashes/tests/MD5.test.js |  38 ++++++++
 2 files changed, 243 insertions(+)
 create mode 100644 Hashes/MD5.js
 create mode 100644 Hashes/tests/MD5.test.js

diff --git a/Hashes/MD5.js b/Hashes/MD5.js
new file mode 100644
index 0000000000..42bef45cc5
--- /dev/null
+++ b/Hashes/MD5.js
@@ -0,0 +1,205 @@
+// Module that replicates the MD5 Cryptographic Hash
+// function in Javascript.
+
+// main variables
+const S = [
+  7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5,
+  9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11,
+  16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15,
+  21
+]
+
+const K = [
+  0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,
+  0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+  0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340,
+  0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+  0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,
+  0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+  0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,
+  0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+  0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,
+  0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+  0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+]
+
+/**
+ * Separates an array into equal sized chunks
+ *
+ * @param {Array|string} array - array or string to separate into chunks
+ * @param {number} size - number of elements wanted in each chunk
+ * @return {Array} - array of original array split into chunks
+ *
+ * @example
+ *      chunkify("this is a test", 2)
+ */
+function chunkify(array, size) {
+  const chunks = []
+  for (let i = 0; i < array.length; i += size) {
+    chunks.push(array.slice(i, i + size))
+  }
+  return chunks
+}
+
+/**
+ * Rotates the bits to the left
+ *
+ * @param {number} bits - 32 bit number
+ * @param {number} turns - number of rotations to make
+ * @return {number} - number after bits rotation
+ *
+ * @example
+ *      rotateLeft(0b1011, 3); // 0b1011000
+ */
+function rotateLeft(bits, turns) {
+  return (bits << turns) | (bits >>> (32 - turns))
+}
+
+/**
+ * Converts Uint8Array to Uint32Array
+ *
+ * @param {Uint8Array} u8Array Uint8Array to convert
+ * @returns {Uint32Array} - Required Uint32Array
+ */
+function u8ToU32(u8Array) {
+  const uint32Array = new Uint32Array(u8Array.length / 4)
+
+  for (let i = 0; i < u8Array.length; i += 4) {
+    uint32Array[i / 4] =
+      (u8Array[i] |
+        (u8Array[i + 1] << 8) |
+        (u8Array[i + 2] << 16) |
+        (u8Array[i + 3] << 24)) >>>
+      0
+  }
+
+  return uint32Array
+}
+
+/**
+ * Converts Uint32Array to Uint8Array
+ *
+ * @param {Uint32Array} u32Array Uint32Array to convert
+ * @returns {Uint8Array} - Required Uint8Array
+ */
+function u32ToU8(u32Array) {
+  const uint8Array = new Uint8Array(u32Array.length * 4)
+
+  for (let i = 0; i < u32Array.length; i++) {
+    uint8Array[i * 4] = u32Array[i] & 0xff
+    uint8Array[i * 4 + 1] = (u32Array[i] >> 8) & 0xff
+    uint8Array[i * 4 + 2] = (u32Array[i] >> 16) & 0xff
+    uint8Array[i * 4 + 3] = (u32Array[i] >> 24) & 0xff
+  }
+
+  return uint8Array
+}
+
+/**
+ * Adds padding to the end of the given array
+ *
+ * @param {Uint8Array} u8Array Array to pad
+ * @param {number} size Resulting size of the array
+ */
+function padEnd(u8Array, size) {
+  const result = new Uint8Array(size)
+  result.set(u8Array)
+  result.fill(0, u8Array.length)
+
+  return result
+}
+
+/**
+ * Pre-processes message to feed the algorithm loop
+ *
+ * @param {Uint8Array} message - message to pre-process
+ * @return {Uint32Array} - processed message
+ */
+function preProcess(message) {
+  // Extend message by adding '0'
+  //
+  // message.length + 1 is for adding '1' bit
+  // 56 - (length % 64) is for padding with '0's
+  // 8 is for appending 64 bit message length
+  let m = padEnd(
+    message,
+    message.length + 1 + (56 - ((message.length + 1) % 64)) + 8
+  )
+
+  // Add '1' bit at the end of the message
+  m[message.length] = 1 << 7
+
+  // convert message to 32 bit uint array
+  m = u8ToU32(m)
+
+  // Append the length of the message to the end
+  // (ml / 0x100000000) | 0 is equivalent to (ml >> 32) & 0xffffffff) in other languages
+  let ml = message.length * 8
+  m[m.length - 2] = ml & 0xffffffff
+  m[m.length - 1] = (ml / 0x100000000) | 0
+
+  return m
+}
+
+/**
+ * Hashes message using MD5 Cryptographic Hash Function
+ *
+ * @see
+ * For more info: https://en.wikipedia.org/wiki/MD5
+ *
+ * @param {Uint8Array} message - message to hash
+ * @return {Uint8Array} - message digest (hash value)
+ */
+function MD5(message) {
+  // Initialize variables:
+  let [a0, b0, c0, d0] = [
+    0x67452301 >>> 0,
+    0xefcdab89 >>> 0,
+    0x98badcfe >>> 0,
+    0x10325476 >>> 0
+  ]
+
+  // pre-process message and split into 512 bit chunks
+  const words = Array.from(preProcess(message))
+  const chunks = chunkify(words, 16)
+
+  chunks.forEach(function (chunk, _) {
+    // initialize variables for this chunk
+    let [A, B, C, D] = [a0, b0, c0, d0]
+
+    for (let i = 0; i < 64; i++) {
+      let [F, g] = [0, 0]
+
+      if (i <= 15) {
+        F = (B & C) | (~B & D)
+        g = i
+      } else if (i <= 31) {
+        F = (D & B) | (~D & C)
+        g = (5 * i + 1) % 16
+      } else if (i <= 47) {
+        F = B ^ C ^ D
+        g = (3 * i + 5) % 16
+      } else {
+        F = C ^ (B | ~D)
+        g = (7 * i) % 16
+      }
+
+      F = (F + A + K[i] + chunk[g]) >>> 0
+      A = D
+      D = C
+      C = B
+      B = ((B + rotateLeft(F, S[i])) & 0xffffffff) >>> 0
+    }
+
+    // add values for this chunk to main hash variables (unsigned)
+    a0 = (a0 + A) >>> 0
+    b0 = (b0 + B) >>> 0
+    c0 = (c0 + C) >>> 0
+    d0 = (d0 + D) >>> 0
+  })
+
+  return u32ToU8([a0, b0, c0, d0])
+}
+
+// export MD5 function
+export { MD5 }
diff --git a/Hashes/tests/MD5.test.js b/Hashes/tests/MD5.test.js
new file mode 100644
index 0000000000..5c44c7a57c
--- /dev/null
+++ b/Hashes/tests/MD5.test.js
@@ -0,0 +1,38 @@
+import { MD5 } from '../MD5'
+
+/**
+ * Returns the MD5 hash of the given message as a hexadecimal string
+ *
+ * @param {Uint8Array} message - message to hash
+ * @return {string} - hash as a hexadecimal string
+ */
+function hexMD5(message) {
+  return Array.from(MD5(message), (byte) =>
+    byte.toString(16).padStart(2, '0')
+  ).join('')
+}
+
+describe('Testing MD5 function', () => {
+  it('should return the correct hash for "The quick brown fox jumps over the lazy dog"', () => {
+    const input = new TextEncoder().encode(
+      'The quick brown fox jumps over the lazy dog'
+    )
+    const hash = hexMD5(input)
+
+    expect(hash).toBe('9e107d9d372bb6826bd81d3542a419d6')
+  })
+
+  it('should return the correct hash for "JavaScript!"', () => {
+    const input = new TextEncoder().encode('JavaScript!')
+    const hash = hexMD5(input)
+
+    expect(hash).toBe('209eddd6b61af0643907a8e069a08fb8')
+  })
+
+  it('should correctly hash an empty string', () => {
+    const input = new TextEncoder().encode('')
+    const hash = hexMD5(input)
+
+    expect(hash).toBe('d41d8cd98f00b204e9800998ecf8427e')
+  })
+})

From d74f242ac4f8cedb4c5de106f2e571d94daeefe7 Mon Sep 17 00:00:00 2001
From: Mahfoudh Arous <mahfoudh.arous@gmail.com>
Date: Mon, 30 Oct 2023 06:30:31 +0100
Subject: [PATCH 14/73] Rabin Karp Search Algorithm (#1545)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Search: Rabin-Karp algorithm

* Prettier Style

* Search: Rabin-Karp adding reference

* Search: Rabin-Karp styling and remove unecessary logging

* Search: Rabin-Karp review notes

* Simplify return

* Updated Documentation in README.md

---------

Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>
Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
---
 DIRECTORY.md                  |  1 +
 Search/RabinKarp.js           | 64 +++++++++++++++++++++++++++++++++++
 Search/test/RabinKarp.test.js | 30 ++++++++++++++++
 3 files changed, 95 insertions(+)
 create mode 100644 Search/RabinKarp.js
 create mode 100644 Search/test/RabinKarp.test.js

diff --git a/DIRECTORY.md b/DIRECTORY.md
index 730df9cdf9..1b2c40b3c8 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -311,6 +311,7 @@
   * [LinearSearch](Search/LinearSearch.js)
   * [Minesweeper](Search/Minesweeper.js)
   * [QuickSelectSearch](Search/QuickSelectSearch.js)
+  * [RabinKarp](Search/RabinKarp.js)
   * [SlidingWindow](Search/SlidingWindow.js)
   * [StringSearch](Search/StringSearch.js)
   * [TernarySearch](Search/TernarySearch.js)
diff --git a/Search/RabinKarp.js b/Search/RabinKarp.js
new file mode 100644
index 0000000000..e6d6394ede
--- /dev/null
+++ b/Search/RabinKarp.js
@@ -0,0 +1,64 @@
+/*
+ * Implements the Rabin-Karp algorithm for pattern searching.
+ *
+ * The Rabin-Karp algorithm is a string searching algorithm that uses hashing to find patterns in strings.
+ * It is faster than naive string matching algorithms because it avoids comparing every character in the text.
+ *
+ * This implementation uses a rolling hash function to efficiently compute the hash values of substrings.
+ * It also uses a modulo operator to reduce the size of the hash values, which helps to prevent hash collisions.
+ *
+ * The algorithm returns an array of indices where the pattern is found in the text. If the pattern is not
+ * found, the algorithm returns an empty array.
+ *
+ * [Reference](https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm)
+ */
+
+const BASE = 256 // The number of characters in the alphabet
+const MOD = 997 // A prime number used for the hash function
+
+function rabinKarpSearch(text, pattern) {
+  const patternLength = pattern.length
+  const textLength = text.length
+  const hashPattern = hash(pattern, patternLength)
+  const hashText = []
+  const indices = []
+
+  // Calculate the hash of the first substring in the text
+  hashText[0] = hash(text, patternLength)
+
+  // Precompute BASE^(patternLength-1) % MOD
+  const basePow = Math.pow(BASE, patternLength - 1) % MOD
+
+  for (let i = 1; i <= textLength - patternLength + 1; i++) {
+    // Update the rolling hash by removing the first character
+    // and adding the next character in the text
+    hashText[i] =
+      (BASE * (hashText[i - 1] - text.charCodeAt(i - 1) * basePow) +
+        text.charCodeAt(i + patternLength - 1)) %
+      MOD
+
+    // In case of hash collision, check character by character
+    if (hashText[i] < 0) {
+      hashText[i] += MOD
+    }
+
+    // Check if the hashes match and perform a character-wise comparison
+    if (hashText[i] === hashPattern) {
+      if (text.substring(i, i + patternLength) === pattern) {
+        indices.push(i) // Store the index where the pattern is found
+      }
+    }
+  }
+
+  return indices
+}
+
+function hash(str, length) {
+  let hashValue = 0
+  for (let i = 0; i < length; i++) {
+    hashValue = (hashValue * BASE + str.charCodeAt(i)) % MOD
+  }
+  return hashValue
+}
+
+export { rabinKarpSearch }
diff --git a/Search/test/RabinKarp.test.js b/Search/test/RabinKarp.test.js
new file mode 100644
index 0000000000..3d10097509
--- /dev/null
+++ b/Search/test/RabinKarp.test.js
@@ -0,0 +1,30 @@
+import { rabinKarpSearch } from '../RabinKarp'
+
+describe('Rabin-Karp Search', function () {
+  it('should find the pattern in the text', function () {
+    const text = 'ABABDABACDABABCABAB'
+    const pattern = 'DAB'
+    const expected = [4, 9]
+
+    const result = rabinKarpSearch(text, pattern)
+    expect(result).to.deep.equal(expected)
+  })
+
+  it('should handle multiple occurrences of the pattern', function () {
+    const text = 'ABABABABABAB'
+    const pattern = 'ABAB'
+    const expected = [2, 4, 6, 8]
+
+    const result = rabinKarpSearch(text, pattern)
+    expect(result).to.deep.equal(expected)
+  })
+
+  it('should handle pattern not found', function () {
+    const text = 'ABCD'
+    const pattern = 'XYZ'
+    const expected = []
+
+    const result = rabinKarpSearch(text, pattern)
+    expect(result).to.deep.equal(expected)
+  })
+})

From e5af4c24b4156279827f6a6cc4349f70247a53f2 Mon Sep 17 00:00:00 2001
From: Hardik Pawar <97388607+Hardvan@users.noreply.github.com>
Date: Mon, 30 Oct 2023 11:04:06 +0530
Subject: [PATCH 15/73] Enhance readability of ZeroOneKnapsack.js (#1574)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Enhance readability of ZeroOneKnapsack.js

* Update ZeroOneKnapsack.js

---------

Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>
---
 Dynamic-Programming/ZeroOneKnapsack.js | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/Dynamic-Programming/ZeroOneKnapsack.js b/Dynamic-Programming/ZeroOneKnapsack.js
index 3913d016b3..52a06aa130 100644
--- a/Dynamic-Programming/ZeroOneKnapsack.js
+++ b/Dynamic-Programming/ZeroOneKnapsack.js
@@ -1,26 +1,34 @@
 /**
  * A Dynamic Programming based solution for calculating Zero One Knapsack
  * https://en.wikipedia.org/wiki/Knapsack_problem
+ *
+ * Time and Space Complexity: O(n*cap)
  */
-
 const zeroOneKnapsack = (arr, n, cap, cache) => {
+  // Base Case: No capacity or no items
   if (cap === 0 || n === 0) {
     cache[n][cap] = 0
     return cache[n][cap]
   }
+
+  // Lookup (value already calculated)
   if (cache[n][cap] !== -1) {
     return cache[n][cap]
   }
+
+  // Profit when excluding the nth item
+  let notPick = zeroOneKnapsack(arr, n - 1, cap, cache)
+
+  // Profit when including the nth item
+  let pick = 0
   if (arr[n - 1][0] <= cap) {
-    cache[n][cap] = Math.max(
-      arr[n - 1][1] + zeroOneKnapsack(arr, n - 1, cap - arr[n - 1][0], cache),
-      zeroOneKnapsack(arr, n - 1, cap, cache)
-    )
-    return cache[n][cap]
-  } else {
-    cache[n][cap] = zeroOneKnapsack(arr, n - 1, cap, cache)
-    return cache[n][cap]
+    // If weight of the nth item is within the capacity
+    pick =
+      arr[n - 1][1] + zeroOneKnapsack(arr, n - 1, cap - arr[n - 1][0], cache)
   }
+
+  cache[n][cap] = Math.max(pick, notPick) // maximize profit
+  return cache[n][cap]
 }
 
 const example = () => {

From 1cc5e61ff04c4db06f2775fdabde5231b0e0f521 Mon Sep 17 00:00:00 2001
From: Rahul Bhandari <90493221+imrahulkb@users.noreply.github.com>
Date: Mon, 30 Oct 2023 11:09:26 +0530
Subject: [PATCH 16/73] Update Problem001.js (#1536)

* Update Problem001.js

* Update Problem001.js

* Update Problem001.js

* Update Problem001.js

* Update Problem001.js
---
 Project-Euler/Problem001.js | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/Project-Euler/Problem001.js b/Project-Euler/Problem001.js
index c47c10bd1c..a88f912603 100644
--- a/Project-Euler/Problem001.js
+++ b/Project-Euler/Problem001.js
@@ -1,20 +1,23 @@
 // https://projecteuler.net/problem=1
-/*    Multiples of 3 and 5
-    If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
+/* Multiples of 3 and 5
+If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6, and 9. The sum of these multiples is 23.
 Find the sum of all the multiples of 3 or 5 below the provided parameter value number.
 */
 
+// This method uses the nSum function to add the nSum for 3 and 5. However, it needs to subtract the nSum for 15 once to avoid double counting.
 const multiplesThreeAndFive = (num) => {
   if (num < 1) throw new Error('No natural numbers exist below 1')
+  num -= 1
+  let sum = 0
 
-  let total = 0
-  // total for calculating the sum
-  for (let i = 1; i < num; i++) {
-    if (i % 3 === 0 || i % 5 === 0) {
-      total += i
-    }
-  }
-  return total
+  // The nSum function calculates the sum of the first n numbers in the sequence with a common difference of num.
+  // Here, n is denoted as frequency.
+  const nSum = (num, frequency) => (frequency * (frequency + 1) * num) >> 1
+
+  sum += nSum(3, Math.floor(num / 3))
+  sum += nSum(5, Math.floor(num / 5))
+  sum -= nSum(15, Math.floor(num / 15))
+  return sum
 }
 
 export { multiplesThreeAndFive }

From cafb3433e816bafc8115315a5771a7a01d5a174a Mon Sep 17 00:00:00 2001
From: Rahul Bhandari <90493221+imrahulkb@users.noreply.github.com>
Date: Mon, 30 Oct 2023 11:10:02 +0530
Subject: [PATCH 17/73] Update AllCombinationsOfSizeK.js (#1530)

* Update AllCombinationsOfSizeK.js

* Update AllCombinationsOfSizeK.js

* Update AllCombinationsOfSizeK.test.js

Changes made it the type of testing.
Instead of testing the class now the program will test the function

* Update AllCombinationsOfSizeK.js

* Update AllCombinationsOfSizeK.js

* Update AllCombinationsOfSizeK.js

* Update AllCombinationsOfSizeK.test.js

* Update AllCombinationsOfSizeK.test.js
---
 Backtracking/AllCombinationsOfSizeK.js        | 64 +++++++------------
 .../tests/AllCombinationsOfSizeK.test.js      | 10 +--
 2 files changed, 28 insertions(+), 46 deletions(-)

diff --git a/Backtracking/AllCombinationsOfSizeK.js b/Backtracking/AllCombinationsOfSizeK.js
index 264acb1f19..bbe4e7fd5b 100644
--- a/Backtracking/AllCombinationsOfSizeK.js
+++ b/Backtracking/AllCombinationsOfSizeK.js
@@ -1,46 +1,28 @@
-/*
-  Problem: Given two numbers, n and k, make all unique combinations of k numbers from 1 to n and in sorted order
-
-  What is combinations?
-  - Combinations is selecting items from a collections without considering the order of selection
-
-  Example:
-  - We have an apple, a banana, and a jackfruit
-  - We have three objects, and need to choose two items, then combinations will be
-
-  1. Apple & Banana
-  2. Apple & Jackfruit
-  3. Banana & Jackfruit
-
-  To read more about combinations, you can visit the following link:
-  - https://betterexplained.com/articles/easy-permutations-and-combinations/
-
-  Solution:
-  - We will be using backtracking to solve this questions
-  - Take one element, and make all them combinations for k-1 elements
-  - Once we get all combinations of that element, pop it and do same for next element
-*/
-
-class Combinations {
-  constructor(n, k) {
-    this.n = n
-    this.k = k
-    this.current = [] // will be used for storing current combination
-    this.combinations = []
-  }
-
-  findCombinations(high = this.n, total = this.k, low = 1) {
-    if (total === 0) {
-      this.combinations.push([...this.current])
-      return this.combinations
+function generateCombinations(n, k) {
+  let currentCombination = []
+  let allCombinations = [] // will be used for storing all combinations
+  let currentValue = 1
+
+  function findCombinations() {
+    if (currentCombination.length === k) {
+      // Add the array of size k to the allCombinations array
+      allCombinations.push([...currentCombination])
+      return
     }
-    for (let i = low; i <= high; i++) {
-      this.current.push(i)
-      this.findCombinations(high, total - 1, i + 1)
-      this.current.pop()
+    if (currentValue > n) {
+      // Check for exceeding the range
+      return
     }
-    return this.combinations
+    currentCombination.push(currentValue++)
+    findCombinations()
+    currentCombination.pop()
+    findCombinations()
+    currentValue--
   }
+
+  findCombinations()
+
+  return allCombinations
 }
 
-export { Combinations }
+export { generateCombinations }
diff --git a/Backtracking/tests/AllCombinationsOfSizeK.test.js b/Backtracking/tests/AllCombinationsOfSizeK.test.js
index a2135e54bf..29b656a2c4 100644
--- a/Backtracking/tests/AllCombinationsOfSizeK.test.js
+++ b/Backtracking/tests/AllCombinationsOfSizeK.test.js
@@ -1,9 +1,9 @@
-import { Combinations } from '../AllCombinationsOfSizeK'
+import { generateCombinations } from '../AllCombinationsOfSizeK'
 
 describe('AllCombinationsOfSizeK', () => {
   it('should return 3x2 matrix solution for n = 3 and k = 2', () => {
-    const test1 = new Combinations(3, 2)
-    expect(test1.findCombinations()).toEqual([
+    const res = generateCombinations(3, 2)
+    expect(res).toEqual([
       [1, 2],
       [1, 3],
       [2, 3]
@@ -11,8 +11,8 @@ describe('AllCombinationsOfSizeK', () => {
   })
 
   it('should return 6x2 matrix solution for n = 4 and k = 2', () => {
-    const test2 = new Combinations(4, 2)
-    expect(test2.findCombinations()).toEqual([
+    const res = generateCombinations(4, 2)
+    expect(res).toEqual([
       [1, 2],
       [1, 3],
       [1, 4],

From a044c574016ba0116d426fbe3bb0228f095ff821 Mon Sep 17 00:00:00 2001
From: Elias Afara <afaraelias@gmail.com>
Date: Wed, 8 Nov 2023 04:46:52 +0100
Subject: [PATCH 18/73] docs: Update script usage in CONTRIBUTING.md (#1587)

---
 CONTRIBUTING.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 289f9acd34..83f0624254 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -125,7 +125,7 @@ npm test -- koch
 You can also start Vitest in "watch" mode:
 
 ```bash
-npm test-watch
+npm run test-watch
 ```
 
 This will run all tests and watch source and test files for changes. When a change is made, the tests will run again.

From e9e3ea4684332263fa7afbdd0e18780158888e7d Mon Sep 17 00:00:00 2001
From: Vedas Dixit <111585043+vedas-dixit@users.noreply.github.com>
Date: Wed, 15 Nov 2023 19:22:57 +0530
Subject: [PATCH 19/73] Implemented Partition Problem, Recursive problem
 (#1582)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Add Tug of War solution using backtracking

* Updated Documentation in README.md

* Added Tug of war problem link

* Updated Documentation in README.md

* Updated Documentation in README.md

* Refactor tugOfWar: remove unused vars, optimize initialization, and remove redundant checks

* Added Function Export Statment

* Updated Documentation in README.md

* Resolved Code Style --Prettier

* Rename "backtrack" to "recurse"

* Fix test case: The difference needs to be exactly 1.

* Code Modification: subsets should have sizes as close to n/2 as possible

* Updated test-case of TugOfWar

* Changed TugOfWar problem to Partition

* Modified partition problem

* Updated Documentation in README.md

* fixed code style

---------

Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>
---
 DIRECTORY.md                     |  2 ++
 Recursive/Partition.js           | 39 ++++++++++++++++++++++++++++++++
 Recursive/test/Partition.test.js | 24 ++++++++++++++++++++
 3 files changed, 65 insertions(+)
 create mode 100644 Recursive/Partition.js
 create mode 100644 Recursive/test/Partition.test.js

diff --git a/DIRECTORY.md b/DIRECTORY.md
index 1b2c40b3c8..2ede552665 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -160,6 +160,7 @@
   * [NumberOfIslands](Graphs/NumberOfIslands.js)
   * [PrimMST](Graphs/PrimMST.js)
 * **Hashes**
+  * [MD5](Hashes/MD5.js)
   * [SHA1](Hashes/SHA1.js)
   * [SHA256](Hashes/SHA256.js)
 * **Maths**
@@ -300,6 +301,7 @@
   * [KochSnowflake](Recursive/KochSnowflake.js)
   * [LetterCombination](Recursive/LetterCombination.js)
   * [Palindrome](Recursive/Palindrome.js)
+  * [Partition](Recursive/Partition.js)
   * [SubsequenceRecursive](Recursive/SubsequenceRecursive.js)
   * [TowerOfHanoi](Recursive/TowerOfHanoi.js)
 * **Search**
diff --git a/Recursive/Partition.js b/Recursive/Partition.js
new file mode 100644
index 0000000000..51465f8e93
--- /dev/null
+++ b/Recursive/Partition.js
@@ -0,0 +1,39 @@
+/**
+ * @function canPartition
+ * @description Check whether it is possible to partition the given array into two equal sum subsets using recursion.
+ * @param {number[]} nums - The input array of numbers.
+ * @param {number} index - The current index in the array being considered.
+ * @param {number} target - The target sum for each subset.
+ * @return {boolean}.
+ * @see [Partition Problem](https://en.wikipedia.org/wiki/Partition_problem)
+ */
+
+const canPartition = (nums, index = 0, target = 0) => {
+  if (!Array.isArray(nums)) {
+    throw new TypeError('Invalid Input')
+  }
+
+  const sum = nums.reduce((acc, num) => acc + num, 0)
+
+  if (sum % 2 !== 0) {
+    return false
+  }
+
+  if (target === sum / 2) {
+    return true
+  }
+
+  if (index >= nums.length || target > sum / 2) {
+    return false
+  }
+
+  // Include the current number in the first subset and check if a solution is possible.
+  const withCurrent = canPartition(nums, index + 1, target + nums[index])
+
+  // Exclude the current number from the first subset and check if a solution is possible.
+  const withoutCurrent = canPartition(nums, index + 1, target)
+
+  return withCurrent || withoutCurrent
+}
+
+export { canPartition }
diff --git a/Recursive/test/Partition.test.js b/Recursive/test/Partition.test.js
new file mode 100644
index 0000000000..929519999a
--- /dev/null
+++ b/Recursive/test/Partition.test.js
@@ -0,0 +1,24 @@
+import { canPartition } from '../Partition'
+
+describe('Partition (Recursive)', () => {
+  it('expects to return true for an array that can be partitioned', () => {
+    const result = canPartition([1, 5, 11, 5])
+    expect(result).toBe(true)
+  })
+
+  it('expects to return false for an array that cannot be partitioned', () => {
+    const result = canPartition([1, 2, 3, 5])
+    expect(result).toBe(false)
+  })
+
+  it('expects to return true for an empty array (0 elements)', () => {
+    const result = canPartition([])
+    expect(result).toBe(true)
+  })
+
+  it('Throw Error for Invalid Input', () => {
+    expect(() => canPartition(123)).toThrow('Invalid Input')
+    expect(() => canPartition(null)).toThrow('Invalid Input')
+    expect(() => canPartition(undefined)).toThrow('Invalid Input')
+  })
+})

From 39d01138ecf6077cc1ecde0a06b22cfe3cda595b Mon Sep 17 00:00:00 2001
From: Rob Simpson <rsimpson2@me.com>
Date: Wed, 15 Nov 2023 08:55:30 -0500
Subject: [PATCH 20/73] Abbreviation (#1547)

* Abbreviation

* Updates from code review
---
 Dynamic-Programming/Abbreviation.js           | 47 +++++++++++++++++++
 .../tests/Abbreviation.test.js                | 30 ++++++++++++
 2 files changed, 77 insertions(+)
 create mode 100644 Dynamic-Programming/Abbreviation.js
 create mode 100644 Dynamic-Programming/tests/Abbreviation.test.js

diff --git a/Dynamic-Programming/Abbreviation.js b/Dynamic-Programming/Abbreviation.js
new file mode 100644
index 0000000000..06092216b8
--- /dev/null
+++ b/Dynamic-Programming/Abbreviation.js
@@ -0,0 +1,47 @@
+/**
+ * @description
+ * Given two strings, `source` and `target`, determine if it's possible to make `source` equal
+ * to `target` You can perform the following operations on the string `source`:
+ * 1. Capitalize zero or more of `source`'s lowercase letters.
+ * 2. Delete all the remaining lowercase letters in `source`.
+ *
+ * Time Complexity: (O(|source|*|target|)) where `|source|` => length of string `source`
+ *
+ * @param {String} source - The string to be transformed.
+ * @param {String} target - The string we want to transform `source` into.
+ * @returns {Boolean} - Whether the transformation is possible.
+ * @see https://www.hackerrank.com/challenges/abbr/problem - Related problem on HackerRank.
+ */
+export const isAbbreviation = (source, target) => {
+  const sourceLength = source.length
+  const targetLength = target.length
+
+  // Initialize a table to keep track of possible abbreviations
+  let canAbbreviate = Array.from({ length: sourceLength + 1 }, () =>
+    Array(targetLength + 1).fill(false)
+  )
+  // Empty strings are trivially abbreviatable
+  canAbbreviate[0][0] = true
+
+  for (let sourceIndex = 0; sourceIndex < sourceLength; sourceIndex++) {
+    for (let targetIndex = 0; targetIndex <= targetLength; targetIndex++) {
+      if (canAbbreviate[sourceIndex][targetIndex]) {
+        // If characters at the current position are equal, move to the next position in both strings.
+        if (
+          targetIndex < targetLength &&
+          source[sourceIndex].toUpperCase() === target[targetIndex]
+        ) {
+          canAbbreviate[sourceIndex + 1][targetIndex + 1] = true
+        }
+        // If the current character in `source` is lowercase, explore two possibilities:
+        // a) Capitalize it (which is akin to "using" it in `source` to match `target`), or
+        // b) Skip it (effectively deleting it from `source`).
+        if (source[sourceIndex] === source[sourceIndex].toLowerCase()) {
+          canAbbreviate[sourceIndex + 1][targetIndex] = true
+        }
+      }
+    }
+  }
+
+  return canAbbreviate[sourceLength][targetLength]
+}
diff --git a/Dynamic-Programming/tests/Abbreviation.test.js b/Dynamic-Programming/tests/Abbreviation.test.js
new file mode 100644
index 0000000000..86e0f97336
--- /dev/null
+++ b/Dynamic-Programming/tests/Abbreviation.test.js
@@ -0,0 +1,30 @@
+import { isAbbreviation } from '../Abbreviation.js'
+
+const expectPositive = (word, abbr) =>
+  expect(isAbbreviation(word, abbr)).toBe(true)
+const expectNegative = (word, abbr) =>
+  expect(isAbbreviation(word, abbr)).toBe(false)
+
+describe('Abbreviation - Positive Tests', () => {
+  test('it should correctly abbreviate or transform the source string to match the target string', () => {
+    expectPositive('', '')
+    expectPositive('a', '')
+    expectPositive('a', 'A')
+    expectPositive('abcDE', 'ABCDE')
+    expectPositive('ABcDE', 'ABCDE')
+    expectPositive('abcde', 'ABCDE')
+    expectPositive('abcde', 'ABC')
+    expectPositive('abcXYdefghijKLmnopqrs', 'XYKL')
+    expectPositive('abc123', 'ABC')
+    expectPositive('abc123', 'ABC123')
+    expectPositive('abc!@#def', 'ABC')
+  })
+})
+
+describe('Abbreviation - Negative Tests', () => {
+  test('it should fail to abbreviate or transform the source string when it is not possible to match the target string', () => {
+    expectNegative('', 'A')
+    expectNegative('a', 'ABC')
+    expectNegative('aBcXYdefghijKLmnOpqrs', 'XYKLOP')
+  })
+})

From 1b66d86bd743c48100a42cf0927d78d15ccca239 Mon Sep 17 00:00:00 2001
From: Nobert Patrick Ayesiga <ayesiganobert@gmail.com>
Date: Tue, 28 Nov 2023 07:28:32 +0300
Subject: [PATCH 21/73] Implemented Palindrome Partitioning using Backtracking
 algorithm (#1591)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Implemented Palindrome Partitioning using Backtracking algorithm

* fix:Updated palindromePartition algorithm

* code clean up

* Rephrase doc comment & move to appropriate function

---------

Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>
---
 Recursive/PalindromePartitioning.js           | 30 +++++++++++++++++++
 Recursive/test/PalindromePartitioning.test.js | 12 ++++++++
 2 files changed, 42 insertions(+)
 create mode 100644 Recursive/PalindromePartitioning.js
 create mode 100644 Recursive/test/PalindromePartitioning.test.js

diff --git a/Recursive/PalindromePartitioning.js b/Recursive/PalindromePartitioning.js
new file mode 100644
index 0000000000..9a5150f65d
--- /dev/null
+++ b/Recursive/PalindromePartitioning.js
@@ -0,0 +1,30 @@
+import { palindrome } from './Palindrome'
+
+/*
+ * Given a string s, return all possible palindrome partitionings of s.
+ * A palindrome partitioning partitions a string into palindromic substrings.
+ * @see https://www.cs.columbia.edu/~sedwards/classes/2021/4995-fall/proposals/Palindrome.pdf
+ */
+const partitionPalindrome = (s) => {
+  const result = []
+  backtrack(s, [], result)
+  return result
+}
+
+const backtrack = (s, path, result) => {
+  if (s.length === 0) {
+    result.push([...path])
+    return
+  }
+
+  for (let i = 0; i < s.length; i++) {
+    const prefix = s.substring(0, i + 1)
+    if (palindrome(prefix)) {
+      path.push(prefix)
+      backtrack(s.substring(i + 1), path, result)
+      path.pop()
+    }
+  }
+}
+
+export default partitionPalindrome
diff --git a/Recursive/test/PalindromePartitioning.test.js b/Recursive/test/PalindromePartitioning.test.js
new file mode 100644
index 0000000000..1bb218cdd4
--- /dev/null
+++ b/Recursive/test/PalindromePartitioning.test.js
@@ -0,0 +1,12 @@
+import partitionPalindrome from '../PalindromePartitioning'
+
+describe('Palindrome Partitioning', () => {
+  it('should return all possible palindrome partitioning of s', () => {
+    expect(partitionPalindrome('aab')).toEqual([
+      ['a', 'a', 'b'],
+      ['aa', 'b']
+    ])
+    expect(partitionPalindrome('a')).toEqual([['a']])
+    expect(partitionPalindrome('ab')).toEqual([['a', 'b']])
+  })
+})

From 5a7e8d1325dc441180c5e05685a1f5590683ff2c Mon Sep 17 00:00:00 2001
From: Akshay Chavan <118964099+Akshay73c@users.noreply.github.com>
Date: Thu, 4 Jan 2024 18:19:13 +0530
Subject: [PATCH 22/73] implemented CycleDetectionII code in LinkedList (#1482)

* implemented CycleTectionII code

* changes made per review by appgurueu

* made the changes per review by appgurueu

* changes made per review by appgurueu

* did some changes

* fixed the test file with prettier

* Simplify code, renames for clarity

---------

Co-authored-by: Lars Mueller <appgurulars@gmx.de>
---
 DIRECTORY.md                                  |  1 +
 .../Linked-List/CycleDetectionII.js           | 57 +++++++++++++++++++
 .../Linked-List/test/CycleDetectionII.test.js | 39 +++++++++++++
 3 files changed, 97 insertions(+)
 create mode 100644 Data-Structures/Linked-List/CycleDetectionII.js
 create mode 100644 Data-Structures/Linked-List/test/CycleDetectionII.test.js

diff --git a/DIRECTORY.md b/DIRECTORY.md
index 2ede552665..457b166a22 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -82,6 +82,7 @@
   * **Linked-List**
     * [AddTwoNumbers](Data-Structures/Linked-List/AddTwoNumbers.js)
     * [CycleDetection](Data-Structures/Linked-List/CycleDetection.js)
+    * [CycleDetectionII](Data-Structures/Linked-List/CycleDetectionII.js)
     * [DoublyLinkedList](Data-Structures/Linked-List/DoublyLinkedList.js)
     * [MergeTwoSortedLinkedLists](Data-Structures/Linked-List/MergeTwoSortedLinkedLists.js)
     * [ReverseSinglyLinkedList](Data-Structures/Linked-List/ReverseSinglyLinkedList.js)
diff --git a/Data-Structures/Linked-List/CycleDetectionII.js b/Data-Structures/Linked-List/CycleDetectionII.js
new file mode 100644
index 0000000000..478586e6eb
--- /dev/null
+++ b/Data-Structures/Linked-List/CycleDetectionII.js
@@ -0,0 +1,57 @@
+/**
+ * A LinkedList based solution for finding the starting node of the cycle in a list.
+ * @returns the node where cycle begins in the linked list. If there is no cycle present, returns null.
+ * @see https://en.wikipedia.org/wiki/Cycle_detection
+ * @see https://leetcode.com/problems/linked-list-cycle-ii/
+ */
+
+function findCycleStart(head) {
+  let length = 0
+  let fast = head
+  let slow = head
+
+  while (fast !== null && fast.next !== null) {
+    fast = fast.next.next
+    slow = slow.next
+    if (fast === slow) {
+      length = cycleLength(slow)
+      break
+    }
+  }
+
+  if (length === 0) {
+    // If there is no cycle, return null.
+    return null
+  }
+
+  let ahead = head
+  let behind = head
+  // Move slow pointer ahead 'length' of cycle times
+  while (length > 0) {
+    ahead = ahead.next
+    length--
+  }
+
+  // Now move both pointers until they meet - this will be the start of cycle
+  while (ahead !== behind) {
+    ahead = ahead.next
+    behind = behind.next
+  }
+
+  // return the meeting node
+  return ahead
+}
+
+// head is a node on a cycle
+function cycleLength(head) {
+  // How long until we visit head again?
+  let cur = head
+  let len = 0
+  do {
+    cur = cur.next
+    len++
+  } while (cur != head)
+  return len
+}
+
+export { findCycleStart }
diff --git a/Data-Structures/Linked-List/test/CycleDetectionII.test.js b/Data-Structures/Linked-List/test/CycleDetectionII.test.js
new file mode 100644
index 0000000000..f741c53622
--- /dev/null
+++ b/Data-Structures/Linked-List/test/CycleDetectionII.test.js
@@ -0,0 +1,39 @@
+import { findCycleStart } from '../CycleDetectionII'
+import { Node } from '../SinglyLinkedList'
+
+describe('Detect Cycle', () => {
+  it('no cycle', () => {
+    const head = new Node(1)
+    head.next = new Node(2)
+
+    expect(findCycleStart(head)).toBeNull()
+  })
+
+  it('simple cycle', () => {
+    const head = new Node(1)
+    head.next = new Node(2)
+    head.next.next = new Node(3)
+    head.next.next.next = head.next // Creates a cycle
+
+    expect(findCycleStart(head)).toBe(head.next)
+  })
+
+  it('long list with cycle', () => {
+    const head = new Node(1)
+    head.next = new Node(2)
+    head.next.next = new Node(3)
+    head.next.next.next = new Node(4)
+    head.next.next.next.next = new Node(5)
+    head.next.next.next.next.next = head.next.next // Cycle
+
+    expect(findCycleStart(head)).toBe(head.next.next)
+  })
+
+  it('cycle on last node', () => {
+    const head = new Node(1)
+    head.next = new Node(2)
+    head.next.next = head
+
+    expect(findCycleStart(head)).toBe(head)
+  })
+})

From 203b7a0aa88d1b2c0f3459432d9ac1aa839c7756 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sat, 13 Jan 2024 16:25:28 +0100
Subject: [PATCH 23/73] Properly evaluate `GITHUB_ACTOR` (#1594)

* fix: use `GITHUB_ACTOR` in `git config`

* Updated Documentation in README.md

---------

Co-authored-by: vil02 <vil02@users.noreply.github.com>
---
 .github/workflows/UpdateDirectory.yml | 4 ++--
 DIRECTORY.md                          | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/UpdateDirectory.yml b/.github/workflows/UpdateDirectory.yml
index 624047758a..17ba375fb7 100644
--- a/.github/workflows/UpdateDirectory.yml
+++ b/.github/workflows/UpdateDirectory.yml
@@ -25,8 +25,8 @@ jobs:
 
       - name: Configure Github Action
         run: |
-          git config --global user.name github-actions
-          git config --global user.email '${GITHUB_ACTOR}@users.noreply.github.com'
+          git config --global user.name "$GITHUB_ACTOR"
+          git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com"
 
       - name: 🤓 Commit & push new Directory (if needed)
         run: |
diff --git a/DIRECTORY.md b/DIRECTORY.md
index 457b166a22..8b51ce3bf7 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -104,6 +104,7 @@
   * **Vectors**
     * [Vector2](Data-Structures/Vectors/Vector2.js)
 * **Dynamic-Programming**
+  * [Abbreviation](Dynamic-Programming/Abbreviation.js)
   * [CatalanNumbers](Dynamic-Programming/CatalanNumbers.js)
   * [ClimbingStairs](Dynamic-Programming/ClimbingStairs.js)
   * [CoinChange](Dynamic-Programming/CoinChange.js)
@@ -302,6 +303,7 @@
   * [KochSnowflake](Recursive/KochSnowflake.js)
   * [LetterCombination](Recursive/LetterCombination.js)
   * [Palindrome](Recursive/Palindrome.js)
+  * [PalindromePartitioning](Recursive/PalindromePartitioning.js)
   * [Partition](Recursive/Partition.js)
   * [SubsequenceRecursive](Recursive/SubsequenceRecursive.js)
   * [TowerOfHanoi](Recursive/TowerOfHanoi.js)

From f0cfa8557f473a672d29ed4b5cfa1d6e095e72c8 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Mon, 15 Jan 2024 19:59:36 +0100
Subject: [PATCH 24/73] chore: update `actions/setup-node` to `v4` (#1596)

---
 .github/workflows/Ci.yml              | 2 +-
 .github/workflows/UpdateDirectory.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/Ci.yml b/.github/workflows/Ci.yml
index 12093c2738..9ea6fc558a 100644
--- a/.github/workflows/Ci.yml
+++ b/.github/workflows/Ci.yml
@@ -13,7 +13,7 @@ jobs:
     steps:
       - uses: actions/checkout@v3
 
-      - uses: actions/setup-node@v3
+      - uses: actions/setup-node@v4
         with:
           node-version: 20
           cache: npm
diff --git a/.github/workflows/UpdateDirectory.yml b/.github/workflows/UpdateDirectory.yml
index 17ba375fb7..d6d6c11973 100644
--- a/.github/workflows/UpdateDirectory.yml
+++ b/.github/workflows/UpdateDirectory.yml
@@ -12,7 +12,7 @@ jobs:
     steps:
       - uses: actions/checkout@v3
 
-      - uses: actions/setup-node@v3
+      - uses: actions/setup-node@v4
         with:
           node-version: 20
           cache: npm

From 83eb73b26f4d6eab860e2cd14cb32adcace35a21 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Mon, 15 Jan 2024 19:59:53 +0100
Subject: [PATCH 25/73] chore: update `actions/checkout` to `v4` (#1595)

---
 .github/workflows/Ci.yml              | 4 ++--
 .github/workflows/UpdateDirectory.yml | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/Ci.yml b/.github/workflows/Ci.yml
index 9ea6fc558a..571b8a0fa8 100644
--- a/.github/workflows/Ci.yml
+++ b/.github/workflows/Ci.yml
@@ -11,7 +11,7 @@ jobs:
     name: Code style and tests
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - uses: actions/setup-node@v4
         with:
@@ -31,7 +31,7 @@ jobs:
     name: Check for spelling errors
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: codespell-project/actions-codespell@master
         with:
           # file types to ignore
diff --git a/.github/workflows/UpdateDirectory.yml b/.github/workflows/UpdateDirectory.yml
index d6d6c11973..cb649e1c8b 100644
--- a/.github/workflows/UpdateDirectory.yml
+++ b/.github/workflows/UpdateDirectory.yml
@@ -10,7 +10,7 @@ jobs:
   updateDirectory:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - uses: actions/setup-node@v4
         with:

From 069803f2718b379b8c1b67c5da6e74820bd57cce Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Tue, 16 Jan 2024 08:00:39 +0100
Subject: [PATCH 26/73] style: remove trailing spaces (#1597)

---
 .github/ISSUE_TEMPLATE/bug_report.yml | 6 +++---
 .github/stale.yml                     | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index a6b7e0da16..6a4de4e591 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -33,9 +33,9 @@ body:
       label: Steps to reproduce (if applicable)
       description: List steps to reproduce the behavior.
       placeholder: |
-        1. 
-        2. 
-        3. 
+        1.
+        2.
+        3.
         4.
     validations:
       required: false
diff --git a/.github/stale.yml b/.github/stale.yml
index 1f3872c524..9692a0a677 100644
--- a/.github/stale.yml
+++ b/.github/stale.yml
@@ -16,5 +16,5 @@ markComment: >
   for your contributions.
 # Comment to post when closing a stale issue. Set to `false` to disable
 closeComment: >
-  Please reopen this issue once you commit the changes requested or 
+  Please reopen this issue once you commit the changes requested or
   make improvements on the code. Thank you for your contributions.

From 0e5cf5e843fd3509553f1f53e296bd21881f950d Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sat, 27 Jan 2024 17:57:40 +0100
Subject: [PATCH 27/73] tests: add missing test for `KnightTour` (#1598)

---
 Backtracking/tests/KnightTour.test.js | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/Backtracking/tests/KnightTour.test.js b/Backtracking/tests/KnightTour.test.js
index a3af01a095..f7dc511df9 100644
--- a/Backtracking/tests/KnightTour.test.js
+++ b/Backtracking/tests/KnightTour.test.js
@@ -11,7 +11,7 @@ describe('OpenKnightTour', () => {
       [0, 0, 0, 0, 0]
     ])
 
-    KT.solve()
+    expect(KT.solve()).toBe(true)
     expect(KT.board).toEqual([
       [19, 4, 15, 10, 25],
       [14, 9, 18, 5, 16],
@@ -20,4 +20,18 @@ describe('OpenKnightTour', () => {
       [21, 2, 7, 12, 23]
     ])
   })
+
+  it('OpenKnightTour(2)', () => {
+    const KT = new OpenKnightTour(2)
+    expect(KT.board).toEqual([
+      [0, 0],
+      [0, 0]
+    ])
+
+    expect(KT.solve()).toBe(false)
+    expect(KT.board).toEqual([
+      [0, 0],
+      [0, 0]
+    ])
+  })
 })

From 1d6340086728355189c194ff8ddb22b337f18535 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sat, 27 Jan 2024 17:58:12 +0100
Subject: [PATCH 28/73] chore: add `UploadCoverageReport.yml` (#1599)

---
 .github/workflows/UploadCoverageReport.yml |   33 +
 .gitignore                                 |    2 +
 package-lock.json                          | 2325 ++++++++------------
 package.json                               |    3 +-
 vitest.config.ts                           |    5 +-
 5 files changed, 901 insertions(+), 1467 deletions(-)
 create mode 100644 .github/workflows/UploadCoverageReport.yml

diff --git a/.github/workflows/UploadCoverageReport.yml b/.github/workflows/UploadCoverageReport.yml
new file mode 100644
index 0000000000..4dcad584bf
--- /dev/null
+++ b/.github/workflows/UploadCoverageReport.yml
@@ -0,0 +1,33 @@
+---
+name: UploadCoverageReport
+
+'on':
+  workflow_dispatch:
+  push:
+    branches:
+      - master
+  pull_request:
+
+jobs:
+  UploadCoverageReport:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - uses: actions/setup-node@v4
+        with:
+          node-version: 20
+          cache: npm
+
+      - name: Install dependencies
+        run: npm ci
+
+      - name: Generate coverage report
+        run: npm test -- --coverage
+
+      - name: Upload coverage to codecov
+        uses: codecov/codecov-action@v3
+        with:
+          files: "coverage/coverage-final.json"
+          fail_ci_if_error: true
+...
diff --git a/.gitignore b/.gitignore
index 1714facbfa..1cc076e7bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,5 @@ yarn-error.log*
 
 # intelliJ workspace folder
 .idea
+
+/coverage
diff --git a/package-lock.json b/package-lock.json
index 7a282547ae..a4efa09c1b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,7 +1,7 @@
 {
   "name": "javascript",
   "version": "1.0.0",
-  "lockfileVersion": 2,
+  "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
@@ -9,135 +9,80 @@
       "version": "1.0.0",
       "license": "GPL-3.0",
       "devDependencies": {
+        "@vitest/coverage-v8": "^1.2.1",
         "globby": "^13.2.2",
         "husky": "^8.0.3",
         "prettier": "^3.0.3",
-        "vitest": "^0.34.6"
+        "vitest": "^1.2.1"
       },
       "engines": {
         "node": ">=20.6.0"
       }
     },
-    "node_modules/@esbuild/android-arm": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
-      "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
-      "cpu": [
-        "arm"
-      ],
+    "node_modules/@ampproject/remapping": {
+      "version": "2.2.1",
       "dev": true,
-      "optional": true,
-      "os": [
-        "android"
-      ],
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.0",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
       "engines": {
-        "node": ">=12"
+        "node": ">=6.0.0"
       }
     },
-    "node_modules/@esbuild/android-arm64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
-      "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
-      "cpu": [
-        "arm64"
-      ],
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.23.4",
       "dev": true,
-      "optional": true,
-      "os": [
-        "android"
-      ],
+      "license": "MIT",
       "engines": {
-        "node": ">=12"
+        "node": ">=6.9.0"
       }
     },
-    "node_modules/@esbuild/android-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
-      "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
-      "cpu": [
-        "x64"
-      ],
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.22.20",
       "dev": true,
-      "optional": true,
-      "os": [
-        "android"
-      ],
+      "license": "MIT",
       "engines": {
-        "node": ">=12"
+        "node": ">=6.9.0"
       }
     },
-    "node_modules/@esbuild/darwin-arm64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
-      "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
-      "cpu": [
-        "arm64"
-      ],
+    "node_modules/@babel/parser": {
+      "version": "7.23.6",
       "dev": true,
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
+      "license": "MIT",
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
       "engines": {
-        "node": ">=12"
+        "node": ">=6.0.0"
       }
     },
-    "node_modules/@esbuild/darwin-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
-      "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
-      "cpu": [
-        "x64"
-      ],
+    "node_modules/@babel/types": {
+      "version": "7.23.6",
       "dev": true,
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.23.4",
+        "@babel/helper-validator-identifier": "^7.22.20",
+        "to-fast-properties": "^2.0.0"
+      },
       "engines": {
-        "node": ">=12"
+        "node": ">=6.9.0"
       }
     },
-    "node_modules/@esbuild/freebsd-arm64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
-      "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
-      "cpu": [
-        "arm64"
-      ],
+    "node_modules/@bcoe/v8-coverage": {
+      "version": "0.2.3",
       "dev": true,
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
+      "license": "MIT"
     },
-    "node_modules/@esbuild/freebsd-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
-      "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.19.12",
       "cpu": [
         "x64"
       ],
       "dev": true,
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/linux-arm": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
-      "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
-      "cpu": [
-        "arm"
-      ],
-      "dev": true,
+      "license": "MIT",
       "optional": true,
       "os": [
         "linux"
@@ -146,318 +91,166 @@
         "node": ">=12"
       }
     },
-    "node_modules/@esbuild/linux-arm64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
-      "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
-      "cpu": [
-        "arm64"
-      ],
+    "node_modules/@istanbuljs/schema": {
+      "version": "0.1.3",
       "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+      "license": "MIT",
       "engines": {
-        "node": ">=12"
+        "node": ">=8"
       }
     },
-    "node_modules/@esbuild/linux-ia32": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
-      "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
-      "cpu": [
-        "ia32"
-      ],
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.3",
       "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/set-array": "^1.0.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
       "engines": {
-        "node": ">=12"
+        "node": ">=6.0.0"
       }
     },
-    "node_modules/@esbuild/linux-loong64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
-      "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
-      "cpu": [
-        "loong64"
-      ],
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.1",
       "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+      "license": "MIT",
       "engines": {
-        "node": ">=12"
+        "node": ">=6.0.0"
       }
     },
-    "node_modules/@esbuild/linux-mips64el": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
-      "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
-      "cpu": [
-        "mips64el"
-      ],
+    "node_modules/@jridgewell/set-array": {
+      "version": "1.1.2",
       "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+      "license": "MIT",
       "engines": {
-        "node": ">=12"
+        "node": ">=6.0.0"
       }
     },
-    "node_modules/@esbuild/linux-ppc64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
-      "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
-      "cpu": [
-        "ppc64"
-      ],
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.4.15",
       "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
+      "license": "MIT"
     },
-    "node_modules/@esbuild/linux-riscv64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
-      "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
-      "cpu": [
-        "riscv64"
-      ],
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.22",
       "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
       }
     },
-    "node_modules/@esbuild/linux-s390x": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
-      "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
-      "cpu": [
-        "s390x"
-      ],
+    "node_modules/@nodelib/fs.scandir": {
+      "version": "2.1.5",
       "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+      "license": "MIT",
+      "dependencies": {
+        "@nodelib/fs.stat": "2.0.5",
+        "run-parallel": "^1.1.9"
+      },
       "engines": {
-        "node": ">=12"
+        "node": ">= 8"
       }
     },
-    "node_modules/@esbuild/linux-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
-      "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
-      "cpu": [
-        "x64"
-      ],
+    "node_modules/@nodelib/fs.stat": {
+      "version": "2.0.5",
       "dev": true,
-      "optional": true,
-      "os": [
-        "linux"
-      ],
+      "license": "MIT",
       "engines": {
-        "node": ">=12"
+        "node": ">= 8"
       }
     },
-    "node_modules/@esbuild/netbsd-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
-      "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
-      "cpu": [
-        "x64"
-      ],
+    "node_modules/@nodelib/fs.walk": {
+      "version": "1.2.8",
       "dev": true,
-      "optional": true,
-      "os": [
-        "netbsd"
-      ],
+      "license": "MIT",
+      "dependencies": {
+        "@nodelib/fs.scandir": "2.1.5",
+        "fastq": "^1.6.0"
+      },
       "engines": {
-        "node": ">=12"
+        "node": ">= 8"
       }
     },
-    "node_modules/@esbuild/openbsd-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
-      "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
+    "node_modules/@rollup/rollup-linux-x64-gnu": {
+      "version": "4.9.6",
       "cpu": [
         "x64"
       ],
       "dev": true,
+      "license": "MIT",
       "optional": true,
       "os": [
-        "openbsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
+        "linux"
+      ]
     },
-    "node_modules/@esbuild/sunos-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
-      "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
+    "node_modules/@rollup/rollup-linux-x64-musl": {
+      "version": "4.9.6",
       "cpu": [
         "x64"
       ],
       "dev": true,
+      "license": "MIT",
       "optional": true,
       "os": [
-        "sunos"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
+        "linux"
+      ]
     },
-    "node_modules/@esbuild/win32-arm64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
-      "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
-      "cpu": [
-        "arm64"
-      ],
+    "node_modules/@types/estree": {
+      "version": "1.0.5",
       "dev": true,
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
+      "license": "MIT"
     },
-    "node_modules/@esbuild/win32-ia32": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
-      "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
-      "cpu": [
-        "ia32"
-      ],
+    "node_modules/@types/istanbul-lib-coverage": {
+      "version": "2.0.6",
       "dev": true,
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
+      "license": "MIT"
     },
-    "node_modules/@esbuild/win32-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
-      "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
-      "cpu": [
-        "x64"
-      ],
+    "node_modules/@types/node": {
+      "version": "20.11.6",
       "dev": true,
+      "license": "MIT",
       "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@jest/schemas": {
-      "version": "29.6.3",
-      "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
-      "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
-      "dev": true,
+      "peer": true,
       "dependencies": {
-        "@sinclair/typebox": "^0.27.8"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+        "undici-types": "~5.26.4"
       }
     },
-    "node_modules/@jridgewell/sourcemap-codec": {
-      "version": "1.4.15",
-      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
-      "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
-      "dev": true
-    },
-    "node_modules/@nodelib/fs.scandir": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
-      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+    "node_modules/@vitest/coverage-v8": {
+      "version": "1.2.1",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@nodelib/fs.stat": "2.0.5",
-        "run-parallel": "^1.1.9"
+        "@ampproject/remapping": "^2.2.1",
+        "@bcoe/v8-coverage": "^0.2.3",
+        "debug": "^4.3.4",
+        "istanbul-lib-coverage": "^3.2.2",
+        "istanbul-lib-report": "^3.0.1",
+        "istanbul-lib-source-maps": "^4.0.1",
+        "istanbul-reports": "^3.1.6",
+        "magic-string": "^0.30.5",
+        "magicast": "^0.3.3",
+        "picocolors": "^1.0.0",
+        "std-env": "^3.5.0",
+        "test-exclude": "^6.0.0",
+        "v8-to-istanbul": "^9.2.0"
       },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@nodelib/fs.stat": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
-      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
-      "dev": true,
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@nodelib/fs.walk": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
-      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
-      "dev": true,
-      "dependencies": {
-        "@nodelib/fs.scandir": "2.1.5",
-        "fastq": "^1.6.0"
+      "funding": {
+        "url": "https://opencollective.com/vitest"
       },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@sinclair/typebox": {
-      "version": "0.27.8",
-      "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
-      "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
-      "dev": true
-    },
-    "node_modules/@types/chai": {
-      "version": "4.3.6",
-      "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.6.tgz",
-      "integrity": "sha512-VOVRLM1mBxIRxydiViqPcKn6MIxZytrbMpd6RJLIWKxUNr3zux8no0Oc7kJx0WAPIitgZ0gkrDS+btlqQpubpw==",
-      "dev": true
-    },
-    "node_modules/@types/chai-subset": {
-      "version": "1.3.3",
-      "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz",
-      "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==",
-      "dev": true,
-      "dependencies": {
-        "@types/chai": "*"
+      "peerDependencies": {
+        "vitest": "^1.0.0"
       }
     },
-    "node_modules/@types/node": {
-      "version": "18.11.0",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.0.tgz",
-      "integrity": "sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w==",
-      "dev": true
-    },
     "node_modules/@vitest/expect": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz",
-      "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==",
+      "version": "1.2.1",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@vitest/spy": "0.34.6",
-        "@vitest/utils": "0.34.6",
+        "@vitest/spy": "1.2.1",
+        "@vitest/utils": "1.2.1",
         "chai": "^4.3.10"
       },
       "funding": {
@@ -465,13 +258,12 @@
       }
     },
     "node_modules/@vitest/runner": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz",
-      "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==",
+      "version": "1.2.1",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "@vitest/utils": "0.34.6",
-        "p-limit": "^4.0.0",
+        "@vitest/utils": "1.2.1",
+        "p-limit": "^5.0.0",
         "pathe": "^1.1.1"
       },
       "funding": {
@@ -479,15 +271,14 @@
       }
     },
     "node_modules/@vitest/runner/node_modules/p-limit": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
-      "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
+      "version": "5.0.0",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "yocto-queue": "^1.0.0"
       },
       "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+        "node": ">=18"
       },
       "funding": {
         "url": "https://github.com/sponsors/sindresorhus"
@@ -495,9 +286,8 @@
     },
     "node_modules/@vitest/runner/node_modules/yocto-queue": {
       "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
-      "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=12.20"
       },
@@ -506,80 +296,176 @@
       }
     },
     "node_modules/@vitest/snapshot": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz",
-      "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==",
+      "version": "1.2.1",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "magic-string": "^0.30.1",
+        "magic-string": "^0.30.5",
         "pathe": "^1.1.1",
-        "pretty-format": "^29.5.0"
+        "pretty-format": "^29.7.0"
       },
       "funding": {
         "url": "https://opencollective.com/vitest"
       }
     },
-    "node_modules/@vitest/spy": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz",
-      "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==",
+    "node_modules/@vitest/snapshot/node_modules/@jest/schemas": {
+      "version": "29.6.3",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "tinyspy": "^2.1.1"
+        "@sinclair/typebox": "^0.27.8"
       },
-      "funding": {
-        "url": "https://opencollective.com/vitest"
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
       }
     },
-    "node_modules/@vitest/utils": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz",
-      "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==",
+    "node_modules/@vitest/snapshot/node_modules/@sinclair/typebox": {
+      "version": "0.27.8",
       "dev": true,
-      "dependencies": {
-        "diff-sequences": "^29.4.3",
-        "loupe": "^2.3.6",
-        "pretty-format": "^29.5.0"
+      "license": "MIT"
+    },
+    "node_modules/@vitest/snapshot/node_modules/ansi-styles": {
+      "version": "5.2.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
       },
       "funding": {
-        "url": "https://opencollective.com/vitest"
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
       }
     },
-    "node_modules/acorn": {
-      "version": "8.10.0",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
-      "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
+    "node_modules/@vitest/snapshot/node_modules/pretty-format": {
+      "version": "29.7.0",
       "dev": true,
-      "bin": {
-        "acorn": "bin/acorn"
+      "license": "MIT",
+      "dependencies": {
+        "@jest/schemas": "^29.6.3",
+        "ansi-styles": "^5.0.0",
+        "react-is": "^18.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@vitest/spy": {
+      "version": "1.2.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "tinyspy": "^2.2.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/vitest"
+      }
+    },
+    "node_modules/@vitest/utils": {
+      "version": "1.2.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "diff-sequences": "^29.6.3",
+        "estree-walker": "^3.0.3",
+        "loupe": "^2.3.7",
+        "pretty-format": "^29.7.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/vitest"
+      }
+    },
+    "node_modules/@vitest/utils/node_modules/@jest/schemas": {
+      "version": "29.6.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@sinclair/typebox": "^0.27.8"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@vitest/utils/node_modules/@sinclair/typebox": {
+      "version": "0.27.8",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@vitest/utils/node_modules/ansi-styles": {
+      "version": "5.2.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/@vitest/utils/node_modules/diff-sequences": {
+      "version": "29.6.3",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@vitest/utils/node_modules/pretty-format": {
+      "version": "29.7.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@jest/schemas": "^29.6.3",
+        "ansi-styles": "^5.0.0",
+        "react-is": "^18.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/acorn": {
+      "version": "8.11.3",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "acorn": "bin/acorn"
       },
       "engines": {
         "node": ">=0.4.0"
       }
     },
     "node_modules/acorn-walk": {
-      "version": "8.2.0",
-      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
-      "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
+      "version": "8.3.2",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=0.4.0"
       }
     },
     "node_modules/assertion-error": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
-      "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": "*"
       }
     },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
     "node_modules/braces": {
       "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "fill-range": "^7.0.1"
       },
@@ -589,18 +475,16 @@
     },
     "node_modules/cac": {
       "version": "6.7.14",
-      "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
-      "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=8"
       }
     },
     "node_modules/chai": {
-      "version": "4.3.10",
-      "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz",
-      "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==",
+      "version": "4.4.1",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "assertion-error": "^1.1.0",
         "check-error": "^1.0.3",
@@ -616,9 +500,8 @@
     },
     "node_modules/check-error": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
-      "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "get-func-name": "^2.0.2"
       },
@@ -626,11 +509,28 @@
         "node": "*"
       }
     },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
     "node_modules/debug": {
       "version": "4.3.4",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "ms": "2.1.2"
       },
@@ -645,9 +545,8 @@
     },
     "node_modules/deep-eql": {
       "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
-      "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "type-detect": "^4.0.0"
       },
@@ -655,20 +554,10 @@
         "node": ">=6"
       }
     },
-    "node_modules/diff-sequences": {
-      "version": "29.6.3",
-      "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
-      "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
-      "dev": true,
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
     "node_modules/dir-glob": {
       "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
-      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "path-type": "^4.0.0"
       },
@@ -677,11 +566,10 @@
       }
     },
     "node_modules/esbuild": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
-      "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
+      "version": "0.19.12",
       "dev": true,
       "hasInstallScript": true,
+      "license": "MIT",
       "bin": {
         "esbuild": "bin/esbuild"
       },
@@ -689,35 +577,43 @@
         "node": ">=12"
       },
       "optionalDependencies": {
-        "@esbuild/android-arm": "0.18.20",
-        "@esbuild/android-arm64": "0.18.20",
-        "@esbuild/android-x64": "0.18.20",
-        "@esbuild/darwin-arm64": "0.18.20",
-        "@esbuild/darwin-x64": "0.18.20",
-        "@esbuild/freebsd-arm64": "0.18.20",
-        "@esbuild/freebsd-x64": "0.18.20",
-        "@esbuild/linux-arm": "0.18.20",
-        "@esbuild/linux-arm64": "0.18.20",
-        "@esbuild/linux-ia32": "0.18.20",
-        "@esbuild/linux-loong64": "0.18.20",
-        "@esbuild/linux-mips64el": "0.18.20",
-        "@esbuild/linux-ppc64": "0.18.20",
-        "@esbuild/linux-riscv64": "0.18.20",
-        "@esbuild/linux-s390x": "0.18.20",
-        "@esbuild/linux-x64": "0.18.20",
-        "@esbuild/netbsd-x64": "0.18.20",
-        "@esbuild/openbsd-x64": "0.18.20",
-        "@esbuild/sunos-x64": "0.18.20",
-        "@esbuild/win32-arm64": "0.18.20",
-        "@esbuild/win32-ia32": "0.18.20",
-        "@esbuild/win32-x64": "0.18.20"
+        "@esbuild/aix-ppc64": "0.19.12",
+        "@esbuild/android-arm": "0.19.12",
+        "@esbuild/android-arm64": "0.19.12",
+        "@esbuild/android-x64": "0.19.12",
+        "@esbuild/darwin-arm64": "0.19.12",
+        "@esbuild/darwin-x64": "0.19.12",
+        "@esbuild/freebsd-arm64": "0.19.12",
+        "@esbuild/freebsd-x64": "0.19.12",
+        "@esbuild/linux-arm": "0.19.12",
+        "@esbuild/linux-arm64": "0.19.12",
+        "@esbuild/linux-ia32": "0.19.12",
+        "@esbuild/linux-loong64": "0.19.12",
+        "@esbuild/linux-mips64el": "0.19.12",
+        "@esbuild/linux-ppc64": "0.19.12",
+        "@esbuild/linux-riscv64": "0.19.12",
+        "@esbuild/linux-s390x": "0.19.12",
+        "@esbuild/linux-x64": "0.19.12",
+        "@esbuild/netbsd-x64": "0.19.12",
+        "@esbuild/openbsd-x64": "0.19.12",
+        "@esbuild/sunos-x64": "0.19.12",
+        "@esbuild/win32-arm64": "0.19.12",
+        "@esbuild/win32-ia32": "0.19.12",
+        "@esbuild/win32-x64": "0.19.12"
+      }
+    },
+    "node_modules/estree-walker": {
+      "version": "3.0.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/estree": "^1.0.0"
       }
     },
     "node_modules/fast-glob": {
       "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
-      "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "@nodelib/fs.stat": "^2.0.2",
         "@nodelib/fs.walk": "^1.2.3",
@@ -731,18 +627,16 @@
     },
     "node_modules/fastq": {
       "version": "1.13.0",
-      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
-      "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
       "dev": true,
+      "license": "ISC",
       "dependencies": {
         "reusify": "^1.0.4"
       }
     },
     "node_modules/fill-range": {
       "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "to-regex-range": "^5.0.1"
       },
@@ -750,34 +644,42 @@
         "node": ">=8"
       }
     },
-    "node_modules/fsevents": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
-      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
       "dev": true,
-      "hasInstallScript": true,
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
-      }
+      "license": "ISC"
     },
     "node_modules/get-func-name": {
       "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
-      "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
       "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/glob": {
+      "version": "7.2.3",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
       "engines": {
         "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
       }
     },
     "node_modules/glob-parent": {
       "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
       "dev": true,
+      "license": "ISC",
       "dependencies": {
         "is-glob": "^4.0.1"
       },
@@ -787,9 +689,8 @@
     },
     "node_modules/globby": {
       "version": "13.2.2",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz",
-      "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "dir-glob": "^3.0.1",
         "fast-glob": "^3.3.0",
@@ -806,9 +707,8 @@
     },
     "node_modules/globby/node_modules/slash": {
       "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
-      "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=12"
       },
@@ -816,11 +716,23 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/has-flag": {
+      "version": "4.0.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/html-escaper": {
+      "version": "2.0.2",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/husky": {
       "version": "8.0.3",
-      "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
-      "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==",
       "dev": true,
+      "license": "MIT",
       "bin": {
         "husky": "lib/bin.js"
       },
@@ -833,27 +745,38 @@
     },
     "node_modules/ignore": {
       "version": "5.2.4",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
-      "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">= 4"
       }
     },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "dev": true,
+      "license": "ISC"
+    },
     "node_modules/is-extglob": {
       "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=0.10.0"
       }
     },
     "node_modules/is-glob": {
       "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "is-extglob": "^2.1.1"
       },
@@ -863,24 +786,76 @@
     },
     "node_modules/is-number": {
       "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=0.12.0"
       }
     },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/istanbul-lib-coverage": {
+      "version": "3.2.2",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-report": {
+      "version": "3.0.1",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "istanbul-lib-coverage": "^3.0.0",
+        "make-dir": "^4.0.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/istanbul-lib-source-maps": {
+      "version": "4.0.1",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "debug": "^4.1.1",
+        "istanbul-lib-coverage": "^3.0.0",
+        "source-map": "^0.6.1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/istanbul-reports": {
+      "version": "3.1.6",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "html-escaper": "^2.0.0",
+        "istanbul-lib-report": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/jsonc-parser": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
-      "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
-      "dev": true
+      "version": "3.2.1",
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/local-pkg": {
-      "version": "0.4.3",
-      "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz",
-      "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==",
+      "version": "0.5.0",
       "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "mlly": "^1.4.2",
+        "pkg-types": "^1.0.3"
+      },
       "engines": {
         "node": ">=14"
       },
@@ -889,19 +864,17 @@
       }
     },
     "node_modules/loupe": {
-      "version": "2.3.6",
-      "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz",
-      "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==",
+      "version": "2.3.7",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "get-func-name": "^2.0.0"
+        "get-func-name": "^2.0.1"
       }
     },
     "node_modules/magic-string": {
-      "version": "0.30.4",
-      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.4.tgz",
-      "integrity": "sha512-Q/TKtsC5BPm0kGqgBIF9oXAs/xEf2vRKiIB4wCRQTJOQIByZ1d+NnUOotvJOvNpi5RNIgVOMC3pOuaP1ZTDlVg==",
+      "version": "0.30.5",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "@jridgewell/sourcemap-codec": "^1.4.15"
       },
@@ -909,20 +882,77 @@
         "node": ">=12"
       }
     },
+    "node_modules/magicast": {
+      "version": "0.3.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.23.6",
+        "@babel/types": "^7.23.6",
+        "source-map-js": "^1.0.2"
+      }
+    },
+    "node_modules/make-dir": {
+      "version": "4.0.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "semver": "^7.5.3"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/make-dir/node_modules/lru-cache": {
+      "version": "6.0.0",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/make-dir/node_modules/semver": {
+      "version": "7.5.4",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/make-dir/node_modules/yallist": {
+      "version": "4.0.0",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/merge-stream": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/merge2": {
       "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
-      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">= 8"
       }
     },
     "node_modules/micromatch": {
       "version": "4.0.5",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
-      "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "braces": "^3.0.2",
         "picomatch": "^2.3.1"
@@ -931,28 +961,35 @@
         "node": ">=8.6"
       }
     },
+    "node_modules/minimatch": {
+      "version": "3.1.2",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/mlly": {
-      "version": "1.4.2",
-      "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.2.tgz",
-      "integrity": "sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==",
+      "version": "1.5.0",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "acorn": "^8.10.0",
-        "pathe": "^1.1.1",
+        "acorn": "^8.11.3",
+        "pathe": "^1.1.2",
         "pkg-types": "^1.0.3",
-        "ufo": "^1.3.0"
+        "ufo": "^1.3.2"
       }
     },
     "node_modules/ms": {
       "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/nanoid": {
-      "version": "3.3.6",
-      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
-      "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
+      "version": "3.3.7",
       "dev": true,
       "funding": [
         {
@@ -960,6 +997,7 @@
           "url": "https://github.com/sponsors/ai"
         }
       ],
+      "license": "MIT",
       "bin": {
         "nanoid": "bin/nanoid.cjs"
       },
@@ -967,41 +1005,60 @@
         "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
       }
     },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/path-type": {
       "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
-      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=8"
       }
     },
     "node_modules/pathe": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz",
-      "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==",
-      "dev": true
+      "version": "1.1.2",
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/pathval": {
       "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
-      "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": "*"
       }
     },
     "node_modules/picocolors": {
       "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
-      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
-      "dev": true
+      "dev": true,
+      "license": "ISC"
     },
     "node_modules/picomatch": {
       "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=8.6"
       },
@@ -1011,9 +1068,8 @@
     },
     "node_modules/pkg-types": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz",
-      "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "jsonc-parser": "^3.2.0",
         "mlly": "^1.2.0",
@@ -1021,9 +1077,7 @@
       }
     },
     "node_modules/postcss": {
-      "version": "8.4.31",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
-      "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+      "version": "8.4.33",
       "dev": true,
       "funding": [
         {
@@ -1039,8 +1093,9 @@
           "url": "https://github.com/sponsors/ai"
         }
       ],
+      "license": "MIT",
       "dependencies": {
-        "nanoid": "^3.3.6",
+        "nanoid": "^3.3.7",
         "picocolors": "^1.0.0",
         "source-map-js": "^1.0.2"
       },
@@ -1050,9 +1105,8 @@
     },
     "node_modules/prettier": {
       "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
-      "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
       "dev": true,
+      "license": "MIT",
       "bin": {
         "prettier": "bin/prettier.cjs"
       },
@@ -1063,36 +1117,8 @@
         "url": "https://github.com/prettier/prettier?sponsor=1"
       }
     },
-    "node_modules/pretty-format": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
-      "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
-      "dev": true,
-      "dependencies": {
-        "@jest/schemas": "^29.6.3",
-        "ansi-styles": "^5.0.0",
-        "react-is": "^18.0.0"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/pretty-format/node_modules/ansi-styles": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
-      "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
     "node_modules/queue-microtask": {
       "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
-      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
       "dev": true,
       "funding": [
         {
@@ -1107,44 +1133,56 @@
           "type": "consulting",
           "url": "https://feross.org/support"
         }
-      ]
+      ],
+      "license": "MIT"
     },
     "node_modules/react-is": {
       "version": "18.2.0",
-      "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
-      "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/reusify": {
       "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
-      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "iojs": ">=1.0.0",
         "node": ">=0.10.0"
       }
     },
     "node_modules/rollup": {
-      "version": "3.29.4",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz",
-      "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==",
+      "version": "4.9.6",
       "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/estree": "1.0.5"
+      },
       "bin": {
         "rollup": "dist/bin/rollup"
       },
       "engines": {
-        "node": ">=14.18.0",
+        "node": ">=18.0.0",
         "npm": ">=8.0.0"
       },
       "optionalDependencies": {
+        "@rollup/rollup-android-arm-eabi": "4.9.6",
+        "@rollup/rollup-android-arm64": "4.9.6",
+        "@rollup/rollup-darwin-arm64": "4.9.6",
+        "@rollup/rollup-darwin-x64": "4.9.6",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.9.6",
+        "@rollup/rollup-linux-arm64-gnu": "4.9.6",
+        "@rollup/rollup-linux-arm64-musl": "4.9.6",
+        "@rollup/rollup-linux-riscv64-gnu": "4.9.6",
+        "@rollup/rollup-linux-x64-gnu": "4.9.6",
+        "@rollup/rollup-linux-x64-musl": "4.9.6",
+        "@rollup/rollup-win32-arm64-msvc": "4.9.6",
+        "@rollup/rollup-win32-ia32-msvc": "4.9.6",
+        "@rollup/rollup-win32-x64-msvc": "4.9.6",
         "fsevents": "~2.3.2"
       }
     },
     "node_modules/run-parallel": {
       "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
-      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
       "dev": true,
       "funding": [
         {
@@ -1160,42 +1198,65 @@
           "url": "https://feross.org/support"
         }
       ],
+      "license": "MIT",
       "dependencies": {
         "queue-microtask": "^1.2.2"
       }
     },
-    "node_modules/siginfo": {
+    "node_modules/shebang-command": {
       "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
-      "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
-      "dev": true
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
     },
-    "node_modules/source-map-js": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
-      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
       "dev": true,
+      "license": "MIT",
       "engines": {
-        "node": ">=0.10.0"
+        "node": ">=8"
+      }
+    },
+    "node_modules/siginfo": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.0.2",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
       }
     },
     "node_modules/stackback": {
       "version": "0.0.2",
-      "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
-      "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/std-env": {
-      "version": "3.4.3",
-      "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.4.3.tgz",
-      "integrity": "sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q==",
-      "dev": true
+      "version": "3.7.0",
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/strip-literal": {
       "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz",
-      "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "acorn": "^8.10.0"
       },
@@ -1203,35 +1264,63 @@
         "url": "https://github.com/sponsors/antfu"
       }
     },
+    "node_modules/supports-color": {
+      "version": "7.2.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/test-exclude": {
+      "version": "6.0.0",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "@istanbuljs/schema": "^0.1.2",
+        "glob": "^7.1.4",
+        "minimatch": "^3.0.4"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/tinybench": {
       "version": "2.5.1",
-      "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz",
-      "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/tinypool": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz",
-      "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==",
+      "version": "0.8.2",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=14.0.0"
       }
     },
     "node_modules/tinyspy": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.1.1.tgz",
-      "integrity": "sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==",
+      "version": "2.2.0",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=14.0.0"
       }
     },
+    "node_modules/to-fast-properties": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/to-regex-range": {
       "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "is-number": "^7.0.0"
       },
@@ -1241,43 +1330,65 @@
     },
     "node_modules/type-detect": {
       "version": "4.0.8",
-      "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
-      "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=4"
       }
     },
     "node_modules/ufo": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.1.tgz",
-      "integrity": "sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==",
-      "dev": true
+      "version": "1.3.2",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/undici-types": {
+      "version": "5.26.5",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "peer": true
+    },
+    "node_modules/v8-to-istanbul": {
+      "version": "9.2.0",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "@jridgewell/trace-mapping": "^0.3.12",
+        "@types/istanbul-lib-coverage": "^2.0.1",
+        "convert-source-map": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10.12.0"
+      }
+    },
+    "node_modules/v8-to-istanbul/node_modules/convert-source-map": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/vite": {
-      "version": "4.4.9",
-      "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz",
-      "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==",
+      "version": "5.0.12",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "esbuild": "^0.18.10",
-        "postcss": "^8.4.27",
-        "rollup": "^3.27.1"
+        "esbuild": "^0.19.3",
+        "postcss": "^8.4.32",
+        "rollup": "^4.2.0"
       },
       "bin": {
         "vite": "bin/vite.js"
       },
       "engines": {
-        "node": "^14.18.0 || >=16.0.0"
+        "node": "^18.0.0 || >=20.0.0"
       },
       "funding": {
         "url": "https://github.com/vitejs/vite?sponsor=1"
       },
       "optionalDependencies": {
-        "fsevents": "~2.3.2"
+        "fsevents": "~2.3.3"
       },
       "peerDependencies": {
-        "@types/node": ">= 14",
+        "@types/node": "^18.0.0 || >=20.0.0",
         "less": "*",
         "lightningcss": "^1.21.0",
         "sass": "*",
@@ -1310,82 +1421,77 @@
       }
     },
     "node_modules/vite-node": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz",
-      "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==",
+      "version": "1.2.1",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "cac": "^6.7.14",
         "debug": "^4.3.4",
-        "mlly": "^1.4.0",
         "pathe": "^1.1.1",
         "picocolors": "^1.0.0",
-        "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0"
+        "vite": "^5.0.0"
       },
       "bin": {
         "vite-node": "vite-node.mjs"
       },
       "engines": {
-        "node": ">=v14.18.0"
+        "node": "^18.0.0 || >=20.0.0"
       },
       "funding": {
         "url": "https://opencollective.com/vitest"
       }
     },
     "node_modules/vitest": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz",
-      "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==",
-      "dev": true,
-      "dependencies": {
-        "@types/chai": "^4.3.5",
-        "@types/chai-subset": "^1.3.3",
-        "@types/node": "*",
-        "@vitest/expect": "0.34.6",
-        "@vitest/runner": "0.34.6",
-        "@vitest/snapshot": "0.34.6",
-        "@vitest/spy": "0.34.6",
-        "@vitest/utils": "0.34.6",
-        "acorn": "^8.9.0",
-        "acorn-walk": "^8.2.0",
+      "version": "1.2.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@vitest/expect": "1.2.1",
+        "@vitest/runner": "1.2.1",
+        "@vitest/snapshot": "1.2.1",
+        "@vitest/spy": "1.2.1",
+        "@vitest/utils": "1.2.1",
+        "acorn-walk": "^8.3.2",
         "cac": "^6.7.14",
         "chai": "^4.3.10",
         "debug": "^4.3.4",
-        "local-pkg": "^0.4.3",
-        "magic-string": "^0.30.1",
+        "execa": "^8.0.1",
+        "local-pkg": "^0.5.0",
+        "magic-string": "^0.30.5",
         "pathe": "^1.1.1",
         "picocolors": "^1.0.0",
-        "std-env": "^3.3.3",
-        "strip-literal": "^1.0.1",
-        "tinybench": "^2.5.0",
-        "tinypool": "^0.7.0",
-        "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0",
-        "vite-node": "0.34.6",
+        "std-env": "^3.5.0",
+        "strip-literal": "^1.3.0",
+        "tinybench": "^2.5.1",
+        "tinypool": "^0.8.1",
+        "vite": "^5.0.0",
+        "vite-node": "1.2.1",
         "why-is-node-running": "^2.2.2"
       },
       "bin": {
         "vitest": "vitest.mjs"
       },
       "engines": {
-        "node": ">=v14.18.0"
+        "node": "^18.0.0 || >=20.0.0"
       },
       "funding": {
         "url": "https://opencollective.com/vitest"
       },
       "peerDependencies": {
         "@edge-runtime/vm": "*",
-        "@vitest/browser": "*",
-        "@vitest/ui": "*",
+        "@types/node": "^18.0.0 || >=20.0.0",
+        "@vitest/browser": "^1.0.0",
+        "@vitest/ui": "^1.0.0",
         "happy-dom": "*",
-        "jsdom": "*",
-        "playwright": "*",
-        "safaridriver": "*",
-        "webdriverio": "*"
+        "jsdom": "*"
       },
       "peerDependenciesMeta": {
         "@edge-runtime/vm": {
           "optional": true
         },
+        "@types/node": {
+          "optional": true
+        },
         "@vitest/browser": {
           "optional": true
         },
@@ -1397,877 +1503,166 @@
         },
         "jsdom": {
           "optional": true
-        },
-        "playwright": {
-          "optional": true
-        },
-        "safaridriver": {
-          "optional": true
-        },
-        "webdriverio": {
-          "optional": true
         }
       }
     },
-    "node_modules/why-is-node-running": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz",
-      "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==",
+    "node_modules/vitest/node_modules/execa": {
+      "version": "8.0.1",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
-        "siginfo": "^2.0.0",
-        "stackback": "0.0.2"
-      },
-      "bin": {
-        "why-is-node-running": "cli.js"
+        "cross-spawn": "^7.0.3",
+        "get-stream": "^8.0.1",
+        "human-signals": "^5.0.0",
+        "is-stream": "^3.0.0",
+        "merge-stream": "^2.0.0",
+        "npm-run-path": "^5.1.0",
+        "onetime": "^6.0.0",
+        "signal-exit": "^4.1.0",
+        "strip-final-newline": "^3.0.0"
       },
       "engines": {
-        "node": ">=8"
-      }
-    }
-  },
-  "dependencies": {
-    "@esbuild/android-arm": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
-      "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/android-arm64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
-      "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/android-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
-      "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/darwin-arm64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
-      "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/darwin-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
-      "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/freebsd-arm64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
-      "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/freebsd-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
-      "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/linux-arm": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
-      "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/linux-arm64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
-      "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/linux-ia32": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
-      "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/linux-loong64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
-      "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/linux-mips64el": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
-      "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/linux-ppc64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
-      "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/linux-riscv64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
-      "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/linux-s390x": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
-      "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/linux-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
-      "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/netbsd-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
-      "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/openbsd-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
-      "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/sunos-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
-      "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/win32-arm64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
-      "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/win32-ia32": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
-      "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
-      "dev": true,
-      "optional": true
-    },
-    "@esbuild/win32-x64": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
-      "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
-      "dev": true,
-      "optional": true
-    },
-    "@jest/schemas": {
-      "version": "29.6.3",
-      "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
-      "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
-      "dev": true,
-      "requires": {
-        "@sinclair/typebox": "^0.27.8"
-      }
-    },
-    "@jridgewell/sourcemap-codec": {
-      "version": "1.4.15",
-      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
-      "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
-      "dev": true
-    },
-    "@nodelib/fs.scandir": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
-      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
-      "dev": true,
-      "requires": {
-        "@nodelib/fs.stat": "2.0.5",
-        "run-parallel": "^1.1.9"
-      }
-    },
-    "@nodelib/fs.stat": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
-      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
-      "dev": true
-    },
-    "@nodelib/fs.walk": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
-      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
-      "dev": true,
-      "requires": {
-        "@nodelib/fs.scandir": "2.1.5",
-        "fastq": "^1.6.0"
-      }
-    },
-    "@sinclair/typebox": {
-      "version": "0.27.8",
-      "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
-      "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
-      "dev": true
-    },
-    "@types/chai": {
-      "version": "4.3.6",
-      "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.6.tgz",
-      "integrity": "sha512-VOVRLM1mBxIRxydiViqPcKn6MIxZytrbMpd6RJLIWKxUNr3zux8no0Oc7kJx0WAPIitgZ0gkrDS+btlqQpubpw==",
-      "dev": true
-    },
-    "@types/chai-subset": {
-      "version": "1.3.3",
-      "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz",
-      "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==",
-      "dev": true,
-      "requires": {
-        "@types/chai": "*"
-      }
-    },
-    "@types/node": {
-      "version": "18.11.0",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.0.tgz",
-      "integrity": "sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w==",
-      "dev": true
-    },
-    "@vitest/expect": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz",
-      "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==",
-      "dev": true,
-      "requires": {
-        "@vitest/spy": "0.34.6",
-        "@vitest/utils": "0.34.6",
-        "chai": "^4.3.10"
-      }
-    },
-    "@vitest/runner": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz",
-      "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==",
-      "dev": true,
-      "requires": {
-        "@vitest/utils": "0.34.6",
-        "p-limit": "^4.0.0",
-        "pathe": "^1.1.1"
+        "node": ">=16.17"
       },
-      "dependencies": {
-        "p-limit": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
-          "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
-          "dev": true,
-          "requires": {
-            "yocto-queue": "^1.0.0"
-          }
-        },
-        "yocto-queue": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
-          "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
-          "dev": true
-        }
-      }
-    },
-    "@vitest/snapshot": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz",
-      "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==",
-      "dev": true,
-      "requires": {
-        "magic-string": "^0.30.1",
-        "pathe": "^1.1.1",
-        "pretty-format": "^29.5.0"
-      }
-    },
-    "@vitest/spy": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz",
-      "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==",
-      "dev": true,
-      "requires": {
-        "tinyspy": "^2.1.1"
-      }
-    },
-    "@vitest/utils": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz",
-      "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==",
-      "dev": true,
-      "requires": {
-        "diff-sequences": "^29.4.3",
-        "loupe": "^2.3.6",
-        "pretty-format": "^29.5.0"
-      }
-    },
-    "acorn": {
-      "version": "8.10.0",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
-      "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
-      "dev": true
-    },
-    "acorn-walk": {
-      "version": "8.2.0",
-      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
-      "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
-      "dev": true
-    },
-    "assertion-error": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
-      "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
-      "dev": true
-    },
-    "braces": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
-      "dev": true,
-      "requires": {
-        "fill-range": "^7.0.1"
-      }
-    },
-    "cac": {
-      "version": "6.7.14",
-      "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
-      "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
-      "dev": true
-    },
-    "chai": {
-      "version": "4.3.10",
-      "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz",
-      "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==",
-      "dev": true,
-      "requires": {
-        "assertion-error": "^1.1.0",
-        "check-error": "^1.0.3",
-        "deep-eql": "^4.1.3",
-        "get-func-name": "^2.0.2",
-        "loupe": "^2.3.6",
-        "pathval": "^1.1.1",
-        "type-detect": "^4.0.8"
-      }
-    },
-    "check-error": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
-      "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==",
-      "dev": true,
-      "requires": {
-        "get-func-name": "^2.0.2"
-      }
-    },
-    "debug": {
-      "version": "4.3.4",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-      "dev": true,
-      "requires": {
-        "ms": "2.1.2"
-      }
-    },
-    "deep-eql": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
-      "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
-      "dev": true,
-      "requires": {
-        "type-detect": "^4.0.0"
-      }
-    },
-    "diff-sequences": {
-      "version": "29.6.3",
-      "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
-      "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
-      "dev": true
-    },
-    "dir-glob": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
-      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
-      "dev": true,
-      "requires": {
-        "path-type": "^4.0.0"
-      }
-    },
-    "esbuild": {
-      "version": "0.18.20",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
-      "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
-      "dev": true,
-      "requires": {
-        "@esbuild/android-arm": "0.18.20",
-        "@esbuild/android-arm64": "0.18.20",
-        "@esbuild/android-x64": "0.18.20",
-        "@esbuild/darwin-arm64": "0.18.20",
-        "@esbuild/darwin-x64": "0.18.20",
-        "@esbuild/freebsd-arm64": "0.18.20",
-        "@esbuild/freebsd-x64": "0.18.20",
-        "@esbuild/linux-arm": "0.18.20",
-        "@esbuild/linux-arm64": "0.18.20",
-        "@esbuild/linux-ia32": "0.18.20",
-        "@esbuild/linux-loong64": "0.18.20",
-        "@esbuild/linux-mips64el": "0.18.20",
-        "@esbuild/linux-ppc64": "0.18.20",
-        "@esbuild/linux-riscv64": "0.18.20",
-        "@esbuild/linux-s390x": "0.18.20",
-        "@esbuild/linux-x64": "0.18.20",
-        "@esbuild/netbsd-x64": "0.18.20",
-        "@esbuild/openbsd-x64": "0.18.20",
-        "@esbuild/sunos-x64": "0.18.20",
-        "@esbuild/win32-arm64": "0.18.20",
-        "@esbuild/win32-ia32": "0.18.20",
-        "@esbuild/win32-x64": "0.18.20"
-      }
-    },
-    "fast-glob": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
-      "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
-      "dev": true,
-      "requires": {
-        "@nodelib/fs.stat": "^2.0.2",
-        "@nodelib/fs.walk": "^1.2.3",
-        "glob-parent": "^5.1.2",
-        "merge2": "^1.3.0",
-        "micromatch": "^4.0.4"
-      }
-    },
-    "fastq": {
-      "version": "1.13.0",
-      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
-      "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
-      "dev": true,
-      "requires": {
-        "reusify": "^1.0.4"
-      }
-    },
-    "fill-range": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-      "dev": true,
-      "requires": {
-        "to-regex-range": "^5.0.1"
-      }
-    },
-    "fsevents": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
-      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
-      "dev": true,
-      "optional": true
-    },
-    "get-func-name": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
-      "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
-      "dev": true
-    },
-    "glob-parent": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
-      "requires": {
-        "is-glob": "^4.0.1"
+      "funding": {
+        "url": "https://github.com/sindresorhus/execa?sponsor=1"
       }
     },
-    "globby": {
-      "version": "13.2.2",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz",
-      "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==",
+    "node_modules/vitest/node_modules/get-stream": {
+      "version": "8.0.1",
       "dev": true,
-      "requires": {
-        "dir-glob": "^3.0.1",
-        "fast-glob": "^3.3.0",
-        "ignore": "^5.2.4",
-        "merge2": "^1.4.1",
-        "slash": "^4.0.0"
+      "license": "MIT",
+      "engines": {
+        "node": ">=16"
       },
-      "dependencies": {
-        "slash": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
-          "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
-          "dev": true
-        }
-      }
-    },
-    "husky": {
-      "version": "8.0.3",
-      "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
-      "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==",
-      "dev": true
-    },
-    "ignore": {
-      "version": "5.2.4",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
-      "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
-      "dev": true
-    },
-    "is-extglob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
-      "dev": true
-    },
-    "is-glob": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
-      "requires": {
-        "is-extglob": "^2.1.1"
-      }
-    },
-    "is-number": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-      "dev": true
-    },
-    "jsonc-parser": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
-      "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
-      "dev": true
-    },
-    "local-pkg": {
-      "version": "0.4.3",
-      "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz",
-      "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==",
-      "dev": true
-    },
-    "loupe": {
-      "version": "2.3.6",
-      "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz",
-      "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==",
-      "dev": true,
-      "requires": {
-        "get-func-name": "^2.0.0"
-      }
-    },
-    "magic-string": {
-      "version": "0.30.4",
-      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.4.tgz",
-      "integrity": "sha512-Q/TKtsC5BPm0kGqgBIF9oXAs/xEf2vRKiIB4wCRQTJOQIByZ1d+NnUOotvJOvNpi5RNIgVOMC3pOuaP1ZTDlVg==",
-      "dev": true,
-      "requires": {
-        "@jridgewell/sourcemap-codec": "^1.4.15"
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "merge2": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
-      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
-      "dev": true
-    },
-    "micromatch": {
-      "version": "4.0.5",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
-      "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+    "node_modules/vitest/node_modules/human-signals": {
+      "version": "5.0.0",
       "dev": true,
-      "requires": {
-        "braces": "^3.0.2",
-        "picomatch": "^2.3.1"
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=16.17.0"
       }
     },
-    "mlly": {
-      "version": "1.4.2",
-      "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.2.tgz",
-      "integrity": "sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==",
+    "node_modules/vitest/node_modules/is-stream": {
+      "version": "3.0.0",
       "dev": true,
-      "requires": {
-        "acorn": "^8.10.0",
-        "pathe": "^1.1.1",
-        "pkg-types": "^1.0.3",
-        "ufo": "^1.3.0"
+      "license": "MIT",
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "ms": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-      "dev": true
-    },
-    "nanoid": {
-      "version": "3.3.6",
-      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
-      "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
-      "dev": true
-    },
-    "path-type": {
+    "node_modules/vitest/node_modules/mimic-fn": {
       "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
-      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
-      "dev": true
-    },
-    "pathe": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz",
-      "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==",
-      "dev": true
-    },
-    "pathval": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
-      "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
-      "dev": true
-    },
-    "picocolors": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
-      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
-      "dev": true
-    },
-    "picomatch": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-      "dev": true
-    },
-    "pkg-types": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz",
-      "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==",
       "dev": true,
-      "requires": {
-        "jsonc-parser": "^3.2.0",
-        "mlly": "^1.2.0",
-        "pathe": "^1.1.0"
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "postcss": {
-      "version": "8.4.31",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
-      "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+    "node_modules/vitest/node_modules/npm-run-path": {
+      "version": "5.2.0",
       "dev": true,
-      "requires": {
-        "nanoid": "^3.3.6",
-        "picocolors": "^1.0.0",
-        "source-map-js": "^1.0.2"
+      "license": "MIT",
+      "dependencies": {
+        "path-key": "^4.0.0"
+      },
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "prettier": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
-      "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
-      "dev": true
-    },
-    "pretty-format": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
-      "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+    "node_modules/vitest/node_modules/onetime": {
+      "version": "6.0.0",
       "dev": true,
-      "requires": {
-        "@jest/schemas": "^29.6.3",
-        "ansi-styles": "^5.0.0",
-        "react-is": "^18.0.0"
-      },
+      "license": "MIT",
       "dependencies": {
-        "ansi-styles": {
-          "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
-          "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
-          "dev": true
-        }
+        "mimic-fn": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "queue-microtask": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
-      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
-      "dev": true
-    },
-    "react-is": {
-      "version": "18.2.0",
-      "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
-      "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
-      "dev": true
-    },
-    "reusify": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
-      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
-      "dev": true
-    },
-    "rollup": {
-      "version": "3.29.4",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz",
-      "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==",
+    "node_modules/vitest/node_modules/path-key": {
+      "version": "4.0.0",
       "dev": true,
-      "requires": {
-        "fsevents": "~2.3.2"
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "run-parallel": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
-      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+    "node_modules/vitest/node_modules/signal-exit": {
+      "version": "4.1.0",
       "dev": true,
-      "requires": {
-        "queue-microtask": "^1.2.2"
+      "license": "ISC",
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
       }
     },
-    "siginfo": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
-      "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
-      "dev": true
-    },
-    "source-map-js": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
-      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
-      "dev": true
-    },
-    "stackback": {
-      "version": "0.0.2",
-      "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
-      "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
-      "dev": true
-    },
-    "std-env": {
-      "version": "3.4.3",
-      "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.4.3.tgz",
-      "integrity": "sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q==",
-      "dev": true
-    },
-    "strip-literal": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz",
-      "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==",
+    "node_modules/vitest/node_modules/strip-final-newline": {
+      "version": "3.0.0",
       "dev": true,
-      "requires": {
-        "acorn": "^8.10.0"
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "tinybench": {
-      "version": "2.5.1",
-      "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz",
-      "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==",
-      "dev": true
-    },
-    "tinypool": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz",
-      "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==",
-      "dev": true
-    },
-    "tinyspy": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.1.1.tgz",
-      "integrity": "sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==",
-      "dev": true
-    },
-    "to-regex-range": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+    "node_modules/which": {
+      "version": "2.0.2",
       "dev": true,
-      "requires": {
-        "is-number": "^7.0.0"
-      }
-    },
-    "type-detect": {
-      "version": "4.0.8",
-      "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
-      "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
-      "dev": true
-    },
-    "ufo": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.1.tgz",
-      "integrity": "sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==",
-      "dev": true
-    },
-    "vite": {
-      "version": "4.4.9",
-      "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz",
-      "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==",
-      "dev": true,
-      "requires": {
-        "esbuild": "^0.18.10",
-        "fsevents": "~2.3.2",
-        "postcss": "^8.4.27",
-        "rollup": "^3.27.1"
-      }
-    },
-    "vite-node": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz",
-      "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==",
-      "dev": true,
-      "requires": {
-        "cac": "^6.7.14",
-        "debug": "^4.3.4",
-        "mlly": "^1.4.0",
-        "pathe": "^1.1.1",
-        "picocolors": "^1.0.0",
-        "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0"
-      }
-    },
-    "vitest": {
-      "version": "0.34.6",
-      "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz",
-      "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==",
-      "dev": true,
-      "requires": {
-        "@types/chai": "^4.3.5",
-        "@types/chai-subset": "^1.3.3",
-        "@types/node": "*",
-        "@vitest/expect": "0.34.6",
-        "@vitest/runner": "0.34.6",
-        "@vitest/snapshot": "0.34.6",
-        "@vitest/spy": "0.34.6",
-        "@vitest/utils": "0.34.6",
-        "acorn": "^8.9.0",
-        "acorn-walk": "^8.2.0",
-        "cac": "^6.7.14",
-        "chai": "^4.3.10",
-        "debug": "^4.3.4",
-        "local-pkg": "^0.4.3",
-        "magic-string": "^0.30.1",
-        "pathe": "^1.1.1",
-        "picocolors": "^1.0.0",
-        "std-env": "^3.3.3",
-        "strip-literal": "^1.0.1",
-        "tinybench": "^2.5.0",
-        "tinypool": "^0.7.0",
-        "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0",
-        "vite-node": "0.34.6",
-        "why-is-node-running": "^2.2.2"
+      "license": "ISC",
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
       }
     },
-    "why-is-node-running": {
+    "node_modules/why-is-node-running": {
       "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz",
-      "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==",
       "dev": true,
-      "requires": {
+      "license": "MIT",
+      "dependencies": {
         "siginfo": "^2.0.0",
         "stackback": "0.0.2"
+      },
+      "bin": {
+        "why-is-node-running": "cli.js"
+      },
+      "engines": {
+        "node": ">=8"
       }
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "dev": true,
+      "license": "ISC"
     }
   }
 }
diff --git a/package.json b/package.json
index 9ce6f3cb0f..e667e1eea2 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,8 @@
     "globby": "^13.2.2",
     "husky": "^8.0.3",
     "prettier": "^3.0.3",
-    "vitest": "^0.34.6"
+    "vitest": "^1.2.1",
+    "@vitest/coverage-v8": "^1.2.1"
   },
   "engines": {
     "node": ">=20.6.0"
diff --git a/vitest.config.ts b/vitest.config.ts
index 5709b1addc..05f33b84f5 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -3,6 +3,9 @@ import { defineConfig } from 'vitest/config'
 export default defineConfig({
   test: {
     globals: true,
-    restoreMocks: true
+    restoreMocks: true,
+    coverage: {
+      reporter: ['text', 'json', 'html']
+    }
   }
 })

From cf0004190ab69c947d781f5cb8537b446beb8cbf Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Mon, 29 Jan 2024 06:30:44 +0100
Subject: [PATCH 29/73] docs: add codecov badge (#1600)

---
 README.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/README.md b/README.md
index 65dfb501df..bd9582fe94 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@ JavaScript Repository of TheAlgorithms, which implements various algorithms and
 
 [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/TheAlgorithms/JavaScript)
 [![Checks][checks]][actions]
+[![codecov](https://codecov.io/gh/TheAlgorithms/JavaScript/graph/badge.svg?token=8VeZwL31KZ)](https://codecov.io/gh/TheAlgorithms/JavaScript)
 [![Contributions Welcome][welcome]](CONTRIBUTING.md)
 [![standard.js][standard-logo]][standard-js]
 [![Discord chat][chat]][discord-server]

From 6aaa376500a7312d6980957c5ac2288282d0bed7 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Wed, 31 Jan 2024 07:07:54 +0100
Subject: [PATCH 30/73] tests: add tests for `SHA1` (#1602)

* tests: add tests for `SHA1`

* style: use `it.each`

---------

Co-authored-by: appgurueu <34514239+appgurueu@users.noreply.github.com>

---------

Co-authored-by: appgurueu <34514239+appgurueu@users.noreply.github.com>
---
 Hashes/tests/SHA1.test.js | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 Hashes/tests/SHA1.test.js

diff --git a/Hashes/tests/SHA1.test.js b/Hashes/tests/SHA1.test.js
new file mode 100644
index 0000000000..8032e29908
--- /dev/null
+++ b/Hashes/tests/SHA1.test.js
@@ -0,0 +1,25 @@
+import { describe, test } from 'vitest'
+import { SHA1 } from '../SHA1'
+
+describe('Testing SHA1 function', () => {
+  it.each([
+    ['', 'da39a3ee5e6b4b0d3255bfef95601890afd80709'],
+    [
+      'The quick brown fox jumps over the lazy dog',
+      '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'
+    ],
+    [
+      'The quick brown fox jumps over the lazy cog',
+      'de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3'
+    ],
+    ['a', '86f7e437faa5a7fce15d1ddcb9eaeaea377667b8'],
+    ['Today is 29.01.2024!', 'ae829b60d11fb5ab527d5db2501e06da3402718d'],
+    ['Have a nice day.', 'ed51dd3909281c25db5e1d8b1ce6fc701fda20ab'],
+    [
+      '12345678901234567890123456789012345678901234567890123456789012345678901234567890',
+      '50abf5706a150990a08b2c5ea40fa0e585554732'
+    ]
+  ])('check with %j', (input, expected) => {
+    expect(SHA1(input)).toBe(expected)
+  })
+})

From f31349812ce25d2046b0e46688381adc942880c7 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Fri, 9 Feb 2024 18:00:47 +0100
Subject: [PATCH 31/73] tests: add tests for `SHA256` (#1604)

---
 Hashes/tests/SHA256.test.js | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 Hashes/tests/SHA256.test.js

diff --git a/Hashes/tests/SHA256.test.js b/Hashes/tests/SHA256.test.js
new file mode 100644
index 0000000000..1ffb236cea
--- /dev/null
+++ b/Hashes/tests/SHA256.test.js
@@ -0,0 +1,27 @@
+import { describe, test } from 'vitest'
+import { SHA256 } from '../SHA256'
+
+describe('Testing SHA256 function', () => {
+  it.each([
+    ['', 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'],
+    [
+      'The quick brown fox jumps over the lazy dog',
+      'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592'
+    ],
+    [
+      'The quick brown fox jumps over the lazy cog',
+      'e4c4d8f3bf76b692de791a173e05321150f7a345b46484fe427f6acc7ecc81be'
+    ],
+    [
+      'This was added by vil02 on 01.02.2024. Have a nice day!',
+      '476025d91db754ab6ac0c124367afd7c108d041b2f497006a214d5035769ed5d'
+    ],
+    [
+      '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789',
+      '14582b3f153941891dca966b036a5b1de65fa3b7a2540095a31614da1de0feaf'
+    ],
+    ['a', 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb']
+  ])('check with %j', (input, expected) => {
+    expect(SHA256(input)).toBe(expected)
+  })
+})

From 10febce31a1623eebc3c81a99b9de2225963d62b Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Fri, 9 Feb 2024 18:01:20 +0100
Subject: [PATCH 32/73] style: cleanup `PascalTriangle` (#1606)

* tests: add missing tests for `PascalTriangle`

* style: remove redundant branch in `generate`

* tests: simplify tests of `PascalTriangle`
---
 Maths/PascalTriangle.js           |  2 --
 Maths/test/PascalTriangle.test.js | 24 ++++++++++++------------
 2 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/Maths/PascalTriangle.js b/Maths/PascalTriangle.js
index 868e36fcac..71d782cd61 100644
--- a/Maths/PascalTriangle.js
+++ b/Maths/PascalTriangle.js
@@ -17,8 +17,6 @@ const generate = (numRows) => {
     return []
   } else if (numRows === 1) {
     return [[1]]
-  } else if (numRows === 2) {
-    return [[1], [1, 1]]
   } else {
     for (let i = 2; i < numRows; i++) {
       addRow(triangle)
diff --git a/Maths/test/PascalTriangle.test.js b/Maths/test/PascalTriangle.test.js
index 314d0f3211..65c736f14f 100644
--- a/Maths/test/PascalTriangle.test.js
+++ b/Maths/test/PascalTriangle.test.js
@@ -1,20 +1,20 @@
+import { expect } from 'vitest'
 import { generate } from '../PascalTriangle'
 
 describe('Pascals Triangle', () => {
-  it('should have the the same length as the number', () => {
-    const pascalsTriangle = generate(5)
-    expect(pascalsTriangle.length).toEqual(5)
-  })
-  it('should have same length as its index in the array', () => {
-    const pascalsTriangle = generate(5)
+  it.each([
+    [0, []],
+    [1, [[1]]],
+    [2, [[1], [1, 1]]],
+    [3, [[1], [1, 1], [1, 2, 1]]],
+    [4, [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]]],
+    [5, [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]], [1, 4, 6, 4, 1]]
+  ])('check with %j', (input, expected) => {
+    const pascalsTriangle = generate(input)
+    expect(pascalsTriangle.length).toEqual(input)
     pascalsTriangle.forEach((arr, index) => {
       expect(arr.length).toEqual(index + 1)
     })
-  })
-  it('should return an array of arrays', () => {
-    const pascalsTriangle = generate(3)
-    expect(pascalsTriangle).toEqual(
-      expect.arrayContaining([[1], [1, 1], [1, 2, 1]])
-    )
+    expect(pascalsTriangle).toEqual(expect.arrayContaining(expected))
   })
 })

From 1ea7a5cd5e455011a26b07b7e43b9c5471e1e501 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Wed, 14 Feb 2024 16:43:38 +0100
Subject: [PATCH 33/73] test: add missing test for `SumOfGeometricProgression`
 (#1607)

---
 Maths/test/SumOfGeometricProgression.test.js | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Maths/test/SumOfGeometricProgression.test.js b/Maths/test/SumOfGeometricProgression.test.js
index f459835232..0edf2b9f8e 100644
--- a/Maths/test/SumOfGeometricProgression.test.js
+++ b/Maths/test/SumOfGeometricProgression.test.js
@@ -8,4 +8,8 @@ describe('Sum Of Geometric Progression', () => {
   it('should return the sum of an infinite GP', () => {
     expect(sumOfGeometricProgression(2, 0.5, Infinity)).toBe(4)
   })
+
+  it('should throw when series diverges', () => {
+    expect(() => sumOfGeometricProgression(1, 1, Infinity)).toThrowError()
+  })
 })

From fb0a99c15a39a222da960fc4ff0be12bdbae3517 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Mon, 19 Feb 2024 14:56:54 +0100
Subject: [PATCH 34/73] fix: throw error and add tests for `ReverseNumber`
 (#1608)

---
 Maths/ReverseNumber.js           |  2 +-
 Maths/test/ReverseNumber.test.js | 16 ++++++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)
 create mode 100644 Maths/test/ReverseNumber.test.js

diff --git a/Maths/ReverseNumber.js b/Maths/ReverseNumber.js
index 2f29903c93..4874cb3a86 100644
--- a/Maths/ReverseNumber.js
+++ b/Maths/ReverseNumber.js
@@ -10,7 +10,7 @@
 const ReverseNumber = (number) => {
   // firstly, check that input is a number or not.
   if (typeof number !== 'number') {
-    return new TypeError('Argument is not a number.')
+    throw new TypeError('Argument is not a number.')
   }
   // A variable for storing the reversed number.
   let reverseNumber = 0
diff --git a/Maths/test/ReverseNumber.test.js b/Maths/test/ReverseNumber.test.js
new file mode 100644
index 0000000000..64593cbe14
--- /dev/null
+++ b/Maths/test/ReverseNumber.test.js
@@ -0,0 +1,16 @@
+import { ReverseNumber } from '../ReverseNumber'
+
+describe('ReverseNumber', () => {
+  it.each([
+    [0, 0],
+    [10, 1],
+    [123, 321],
+    [100001, 100001]
+  ])('check with %j', (input, expected) => {
+    expect(expected).toEqual(ReverseNumber(input))
+  })
+
+  it('should throw when input is not a number', () => {
+    expect(() => ReverseNumber('100')).toThrowError()
+  })
+})

From 0e0cf98ce7cc976ea31349bd4db17afef76456c4 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Tue, 27 Feb 2024 09:54:29 +0100
Subject: [PATCH 35/73] fix: cleanup `CoPrimeCheck` (#1609)

---
 Maths/CoPrimeCheck.js           |  4 ++--
 Maths/test/CoPrimeCheck.test.js | 29 +++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 2 deletions(-)
 create mode 100644 Maths/test/CoPrimeCheck.test.js

diff --git a/Maths/CoPrimeCheck.js b/Maths/CoPrimeCheck.js
index 3d9a0a3993..bade446771 100644
--- a/Maths/CoPrimeCheck.js
+++ b/Maths/CoPrimeCheck.js
@@ -28,13 +28,13 @@ const GetEuclidGCD = (arg1, arg2) => {
 const CoPrimeCheck = (firstNumber, secondNumber) => {
   // firstly, check that input is a number or not.
   if (typeof firstNumber !== 'number' || typeof secondNumber !== 'number') {
-    return new TypeError('Argument is not a number.')
+    throw new TypeError('Argument is not a number.')
   }
   /*
     This is the most efficient algorithm for checking co-primes
     if the GCD of both the numbers is 1 that means they are co-primes.
     */
-  return GetEuclidGCD(firstNumber, secondNumber) === 1
+  return GetEuclidGCD(Math.abs(firstNumber), Math.abs(secondNumber)) === 1
 }
 
 export { CoPrimeCheck }
diff --git a/Maths/test/CoPrimeCheck.test.js b/Maths/test/CoPrimeCheck.test.js
new file mode 100644
index 0000000000..2276f055d3
--- /dev/null
+++ b/Maths/test/CoPrimeCheck.test.js
@@ -0,0 +1,29 @@
+import { CoPrimeCheck } from '../CoPrimeCheck'
+
+describe('CoPrimeCheck', () => {
+  it.each([
+    [1, 1],
+    [1, 2],
+    [1, 3],
+    [1, 7],
+    [20, 21],
+    [5, 7],
+    [-5, -7]
+  ])('returns true for %j and %i', (inputA, inputB) => {
+    expect(CoPrimeCheck(inputA, inputB)).toBe(true)
+    expect(CoPrimeCheck(inputB, inputA)).toBe(true)
+  })
+
+  it.each([
+    [5, 15],
+    [13 * 17 * 19, 17 * 23 * 29]
+  ])('returns false for %j and %i', (inputA, inputB) => {
+    expect(CoPrimeCheck(inputA, inputB)).toBe(false)
+    expect(CoPrimeCheck(inputB, inputA)).toBe(false)
+  })
+
+  it('should throw when any of the inputs is not a number', () => {
+    expect(() => CoPrimeCheck('1', 2)).toThrowError()
+    expect(() => CoPrimeCheck(1, '2')).toThrowError()
+  })
+})

From c067a34faeedeec4c2411d17548c230833230d71 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Wed, 28 Feb 2024 07:17:22 +0100
Subject: [PATCH 36/73] fix: `GetEuclidGCD(0, 0)` is `0` (#1621)

---
 Maths/GetEuclidGCD.js           |  1 -
 Maths/test/GetEuclidGCD.test.js | 26 ++++++++++++++++++--------
 2 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/Maths/GetEuclidGCD.js b/Maths/GetEuclidGCD.js
index 5499057d78..31eeab42ec 100644
--- a/Maths/GetEuclidGCD.js
+++ b/Maths/GetEuclidGCD.js
@@ -8,7 +8,6 @@ export function GetEuclidGCD(a, b) {
   if (typeof a !== 'number' || typeof b !== 'number') {
     throw new TypeError('Arguments must be numbers')
   }
-  if (a === 0 && b === 0) return undefined // infinitely many numbers divide 0
   a = Math.abs(a)
   b = Math.abs(b)
   while (b !== 0) {
diff --git a/Maths/test/GetEuclidGCD.test.js b/Maths/test/GetEuclidGCD.test.js
index 1639d9cb7f..a6c7cb22e6 100644
--- a/Maths/test/GetEuclidGCD.test.js
+++ b/Maths/test/GetEuclidGCD.test.js
@@ -1,12 +1,22 @@
 import { GetEuclidGCD } from '../GetEuclidGCD'
 
-function testEuclidGCD(n, m, expected) {
-  test('Testing on ' + n + ' and ' + m + '!', () => {
-    expect(GetEuclidGCD(n, m)).toBe(expected)
+describe('GetEuclidGCD', () => {
+  it.each([
+    [5, 20, 5],
+    [109, 902, 1],
+    [290, 780, 10],
+    [104, 156, 52],
+    [0, 100, 100],
+    [-5, 50, 5],
+    [0, 0, 0],
+    [1, 1234567, 1]
+  ])('returns correct result for %i and %j', (inputA, inputB, expected) => {
+    expect(GetEuclidGCD(inputA, inputB)).toBe(expected)
+    expect(GetEuclidGCD(inputB, inputA)).toBe(expected)
   })
-}
 
-testEuclidGCD(5, 20, 5)
-testEuclidGCD(109, 902, 1)
-testEuclidGCD(290, 780, 10)
-testEuclidGCD(104, 156, 52)
+  it('should throw when any of the inputs is not a number', () => {
+    expect(() => GetEuclidGCD('1', 2)).toThrowError()
+    expect(() => GetEuclidGCD(1, '2')).toThrowError()
+  })
+})

From a5945e37c257553bb77cbce95cb6f753ce6d1ab5 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Thu, 29 Feb 2024 05:55:11 +0100
Subject: [PATCH 37/73] fix: throw error instead of returning it (#1624)

---
 String/CheckFlatCase.js             | 2 +-
 String/CheckKebabCase.js            | 2 +-
 String/CheckPascalCase.js           | 2 +-
 String/test/CheckCamelCase.test.js  | 4 ++++
 String/test/CheckFlatCase.test.js   | 4 ++++
 String/test/CheckKebabCase.test.js  | 4 ++++
 String/test/CheckPascalCase.test.js | 4 ++++
 7 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/String/CheckFlatCase.js b/String/CheckFlatCase.js
index 709825edd1..5f8a332999 100644
--- a/String/CheckFlatCase.js
+++ b/String/CheckFlatCase.js
@@ -12,7 +12,7 @@
 const checkFlatCase = (varname) => {
   // firstly, check that input is a string or not.
   if (typeof varname !== 'string') {
-    return new TypeError('Argument is not a string.')
+    throw new TypeError('Argument is not a string.')
   }
 
   const pat = /^[a-z]*$/
diff --git a/String/CheckKebabCase.js b/String/CheckKebabCase.js
index 6e79ba6a5e..52d322f921 100644
--- a/String/CheckKebabCase.js
+++ b/String/CheckKebabCase.js
@@ -10,7 +10,7 @@
 const CheckKebabCase = (varName) => {
   // firstly, check that input is a string or not.
   if (typeof varName !== 'string') {
-    return new TypeError('Argument is not a string.')
+    throw new TypeError('Argument is not a string.')
   }
 
   const pat = /(\w+)-(\w)([\w-]*)/
diff --git a/String/CheckPascalCase.js b/String/CheckPascalCase.js
index 2e4c1ff3fa..71aaa26770 100644
--- a/String/CheckPascalCase.js
+++ b/String/CheckPascalCase.js
@@ -10,7 +10,7 @@
 const CheckPascalCase = (VarName) => {
   // firstly, check that input is a string or not.
   if (typeof VarName !== 'string') {
-    return new TypeError('Argument is not a string.')
+    throw new TypeError('Argument is not a string.')
   }
 
   const pat = /^[A-Z][A-Za-z]*$/
diff --git a/String/test/CheckCamelCase.test.js b/String/test/CheckCamelCase.test.js
index c1e2d83005..5875e0cd10 100644
--- a/String/test/CheckCamelCase.test.js
+++ b/String/test/CheckCamelCase.test.js
@@ -15,4 +15,8 @@ describe('checkCamelCase', () => {
     const result = checkCamelCase(value)
     expect(result).toBe(false)
   })
+
+  it('should throw when input is not a string', () => {
+    expect(() => checkCamelCase(100)).toThrowError()
+  })
 })
diff --git a/String/test/CheckFlatCase.test.js b/String/test/CheckFlatCase.test.js
index 0277f7c0e1..ccac811bf6 100644
--- a/String/test/CheckFlatCase.test.js
+++ b/String/test/CheckFlatCase.test.js
@@ -15,4 +15,8 @@ describe('checkFlatCase function', () => {
     const actual = checkFlatCase('abcdefghijklmnopqrstuvwxyz')
     expect(actual).toBe(true)
   })
+
+  it('should throw when input is not a string', () => {
+    expect(() => checkFlatCase(100)).toThrowError()
+  })
 })
diff --git a/String/test/CheckKebabCase.test.js b/String/test/CheckKebabCase.test.js
index 45bc5f2d52..239d91674e 100644
--- a/String/test/CheckKebabCase.test.js
+++ b/String/test/CheckKebabCase.test.js
@@ -11,3 +11,7 @@ test('CheckKebabCase(The Algorithms) -> false', () => {
   const res = CheckKebabCase(word)
   expect(res).toBeFalsy()
 })
+
+test('CheckKebabCase throws when input is not a string', () => {
+  expect(() => CheckKebabCase(100)).toThrowError()
+})
diff --git a/String/test/CheckPascalCase.test.js b/String/test/CheckPascalCase.test.js
index 2587023f79..139b66844b 100644
--- a/String/test/CheckPascalCase.test.js
+++ b/String/test/CheckPascalCase.test.js
@@ -17,3 +17,7 @@ test('CheckPascalCase(The Algorithms) -> false', () => {
   const res = CheckPascalCase(word)
   expect(res).toBeFalsy()
 })
+
+test('CheckPascalCase throws when input is not a string', () => {
+  expect(() => CheckPascalCase(100)).toThrowError()
+})

From 8734dfccf90b835b4ca9e09579af4528934a130d Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Thu, 29 Feb 2024 06:06:08 +0100
Subject: [PATCH 38/73] fix: handle zeros in `CoPrimeCheck` (#1622)

---
 Maths/CoPrimeCheck.js           | 15 ++-------------
 Maths/test/CoPrimeCheck.test.js |  8 ++++++--
 2 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/Maths/CoPrimeCheck.js b/Maths/CoPrimeCheck.js
index bade446771..6f0437eaac 100644
--- a/Maths/CoPrimeCheck.js
+++ b/Maths/CoPrimeCheck.js
@@ -9,14 +9,7 @@
     is coprime with b.
 */
 
-// Here we use a GetEuclidGCD method as a utility.
-const GetEuclidGCD = (arg1, arg2) => {
-  let less = arg1 > arg2 ? arg2 : arg1
-  for (less; less >= 2; less--) {
-    if (arg1 % less === 0 && arg2 % less === 0) return less
-  }
-  return less
-}
+import { GetEuclidGCD } from './GetEuclidGCD'
 
 // CoPrimeCheck function return the boolean in respect of the given number is co-prime or not.
 /**
@@ -26,15 +19,11 @@ const GetEuclidGCD = (arg1, arg2) => {
  * @returns return correspond boolean value, if both number are co-prime return `true`, else return `false`.
  */
 const CoPrimeCheck = (firstNumber, secondNumber) => {
-  // firstly, check that input is a number or not.
-  if (typeof firstNumber !== 'number' || typeof secondNumber !== 'number') {
-    throw new TypeError('Argument is not a number.')
-  }
   /*
     This is the most efficient algorithm for checking co-primes
     if the GCD of both the numbers is 1 that means they are co-primes.
     */
-  return GetEuclidGCD(Math.abs(firstNumber), Math.abs(secondNumber)) === 1
+  return GetEuclidGCD(firstNumber, secondNumber) === 1
 }
 
 export { CoPrimeCheck }
diff --git a/Maths/test/CoPrimeCheck.test.js b/Maths/test/CoPrimeCheck.test.js
index 2276f055d3..7a46bcf6cf 100644
--- a/Maths/test/CoPrimeCheck.test.js
+++ b/Maths/test/CoPrimeCheck.test.js
@@ -8,7 +8,9 @@ describe('CoPrimeCheck', () => {
     [1, 7],
     [20, 21],
     [5, 7],
-    [-5, -7]
+    [-5, -7],
+    [1, 0],
+    [-1, 0]
   ])('returns true for %j and %i', (inputA, inputB) => {
     expect(CoPrimeCheck(inputA, inputB)).toBe(true)
     expect(CoPrimeCheck(inputB, inputA)).toBe(true)
@@ -16,7 +18,9 @@ describe('CoPrimeCheck', () => {
 
   it.each([
     [5, 15],
-    [13 * 17 * 19, 17 * 23 * 29]
+    [13 * 17 * 19, 17 * 23 * 29],
+    [2, 0],
+    [0, 0]
   ])('returns false for %j and %i', (inputA, inputB) => {
     expect(CoPrimeCheck(inputA, inputB)).toBe(false)
     expect(CoPrimeCheck(inputB, inputA)).toBe(false)

From 894a46ca67ed25ba52297d72dbc37d2698ac4763 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sat, 2 Mar 2024 08:54:46 +0100
Subject: [PATCH 39/73] fix: throw error instead of returning it
 `RailwayTimeConversion` (#1625)

---
 Conversions/RailwayTimeConversion.js           | 2 +-
 Conversions/test/RailwayTimeConversion.test.js | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/Conversions/RailwayTimeConversion.js b/Conversions/RailwayTimeConversion.js
index fd4f9a5dad..15f837b0da 100644
--- a/Conversions/RailwayTimeConversion.js
+++ b/Conversions/RailwayTimeConversion.js
@@ -18,7 +18,7 @@
 const RailwayTimeConversion = (timeString) => {
   // firstly, check that input is a string or not.
   if (typeof timeString !== 'string') {
-    return new TypeError('Argument is not a string.')
+    throw new TypeError('Argument is not a string.')
   }
   // split the string by ':' character.
   const [hour, minute, secondWithShift] = timeString.split(':')
diff --git a/Conversions/test/RailwayTimeConversion.test.js b/Conversions/test/RailwayTimeConversion.test.js
index 0e49af3b7f..6579420049 100644
--- a/Conversions/test/RailwayTimeConversion.test.js
+++ b/Conversions/test/RailwayTimeConversion.test.js
@@ -19,3 +19,7 @@ test('The RailwayTimeConversion of 11:20:00PM is 23:20:00', () => {
   const res = RailwayTimeConversion('11:20:00PM')
   expect(res).toEqual('23:20:00')
 })
+
+test('The RailwayTimeConversion throws when input is not a string', () => {
+  expect(() => RailwayTimeConversion(1120)).toThrowError()
+})

From 83b4dd82909badb19ad0a10e658ace64d69cd4da Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sat, 2 Mar 2024 08:55:14 +0100
Subject: [PATCH 40/73] fix: cleanup `CheckKishnamurthyNumber` (#1626)

---
 Maths/CheckKishnamurthyNumber.js           |  5 ++++-
 Maths/test/CheckKishnamurthyNumber.test.js | 18 ++++++++++++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)
 create mode 100644 Maths/test/CheckKishnamurthyNumber.test.js

diff --git a/Maths/CheckKishnamurthyNumber.js b/Maths/CheckKishnamurthyNumber.js
index 7a0cc9a0cc..5098b0fa7f 100644
--- a/Maths/CheckKishnamurthyNumber.js
+++ b/Maths/CheckKishnamurthyNumber.js
@@ -24,7 +24,10 @@ const factorial = (n) => {
 const CheckKishnamurthyNumber = (number) => {
   // firstly, check that input is a number or not.
   if (typeof number !== 'number') {
-    return new TypeError('Argument is not a number.')
+    throw new TypeError('Argument is not a number.')
+  }
+  if (number === 0) {
+    return false
   }
   // create a variable to store the sum of all digits factorial.
   let sumOfAllDigitFactorial = 0
diff --git a/Maths/test/CheckKishnamurthyNumber.test.js b/Maths/test/CheckKishnamurthyNumber.test.js
new file mode 100644
index 0000000000..4f2e0db952
--- /dev/null
+++ b/Maths/test/CheckKishnamurthyNumber.test.js
@@ -0,0 +1,18 @@
+import { CheckKishnamurthyNumber } from '../CheckKishnamurthyNumber'
+
+describe('CheckKishnamurthyNumber', () => {
+  it.each([1, 2, 145, 40585])('returns true for %i', (num) => {
+    expect(CheckKishnamurthyNumber(num)).toBe(true)
+  })
+
+  it.each([0, 3, 4, 5, 100, 146, 1019823, -1])(
+    'returns false for %i',
+    (num) => {
+      expect(CheckKishnamurthyNumber(num)).toBe(false)
+    }
+  )
+
+  it('should throw when input is not a number', () => {
+    expect(() => CheckKishnamurthyNumber('2')).toThrowError()
+  })
+})

From 2fe0dfde23b1179a6fa5fdd7425a3f2bf303d538 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Mon, 4 Mar 2024 23:03:19 +0100
Subject: [PATCH 41/73] fix: `throw` form `DateToDay` (#1628)

---
 Conversions/DateToDay.js           |  4 +--
 Conversions/test/DateToDay.test.js | 53 +++++++++++++-----------------
 2 files changed, 25 insertions(+), 32 deletions(-)

diff --git a/Conversions/DateToDay.js b/Conversions/DateToDay.js
index 378489e50e..f360c9c737 100644
--- a/Conversions/DateToDay.js
+++ b/Conversions/DateToDay.js
@@ -26,13 +26,13 @@ const daysNameArr = [
 const DateToDay = (date) => {
   // firstly, check that input is a string or not.
   if (typeof date !== 'string') {
-    return new TypeError('Argument is not a string.')
+    throw new TypeError('Argument is not a string.')
   }
   // extract the date
   let [day, month, year] = date.split('/').map((x) => Number(x))
   // check the data are valid or not.
   if (day < 1 || day > 31 || month > 12 || month < 1) {
-    return new TypeError('Date is not valid.')
+    throw new TypeError('Date is not valid.')
   }
 
   // In case of Jan and Feb:
diff --git a/Conversions/test/DateToDay.test.js b/Conversions/test/DateToDay.test.js
index f0809821db..38b63d33da 100644
--- a/Conversions/test/DateToDay.test.js
+++ b/Conversions/test/DateToDay.test.js
@@ -1,35 +1,28 @@
 import { DateToDay } from '../DateToDay'
 
-test('The date 18/02/2001 is Sunday', () => {
-  const res = DateToDay('18/02/2001')
-  expect(res).toBe('Sunday')
-})
-
-test('The date 18/12/2020 is Friday', () => {
-  const res = DateToDay('18/12/2020')
-  expect(res).toBe('Friday')
-})
+describe('DateToDay', () => {
+  it.each([
+    ['18/02/2001', 'Sunday'],
+    ['18/12/2020', 'Friday'],
+    ['12/12/2012', 'Wednesday'],
+    ['01/01/2001', 'Monday'],
+    ['1/1/2020', 'Wednesday'],
+    ['2/3/2014', 'Sunday'],
+    ['28/2/2017', 'Tuesday'],
+    ['02/03/2024', 'Saturday'],
+    ['29/02/2024', 'Thursday']
+  ])('%s is %s', (date, day) => {
+    expect(DateToDay(date)).toBe(day)
+  })
 
-test('The date 12/12/2012 is Wednesday', () => {
-  const res = DateToDay('12/12/2012')
-  expect(res).toBe('Wednesday')
-})
-test('The date 01/01/2001 is Monday', () => {
-  const res = DateToDay('01/01/2001')
-  expect(res).toBe('Monday')
-})
-
-test('The date 1/1/2020 is Wednesday', () => {
-  const res = DateToDay('1/1/2020')
-  expect(res).toBe('Wednesday')
-})
-
-test('The date 2/3/2014 is Sunday', () => {
-  const res = DateToDay('2/3/2014')
-  expect(res).toBe('Sunday')
-})
+  it('should throw when input is not a string', () => {
+    expect(() => DateToDay(100)).toThrowError()
+  })
 
-test('The date 28/2/2017 is Tuesday', () => {
-  const res = DateToDay('28/2/2017')
-  expect(res).toBe('Tuesday')
+  it.each(['32/01/2000', '00/01/2000', '15/00/2000', '15/13/2000'])(
+    'should throw when input is not a correct date %s',
+    (wrongDate) => {
+      expect(() => DateToDay(wrongDate)).toThrowError()
+    }
+  )
 })

From f13eec1bbb94484912d10a4e5376aacf533b3de6 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Mon, 4 Mar 2024 23:06:50 +0100
Subject: [PATCH 42/73] fix: properly floor the partial results (#1629)

---
 Conversions/DateDayDifference.js          | 37 ++++++++----------
 Conversions/test/DateDayDiffernce.test.js | 47 +++++++++++++++--------
 2 files changed, 48 insertions(+), 36 deletions(-)

diff --git a/Conversions/DateDayDifference.js b/Conversions/DateDayDifference.js
index 770b64c174..e03a5aa24b 100644
--- a/Conversions/DateDayDifference.js
+++ b/Conversions/DateDayDifference.js
@@ -14,21 +14,27 @@ const isLeap = (year) => {
   else return false
 }
 const DateToDay = (dd, mm, yyyy) => {
-  return Math.floor(
+  return (
     365 * (yyyy - 1) +
-      (yyyy - 1) / 4 -
-      (yyyy - 1) / 100 +
-      (yyyy - 1) / 400 +
-      dd +
-      (367 * mm - 362) / 12 +
-      (mm <= 2 ? 0 : isLeap(yyyy) ? -1 : -2)
+    Math.floor((yyyy - 1) / 4) -
+    Math.floor((yyyy - 1) / 100) +
+    Math.floor((yyyy - 1) / 400) +
+    dd +
+    Math.floor((367 * mm - 362) / 12) +
+    (mm <= 2 ? 0 : isLeap(yyyy) ? -1 : -2)
   )
 }
 
+const CheckDayAndMonth = (inDay, inMonth) => {
+  if (inDay <= 0 || inDay > 31 || inMonth <= 0 || inMonth > 12) {
+    throw new TypeError('Date is not valid.')
+  }
+}
+
 const DateDayDifference = (date1, date2) => {
   // firstly, check that both input are string or not.
   if (typeof date1 !== 'string' || typeof date2 !== 'string') {
-    return new TypeError('Argument is not a string.')
+    throw new TypeError('Argument is not a string.')
   }
   // extract the first date
   const [firstDateDay, firstDateMonth, firstDateYear] = date1
@@ -39,18 +45,9 @@ const DateDayDifference = (date1, date2) => {
     .split('/')
     .map((ele) => Number(ele))
   // check the both data are valid or not.
-  if (
-    firstDateDay < 0 ||
-    firstDateDay > 31 ||
-    firstDateMonth > 12 ||
-    firstDateMonth < 0 ||
-    secondDateDay < 0 ||
-    secondDateDay > 31 ||
-    secondDateMonth > 12 ||
-    secondDateMonth < 0
-  ) {
-    return new TypeError('Date is not valid.')
-  }
+  CheckDayAndMonth(firstDateDay, firstDateMonth)
+  CheckDayAndMonth(secondDateDay, secondDateMonth)
+
   return Math.abs(
     DateToDay(secondDateDay, secondDateMonth, secondDateYear) -
       DateToDay(firstDateDay, firstDateMonth, firstDateYear)
diff --git a/Conversions/test/DateDayDiffernce.test.js b/Conversions/test/DateDayDiffernce.test.js
index 713ee1272e..a0f8834593 100644
--- a/Conversions/test/DateDayDiffernce.test.js
+++ b/Conversions/test/DateDayDiffernce.test.js
@@ -1,21 +1,36 @@
 import { DateDayDifference } from '../DateDayDifference'
 
-test('The difference between 17/08/2002 & 10/10/2020 is 6630', () => {
-  const res = DateDayDifference('17/08/2002', '10/10/2020')
-  expect(res).toBe(6630)
-})
-
-test('The difference between 18/02/2001 & 16/03/2022 is 7696', () => {
-  const res = DateDayDifference('18/02/2001', '16/03/2022')
-  expect(res).toBe(7696)
-})
+describe('DateDayDifference', () => {
+  it.each([
+    ['17/08/2002', '10/10/2020', 6629],
+    ['18/02/2001', '16/03/2022', 7696],
+    ['11/11/2011', '12/12/2012', 397],
+    ['01/01/2001', '16/03/2011', 3726],
+    ['04/03/2024', '04/03/2024', 0],
+    ['03/03/2024', '04/03/2024', 1],
+    ['02/03/2024', '04/03/2024', 2],
+    ['01/03/2024', '04/03/2024', 3],
+    ['29/02/2024', '04/03/2024', 4],
+    ['04/03/2024', '04/03/2025', 365],
+    ['04/03/2023', '04/03/2024', 366]
+  ])(
+    'The difference between %s and %s is %i',
+    (firstDate, secondDate, expected) => {
+      expect(DateDayDifference(firstDate, secondDate)).toBe(expected)
+      expect(DateDayDifference(secondDate, firstDate)).toBe(expected)
+    }
+  )
 
-test('The difference between 11/11/2011 & 12/12/2012 is 398', () => {
-  const res = DateDayDifference('11/11/2011', '12/12/2012')
-  expect(res).toBe(398)
-})
+  it('should throw when any input is not a string', () => {
+    expect(() => DateDayDifference(10102024, '11/10/2024')).toThrowError()
+    expect(() => DateDayDifference('11/10/2024', 10102024)).toThrowError()
+  })
 
-test('The difference between 01/01/2001 & 16/03/2011 is 3727', () => {
-  const res = DateDayDifference('01/01/2001', '16/03/2011')
-  expect(res).toBe(3727)
+  it.each(['32/01/2000', '00/01/2000', '15/00/2000', '15/13/2000'])(
+    'should throw when input is not a correct date %s',
+    (wrongDate) => {
+      expect(() => DateDayDifference(wrongDate, '04/03/2024')).toThrowError()
+      expect(() => DateDayDifference('04/03/2024', wrongDate)).toThrowError()
+    }
+  )
 })

From d8cfdcd8002a58d9ec2d1c2880cbe20d5478104d Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Mon, 4 Mar 2024 23:07:16 +0100
Subject: [PATCH 43/73] chore: use `check-style` in (#1630)

---
 .husky/pre-commit | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.husky/pre-commit b/.husky/pre-commit
index 35ea7e3c08..037dbe870a 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,5 +1,5 @@
 #!/bin/sh
 . "$(dirname "$0")/_/husky.sh"
 
-npm run style
+npm run check-style
 npm run test

From 4a4ed57d4285fc61b5385d2c2525369ce2c4e6fb Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Thu, 7 Mar 2024 05:53:43 +0100
Subject: [PATCH 44/73] refactor: use `isLeapYear` (#1638)

---
 Conversions/DateDayDifference.js           | 11 ++-----
 Timing-Functions/GetMonthDays.js           |  9 +++---
 Timing-Functions/test/GetMonthDays.test.js | 37 ++++++++++++++++------
 3 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/Conversions/DateDayDifference.js b/Conversions/DateDayDifference.js
index e03a5aa24b..fef242568d 100644
--- a/Conversions/DateDayDifference.js
+++ b/Conversions/DateDayDifference.js
@@ -6,13 +6,8 @@
     Algorithm & Explanation : https://ncalculators.com/time-date/date-difference-calculator.htm
 */
 
-// Internal method for make calculations easier
-const isLeap = (year) => {
-  if (year % 400 === 0) return true
-  else if (year % 100 === 0) return false
-  else if (year % 4 === 0) return true
-  else return false
-}
+import { isLeapYear } from '../Maths/LeapYear'
+
 const DateToDay = (dd, mm, yyyy) => {
   return (
     365 * (yyyy - 1) +
@@ -21,7 +16,7 @@ const DateToDay = (dd, mm, yyyy) => {
     Math.floor((yyyy - 1) / 400) +
     dd +
     Math.floor((367 * mm - 362) / 12) +
-    (mm <= 2 ? 0 : isLeap(yyyy) ? -1 : -2)
+    (mm <= 2 ? 0 : isLeapYear(yyyy) ? -1 : -2)
   )
 }
 
diff --git a/Timing-Functions/GetMonthDays.js b/Timing-Functions/GetMonthDays.js
index ce188c9603..43c2e7e6e6 100644
--- a/Timing-Functions/GetMonthDays.js
+++ b/Timing-Functions/GetMonthDays.js
@@ -6,6 +6,8 @@
   e.g.: mahfoudh.arous.com ->false
 */
 
+import { isLeapYear } from '../Maths/LeapYear'
+
 const getMonthDays = (monthNumber, year) => {
   const the31DaysMonths = [1, 3, 5, 7, 8, 10, 12]
   const the30DaysMonths = [4, 6, 9, 11]
@@ -26,11 +28,8 @@ const getMonthDays = (monthNumber, year) => {
     return 30
   }
 
-  // Check for Leap year
-  if (year % 4 === 0) {
-    if (year % 100 !== 0 || (year % 100 === 0 && year % 400 === 0)) {
-      return 29
-    }
+  if (isLeapYear(year)) {
+    return 29
   }
 
   return 28
diff --git a/Timing-Functions/test/GetMonthDays.test.js b/Timing-Functions/test/GetMonthDays.test.js
index b7527c0ac6..1222cc4ae0 100644
--- a/Timing-Functions/test/GetMonthDays.test.js
+++ b/Timing-Functions/test/GetMonthDays.test.js
@@ -1,16 +1,33 @@
 import { getMonthDays } from '../GetMonthDays'
 
 describe('Get the Days of a Month', () => {
-  it('expects to return 28', () => {
-    expect(getMonthDays(2, 2018)).toEqual(28)
-  })
-
-  it('expects to return 30', () => {
-    expect(getMonthDays(6, 254)).toEqual(30)
-  })
-
-  it('expects to return 29', () => {
-    expect(getMonthDays(2, 2024)).toEqual(29)
+  it.each([
+    [1, 2024, 31],
+    [2, 2024, 29],
+    [3, 2024, 31],
+    [4, 2024, 30],
+    [5, 2024, 31],
+    [6, 2024, 30],
+    [7, 2024, 31],
+    [8, 2024, 31],
+    [9, 2024, 30],
+    [10, 2024, 31],
+    [11, 2024, 30],
+    [12, 2024, 31],
+    [1, 2023, 31],
+    [2, 2023, 28],
+    [3, 2023, 31],
+    [4, 2023, 30],
+    [5, 2023, 31],
+    [6, 2023, 30],
+    [7, 2023, 31],
+    [8, 2023, 31],
+    [9, 2023, 30],
+    [10, 2023, 31],
+    [11, 2023, 30],
+    [12, 2023, 31]
+  ])('Month %i in year %i has %i days', (month, year, expected) => {
+    expect(getMonthDays(month, year)).toBe(expected)
   })
 
   it('expects to throw a type error', () => {

From 02041984653585c09ced6f8c2a9a1d983b26797a Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Mon, 11 Mar 2024 21:26:29 +0100
Subject: [PATCH 45/73] feat: remove `twinPrime` (#1641)

* tests: add missing test of `twinPrime`

* feat: remove `twinPrime`
---
 Maths/TwinPrime.js           | 29 -----------------------------
 Maths/test/TwinPrime.test.js | 10 ----------
 2 files changed, 39 deletions(-)
 delete mode 100644 Maths/TwinPrime.js
 delete mode 100644 Maths/test/TwinPrime.test.js

diff --git a/Maths/TwinPrime.js b/Maths/TwinPrime.js
deleted file mode 100644
index 0bb17e0ebe..0000000000
--- a/Maths/TwinPrime.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import { PrimeCheck } from './PrimeCheck'
-
-/**
- * @function twinPrime
- * Gets the 'twin prime' of a prime number.
- *
- * @param {Integer} n The number to find the twin prime of.
- * @returns {Integer} Either the twin, or -1 if n or n + 2 is not prime.
- *
- * @see https://en.wikipedia.org/wiki/Twin_prime
- *
- * @example twinPrime(5) = 7
- * @example twinPrime(4) = -1
- */
-function twinPrime(n) {
-  const prime = PrimeCheck(n)
-
-  if (!prime) {
-    return -1
-  }
-
-  if (!PrimeCheck(n + 2)) {
-    return -1
-  }
-
-  return n + 2
-}
-
-export { twinPrime }
diff --git a/Maths/test/TwinPrime.test.js b/Maths/test/TwinPrime.test.js
deleted file mode 100644
index c3e057e10e..0000000000
--- a/Maths/test/TwinPrime.test.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { twinPrime } from '../TwinPrime.js'
-
-describe('Twin Primes', () => {
-  it('Should be valid twin primes', () => {
-    expect(twinPrime(3)).toBe(5)
-    expect(twinPrime(5)).toBe(7)
-    expect(twinPrime(4)).toBe(-1)
-    expect(twinPrime(17)).toBe(19)
-  })
-})

From bd34e9fa61627853dd226d5695be57e3544a061c Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sat, 16 Mar 2024 04:59:14 +0100
Subject: [PATCH 46/73] feat: remove duplicated `gcd`-like functions (#1642)

* feat: remove duplicated `gcd`-like functions

* Updated Documentation in README.md

---------

Co-authored-by: vil02 <vil02@users.noreply.github.com>
---
 DIRECTORY.md                    |  2 --
 Maths/GetEuclidGCD.js           | 26 +++++++++++++++++---
 Maths/test/GetEuclidGCD.test.js | 43 ++++++++++++++++++---------------
 Recursive/EucledianGCD.js       | 30 -----------------------
 4 files changed, 46 insertions(+), 55 deletions(-)
 delete mode 100644 Recursive/EucledianGCD.js

diff --git a/DIRECTORY.md b/DIRECTORY.md
index 8b51ce3bf7..59f6273bf2 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -260,7 +260,6 @@
   * [SquareRootLogarithmic](Maths/SquareRootLogarithmic.js)
   * [SumOfDigits](Maths/SumOfDigits.js)
   * [SumOfGeometricProgression](Maths/SumOfGeometricProgression.js)
-  * [TwinPrime](Maths/TwinPrime.js)
   * [TwoSum](Maths/TwoSum.js)
   * [Volume](Maths/Volume.js)
   * [WhileLoopFactorial](Maths/WhileLoopFactorial.js)
@@ -296,7 +295,6 @@
 * **Recursive**
   * [BinaryEquivalent](Recursive/BinaryEquivalent.js)
   * [BinarySearch](Recursive/BinarySearch.js)
-  * [EucledianGCD](Recursive/EucledianGCD.js)
   * [Factorial](Recursive/Factorial.js)
   * [FibonacciNumberRecursive](Recursive/FibonacciNumberRecursive.js)
   * [FloodFill](Recursive/FloodFill.js)
diff --git a/Maths/GetEuclidGCD.js b/Maths/GetEuclidGCD.js
index 31eeab42ec..42a30a6042 100644
--- a/Maths/GetEuclidGCD.js
+++ b/Maths/GetEuclidGCD.js
@@ -1,3 +1,9 @@
+function CheckInput(a, b) {
+  if (typeof a !== 'number' || typeof b !== 'number') {
+    throw new TypeError('Arguments must be numbers')
+  }
+}
+
 /**
  * GetEuclidGCD Euclidean algorithm to determine the GCD of two numbers
  * @param {Number} a integer (may be negative)
@@ -5,9 +11,7 @@
  * @returns {Number} Greatest Common Divisor gcd(a, b)
  */
 export function GetEuclidGCD(a, b) {
-  if (typeof a !== 'number' || typeof b !== 'number') {
-    throw new TypeError('Arguments must be numbers')
-  }
+  CheckInput(a, b)
   a = Math.abs(a)
   b = Math.abs(b)
   while (b !== 0) {
@@ -17,3 +21,19 @@ export function GetEuclidGCD(a, b) {
   }
   return a
 }
+
+/**
+ * Recursive version of GetEuclidGCD
+ * @param {Number} a integer (may be negative)
+ * @param {Number} b integer (may be negative)
+ * @returns {Number} Greatest Common Divisor gcd(a, b)
+ */
+export function GetEuclidGCDRecursive(a, b) {
+  CheckInput(a, b)
+  a = Math.abs(a)
+  b = Math.abs(b)
+  if (b == 0) {
+    return a
+  }
+  return GetEuclidGCDRecursive(b, a % b)
+}
diff --git a/Maths/test/GetEuclidGCD.test.js b/Maths/test/GetEuclidGCD.test.js
index a6c7cb22e6..070a8479e3 100644
--- a/Maths/test/GetEuclidGCD.test.js
+++ b/Maths/test/GetEuclidGCD.test.js
@@ -1,22 +1,25 @@
-import { GetEuclidGCD } from '../GetEuclidGCD'
+import { GetEuclidGCD, GetEuclidGCDRecursive } from '../GetEuclidGCD'
 
-describe('GetEuclidGCD', () => {
-  it.each([
-    [5, 20, 5],
-    [109, 902, 1],
-    [290, 780, 10],
-    [104, 156, 52],
-    [0, 100, 100],
-    [-5, 50, 5],
-    [0, 0, 0],
-    [1, 1234567, 1]
-  ])('returns correct result for %i and %j', (inputA, inputB, expected) => {
-    expect(GetEuclidGCD(inputA, inputB)).toBe(expected)
-    expect(GetEuclidGCD(inputB, inputA)).toBe(expected)
-  })
+describe.each([GetEuclidGCD, GetEuclidGCDRecursive])(
+  '%# GetEuclidGCD',
+  (gcdFunction) => {
+    it.each([
+      [5, 20, 5],
+      [109, 902, 1],
+      [290, 780, 10],
+      [104, 156, 52],
+      [0, 100, 100],
+      [-5, 50, 5],
+      [0, 0, 0],
+      [1, 1234567, 1]
+    ])('returns correct result for %i and %j', (inputA, inputB, expected) => {
+      expect(gcdFunction(inputA, inputB)).toBe(expected)
+      expect(gcdFunction(inputB, inputA)).toBe(expected)
+    })
 
-  it('should throw when any of the inputs is not a number', () => {
-    expect(() => GetEuclidGCD('1', 2)).toThrowError()
-    expect(() => GetEuclidGCD(1, '2')).toThrowError()
-  })
-})
+    it('should throw when any of the inputs is not a number', () => {
+      expect(() => gcdFunction('1', 2)).toThrowError()
+      expect(() => gcdFunction(1, '2')).toThrowError()
+    })
+  }
+)
diff --git a/Recursive/EucledianGCD.js b/Recursive/EucledianGCD.js
deleted file mode 100644
index e0cc15ed56..0000000000
--- a/Recursive/EucledianGCD.js
+++ /dev/null
@@ -1,30 +0,0 @@
-function euclideanGCDRecursive(first, second) {
-  /*
-    Calculates GCD of two numbers using Euclidean Recursive Algorithm
-    :param first: First number
-    :param second: Second number
-    :return: GCD of the numbers
-    */
-  if (second === 0) {
-    return first
-  } else {
-    return euclideanGCDRecursive(second, first % second)
-  }
-}
-
-function euclideanGCDIterative(first, second) {
-  /*
-    Calculates GCD of two numbers using Euclidean Iterative Algorithm
-    :param first: First number
-    :param second: Second number
-    :return: GCD of the numbers
-    */
-  while (second !== 0) {
-    const temp = second
-    second = first % second
-    first = temp
-  }
-  return first
-}
-
-export { euclideanGCDIterative, euclideanGCDRecursive }

From 702840b4c8b6582e6ee8ef0521b49b4b2db04225 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Thu, 28 Mar 2024 12:12:40 +0100
Subject: [PATCH 47/73] style: improve test names of `GetEuclidGCD'` (#1646)

---
 Maths/test/GetEuclidGCD.test.js | 41 +++++++++++++++------------------
 1 file changed, 19 insertions(+), 22 deletions(-)

diff --git a/Maths/test/GetEuclidGCD.test.js b/Maths/test/GetEuclidGCD.test.js
index 070a8479e3..92f888acea 100644
--- a/Maths/test/GetEuclidGCD.test.js
+++ b/Maths/test/GetEuclidGCD.test.js
@@ -1,25 +1,22 @@
 import { GetEuclidGCD, GetEuclidGCDRecursive } from '../GetEuclidGCD'
 
-describe.each([GetEuclidGCD, GetEuclidGCDRecursive])(
-  '%# GetEuclidGCD',
-  (gcdFunction) => {
-    it.each([
-      [5, 20, 5],
-      [109, 902, 1],
-      [290, 780, 10],
-      [104, 156, 52],
-      [0, 100, 100],
-      [-5, 50, 5],
-      [0, 0, 0],
-      [1, 1234567, 1]
-    ])('returns correct result for %i and %j', (inputA, inputB, expected) => {
-      expect(gcdFunction(inputA, inputB)).toBe(expected)
-      expect(gcdFunction(inputB, inputA)).toBe(expected)
-    })
+describe.each([GetEuclidGCD, GetEuclidGCDRecursive])('%o', (gcdFunction) => {
+  it.each([
+    [5, 20, 5],
+    [109, 902, 1],
+    [290, 780, 10],
+    [104, 156, 52],
+    [0, 100, 100],
+    [-5, 50, 5],
+    [0, 0, 0],
+    [1, 1234567, 1]
+  ])('returns correct result for %i and %j', (inputA, inputB, expected) => {
+    expect(gcdFunction(inputA, inputB)).toBe(expected)
+    expect(gcdFunction(inputB, inputA)).toBe(expected)
+  })
 
-    it('should throw when any of the inputs is not a number', () => {
-      expect(() => gcdFunction('1', 2)).toThrowError()
-      expect(() => gcdFunction(1, '2')).toThrowError()
-    })
-  }
-)
+  it('should throw when any of the inputs is not a number', () => {
+    expect(() => gcdFunction('1', 2)).toThrowError()
+    expect(() => gcdFunction(1, '2')).toThrowError()
+  })
+})

From 34a663aca7c93aa3de3bd190e0f6cc467be75aa6 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Wed, 3 Apr 2024 17:18:45 +0200
Subject: [PATCH 48/73] fix: hadnle zeros at the endpoints in `BisectionMethod`
 (#1640)

* fix: hadnle zeros at the endpoints

* style: use simpler syntax express polynomials

Co-authored-by: appgurueu <34514239+appgurueu@users.noreply.github.com>

---------

Co-authored-by: appgurueu <34514239+appgurueu@users.noreply.github.com>
---
 Maths/BisectionMethod.js           |  9 ++++-----
 Maths/test/BisectionMethod.test.js | 18 ++++++++++--------
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/Maths/BisectionMethod.js b/Maths/BisectionMethod.js
index 49b8c8ecc0..4539e6d466 100644
--- a/Maths/BisectionMethod.js
+++ b/Maths/BisectionMethod.js
@@ -23,7 +23,7 @@ const findRoot = (a, b, func, numberOfIterations) => {
 
   // Bolzano theorem
   const hasRoot = (a, b, func) => {
-    return func(a) * func(b) < 0
+    return func(a) * func(b) <= 0
   }
   if (hasRoot(a, b, func) === false) {
     throw Error(
@@ -45,10 +45,9 @@ const findRoot = (a, b, func, numberOfIterations) => {
   const prod2 = fm * func(b)
 
   // Depending on the sign of the products above, decide which position will m fill (a's or b's)
-  if (prod1 > 0 && prod2 < 0) return findRoot(m, b, func, --numberOfIterations)
-  else if (prod1 < 0 && prod2 > 0)
-    return findRoot(a, m, func, --numberOfIterations)
-  else throw Error('Unexpected behavior')
+  if (prod2 <= 0) return findRoot(m, b, func, --numberOfIterations)
+
+  return findRoot(a, m, func, --numberOfIterations)
 }
 
 export { findRoot }
diff --git a/Maths/test/BisectionMethod.test.js b/Maths/test/BisectionMethod.test.js
index ad865b6ad6..4a49e8f6a4 100644
--- a/Maths/test/BisectionMethod.test.js
+++ b/Maths/test/BisectionMethod.test.js
@@ -1,14 +1,7 @@
 import { findRoot } from '../BisectionMethod'
 
 test('Equation f(x) = x^2 - 3*x + 2 = 0, has root x = 1 in [a, b] = [0, 1.5]', () => {
-  const root = findRoot(
-    0,
-    1.5,
-    (x) => {
-      return Math.pow(x, 2) - 3 * x + 2
-    },
-    8
-  )
+  const root = findRoot(0, 1.5, (x) => x ** 2 - 3 * x + 2, 8)
   expect(root).toBe(0.9990234375)
 })
 
@@ -35,3 +28,12 @@ test('Equation f(x) = sqrt(x) + e^(2*x) - 8*x = 0, has root x = 0.93945851 in [a
   )
   expect(Number(Number(root).toPrecision(8))).toBe(0.93945851)
 })
+
+test('Equation f(x) = x^3 = 0, has root x = 0.0 in [a, b] = [-1.0, 1.0]', () => {
+  const root = findRoot(-1.0, 1.0, (x) => x ** 3, 32)
+  expect(root).toBeCloseTo(0.0, 5)
+})
+
+test('Throws an error when function does not change sign', () => {
+  expect(() => findRoot(-1.0, 1.0, (x) => x ** 2, 10)).toThrowError()
+})

From 9c622dd0894693adedf18e79310185dd3ff80ecb Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Wed, 3 Apr 2024 17:19:26 +0200
Subject: [PATCH 49/73] refactor: add and use `parseDate` (#1643)

* refactor: add and use `parseDate`

* style: use proper spelling

Co-authored-by: appgurueu <34514239+appgurueu@users.noreply.github.com>

---------

Co-authored-by: appgurueu <34514239+appgurueu@users.noreply.github.com>
---
 Conversions/DateDayDifference.js        | 28 ++++-------------
 Conversions/DateToDay.js                | 15 ++++------
 Timing-Functions/ParseDate.js           | 27 +++++++++++++++++
 Timing-Functions/test/ParseDate.test.js | 40 +++++++++++++++++++++++++
 4 files changed, 78 insertions(+), 32 deletions(-)
 create mode 100644 Timing-Functions/ParseDate.js
 create mode 100644 Timing-Functions/test/ParseDate.test.js

diff --git a/Conversions/DateDayDifference.js b/Conversions/DateDayDifference.js
index fef242568d..726a634253 100644
--- a/Conversions/DateDayDifference.js
+++ b/Conversions/DateDayDifference.js
@@ -7,6 +7,7 @@
 */
 
 import { isLeapYear } from '../Maths/LeapYear'
+import { parseDate } from '../Timing-Functions/ParseDate'
 
 const DateToDay = (dd, mm, yyyy) => {
   return (
@@ -20,32 +21,13 @@ const DateToDay = (dd, mm, yyyy) => {
   )
 }
 
-const CheckDayAndMonth = (inDay, inMonth) => {
-  if (inDay <= 0 || inDay > 31 || inMonth <= 0 || inMonth > 12) {
-    throw new TypeError('Date is not valid.')
-  }
-}
-
 const DateDayDifference = (date1, date2) => {
-  // firstly, check that both input are string or not.
-  if (typeof date1 !== 'string' || typeof date2 !== 'string') {
-    throw new TypeError('Argument is not a string.')
-  }
-  // extract the first date
-  const [firstDateDay, firstDateMonth, firstDateYear] = date1
-    .split('/')
-    .map((ele) => Number(ele))
-  // extract the second date
-  const [secondDateDay, secondDateMonth, secondDateYear] = date2
-    .split('/')
-    .map((ele) => Number(ele))
-  // check the both data are valid or not.
-  CheckDayAndMonth(firstDateDay, firstDateMonth)
-  CheckDayAndMonth(secondDateDay, secondDateMonth)
+  const firstDate = parseDate(date1)
+  const secondDate = parseDate(date2)
 
   return Math.abs(
-    DateToDay(secondDateDay, secondDateMonth, secondDateYear) -
-      DateToDay(firstDateDay, firstDateMonth, firstDateYear)
+    DateToDay(secondDate.day, secondDate.month, secondDate.year) -
+      DateToDay(firstDate.day, firstDate.month, firstDate.year)
   )
 }
 
diff --git a/Conversions/DateToDay.js b/Conversions/DateToDay.js
index f360c9c737..96ec01e82d 100644
--- a/Conversions/DateToDay.js
+++ b/Conversions/DateToDay.js
@@ -12,6 +12,8 @@
     Algorithm & Explanation : https://en.wikipedia.org/wiki/Zeller%27s_congruence
 */
 
+import { parseDate } from '../Timing-Functions/ParseDate'
+
 // Array holding name of the day: Saturday - Sunday - Friday => 0 - 1 - 6
 const daysNameArr = [
   'Saturday',
@@ -25,15 +27,10 @@ const daysNameArr = [
 
 const DateToDay = (date) => {
   // firstly, check that input is a string or not.
-  if (typeof date !== 'string') {
-    throw new TypeError('Argument is not a string.')
-  }
-  // extract the date
-  let [day, month, year] = date.split('/').map((x) => Number(x))
-  // check the data are valid or not.
-  if (day < 1 || day > 31 || month > 12 || month < 1) {
-    throw new TypeError('Date is not valid.')
-  }
+  const dateStruct = parseDate(date)
+  let year = dateStruct.year
+  let month = dateStruct.month
+  let day = dateStruct.day
 
   // In case of Jan and Feb:
   // Year: we consider it as previous year
diff --git a/Timing-Functions/ParseDate.js b/Timing-Functions/ParseDate.js
new file mode 100644
index 0000000000..67f4e4cd0e
--- /dev/null
+++ b/Timing-Functions/ParseDate.js
@@ -0,0 +1,27 @@
+import { getMonthDays } from './GetMonthDays'
+
+function checkDate(date) {
+  if (date.day < 1 || date.day > getMonthDays(date.month, date.year)) {
+    throw new Error('Invalid day value.')
+  }
+}
+
+function parseDate(dateString) {
+  const regex = /^(\d{1,2})\/(\d{1,2})\/(\d{4})$/
+
+  const match = dateString.match(regex)
+
+  if (!match) {
+    throw new Error("Invalid date format. Please use 'dd/mm/yyyy'.")
+  }
+
+  const res = {
+    day: parseInt(match[1], 10),
+    month: parseInt(match[2], 10),
+    year: parseInt(match[3], 10)
+  }
+  checkDate(res)
+  return res
+}
+
+export { parseDate }
diff --git a/Timing-Functions/test/ParseDate.test.js b/Timing-Functions/test/ParseDate.test.js
new file mode 100644
index 0000000000..3b807bb8a5
--- /dev/null
+++ b/Timing-Functions/test/ParseDate.test.js
@@ -0,0 +1,40 @@
+import { parseDate } from '../ParseDate'
+
+describe('parseDate', () => {
+  it.each([
+    ['18/03/2024', { year: 2024, month: 3, day: 18 }],
+    ['29/02/2024', { year: 2024, month: 2, day: 29 }],
+    ['28/02/2023', { year: 2023, month: 2, day: 28 }],
+    ['01/12/2024', { year: 2024, month: 12, day: 1 }],
+    ['1/12/2024', { year: 2024, month: 12, day: 1 }],
+    ['10/1/2024', { year: 2024, month: 1, day: 10 }]
+  ])('Returns correct output for %s', (dateString, expected) => {
+    expect(parseDate(dateString)).toStrictEqual(expected)
+  })
+
+  it.each([
+    '18-03-2024',
+    '18.03.2024',
+    '03/2024',
+    '01/02/03/2024',
+    '123/03/2024'
+  ])('Throws for %s', (wrongDateString) => {
+    expect(() => {
+      parseDate(wrongDateString)
+    }).toThrow()
+  })
+
+  it.each([
+    '40/03/2024',
+    '30/02/2024',
+    '29/02/2023',
+    '31/04/2023',
+    '00/01/2024',
+    '01/00/2024',
+    '01/13/2024'
+  ])('Throws for %s', (wrongDateString) => {
+    expect(() => {
+      parseDate(wrongDateString)
+    }).toThrow()
+  })
+})

From d02e402972c643093701a05138dccb0ce0957754 Mon Sep 17 00:00:00 2001
From: SourabhHere <sourabhkatoch13@gmail.com>
Date: Wed, 3 Apr 2024 20:50:00 +0530
Subject: [PATCH 50/73] removed code already present in test cases related to
 DFT in Trees folder (#1648)

---
 Trees/DepthFirstSearch.js | 26 --------------------------
 1 file changed, 26 deletions(-)

diff --git a/Trees/DepthFirstSearch.js b/Trees/DepthFirstSearch.js
index 7c67afc95e..f4ce2cfed5 100644
--- a/Trees/DepthFirstSearch.js
+++ b/Trees/DepthFirstSearch.js
@@ -44,30 +44,4 @@ function searchDFS(tree, value) {
   return null
 }
 
-const tree = [
-  { value: 6, left: 1, right: 2 },
-  { value: 5, left: 3, right: 4 },
-  { value: 7, left: null, right: 5 },
-  { value: 3, left: 6, right: null },
-  { value: 4, left: null, right: null },
-  { value: 9, left: 7, right: 8 },
-  { value: 2, left: 9, right: null },
-  { value: 8, left: null, right: null },
-  { value: 10, left: null, right: null },
-  { value: 1, left: null, right: null }
-]
-searchDFS(tree, 9) // { value: 9, left: 7, right: 8 }
-searchDFS(tree, 200) // null
-traverseDFS(tree, 6) // [ 1, 2, 3, 4, 5, 8, 10, 9, 7, 6 ]
-traverseDFS(tree, 200) // []
-
-//            6
-//           / \
-//          5   7
-//         / \   \
-//        3   4   9
-//       /       / \
-//      2       8   10
-//     /
-//    1
 export { searchDFS, traverseDFS }

From d920e7f4276f982fcad8016a9c63435cd346e6bd Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Wed, 3 Apr 2024 17:24:06 +0200
Subject: [PATCH 51/73] refactor: reduce code duplication in `FloodFill`
 (#1645)

* tests: add tests checking if floodFill funtions throw when location is outside

* refactor: reduce code duplication by adding `checkLocation` to `FloodFill`

* refactor: add and use `isInside`

Co-authored-by: appgurueu <34514239+appgurueu@users.noreply.github.com>

* Deduplicate further

---------

Co-authored-by: appgurueu <34514239+appgurueu@users.noreply.github.com>
---
 Recursive/FloodFill.js           | 59 +++++++++++++++-----------------
 Recursive/test/FloodFill.test.js | 13 +++++++
 2 files changed, 41 insertions(+), 31 deletions(-)

diff --git a/Recursive/FloodFill.js b/Recursive/FloodFill.js
index 33ea6025ad..5143b8f4ff 100644
--- a/Recursive/FloodFill.js
+++ b/Recursive/FloodFill.js
@@ -9,7 +9,7 @@
  * @see https://www.techiedelight.com/flood-fill-algorithm/
  */
 
-const neighbors = [
+const neighborOffsets = [
   [-1, -1],
   [-1, 0],
   [-1, 1],
@@ -20,6 +20,27 @@ const neighbors = [
   [1, 1]
 ]
 
+function isInside(rgbData, location) {
+  const x = location[0]
+  const y = location[1]
+  return x >= 0 && x < rgbData.length && y >= 0 && y < rgbData[0].length
+}
+
+function checkLocation(rgbData, location) {
+  if (!isInside(rgbData, location)) {
+    throw new Error('location should point to a pixel within the rgbData')
+  }
+}
+
+function* neighbors(rgbData, location) {
+  for (const offset of neighborOffsets) {
+    const neighborLocation = [location[0] + offset[0], location[1] + offset[1]]
+    if (isInside(rgbData, neighborLocation)) {
+      yield neighborLocation
+    }
+  }
+}
+
 /**
  * Implements the flood fill algorithm through a breadth-first approach using a queue.
  *
@@ -34,14 +55,7 @@ export function breadthFirstSearch(
   targetColor,
   replacementColor
 ) {
-  if (
-    location[0] < 0 ||
-    location[0] >= rgbData.length ||
-    location[1] < 0 ||
-    location[1] >= rgbData[0].length
-  ) {
-    throw new Error('location should point to a pixel within the rgbData')
-  }
+  checkLocation(rgbData, location)
 
   const queue = []
   queue.push(location)
@@ -65,14 +79,7 @@ export function depthFirstSearch(
   targetColor,
   replacementColor
 ) {
-  if (
-    location[0] < 0 ||
-    location[0] >= rgbData.length ||
-    location[1] < 0 ||
-    location[1] >= rgbData[0].length
-  ) {
-    throw new Error('location should point to a pixel within the rgbData')
-  }
+  checkLocation(rgbData, location)
 
   depthFirstFill(rgbData, location, targetColor, replacementColor)
 }
@@ -98,13 +105,8 @@ function breadthFirstFill(
 
   if (rgbData[currentLocation[0]][currentLocation[1]] === targetColor) {
     rgbData[currentLocation[0]][currentLocation[1]] = replacementColor
-
-    for (let i = 0; i < neighbors.length; i++) {
-      const x = currentLocation[0] + neighbors[i][0]
-      const y = currentLocation[1] + neighbors[i][1]
-      if (x >= 0 && x < rgbData.length && y >= 0 && y < rgbData[0].length) {
-        queue.push([x, y])
-      }
+    for (const neighborLocation of neighbors(rgbData, currentLocation)) {
+      queue.push(neighborLocation)
     }
   }
 }
@@ -120,13 +122,8 @@ function breadthFirstFill(
 function depthFirstFill(rgbData, location, targetColor, replacementColor) {
   if (rgbData[location[0]][location[1]] === targetColor) {
     rgbData[location[0]][location[1]] = replacementColor
-
-    for (let i = 0; i < neighbors.length; i++) {
-      const x = location[0] + neighbors[i][0]
-      const y = location[1] + neighbors[i][1]
-      if (x >= 0 && x < rgbData.length && y >= 0 && y < rgbData[0].length) {
-        depthFirstFill(rgbData, [x, y], targetColor, replacementColor)
-      }
+    for (const neighborLocation of neighbors(rgbData, location)) {
+      depthFirstFill(rgbData, neighborLocation, targetColor, replacementColor)
     }
   }
 }
diff --git a/Recursive/test/FloodFill.test.js b/Recursive/test/FloodFill.test.js
index 291788addd..618692dd97 100644
--- a/Recursive/test/FloodFill.test.js
+++ b/Recursive/test/FloodFill.test.js
@@ -21,6 +21,19 @@ describe('FloodFill', () => {
   })
 })
 
+describe.each([breadthFirstSearch, depthFirstSearch])('%o', (floodFillFun) => {
+  it.each([
+    [1, -1],
+    [-1, 1],
+    [0, 7],
+    [7, 0]
+  ])('throws for start position [%i, %i]', (location) => {
+    expect(() =>
+      floodFillFun(generateTestRgbData(), location, green, orange)
+    ).toThrowError()
+  })
+})
+
 /**
  * Utility-function to test the function "breadthFirstSearch".
  *

From 314144fae69100c9cf03845434c801f72e4d7714 Mon Sep 17 00:00:00 2001
From: Martin Beacham <martinlutherbeacham@gmail.com>
Date: Wed, 3 Apr 2024 11:25:30 -0400
Subject: [PATCH 52/73] Update CircularQueue.js for zero-length case (#1655)

* Update CircularQueue.js

* Update CircularQueue.js

Taking comments into account for refactoring my change.

* Update CircularQueue.js

Adding "this" to checkEmpty()
---
 Data-Structures/Queue/CircularQueue.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Data-Structures/Queue/CircularQueue.js b/Data-Structures/Queue/CircularQueue.js
index 27f2196780..c716251668 100644
--- a/Data-Structures/Queue/CircularQueue.js
+++ b/Data-Structures/Queue/CircularQueue.js
@@ -77,7 +77,7 @@ class CircularQueue {
 
   // Displays the length of queue
   length() {
-    return this.queue.length - 1
+    return this.checkEmpty() ? 0 : this.queue.length - 1
   }
 
   // Display the top most value of queue

From 6fe21d21e92d4f07b476d56fbcad838633e74550 Mon Sep 17 00:00:00 2001
From: Hasan Al-Kaf <hakalkaf482@gmail.com>
Date: Sat, 13 Apr 2024 20:51:54 +0300
Subject: [PATCH 53/73] chore: convert functions to an ES2015 classes (#1656)

* chore: convert functions to an ES2015 classes

* remove unnecessary functions
---
 Conversions/RailwayTimeConversion.js          |   4 +-
 Data-Structures/Array/Reverse.js              |   8 +-
 Data-Structures/Stack/Stack.js                |  18 +-
 Data-Structures/Tree/AVLTree.js               | 329 +++++++++---------
 Data-Structures/Tree/BinarySearchTree.js      | 184 +++++-----
 Data-Structures/Tree/Trie.js                  | 215 ++++++------
 .../NumberOfSubsetEqualToGivenSum.js          |   2 +-
 Project-Euler/Problem004.js                   |   2 +-
 8 files changed, 384 insertions(+), 378 deletions(-)

diff --git a/Conversions/RailwayTimeConversion.js b/Conversions/RailwayTimeConversion.js
index 15f837b0da..b499023223 100644
--- a/Conversions/RailwayTimeConversion.js
+++ b/Conversions/RailwayTimeConversion.js
@@ -24,8 +24,8 @@ const RailwayTimeConversion = (timeString) => {
   const [hour, minute, secondWithShift] = timeString.split(':')
   // split second and shift value.
   const [second, shift] = [
-    secondWithShift.substr(0, 2),
-    secondWithShift.substr(2)
+    secondWithShift.substring(0, 2),
+    secondWithShift.substring(2)
   ]
   // convert shifted time to not-shift time(Railway time) by using the above explanation.
   if (shift === 'PM') {
diff --git a/Data-Structures/Array/Reverse.js b/Data-Structures/Array/Reverse.js
index 79a789c017..ca08f35f8a 100644
--- a/Data-Structures/Array/Reverse.js
+++ b/Data-Structures/Array/Reverse.js
@@ -7,11 +7,9 @@
 
 const Reverse = (arr) => {
   // limit specifies the amount of Reverse actions
-  for (let i = 0, j = arr.length - 1; i < arr.length / 2; i++, j--) {
-    const temp = arr[i]
-    arr[i] = arr[j]
-    arr[j] = temp
-  }
+  for (let i = 0, j = arr.length - 1; i < arr.length / 2; i++, j--)
+    [arr[i], arr[j]] = [arr[j], arr[i]]
+
   return arr
 }
 export { Reverse }
diff --git a/Data-Structures/Stack/Stack.js b/Data-Structures/Stack/Stack.js
index d3001e8020..d8531fdebf 100644
--- a/Data-Structures/Stack/Stack.js
+++ b/Data-Structures/Stack/Stack.js
@@ -8,8 +8,8 @@
 // Functions: push, pop, peek, view, length
 
 // Creates a stack constructor
-const Stack = (function () {
-  function Stack() {
+class Stack {
+  constructor() {
     // The top of the Stack
     this.top = 0
     // The array representation of the stack
@@ -17,13 +17,13 @@ const Stack = (function () {
   }
 
   // Adds a value onto the end of the stack
-  Stack.prototype.push = function (value) {
+  push(value) {
     this.stack[this.top] = value
     this.top++
   }
 
   // Removes and returns the value at the end of the stack
-  Stack.prototype.pop = function () {
+  pop() {
     if (this.top === 0) {
       return 'Stack is Empty'
     }
@@ -35,23 +35,21 @@ const Stack = (function () {
   }
 
   // Returns the size of the stack
-  Stack.prototype.size = function () {
+  size() {
     return this.top
   }
 
   // Returns the value at the end of the stack
-  Stack.prototype.peek = function () {
+  peek() {
     return this.stack[this.top - 1]
   }
 
   // To see all the elements in the stack
-  Stack.prototype.view = function (output = (value) => console.log(value)) {
+  view(output = (value) => console.log(value)) {
     for (let i = 0; i < this.top; i++) {
       output(this.stack[i])
     }
   }
-
-  return Stack
-})()
+}
 
 export { Stack }
diff --git a/Data-Structures/Tree/AVLTree.js b/Data-Structures/Tree/AVLTree.js
index e5abbf3e55..dd673a9330 100644
--- a/Data-Structures/Tree/AVLTree.js
+++ b/Data-Structures/Tree/AVLTree.js
@@ -31,8 +31,8 @@ let utils
  * @argument comp - A function used by AVL Tree For Comparison
  * If no argument is sent it uses utils.comparator
  */
-const AVLTree = (function () {
-  function _avl(comp) {
+class AVLTree {
+  constructor(comp) {
     /** @public comparator function */
     this._comp = undefined
     this._comp = comp !== undefined ? comp : utils.comparator()
@@ -43,162 +43,6 @@ const AVLTree = (function () {
     this.size = 0
   }
 
-  // creates new Node Object
-  const Node = function (val) {
-    this._val = val
-    this._left = null
-    this._right = null
-    this._height = 1
-  }
-
-  // get height of a node
-  const getHeight = function (node) {
-    if (node == null) {
-      return 0
-    }
-    return node._height
-  }
-
-  // height difference or balance factor of a node
-  const getHeightDifference = function (node) {
-    return node == null ? 0 : getHeight(node._left) - getHeight(node._right)
-  }
-
-  // update height of a node based on children's heights
-  const updateHeight = function (node) {
-    if (node == null) {
-      return
-    }
-    node._height = Math.max(getHeight(node._left), getHeight(node._right)) + 1
-  }
-
-  // Helper: To check if the balanceFactor is valid
-  const isValidBalanceFactor = (balanceFactor) =>
-    [0, 1, -1].includes(balanceFactor)
-
-  // rotations of AVL Tree
-  const leftRotate = function (node) {
-    const temp = node._right
-    node._right = temp._left
-    temp._left = node
-    updateHeight(node)
-    updateHeight(temp)
-    return temp
-  }
-  const rightRotate = function (node) {
-    const temp = node._left
-    node._left = temp._right
-    temp._right = node
-    updateHeight(node)
-    updateHeight(temp)
-    return temp
-  }
-
-  // check if tree is balanced else balance it for insertion
-  const insertBalance = function (node, _val, balanceFactor, tree) {
-    if (balanceFactor > 1 && tree._comp(_val, node._left._val) < 0) {
-      return rightRotate(node) // Left Left Case
-    }
-    if (balanceFactor < 1 && tree._comp(_val, node._right._val) > 0) {
-      return leftRotate(node) // Right Right Case
-    }
-    if (balanceFactor > 1 && tree._comp(_val, node._left._val) > 0) {
-      node._left = leftRotate(node._left) // Left Right Case
-      return rightRotate(node)
-    }
-    node._right = rightRotate(node._right)
-    return leftRotate(node)
-  }
-
-  // check if tree is balanced after deletion
-  const delBalance = function (node) {
-    const balanceFactor1 = getHeightDifference(node)
-    if (isValidBalanceFactor(balanceFactor1)) {
-      return node
-    }
-    if (balanceFactor1 > 1) {
-      if (getHeightDifference(node._left) >= 0) {
-        return rightRotate(node) // Left Left
-      }
-      node._left = leftRotate(node._left)
-      return rightRotate(node) // Left Right
-    }
-    if (getHeightDifference(node._right) > 0) {
-      node._right = rightRotate(node._right)
-      return leftRotate(node) // Right Left
-    }
-    return leftRotate(node) // Right Right
-  }
-
-  // implement avl tree insertion
-  const insert = function (root, val, tree) {
-    if (root == null) {
-      tree.size++
-      return new Node(val)
-    }
-    if (tree._comp(root._val, val) < 0) {
-      root._right = insert(root._right, val, tree)
-    } else if (tree._comp(root._val, val) > 0) {
-      root._left = insert(root._left, val, tree)
-    } else {
-      return root
-    }
-    updateHeight(root)
-    const balanceFactor = getHeightDifference(root)
-    return isValidBalanceFactor(balanceFactor)
-      ? root
-      : insertBalance(root, val, balanceFactor, tree)
-  }
-
-  // delete am element
-  const deleteElement = function (root, _val, tree) {
-    if (root == null) {
-      return root
-    }
-    if (tree._comp(root._val, _val) === 0) {
-      // key found case
-      if (root._left === null && root._right === null) {
-        root = null
-        tree.size--
-      } else if (root._left === null) {
-        root = root._right
-        tree.size--
-      } else if (root._right === null) {
-        root = root._left
-        tree.size--
-      } else {
-        let temp = root._right
-        while (temp._left != null) {
-          temp = temp._left
-        }
-        root._val = temp._val
-        root._right = deleteElement(root._right, temp._val, tree)
-      }
-    } else {
-      if (tree._comp(root._val, _val) < 0) {
-        root._right = deleteElement(root._right, _val, tree)
-      } else {
-        root._left = deleteElement(root._left, _val, tree)
-      }
-    }
-    updateHeight(root)
-    root = delBalance(root)
-    return root
-  }
-  // search tree for a element
-  const searchAVLTree = function (root, val, tree) {
-    if (root == null) {
-      return null
-    }
-    if (tree._comp(root._val, val) === 0) {
-      return root
-    }
-    if (tree._comp(root._val, val) < 0) {
-      return searchAVLTree(root._right, val, tree)
-    }
-    return searchAVLTree(root._left, val, tree)
-  }
-
   /* Public Functions */
   /**
    * For Adding Elements to AVL Tree
@@ -207,20 +51,22 @@ const AVLTree = (function () {
    * if a element exists it return false
    * @returns {Boolean} element added or not
    */
-  _avl.prototype.add = function (_val) {
+  add(_val) {
     const prevSize = this.size
     this.root = insert(this.root, _val, this)
     return this.size !== prevSize
   }
+
   /**
    * TO check is a particular element exists or not
    * @param {any} _val
    * @returns {Boolean} exists or not
    */
-  _avl.prototype.find = function (_val) {
+  find(_val) {
     const temp = searchAVLTree(this.root, _val, this)
     return temp != null
   }
+
   /**
    *
    * @param {any} _val
@@ -228,13 +74,170 @@ const AVLTree = (function () {
    * in that case it return false
    * @returns {Boolean} if element was found and deleted
    */
-  _avl.prototype.remove = function (_val) {
+  remove(_val) {
     const prevSize = this.size
     this.root = deleteElement(this.root, _val, this)
     return prevSize !== this.size
   }
-  return _avl
-})()
+}
+
+// creates new Node Object
+class Node {
+  constructor(val) {
+    this._val = val
+    this._left = null
+    this._right = null
+    this._height = 1
+  }
+}
+
+// get height of a node
+const getHeight = function (node) {
+  if (node == null) {
+    return 0
+  }
+  return node._height
+}
+
+// height difference or balance factor of a node
+const getHeightDifference = function (node) {
+  return node == null ? 0 : getHeight(node._left) - getHeight(node._right)
+}
+
+// update height of a node based on children's heights
+const updateHeight = function (node) {
+  if (node == null) {
+    return
+  }
+  node._height = Math.max(getHeight(node._left), getHeight(node._right)) + 1
+}
+
+// Helper: To check if the balanceFactor is valid
+const isValidBalanceFactor = (balanceFactor) =>
+  [0, 1, -1].includes(balanceFactor)
+
+// rotations of AVL Tree
+const leftRotate = function (node) {
+  const temp = node._right
+  node._right = temp._left
+  temp._left = node
+  updateHeight(node)
+  updateHeight(temp)
+  return temp
+}
+const rightRotate = function (node) {
+  const temp = node._left
+  node._left = temp._right
+  temp._right = node
+  updateHeight(node)
+  updateHeight(temp)
+  return temp
+}
+
+// check if tree is balanced else balance it for insertion
+const insertBalance = function (node, _val, balanceFactor, tree) {
+  if (balanceFactor > 1 && tree._comp(_val, node._left._val) < 0) {
+    return rightRotate(node) // Left Left Case
+  }
+  if (balanceFactor < 1 && tree._comp(_val, node._right._val) > 0) {
+    return leftRotate(node) // Right Right Case
+  }
+  if (balanceFactor > 1 && tree._comp(_val, node._left._val) > 0) {
+    node._left = leftRotate(node._left) // Left Right Case
+    return rightRotate(node)
+  }
+  node._right = rightRotate(node._right)
+  return leftRotate(node)
+}
+
+// check if tree is balanced after deletion
+const delBalance = function (node) {
+  const balanceFactor1 = getHeightDifference(node)
+  if (isValidBalanceFactor(balanceFactor1)) {
+    return node
+  }
+  if (balanceFactor1 > 1) {
+    if (getHeightDifference(node._left) >= 0) {
+      return rightRotate(node) // Left Left
+    }
+    node._left = leftRotate(node._left)
+    return rightRotate(node) // Left Right
+  }
+  if (getHeightDifference(node._right) > 0) {
+    node._right = rightRotate(node._right)
+    return leftRotate(node) // Right Left
+  }
+  return leftRotate(node) // Right Right
+}
+
+// implement avl tree insertion
+const insert = function (root, val, tree) {
+  if (root == null) {
+    tree.size++
+    return new Node(val)
+  }
+  if (tree._comp(root._val, val) < 0) {
+    root._right = insert(root._right, val, tree)
+  } else if (tree._comp(root._val, val) > 0) {
+    root._left = insert(root._left, val, tree)
+  } else {
+    return root
+  }
+  updateHeight(root)
+  const balanceFactor = getHeightDifference(root)
+  return isValidBalanceFactor(balanceFactor)
+    ? root
+    : insertBalance(root, val, balanceFactor, tree)
+}
+
+// delete am element
+const deleteElement = function (root, _val, tree) {
+  if (root == null) {
+    return root
+  }
+  if (tree._comp(root._val, _val) === 0) {
+    // key found case
+    if (root._left === null && root._right === null) {
+      root = null
+      tree.size--
+    } else if (root._left === null) {
+      root = root._right
+      tree.size--
+    } else if (root._right === null) {
+      root = root._left
+      tree.size--
+    } else {
+      let temp = root._right
+      while (temp._left != null) {
+        temp = temp._left
+      }
+      root._val = temp._val
+      root._right = deleteElement(root._right, temp._val, tree)
+    }
+  } else {
+    if (tree._comp(root._val, _val) < 0) {
+      root._right = deleteElement(root._right, _val, tree)
+    } else {
+      root._left = deleteElement(root._left, _val, tree)
+    }
+  }
+  updateHeight(root)
+  root = delBalance(root)
+  return root
+}
+// search tree for a element
+const searchAVLTree = function (root, val, tree) {
+  if (root == null) {
+    return null
+  }
+  if (tree._comp(root._val, val) === 0) {
+    return root
+  }
+  if (tree._comp(root._val, val) < 0) {
+    return searchAVLTree(root._right, val, tree)
+  }
+  return searchAVLTree(root._left, val, tree)
+}
 
 /**
  * A Code for Testing the AVLTree
diff --git a/Data-Structures/Tree/BinarySearchTree.js b/Data-Structures/Tree/BinarySearchTree.js
index c86a2995c0..abbcc3fb62 100644
--- a/Data-Structures/Tree/BinarySearchTree.js
+++ b/Data-Structures/Tree/BinarySearchTree.js
@@ -13,77 +13,79 @@
 // class Node
 const Node = (function Node() {
   // Node in the tree
-  function Node(val) {
-    this.value = val
-    this.left = null
-    this.right = null
-  }
-
-  // Search the tree for a value
-  Node.prototype.search = function (val) {
-    if (this.value === val) {
-      return this
-    } else if (val < this.value && this.left !== null) {
-      return this.left.search(val)
-    } else if (val > this.value && this.right !== null) {
-      return this.right.search(val)
+  class Node {
+    constructor(val) {
+      this.value = val
+      this.left = null
+      this.right = null
     }
-    return null
-  }
 
-  // Visit a node
-  Node.prototype.visit = function (output = (value) => console.log(value)) {
-    // Recursively go left
-    if (this.left !== null) {
-      this.left.visit()
-    }
-    // Print out value
-    output(this.value)
-    // Recursively go right
-    if (this.right !== null) {
-      this.right.visit()
+    // Search the tree for a value
+    search(val) {
+      if (this.value === val) {
+        return this
+      } else if (val < this.value && this.left !== null) {
+        return this.left.search(val)
+      } else if (val > this.value && this.right !== null) {
+        return this.right.search(val)
+      }
+      return null
     }
-  }
 
-  // Add a node
-  Node.prototype.addNode = function (n) {
-    if (n.value < this.value) {
-      if (this.left === null) {
-        this.left = n
-      } else {
-        this.left.addNode(n)
+    // Visit a node
+    visit(output = (value) => console.log(value)) {
+      // Recursively go left
+      if (this.left !== null) {
+        this.left.visit()
       }
-    } else if (n.value > this.value) {
-      if (this.right === null) {
-        this.right = n
-      } else {
-        this.right.addNode(n)
+      // Print out value
+      output(this.value)
+      // Recursively go right
+      if (this.right !== null) {
+        this.right.visit()
       }
     }
-  }
 
-  // remove a node
-  Node.prototype.removeNode = function (val) {
-    if (val === this.value) {
-      if (!this.left && !this.right) {
-        return null
-      } else {
-        if (this.left) {
-          const leftMax = maxVal(this.left)
-          this.value = leftMax
-          this.left = this.left.removeNode(leftMax)
+    // Add a node
+    addNode(n) {
+      if (n.value < this.value) {
+        if (this.left === null) {
+          this.left = n
         } else {
-          const rightMin = minVal(this.right)
-          this.value = rightMin
-          this.right = this.right.removeNode(rightMin)
+          this.left.addNode(n)
+        }
+      } else if (n.value > this.value) {
+        if (this.right === null) {
+          this.right = n
+        } else {
+          this.right.addNode(n)
         }
       }
-    } else if (val < this.value) {
-      this.left = this.left && this.left.removeNode(val)
-    } else if (val > this.value) {
-      this.right = this.right && this.right.removeNode(val)
     }
-    return this
+
+    // remove a node
+    removeNode(val) {
+      if (val === this.value) {
+        if (!this.left && !this.right) {
+          return null
+        } else {
+          if (this.left) {
+            const leftMax = maxVal(this.left)
+            this.value = leftMax
+            this.left = this.left.removeNode(leftMax)
+          } else {
+            const rightMin = minVal(this.right)
+            this.value = rightMin
+            this.right = this.right.removeNode(rightMin)
+          }
+        }
+      } else if (val < this.value) {
+        this.left = this.left && this.left.removeNode(val)
+      } else if (val > this.value) {
+        this.right = this.right && this.right.removeNode(val)
+      }
+      return this
+    }
   }
 
   // find maximum value in the tree
@@ -107,44 +109,46 @@ const Node = (function Node() {
 
 // class Tree
 const Tree = (function () {
-  function Tree() {
-    // Just store the root
-    this.root = null
-  }
+  class Tree {
+    constructor() {
+      // Just store the root
+      this.root = null
+    }
 
-  // Inorder traversal
-  Tree.prototype.traverse = function () {
-    if (!this.root) {
-      // No nodes are there in the tree till now
-      return
+    // Inorder traversal
+    traverse() {
+      if (!this.root) {
+        // No nodes are there in the tree till now
+        return
+      }
+      this.root.visit()
     }
-    this.root.visit()
-  }
 
-  // Start by searching the root
-  Tree.prototype.search = function (val) {
-    const found = this.root.search(val)
-    if (found !== null) {
-      return found.value
+    // Start by searching the root
+    search(val) {
+      const found = this.root.search(val)
+      if (found !== null) {
+        return found.value
+      }
+      // not found
+      return null
     }
-    // not found
-    return null
-  }
 
-  // Add a new value to the tree
-  Tree.prototype.addValue = function (val) {
-    const n = new Node(val)
-    if (this.root === null) {
-      this.root = n
-    } else {
-      this.root.addNode(n)
+    // Add a new value to the tree
+    addValue(val) {
+      const n = new Node(val)
+      if (this.root === null) {
+        this.root = n
+      } else {
+        this.root.addNode(n)
+      }
     }
-  }
 
-  // remove a value from the tree
-  Tree.prototype.removeValue = function (val) {
-    // remove something if root exists
-    this.root = this.root && this.root.removeNode(val)
+    // remove a value from the tree
+    removeValue(val) {
+      // remove something if root exists
+      this.root = this.root && this.root.removeNode(val)
+    }
   }
 
   // returns the constructor
diff --git a/Data-Structures/Tree/Trie.js b/Data-Structures/Tree/Trie.js
index ea59e53846..0d4018f74f 100644
--- a/Data-Structures/Tree/Trie.js
+++ b/Data-Structures/Tree/Trie.js
@@ -1,129 +1,132 @@
-const TrieNode = function TrieNode(key, parent) {
-  this.key = key
-  this.count = 0
-  this.children = Object.create(null)
-  if (parent === undefined) {
-    this.parent = null
-  } else {
-    this.parent = parent
+class TrieNode {
+  constructor(key, parent) {
+    this.key = key
+    this.count = 0
+    this.children = Object.create(null)
+    if (parent === undefined) {
+      this.parent = null
+    } else {
+      this.parent = parent
+    }
   }
 }
 
-function Trie() {
-  // create only root with null key and parent
-  this.root = new TrieNode(null, null)
-}
+class Trie {
+  constructor() {
+    // create only root with null key and parent
+    this.root = new TrieNode(null, null)
+  }
 
-// Recursively finds the occurrence of all words in a given node
-Trie.findAllWords = function (root, word, output) {
-  if (root === null) return
-  if (root.count > 0) {
-    if (typeof output === 'object') {
-      output.push({ word, count: root.count })
+  // Recursively finds the occurrence of all words in a given node
+  static findAllWords(root, word, output) {
+    if (root === null) return
+    if (root.count > 0) {
+      if (typeof output === 'object') {
+        output.push({ word, count: root.count })
+      }
+    }
+    let key
+    for (key in root.children) {
+      word += key
+      this.findAllWords(root.children[key], word, output)
+      word = word.slice(0, -1)
     }
   }
-  let key
-  for (key in root.children) {
-    word += key
-    this.findAllWords(root.children[key], word, output)
-    word = word.slice(0, -1)
-  }
-}
 
-Trie.prototype.insert = function (word) {
-  if (typeof word !== 'string') return
-  if (word === '') {
-    this.root.count += 1
-    return
-  }
-  let node = this.root
-  const len = word.length
-  let i
-  for (i = 0; i < len; i++) {
-    if (node.children[word.charAt(i)] === undefined) {
-      node.children[word.charAt(i)] = new TrieNode(word.charAt(i), node)
+  insert(word) {
+    if (typeof word !== 'string') return
+    if (word === '') {
+      this.root.count += 1
+      return
+    }
+    let node = this.root
+    const len = word.length
+    let i
+    for (i = 0; i < len; i++) {
+      if (node.children[word.charAt(i)] === undefined) {
+        node.children[word.charAt(i)] = new TrieNode(word.charAt(i), node)
+      }
+      node = node.children[word.charAt(i)]
     }
-    node = node.children[word.charAt(i)]
+    node.count += 1
   }
-  node.count += 1
-}
 
-Trie.prototype.findPrefix = function (word) {
-  if (typeof word !== 'string') return null
-  let node = this.root
-  const len = word.length
-  let i
-  // After end of this loop node will be at desired prefix
-  for (i = 0; i < len; i++) {
-    if (node.children[word.charAt(i)] === undefined) return null // No such prefix exists
-    node = node.children[word.charAt(i)]
+  findPrefix(word) {
+    if (typeof word !== 'string') return null
+    let node = this.root
+    const len = word.length
+    let i
+    // After end of this loop node will be at desired prefix
+    for (i = 0; i < len; i++) {
+      if (node.children[word.charAt(i)] === undefined) return null // No such prefix exists
+      node = node.children[word.charAt(i)]
+    }
+    return node
   }
-  return node
-}
 
-Trie.prototype.remove = function (word, count) {
-  if (typeof word !== 'string') return
-  if (typeof count !== 'number') count = 1
-  else if (count <= 0) return
+  remove(word, count) {
+    if (typeof word !== 'string') return
+    if (typeof count !== 'number') count = 1
+    else if (count <= 0) return
 
-  // for empty string just delete count of root
-  if (word === '') {
-    if (this.root.count >= count) this.root.count -= count
-    else this.root.count = 0
-    return
-  }
+    // for empty string just delete count of root
+    if (word === '') {
+      if (this.root.count >= count) this.root.count -= count
+      else this.root.count = 0
+      return
+    }
 
-  let child = this.root
-  const len = word.length
-  let i, key
-  // child: node which is to be deleted
-  for (i = 0; i < len; i++) {
-    key = word.charAt(i)
-    if (child.children[key] === undefined) return
-    child = child.children[key]
-  }
+    let child = this.root
+    const len = word.length
+    let i, key
+    // child: node which is to be deleted
+    for (i = 0; i < len; i++) {
+      key = word.charAt(i)
+      if (child.children[key] === undefined) return
+      child = child.children[key]
+    }
 
-  // Delete no of occurrences specified
-  if (child.count >= count) child.count -= count
-  else child.count = 0
+    // Delete no of occurrences specified
+    if (child.count >= count) child.count -= count
+    else child.count = 0
 
-  // If some occurrences are left we don't delete it or else
-  // if the object forms some other objects prefix we don't delete it
-  // For checking an empty object
-  // https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object
-  if (
-    child.count <= 0 &&
-    Object.keys(child.children).length &&
-    child.children.constructor === Object
-  ) {
-    child.parent.children[child.key] = undefined
+    // If some occurrences are left we don't delete it or else
+    // if the object forms some other objects prefix we don't delete it
+    // For checking an empty object
+    // https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object
+    if (
+      child.count <= 0 &&
+      Object.keys(child.children).length &&
+      child.children.constructor === Object
+    ) {
+      child.parent.children[child.key] = undefined
+    }
   }
-}
 
-Trie.prototype.findAllWords = function (prefix) {
-  const output = []
-  // find the node with provided prefix
-  const node = this.findPrefix(prefix)
-  // No such prefix exists
-  if (node === null) return output
-  Trie.findAllWords(node, prefix, output)
-  return output
-}
-
-Trie.prototype.contains = function (word) {
-  // find the node with given prefix
-  const node = this.findPrefix(word)
-  // No such word exists
+  findAllWords(prefix) {
+    const output = []
+    // find the node with provided prefix
+    const node = this.findPrefix(prefix)
+    // No such prefix exists
+    if (node === null) return output
+    Trie.findAllWords(node, prefix, output)
+    return output
+  }
 
-  return node !== null && node.count !== 0
-}
+  contains(word) {
+    // find the node with given prefix
+    const node = this.findPrefix(word)
+    // No such word exists
+    return node !== null && node.count !== 0
+  }
 
-Trie.prototype.findOccurrences = function (word) {
-  // find the node with given prefix
-  const node = this.findPrefix(word)
-  // No such word exists
-  if (node === null) return 0
-  return node.count
+  findOccurrences(word) {
+    // find the node with given prefix
+    const node = this.findPrefix(word)
+    // No such word exists
+    if (node === null) return 0
+    return node.count
+  }
 }
 
 export { Trie }
diff --git a/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js b/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js
index dee12f8de9..48905c39e2 100644
--- a/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js
+++ b/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js
@@ -4,7 +4,7 @@ determine the total number of the subset with sum
 equal to the given sum.
 */
 /*
- Given solution is O(n*sum) Time complexity and O(sum) Space complexity
+  Given solution is O(n*sum) Time complexity and O(sum) Space complexity
 */
 function NumberOfSubsetSum(array, sum) {
   const dp = [] // create an dp array where dp[i] denote number of subset with sum equal to i
diff --git a/Project-Euler/Problem004.js b/Project-Euler/Problem004.js
index 34fa87471d..7c85dfdb85 100644
--- a/Project-Euler/Problem004.js
+++ b/Project-Euler/Problem004.js
@@ -1,6 +1,6 @@
 // https://projecteuler.net/problem=4
 /* A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
-   Find the largest palindrome made from the product of two 3-digit numbers.
+  Find the largest palindrome made from the product of two 3-digit numbers.
 */
 export const largestPalindromic = (digits) => {
   let i

From 6e27235fb75298833448ba1b23e5178f7eea2290 Mon Sep 17 00:00:00 2001
From: Christian Clauss <cclauss@me.com>
Date: Sun, 5 May 2024 21:22:35 +0200
Subject: [PATCH 54/73] Keep GitHub Actions up to date with GitHub's Dependabot

Fixes software supply chain safety warnings like at the bottom right of
https://github.com/TheAlgorithms/JavaScript/actions/runs/8960545794

* [Keeping your actions up to date with Dependabot](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot)
* [Configuration options for the dependabot.yml file - package-ecosystem](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem)
---
 .github/dependabot.yml | 8 ++++++++
 1 file changed, 8 insertions(+)
 create mode 100644 .github/dependabot.yml

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000000..15e494ec86
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,8 @@
+# Keep GitHub Actions up to date with Dependabot...
+# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
+version: 2
+updates:
+  - package-ecosystem: "github-actions"
+    directory: "/"
+    schedule:
+      interval: "daily"

From 6bb02af09b6d1de02a047b5c4608d2d101984911 Mon Sep 17 00:00:00 2001
From: cclauss <cclauss@users.noreply.github.com>
Date: Sun, 5 May 2024 19:22:50 +0000
Subject: [PATCH 55/73] Updated Documentation in README.md

---
 DIRECTORY.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/DIRECTORY.md b/DIRECTORY.md
index 59f6273bf2..6c1fa7aeb8 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -397,6 +397,7 @@
 * **Timing-Functions**
   * [GetMonthDays](Timing-Functions/GetMonthDays.js)
   * [IntervalTimer](Timing-Functions/IntervalTimer.js)
+  * [ParseDate](Timing-Functions/ParseDate.js)
 * **Trees**
   * [BreadthFirstTreeTraversal](Trees/BreadthFirstTreeTraversal.js)
   * [DepthFirstSearch](Trees/DepthFirstSearch.js)

From cc1e1dc643074f1489aa6ef5a8b7a02d01c7c7f1 Mon Sep 17 00:00:00 2001
From: Christian Clauss <cclauss@me.com>
Date: Fri, 17 May 2024 17:28:38 +0200
Subject: [PATCH 56/73] GitHub Actions: Test on the current version of Node.js
 (#1657)

---
 .github/workflows/Ci.yml                   | 2 +-
 .github/workflows/UpdateDirectory.yml      | 2 +-
 .github/workflows/UploadCoverageReport.yml | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/Ci.yml b/.github/workflows/Ci.yml
index 571b8a0fa8..99e8f7831f 100644
--- a/.github/workflows/Ci.yml
+++ b/.github/workflows/Ci.yml
@@ -15,7 +15,7 @@ jobs:
 
       - uses: actions/setup-node@v4
         with:
-          node-version: 20
+          node-version: 22
           cache: npm
 
       - name: 📦 Install dependencies
diff --git a/.github/workflows/UpdateDirectory.yml b/.github/workflows/UpdateDirectory.yml
index cb649e1c8b..437ab55b91 100644
--- a/.github/workflows/UpdateDirectory.yml
+++ b/.github/workflows/UpdateDirectory.yml
@@ -14,7 +14,7 @@ jobs:
 
       - uses: actions/setup-node@v4
         with:
-          node-version: 20
+          node-version: 22
           cache: npm
 
       - name: 📦 Install dependencies
diff --git a/.github/workflows/UploadCoverageReport.yml b/.github/workflows/UploadCoverageReport.yml
index 4dcad584bf..eee9d4aec9 100644
--- a/.github/workflows/UploadCoverageReport.yml
+++ b/.github/workflows/UploadCoverageReport.yml
@@ -16,7 +16,7 @@ jobs:
 
       - uses: actions/setup-node@v4
         with:
-          node-version: 20
+          node-version: 22
           cache: npm
 
       - name: Install dependencies

From e2b975486234d07bd732bf290fce8cb28144a814 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Thu, 23 May 2024 19:45:08 +0200
Subject: [PATCH 57/73] tests: add tests of `LongestIncreasingSubsequence`
 (#1660)

---
 .../LongestIncreasingSubsequence.js           |  3 +++
 .../LongestIncreasingSubsequence.test.js      | 24 +++++++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 Dynamic-Programming/tests/LongestIncreasingSubsequence.test.js

diff --git a/Dynamic-Programming/LongestIncreasingSubsequence.js b/Dynamic-Programming/LongestIncreasingSubsequence.js
index b9319db586..b8e1847cd8 100644
--- a/Dynamic-Programming/LongestIncreasingSubsequence.js
+++ b/Dynamic-Programming/LongestIncreasingSubsequence.js
@@ -6,6 +6,9 @@
 // Return the length of the Longest Increasing Subsequence, given array x
 function longestIncreasingSubsequence(x) {
   const length = x.length
+  if (length == 0) {
+    return 0
+  }
   const dp = Array(length).fill(1)
 
   let res = 1
diff --git a/Dynamic-Programming/tests/LongestIncreasingSubsequence.test.js b/Dynamic-Programming/tests/LongestIncreasingSubsequence.test.js
new file mode 100644
index 0000000000..9a8024aa95
--- /dev/null
+++ b/Dynamic-Programming/tests/LongestIncreasingSubsequence.test.js
@@ -0,0 +1,24 @@
+import { longestIncreasingSubsequence } from '../LongestIncreasingSubsequence'
+
+describe('Testing longestIncreasingSubsequence', () => {
+  it.each([
+    [[], 0],
+    [[1], 1],
+    [[2, 2], 1],
+    [[3, 3, 3], 1],
+    [[4, 4, 4, 4], 1],
+    [[1, 2], 2],
+    [[1, 2, 2, 2, 2], 2],
+    [[1, 0, 2], 2],
+    [[1, 10, 2, 30], 3],
+    [[5, 8, 3, 7, 9, 1], 3],
+    [[10, 9, 2, 5, 3, 7, 101, 18], 4],
+    [[10, 10, 9, 9, 2, 2, 5, 5, 3, 3, 7, 7, 101, 101, 18, 18], 4],
+    [[0, 1, 0, 3, 2, 3], 4],
+    [[1, 1, 2, 2, 2], 2],
+    [[1, 1, 2, 2, 2, 3, 3, 3, 3], 3],
+    [[0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15], 6]
+  ])('check with %j', (input, expected) => {
+    expect(longestIncreasingSubsequence(input)).toBe(expected)
+  })
+})

From 3623e4270f98d6dd5a1fe6a05cbec3c1a0657fbb Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sat, 25 May 2024 13:01:13 +0200
Subject: [PATCH 58/73] tests: add `HexToDecimal.test.js` (#1662)

---
 Conversions/HexToDecimal.js           |  5 ++++-
 Conversions/test/HexToDecimal.test.js | 24 ++++++++++++++++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)
 create mode 100644 Conversions/test/HexToDecimal.test.js

diff --git a/Conversions/HexToDecimal.js b/Conversions/HexToDecimal.js
index 31ae13932f..e402421399 100644
--- a/Conversions/HexToDecimal.js
+++ b/Conversions/HexToDecimal.js
@@ -1,4 +1,7 @@
 function hexToInt(hexNum) {
+  if (!/^[0-9A-F]+$/.test(hexNum)) {
+    throw new Error('Invalid hex string.')
+  }
   const numArr = hexNum.split('') // converts number to array
   return numArr.map((item, index) => {
     switch (item) {
@@ -29,4 +32,4 @@ function hexToDecimal(hexNum) {
   }, 0)
 }
 
-export { hexToInt, hexToDecimal }
+export { hexToDecimal }
diff --git a/Conversions/test/HexToDecimal.test.js b/Conversions/test/HexToDecimal.test.js
new file mode 100644
index 0000000000..816c70511d
--- /dev/null
+++ b/Conversions/test/HexToDecimal.test.js
@@ -0,0 +1,24 @@
+import { hexToDecimal } from '../HexToDecimal'
+
+describe('Testing HexToDecimal', () => {
+  it.each([
+    ['0', 0],
+    ['1', 1],
+    ['A', 10],
+    ['B', 11],
+    ['C', 12],
+    ['D', 13],
+    ['E', 14],
+    ['F', 15],
+    ['10', 16],
+    ['859', 2137],
+    ['4D2', 1234],
+    ['81323ABD92', 554893491602]
+  ])('check with %s', (hexStr, expected) => {
+    expect(hexToDecimal(hexStr)).toBe(expected)
+  })
+
+  it.each(['a', '-1', 'G', ''])('throws for %s', (hexStr) => {
+    expect(() => hexToDecimal(hexStr)).toThrowError()
+  })
+})

From 1554ba5f9c1bade3e52733a2bf67017b073fbe75 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sat, 25 May 2024 13:01:54 +0200
Subject: [PATCH 59/73] test: add tests for `NumberOfSubsetEqualToGivenSum`
 (#1661)

---
 .../NumberOfSubsetEqualToGivenSum.js          | 15 +++++------
 .../NumberOfSubsetEqualToGivenSum.test.js     | 25 +++++++++++++++++++
 2 files changed, 33 insertions(+), 7 deletions(-)
 create mode 100644 Dynamic-Programming/tests/NumberOfSubsetEqualToGivenSum.test.js

diff --git a/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js b/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js
index 48905c39e2..fd8e70c4d6 100644
--- a/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js
+++ b/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js
@@ -1,5 +1,5 @@
 /*
-Given an array of non-negative integers and a value sum,
+Given an array of positive integers and a value sum,
 determine the total number of the subset with sum
 equal to the given sum.
 */
@@ -7,6 +7,13 @@ equal to the given sum.
   Given solution is O(n*sum) Time complexity and O(sum) Space complexity
 */
 function NumberOfSubsetSum(array, sum) {
+  if (sum < 0) {
+    throw new Error('The sum must be non-negative.')
+  }
+
+  if (!array.every((num) => num > 0)) {
+    throw new Error('All of the inputs of the array must be positive.')
+  }
   const dp = [] // create an dp array where dp[i] denote number of subset with sum equal to i
   for (let i = 1; i <= sum; i++) {
     dp[i] = 0
@@ -23,10 +30,4 @@ function NumberOfSubsetSum(array, sum) {
   return dp[sum]
 }
 
-// example
-
-// const array = [1, 1, 2, 2, 3, 1, 1]
-// const sum = 4
-// const result = NumberOfSubsetSum(array, sum)
-
 export { NumberOfSubsetSum }
diff --git a/Dynamic-Programming/tests/NumberOfSubsetEqualToGivenSum.test.js b/Dynamic-Programming/tests/NumberOfSubsetEqualToGivenSum.test.js
new file mode 100644
index 0000000000..23eed33ebe
--- /dev/null
+++ b/Dynamic-Programming/tests/NumberOfSubsetEqualToGivenSum.test.js
@@ -0,0 +1,25 @@
+import { NumberOfSubsetSum } from '../NumberOfSubsetEqualToGivenSum'
+
+describe('Testing NumberOfSubsetSum', () => {
+  it.each([
+    [[], 0, 1],
+    [[], 1, 0],
+    [[1], 2, 0],
+    [[1, 2, 3, 4, 5], 0, 1],
+    [[1, 1, 1, 1, 1], 5, 1],
+    [[1, 1, 1, 1, 1], 4, 5],
+    [[1, 2, 3, 3], 6, 3],
+    [[10, 20, 30, 1], 31, 2],
+    [[1, 1, 2, 2, 3, 1, 1], 4, 18]
+  ])('check with %j and %i', (arr, sum, expected) => {
+    expect(NumberOfSubsetSum(arr, sum)).toBe(expected)
+  })
+
+  it.each([
+    [[1, 2], -1],
+    [[0, 2], 2],
+    [[1, -1], 0]
+  ])('throws for %j and %i', (arr, sum) => {
+    expect(() => NumberOfSubsetSum(arr, sum)).toThrowError()
+  })
+})

From 79b93d35b6175fe6364fb16c07520e796a3fddb5 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Tue, 11 Jun 2024 22:10:48 +0200
Subject: [PATCH 60/73] style: remove redundant eslint suppressions (#1667)

---
 Backtracking/tests/RatInAMaze.test.js | 4 ----
 Backtracking/tests/Sudoku.test.js     | 1 -
 Data-Structures/Array/QuickSelect.js  | 1 -
 Maths/test/EulerMethod.manual-test.js | 1 -
 Maths/test/FindMinIterator.test.js    | 4 +---
 Recursive/test/FloodFill.test.js      | 1 -
 6 files changed, 1 insertion(+), 11 deletions(-)

diff --git a/Backtracking/tests/RatInAMaze.test.js b/Backtracking/tests/RatInAMaze.test.js
index 6cc5b31aae..52f620027b 100644
--- a/Backtracking/tests/RatInAMaze.test.js
+++ b/Backtracking/tests/RatInAMaze.test.js
@@ -6,7 +6,6 @@ describe('RatInAMaze', () => {
 
     for (const value of values) {
       // we deliberately want to check whether this constructor call fails or not
-      // eslint-disable-next-line no-new
       expect(() => {
         new RatInAMaze(value)
       }).toThrow()
@@ -15,7 +14,6 @@ describe('RatInAMaze', () => {
 
   it('should fail for an empty array', () => {
     // we deliberately want to check whether this constructor call fails or not
-    // eslint-disable-next-line no-new
     expect(() => {
       new RatInAMaze([])
     }).toThrow()
@@ -28,7 +26,6 @@ describe('RatInAMaze', () => {
     ]
 
     // we deliberately want to check whether this constructor call fails or not
-    // eslint-disable-next-line no-new
     expect(() => {
       new RatInAMaze(array)
     }).toThrow()
@@ -39,7 +36,6 @@ describe('RatInAMaze', () => {
 
     for (const value of values) {
       // we deliberately want to check whether this constructor call fails or not
-      // eslint-disable-next-line no-new
       expect(() => {
         new RatInAMaze(value)
       }).toThrow()
diff --git a/Backtracking/tests/Sudoku.test.js b/Backtracking/tests/Sudoku.test.js
index 8cbe187089..c70f7de67a 100644
--- a/Backtracking/tests/Sudoku.test.js
+++ b/Backtracking/tests/Sudoku.test.js
@@ -27,7 +27,6 @@ const solved = [
 describe('Sudoku', () => {
   it('should create a valid board successfully', () => {
     // we deliberately want to check whether this constructor call fails or not
-    // eslint-disable-next-line no-new
     expect(() => {
       new Sudoku(data)
     }).not.toThrow()
diff --git a/Data-Structures/Array/QuickSelect.js b/Data-Structures/Array/QuickSelect.js
index d01555ed95..53c8c8e855 100644
--- a/Data-Structures/Array/QuickSelect.js
+++ b/Data-Structures/Array/QuickSelect.js
@@ -12,7 +12,6 @@
  */
 
 function QuickSelect(items, kth) {
-  // eslint-disable-line no-unused-vars
   if (kth < 1 || kth > items.length) {
     throw new RangeError('Index Out of Bound')
   }
diff --git a/Maths/test/EulerMethod.manual-test.js b/Maths/test/EulerMethod.manual-test.js
index 27b4631a80..e1959280a5 100644
--- a/Maths/test/EulerMethod.manual-test.js
+++ b/Maths/test/EulerMethod.manual-test.js
@@ -15,7 +15,6 @@ function plotLine(label, points, width, height) {
 
   // Chart-class from chartjs
   const chart = new Chart(canvas, {
-    // eslint-disable-line
     type: 'scatter',
     data: {
       datasets: [
diff --git a/Maths/test/FindMinIterator.test.js b/Maths/test/FindMinIterator.test.js
index 7b7229b106..792cb7695e 100644
--- a/Maths/test/FindMinIterator.test.js
+++ b/Maths/test/FindMinIterator.test.js
@@ -22,13 +22,12 @@ describe('FindMinIterator', () => {
   })
 
   test('given empty generator then min is undefined', () => {
-    const src = function* () {} // eslint-disable-line
+    const src = function* () {}
     expect(FindMinIterator(src())).toBeUndefined()
   })
 
   test('given generator then min is found', () => {
     const src = function* () {
-      // eslint-disable-line
       yield 1
       yield -1
       yield 0
@@ -38,7 +37,6 @@ describe('FindMinIterator', () => {
 
   test('given string generator then min string length is found', () => {
     const src = function* () {
-      // eslint-disable-line
       yield 'abc'
       yield 'de'
       yield 'qwerty'
diff --git a/Recursive/test/FloodFill.test.js b/Recursive/test/FloodFill.test.js
index 618692dd97..eb44e75e09 100644
--- a/Recursive/test/FloodFill.test.js
+++ b/Recursive/test/FloodFill.test.js
@@ -69,7 +69,6 @@ function testDepthFirst(
   replacementColor,
   testLocation
 ) {
-  // eslint-disable-line
   const rgbData = generateTestRgbData()
   depthFirstSearch(rgbData, fillLocation, targetColor, replacementColor)
   return rgbData[testLocation[0]][testLocation[1]]

From 0182bcacd0573094452e2130a18e4b947df91e67 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Tue, 11 Jun 2024 22:11:12 +0200
Subject: [PATCH 61/73] style: remove `listIn` and `listOut` (#1669)

---
 Data-Structures/Queue/QueueUsing2Stacks.js | 18 ------------------
 1 file changed, 18 deletions(-)

diff --git a/Data-Structures/Queue/QueueUsing2Stacks.js b/Data-Structures/Queue/QueueUsing2Stacks.js
index 256f11060d..9a51ee3a72 100644
--- a/Data-Structures/Queue/QueueUsing2Stacks.js
+++ b/Data-Structures/Queue/QueueUsing2Stacks.js
@@ -29,24 +29,6 @@ class Queue {
       return top
     }
   }
-
-  // display elements of the inputstack
-  listIn(output = (value) => console.log(value)) {
-    let i = 0
-    while (i < this.inputStack.length) {
-      output(this.inputStack[i])
-      i++
-    }
-  }
-
-  // display element of the outputstack
-  listOut(output = (value) => console.log(value)) {
-    let i = 0
-    while (i < this.outputStack.length) {
-      output(this.outputStack[i])
-      i++
-    }
-  }
 }
 
 export { Queue }

From 584424241c61079940d94a5aed1bed583c555098 Mon Sep 17 00:00:00 2001
From: Daniel <67126972+ddaniel27@users.noreply.github.com>
Date: Mon, 17 Jun 2024 23:08:16 -0500
Subject: [PATCH 62/73] [Solution] Project euler challenge 19 with tests
 (#1659)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* [Solution] Project euler challenge 19 with tests

* update leap year function

* Remove unnecessary, confusingly placed comments

---------

Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>
---
 Project-Euler/Problem019.js           | 48 +++++++++++++++++++++++++++
 Project-Euler/test/Problem019.test.js |  8 +++++
 2 files changed, 56 insertions(+)
 create mode 100644 Project-Euler/Problem019.js
 create mode 100644 Project-Euler/test/Problem019.test.js

diff --git a/Project-Euler/Problem019.js b/Project-Euler/Problem019.js
new file mode 100644
index 0000000000..5b488c7f96
--- /dev/null
+++ b/Project-Euler/Problem019.js
@@ -0,0 +1,48 @@
+/**
+ * Problem 19 - Counting Sundays
+ *
+ * @see {@link https://projecteuler.net/problem=19}
+ *
+ * You are given the following information, but you may prefer to do some research for yourself.
+ * 1 Jan 1900 was a Monday.
+ * Thirty days has September,
+ * April, June and November.
+ * All the rest have thirty-one,
+ * Saving February alone,
+ * Which has twenty-eight, rain or shine.
+ * And on leap years, twenty-nine.
+ * A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
+ * How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
+ *
+ * @author ddaniel27
+ */
+import { isLeapYear } from '../Maths/LeapYear'
+
+function problem19() {
+  let sundaysCount = 0 // Count of Sundays
+  let dayOfWeek = 2 // 1st Jan 1900 was a Monday, so 1st Jan 1901 was a Tuesday
+
+  for (let year = 1901; year <= 2000; year++) {
+    for (let month = 1; month <= 12; month++) {
+      if (dayOfWeek === 0) {
+        // If it's a Sunday (0 is Sunday, 1 is Monday, ..., 6 is Saturday)
+        sundaysCount++
+      }
+
+      let daysInMonth = 31
+      if (month === 4 || month === 6 || month === 9 || month === 11) {
+        // April, June, September, November
+        daysInMonth = 30
+      } else if (month === 2) {
+        // February
+        daysInMonth = isLeapYear(year) ? 29 : 28
+      }
+
+      dayOfWeek = (dayOfWeek + daysInMonth) % 7 // Calculate the day of the week
+    }
+  }
+
+  return sundaysCount
+}
+
+export { problem19 }
diff --git a/Project-Euler/test/Problem019.test.js b/Project-Euler/test/Problem019.test.js
new file mode 100644
index 0000000000..8845e5a0ac
--- /dev/null
+++ b/Project-Euler/test/Problem019.test.js
@@ -0,0 +1,8 @@
+import { problem19 } from '../Problem019.js'
+
+describe('checking sundays during the twentieth century', () => {
+  // Project Euler Challenge Check
+  test('result should be 171', () => {
+    expect(problem19()).toBe(171)
+  })
+})

From 5f8d4d447a85fb4aeb065983ab275a582d4ff07b Mon Sep 17 00:00:00 2001
From: Daniel <67126972+ddaniel27@users.noreply.github.com>
Date: Sun, 23 Jun 2024 00:20:25 -0500
Subject: [PATCH 63/73] [Compressor] RLE Compressor implementation (#1671)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* [Solution] Project euler challenge 19 with tests

* update leap year function

* Remove unnecessary, confusingly placed comments

* [COMPRESSOR] RLE

* [COMPRESSOR] RLE style fixed

---------

Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>
---
 Compression/RLE.js           | 38 ++++++++++++++++++++++++++++++++++++
 Compression/test/RLE.test.js | 13 ++++++++++++
 2 files changed, 51 insertions(+)
 create mode 100644 Compression/RLE.js
 create mode 100644 Compression/test/RLE.test.js

diff --git a/Compression/RLE.js b/Compression/RLE.js
new file mode 100644
index 0000000000..81a1538646
--- /dev/null
+++ b/Compression/RLE.js
@@ -0,0 +1,38 @@
+/*
+ * RLE (Run Length Encoding) is a simple form of data compression.
+ * The basic idea is to represent repeated successive characters as a single count and character.
+ * For example, the string "AAAABBBCCDAA" would be encoded as "4A3B2C1D2A".
+ *
+ * @author - [ddaniel27](https://github.com/ddaniel27)
+ */
+
+function Compress(str) {
+  let compressed = ''
+  let count = 1
+
+  for (let i = 0; i < str.length; i++) {
+    if (str[i] !== str[i + 1]) {
+      compressed += count + str[i]
+      count = 1
+      continue
+    }
+
+    count++
+  }
+
+  return compressed
+}
+
+function Decompress(str) {
+  let decompressed = ''
+  let match = [...str.matchAll(/(\d+)(\D)/g)] // match all groups of digits followed by a non-digit character
+
+  match.forEach((item) => {
+    let [count, char] = [item[1], item[2]]
+    decompressed += char.repeat(count)
+  })
+
+  return decompressed
+}
+
+export { Compress, Decompress }
diff --git a/Compression/test/RLE.test.js b/Compression/test/RLE.test.js
new file mode 100644
index 0000000000..0094b5b7e2
--- /dev/null
+++ b/Compression/test/RLE.test.js
@@ -0,0 +1,13 @@
+import { Compress, Decompress } from '../RLE'
+
+describe('Test RLE Compressor/Decompressor', () => {
+  it('Test - 1, Pass long repetitive strings', () => {
+    expect(Compress('AAAAAAAAAAAAAA')).toBe('14A')
+    expect(Compress('AAABBQQQQQFG')).toBe('3A2B5Q1F1G')
+  })
+
+  it('Test - 2, Pass compressed strings', () => {
+    expect(Decompress('14A')).toBe('AAAAAAAAAAAAAA')
+    expect(Decompress('3A2B5Q1F1G')).toBe('AAABBQQQQQFG')
+  })
+})

From 8ceaa252b9b7aa37f217e1cb0cb65351698b8777 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sun, 23 Jun 2024 10:51:19 +0530
Subject: [PATCH 64/73] chore(deps-dev): bump braces from 3.0.2 to 3.0.3
 (#1670)

Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 package-lock.json | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index a4efa09c1b..9a4fd732a9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -463,11 +463,12 @@
       }
     },
     "node_modules/braces": {
-      "version": "3.0.2",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
       "dev": true,
-      "license": "MIT",
       "dependencies": {
-        "fill-range": "^7.0.1"
+        "fill-range": "^7.1.1"
       },
       "engines": {
         "node": ">=8"
@@ -634,9 +635,10 @@
       }
     },
     "node_modules/fill-range": {
-      "version": "7.0.1",
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
       "dev": true,
-      "license": "MIT",
       "dependencies": {
         "to-regex-range": "^5.0.1"
       },
@@ -786,8 +788,9 @@
     },
     "node_modules/is-number": {
       "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
       "dev": true,
-      "license": "MIT",
       "engines": {
         "node": ">=0.12.0"
       }
@@ -1319,8 +1322,9 @@
     },
     "node_modules/to-regex-range": {
       "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
       "dev": true,
-      "license": "MIT",
       "dependencies": {
         "is-number": "^7.0.0"
       },

From 9010481c2930d65621f18f41c216f29fceaa8807 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sun, 23 Jun 2024 13:40:42 +0200
Subject: [PATCH 65/73] chore: update `codecov-action` to `v4` (#1605)

The token has been added to the repository secrets.
---
 .github/workflows/UploadCoverageReport.yml | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/UploadCoverageReport.yml b/.github/workflows/UploadCoverageReport.yml
index eee9d4aec9..3f8fee4256 100644
--- a/.github/workflows/UploadCoverageReport.yml
+++ b/.github/workflows/UploadCoverageReport.yml
@@ -8,6 +8,9 @@ name: UploadCoverageReport
       - master
   pull_request:
 
+env:
+  REPORT_PATH: "coverage/coverage-final.json"
+
 jobs:
   UploadCoverageReport:
     runs-on: ubuntu-latest
@@ -25,9 +28,18 @@ jobs:
       - name: Generate coverage report
         run: npm test -- --coverage
 
-      - name: Upload coverage to codecov
-        uses: codecov/codecov-action@v3
+      - name: Upload coverage to codecov (tokenless)
+        if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository
+        uses: codecov/codecov-action@v4
+        with:
+          files: "${{ env.REPORT_PATH }}"
+          fail_ci_if_error: true
+
+      - name: Upload coverage to codecov (with token)
+        if: "! github.event.pull_request.head.repo.fork "
+        uses: codecov/codecov-action@v4
         with:
-          files: "coverage/coverage-final.json"
+          token: ${{ secrets.CODECOV_TOKEN }}
+          files: "${{ env.REPORT_PATH }}"
           fail_ci_if_error: true
 ...

From 5b17ea1a93042dc02a597d6fe4a20c0948b0496c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 4 Oct 2024 22:34:29 +0530
Subject: [PATCH 66/73] chore(deps): bump rollup from 4.9.6 to 4.22.4 (#1690)

Bumps [rollup](https://github.com/rollup/rollup) from 4.9.6 to 4.22.4.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.9.6...v4.22.4)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 package-lock.json | 240 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 221 insertions(+), 19 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 9a4fd732a9..c4e8c96761 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -174,30 +174,214 @@
         "node": ">= 8"
       }
     },
+    "node_modules/@rollup/rollup-android-arm-eabi": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz",
+      "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-android-arm64": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz",
+      "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-arm64": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz",
+      "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-x64": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz",
+      "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz",
+      "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz",
+      "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-gnu": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz",
+      "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-musl": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz",
+      "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz",
+      "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz",
+      "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-s390x-gnu": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz",
+      "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
     "node_modules/@rollup/rollup-linux-x64-gnu": {
-      "version": "4.9.6",
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz",
+      "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==",
       "cpu": [
         "x64"
       ],
       "dev": true,
-      "license": "MIT",
       "optional": true,
       "os": [
         "linux"
       ]
     },
     "node_modules/@rollup/rollup-linux-x64-musl": {
-      "version": "4.9.6",
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz",
+      "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==",
       "cpu": [
         "x64"
       ],
       "dev": true,
-      "license": "MIT",
       "optional": true,
       "os": [
         "linux"
       ]
     },
+    "node_modules/@rollup/rollup-win32-arm64-msvc": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz",
+      "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-ia32-msvc": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz",
+      "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-msvc": {
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz",
+      "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
     "node_modules/@types/estree": {
       "version": "1.0.5",
       "dev": true,
@@ -651,6 +835,20 @@
       "dev": true,
       "license": "ISC"
     },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
     "node_modules/get-func-name": {
       "version": "2.0.2",
       "dev": true,
@@ -1154,9 +1352,10 @@
       }
     },
     "node_modules/rollup": {
-      "version": "4.9.6",
+      "version": "4.22.4",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz",
+      "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==",
       "dev": true,
-      "license": "MIT",
       "dependencies": {
         "@types/estree": "1.0.5"
       },
@@ -1168,19 +1367,22 @@
         "npm": ">=8.0.0"
       },
       "optionalDependencies": {
-        "@rollup/rollup-android-arm-eabi": "4.9.6",
-        "@rollup/rollup-android-arm64": "4.9.6",
-        "@rollup/rollup-darwin-arm64": "4.9.6",
-        "@rollup/rollup-darwin-x64": "4.9.6",
-        "@rollup/rollup-linux-arm-gnueabihf": "4.9.6",
-        "@rollup/rollup-linux-arm64-gnu": "4.9.6",
-        "@rollup/rollup-linux-arm64-musl": "4.9.6",
-        "@rollup/rollup-linux-riscv64-gnu": "4.9.6",
-        "@rollup/rollup-linux-x64-gnu": "4.9.6",
-        "@rollup/rollup-linux-x64-musl": "4.9.6",
-        "@rollup/rollup-win32-arm64-msvc": "4.9.6",
-        "@rollup/rollup-win32-ia32-msvc": "4.9.6",
-        "@rollup/rollup-win32-x64-msvc": "4.9.6",
+        "@rollup/rollup-android-arm-eabi": "4.22.4",
+        "@rollup/rollup-android-arm64": "4.22.4",
+        "@rollup/rollup-darwin-arm64": "4.22.4",
+        "@rollup/rollup-darwin-x64": "4.22.4",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.22.4",
+        "@rollup/rollup-linux-arm-musleabihf": "4.22.4",
+        "@rollup/rollup-linux-arm64-gnu": "4.22.4",
+        "@rollup/rollup-linux-arm64-musl": "4.22.4",
+        "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4",
+        "@rollup/rollup-linux-riscv64-gnu": "4.22.4",
+        "@rollup/rollup-linux-s390x-gnu": "4.22.4",
+        "@rollup/rollup-linux-x64-gnu": "4.22.4",
+        "@rollup/rollup-linux-x64-musl": "4.22.4",
+        "@rollup/rollup-win32-arm64-msvc": "4.22.4",
+        "@rollup/rollup-win32-ia32-msvc": "4.22.4",
+        "@rollup/rollup-win32-x64-msvc": "4.22.4",
         "fsevents": "~2.3.2"
       }
     },

From 18da83a5b7acd3a841819ebd24346bba5ada1923 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sat, 5 Oct 2024 23:40:52 +0530
Subject: [PATCH 67/73] chore(deps): bump vite from 5.0.12 to 5.4.8 (#1711)

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.0.12 to 5.4.8.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.8/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.8/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 package-lock.json | 447 +++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 405 insertions(+), 42 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index c4e8c96761..5c38ba06a8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -76,13 +76,270 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/@esbuild/aix-ppc64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+      "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "aix"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+      "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+      "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+      "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+      "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+      "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+      "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+      "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+      "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+      "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+      "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+      "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+      "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+      "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+      "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+      "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/@esbuild/linux-x64": {
-      "version": "0.19.12",
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+      "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
       "cpu": [
         "x64"
       ],
       "dev": true,
-      "license": "MIT",
       "optional": true,
       "os": [
         "linux"
@@ -91,6 +348,102 @@
         "node": ">=12"
       }
     },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+      "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+      "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+      "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+      "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+      "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+      "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/@istanbuljs/schema": {
       "version": "0.1.3",
       "dev": true,
@@ -751,10 +1104,11 @@
       }
     },
     "node_modules/esbuild": {
-      "version": "0.19.12",
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+      "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
       "dev": true,
       "hasInstallScript": true,
-      "license": "MIT",
       "bin": {
         "esbuild": "bin/esbuild"
       },
@@ -762,29 +1116,29 @@
         "node": ">=12"
       },
       "optionalDependencies": {
-        "@esbuild/aix-ppc64": "0.19.12",
-        "@esbuild/android-arm": "0.19.12",
-        "@esbuild/android-arm64": "0.19.12",
-        "@esbuild/android-x64": "0.19.12",
-        "@esbuild/darwin-arm64": "0.19.12",
-        "@esbuild/darwin-x64": "0.19.12",
-        "@esbuild/freebsd-arm64": "0.19.12",
-        "@esbuild/freebsd-x64": "0.19.12",
-        "@esbuild/linux-arm": "0.19.12",
-        "@esbuild/linux-arm64": "0.19.12",
-        "@esbuild/linux-ia32": "0.19.12",
-        "@esbuild/linux-loong64": "0.19.12",
-        "@esbuild/linux-mips64el": "0.19.12",
-        "@esbuild/linux-ppc64": "0.19.12",
-        "@esbuild/linux-riscv64": "0.19.12",
-        "@esbuild/linux-s390x": "0.19.12",
-        "@esbuild/linux-x64": "0.19.12",
-        "@esbuild/netbsd-x64": "0.19.12",
-        "@esbuild/openbsd-x64": "0.19.12",
-        "@esbuild/sunos-x64": "0.19.12",
-        "@esbuild/win32-arm64": "0.19.12",
-        "@esbuild/win32-ia32": "0.19.12",
-        "@esbuild/win32-x64": "0.19.12"
+        "@esbuild/aix-ppc64": "0.21.5",
+        "@esbuild/android-arm": "0.21.5",
+        "@esbuild/android-arm64": "0.21.5",
+        "@esbuild/android-x64": "0.21.5",
+        "@esbuild/darwin-arm64": "0.21.5",
+        "@esbuild/darwin-x64": "0.21.5",
+        "@esbuild/freebsd-arm64": "0.21.5",
+        "@esbuild/freebsd-x64": "0.21.5",
+        "@esbuild/linux-arm": "0.21.5",
+        "@esbuild/linux-arm64": "0.21.5",
+        "@esbuild/linux-ia32": "0.21.5",
+        "@esbuild/linux-loong64": "0.21.5",
+        "@esbuild/linux-mips64el": "0.21.5",
+        "@esbuild/linux-ppc64": "0.21.5",
+        "@esbuild/linux-riscv64": "0.21.5",
+        "@esbuild/linux-s390x": "0.21.5",
+        "@esbuild/linux-x64": "0.21.5",
+        "@esbuild/netbsd-x64": "0.21.5",
+        "@esbuild/openbsd-x64": "0.21.5",
+        "@esbuild/sunos-x64": "0.21.5",
+        "@esbuild/win32-arm64": "0.21.5",
+        "@esbuild/win32-ia32": "0.21.5",
+        "@esbuild/win32-x64": "0.21.5"
       }
     },
     "node_modules/estree-walker": {
@@ -1191,6 +1545,8 @@
     },
     "node_modules/nanoid": {
       "version": "3.3.7",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+      "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
       "dev": true,
       "funding": [
         {
@@ -1198,7 +1554,6 @@
           "url": "https://github.com/sponsors/ai"
         }
       ],
-      "license": "MIT",
       "bin": {
         "nanoid": "bin/nanoid.cjs"
       },
@@ -1252,9 +1607,10 @@
       }
     },
     "node_modules/picocolors": {
-      "version": "1.0.0",
-      "dev": true,
-      "license": "ISC"
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
+      "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==",
+      "dev": true
     },
     "node_modules/picomatch": {
       "version": "2.3.1",
@@ -1278,7 +1634,9 @@
       }
     },
     "node_modules/postcss": {
-      "version": "8.4.33",
+      "version": "8.4.47",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
+      "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
       "dev": true,
       "funding": [
         {
@@ -1294,11 +1652,10 @@
           "url": "https://github.com/sponsors/ai"
         }
       ],
-      "license": "MIT",
       "dependencies": {
         "nanoid": "^3.3.7",
-        "picocolors": "^1.0.0",
-        "source-map-js": "^1.0.2"
+        "picocolors": "^1.1.0",
+        "source-map-js": "^1.2.1"
       },
       "engines": {
         "node": "^10 || ^12 || >=14"
@@ -1441,9 +1798,10 @@
       }
     },
     "node_modules/source-map-js": {
-      "version": "1.0.2",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
       "dev": true,
-      "license": "BSD-3-Clause",
       "engines": {
         "node": ">=0.10.0"
       }
@@ -1573,13 +1931,14 @@
       "license": "MIT"
     },
     "node_modules/vite": {
-      "version": "5.0.12",
+      "version": "5.4.8",
+      "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",
+      "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==",
       "dev": true,
-      "license": "MIT",
       "dependencies": {
-        "esbuild": "^0.19.3",
-        "postcss": "^8.4.32",
-        "rollup": "^4.2.0"
+        "esbuild": "^0.21.3",
+        "postcss": "^8.4.43",
+        "rollup": "^4.20.0"
       },
       "bin": {
         "vite": "bin/vite.js"
@@ -1598,6 +1957,7 @@
         "less": "*",
         "lightningcss": "^1.21.0",
         "sass": "*",
+        "sass-embedded": "*",
         "stylus": "*",
         "sugarss": "*",
         "terser": "^5.4.0"
@@ -1615,6 +1975,9 @@
         "sass": {
           "optional": true
         },
+        "sass-embedded": {
+          "optional": true
+        },
         "stylus": {
           "optional": true
         },

From ff314a2bed38525af0445fde53e37338b4db3406 Mon Sep 17 00:00:00 2001
From: Omkarnath Parida <pomkarnath98@gmail.com>
Date: Wed, 9 Oct 2024 05:24:11 +0530
Subject: [PATCH 68/73] Add tests for Project Euler Problem 5 + minor refactor
 (#1691)

---
 DIRECTORY.md                          |  3 +++
 Project-Euler/Problem005.js           |  8 +++-----
 Project-Euler/test/Problem005.test.js | 12 ++++++++++++
 3 files changed, 18 insertions(+), 5 deletions(-)
 create mode 100644 Project-Euler/test/Problem005.test.js

diff --git a/DIRECTORY.md b/DIRECTORY.md
index 6c1fa7aeb8..7f6484cae5 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -35,6 +35,8 @@
   * [ROT13](Ciphers/ROT13.js)
   * [VigenereCipher](Ciphers/VigenereCipher.js)
   * [XORCipher](Ciphers/XORCipher.js)
+* **Compression**
+  * [RLE](Compression/RLE.js)
 * **Conversions**
   * [ArbitraryBase](Conversions/ArbitraryBase.js)
   * [ArrayBufferToBase64](Conversions/ArrayBufferToBase64.js)
@@ -285,6 +287,7 @@
   * [Problem016](Project-Euler/Problem016.js)
   * [Problem017](Project-Euler/Problem017.js)
   * [Problem018](Project-Euler/Problem018.js)
+  * [Problem019](Project-Euler/Problem019.js)
   * [Problem020](Project-Euler/Problem020.js)
   * [Problem021](Project-Euler/Problem021.js)
   * [Problem023](Project-Euler/Problem023.js)
diff --git a/Project-Euler/Problem005.js b/Project-Euler/Problem005.js
index fe8901c94c..92f3df9b68 100644
--- a/Project-Euler/Problem005.js
+++ b/Project-Euler/Problem005.js
@@ -5,11 +5,9 @@ Smallest multiple
 What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
 */
 
-export const findSmallestMultiple = () => {
-  const divisors = [
-    20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2
-  ]
-  let num = 21
+export const findSmallestMultiple = (maxDivisor) => {
+  const divisors = Array.from({ length: maxDivisor }, (_, i) => i + 1)
+  let num = maxDivisor + 1
   let result
 
   while (!result) {
diff --git a/Project-Euler/test/Problem005.test.js b/Project-Euler/test/Problem005.test.js
new file mode 100644
index 0000000000..f3ac1b03d8
--- /dev/null
+++ b/Project-Euler/test/Problem005.test.js
@@ -0,0 +1,12 @@
+import { expect } from 'vitest'
+import { findSmallestMultiple } from '../Problem005.js'
+
+describe.concurrent('Find smallest multiple', () => {
+  test.each([
+    [10, 2520],
+    [15, 360360],
+    [20, 232792560]
+  ])('max divisor -> %i, smallest multiple -> %i', (a, expected) => {
+    expect(findSmallestMultiple(a)).toBe(expected)
+  })
+})

From 55ff0ade85c3b4857f0a6531a5dfda9f21007aff Mon Sep 17 00:00:00 2001
From: Hridyanshu <124202756+HRIDYANSHU054@users.noreply.github.com>
Date: Wed, 16 Oct 2024 23:52:31 +0530
Subject: [PATCH 69/73] docs: fixed misleading comment about the array method
 (forEach instead of reduce) used in AverageMean.js (#1727)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* docs: fixed misleading comment about the array method (forEach instead of reduce) used in AverageMean.js

* fix: optimized AverageMean.js by removing redundant comments and unnecessary operations.

* Update Maths/AverageMean.js

Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>

---------

Co-authored-by: Hridyanshu7 <himank7794@gmail.com>
Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>
---
 Maths/AverageMean.js | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/Maths/AverageMean.js b/Maths/AverageMean.js
index 75f7b1b58e..8ae3b55992 100644
--- a/Maths/AverageMean.js
+++ b/Maths/AverageMean.js
@@ -13,11 +13,7 @@ const mean = (nums) => {
     throw new TypeError('Invalid Input')
   }
 
-  // This loop sums all values in the 'nums' array using forEach loop
-  const sum = nums.reduce((sum, cur) => sum + cur, 0)
-
-  // Divide sum by the length of the 'nums' array.
-  return sum / nums.length
+  return nums.reduce((sum, cur) => sum + cur, 0) / nums.length
 }
 
 export { mean }

From d8588f9de18db16c29cd6c8332cd0de2c2bb2f3b Mon Sep 17 00:00:00 2001
From: Omkarnath Parida <pomkarnath98@gmail.com>
Date: Sat, 16 Nov 2024 21:38:17 +0530
Subject: [PATCH 70/73] Add tests for Project euler problem 14 solution (#1713)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* 📦 NEW: Added solution for ProjectEuler-007

* 🐛 FIX: Spelling mistake fixes

* 👌 IMPROVE: changed variable name from `inc` to `candidateValue` and thrown error in case of invalid input

* 👌 IMPROVE: Modified the code

* 👌 IMPROVE: Added test case for ProjectEuler Problem001

* 👌 IMPROVE: Added test cases for Project Euler Problem 4

* 👌 IMPROVE: auto prettier fixes

* 📦 NEW: Testcases for Project Euler Problem 14

* Updated Documentation in README.md

* 👌 IMPROVE: code improvements

---------

Co-authored-by: Omkarnath Parida <omkarnath.parida@yocket.in>
Co-authored-by: pomkarnath98 <pomkarnath98@users.noreply.github.com>
---
 Project-Euler/test/Problem014.test.js | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 Project-Euler/test/Problem014.test.js

diff --git a/Project-Euler/test/Problem014.test.js b/Project-Euler/test/Problem014.test.js
new file mode 100644
index 0000000000..ff464dd42d
--- /dev/null
+++ b/Project-Euler/test/Problem014.test.js
@@ -0,0 +1,15 @@
+import { expect } from 'vitest'
+import { findLongestCollatzSequence } from '../Problem014.js'
+
+describe('Longest Collatz Sequence', () => {
+  test.each([
+    [2, 1],
+    [13, 9],
+    [1000000, 837799]
+  ])(
+    'if limit is %i, then the Longest Collatz Sequence will be %i',
+    (a, expected) => {
+      expect(findLongestCollatzSequence(a)).toBe(expected)
+    }
+  )
+})

From 85a55daf49533b9fd558e52f13603a904613e4f2 Mon Sep 17 00:00:00 2001
From: Hridyanshu <124202756+HRIDYANSHU054@users.noreply.github.com>
Date: Fri, 20 Dec 2024 21:35:50 +0530
Subject: [PATCH 71/73] test: added for Linear Search Algorithm (#1753)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* test: added for Linear Search Algorithm

* Update Search/LinearSearch.js

Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>

---------

Co-authored-by: Hridyanshu7 <himank7794@gmail.com>
Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>
---
 Search/LinearSearch.js           |  2 ++
 Search/test/LinearSearch.test.js | 35 ++++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)
 create mode 100644 Search/test/LinearSearch.test.js

diff --git a/Search/LinearSearch.js b/Search/LinearSearch.js
index 637ebc1589..96a9d1fa34 100644
--- a/Search/LinearSearch.js
+++ b/Search/LinearSearch.js
@@ -3,6 +3,8 @@
  * value within a list. It sequentially checks each element of the list
  * for the target value until a match is found or until all the elements
  * have been searched.
+ *
+ * @see https://en.wikipedia.org/wiki/Linear_search
  */
 function SearchArray(searchNum, ar, output = (v) => console.log(v)) {
   const position = Search(ar, searchNum)
diff --git a/Search/test/LinearSearch.test.js b/Search/test/LinearSearch.test.js
new file mode 100644
index 0000000000..d593d9aa1c
--- /dev/null
+++ b/Search/test/LinearSearch.test.js
@@ -0,0 +1,35 @@
+import { Search as linearSearch } from '../LinearSearch'
+
+const tests = [
+  {
+    test: {
+      arr: [1, 2, 300, 401, 450, 504, 800, 821, 855, 900, 1002],
+      target: 900
+    },
+    expectedValue: 9
+  },
+  {
+    test: {
+      arr: [1, 104, 110, 4, 44, 55, 56, 78],
+      target: 104
+    },
+    expectedValue: 1
+  },
+  {
+    test: {
+      arr: [-4, 5, 50, 77, 821, 85, 99, 100],
+      target: 192
+    },
+    expectedValue: -1
+  }
+]
+
+describe('Linear Search', () => {
+  it.each(tests)(
+    'linearSearch($test.arr, $test.target) => $expectedValue',
+    ({ test, expectedValue }) => {
+      const { arr, target } = test
+      expect(linearSearch(arr, target)).toBe(expectedValue)
+    }
+  )
+})

From a62a46e732798622b520769c9c1131a052721ca2 Mon Sep 17 00:00:00 2001
From: Shankha Suvra Dam <71999854+SpiderMath@users.noreply.github.com>
Date: Sun, 12 Jan 2025 15:57:54 +0530
Subject: [PATCH 72/73] Resolve duplicate entries for sieve of eratosthenes 
 (#1770)

* remove intarr test

* Remove main file oops

* FIXES: #1666 , remove references to SieveOfEratosthenesIntArray

* Finally fix the requirements, passes vitest

* Updated Documentation in README.md

* FIXES: #1666 and conform to alg comment standards

---------

Co-authored-by: SpiderMath <SpiderMath@users.noreply.github.com>
---
 DIRECTORY.md                                  |  1 -
 Maths/SieveOfEratosthenes.js                  | 43 ++++++++++---------
 Maths/SieveOfEratosthenesIntArray.js          | 24 -----------
 Maths/test/SieveOfEratosthenes.test.js        | 37 +++++++++++-----
 .../test/SieveOfEratosthenesIntArray.test.js  | 12 ------
 Project-Euler/Problem035.js                   |  2 +-
 6 files changed, 49 insertions(+), 70 deletions(-)
 delete mode 100644 Maths/SieveOfEratosthenesIntArray.js
 delete mode 100644 Maths/test/SieveOfEratosthenesIntArray.test.js

diff --git a/DIRECTORY.md b/DIRECTORY.md
index 7f6484cae5..5e8e1f401a 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -254,7 +254,6 @@
   * [RowEchelon](Maths/RowEchelon.js)
   * [ShorsAlgorithm](Maths/ShorsAlgorithm.js)
   * [SieveOfEratosthenes](Maths/SieveOfEratosthenes.js)
-  * [SieveOfEratosthenesIntArray](Maths/SieveOfEratosthenesIntArray.js)
   * [Signum](Maths/Signum.js)
   * [SimpsonIntegration](Maths/SimpsonIntegration.js)
   * [Softmax](Maths/Softmax.js)
diff --git a/Maths/SieveOfEratosthenes.js b/Maths/SieveOfEratosthenes.js
index 01e141f2f0..681d8ba904 100644
--- a/Maths/SieveOfEratosthenes.js
+++ b/Maths/SieveOfEratosthenes.js
@@ -1,25 +1,26 @@
-const sieveOfEratosthenes = (n) => {
-  /*
-   * Calculates prime numbers till a number n
-   * :param n: Number up to which to calculate primes
-   * :return: A boolean list containing only primes
-   */
-  const primes = new Array(n + 1)
-  primes.fill(true) // set all as true initially
-  primes[0] = primes[1] = false // Handling case for 0 and 1
-  const sqrtn = Math.ceil(Math.sqrt(n))
-  for (let i = 2; i <= sqrtn; i++) {
-    if (primes[i]) {
-      for (let j = i * i; j <= n; j += i) {
-        /*
-        Optimization.
-        Let j start from i * i, not 2 * i, because smaller multiples of i have been marked false.
+/**
+ * @function sieveOfEratosthenes
+ * @description Function to get all the prime numbers below a given number using sieve of eratosthenes algorithm
+ * @param {Number} max The limit below which all the primes are required to be
+ * @returns {Number[]} An array of all the prime numbers below max
+ * @see [Sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes)
+ * @example
+ * sieveOfEratosthenes(1) // ====> []
+ * @example
+ * sieveOfEratosthenes(20) // ====> [2, 3, 5, 7, 11, 13, 17, 19]
+ *
+ */
+function sieveOfEratosthenes(max) {
+  const sieve = []
+  const primes = []
 
-        For example, let i = 4.
-        We do not have to check from 8(4 * 2) to 12(4 * 3)
-        because they have been already marked false when i=2 and i=3.
-        */
-        primes[j] = false
+  for (let i = 2; i <= max; ++i) {
+    if (!sieve[i]) {
+      // If i has not been marked then it is prime
+      primes.push(i)
+      for (let j = i << 1; j <= max; j += i) {
+        // Mark all multiples of i as non-prime
+        sieve[j] = true
       }
     }
   }
diff --git a/Maths/SieveOfEratosthenesIntArray.js b/Maths/SieveOfEratosthenesIntArray.js
deleted file mode 100644
index 56336ce7d8..0000000000
--- a/Maths/SieveOfEratosthenesIntArray.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Function to get all prime numbers below a given number
- * This function returns an array of prime numbers
- * @see {@link https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes}
- */
-
-function sieveOfEratosthenes(max) {
-  const sieve = []
-  const primes = []
-
-  for (let i = 2; i <= max; ++i) {
-    if (!sieve[i]) {
-      // If i has not been marked then it is prime
-      primes.push(i)
-      for (let j = i << 1; j <= max; j += i) {
-        // Mark all multiples of i as non-prime
-        sieve[j] = true
-      }
-    }
-  }
-  return primes
-}
-
-export { sieveOfEratosthenes }
diff --git a/Maths/test/SieveOfEratosthenes.test.js b/Maths/test/SieveOfEratosthenes.test.js
index 056693d39b..1a10b8bc7f 100644
--- a/Maths/test/SieveOfEratosthenes.test.js
+++ b/Maths/test/SieveOfEratosthenes.test.js
@@ -1,14 +1,29 @@
 import { sieveOfEratosthenes } from '../SieveOfEratosthenes'
-import { PrimeCheck } from '../PrimeCheck'
-
-describe('should return an array of prime booleans', () => {
-  it('should have each element in the array as a prime boolean', () => {
-    const n = 30
-    const primes = sieveOfEratosthenes(n)
-    primes.forEach((primeBool, index) => {
-      if (primeBool) {
-        expect(PrimeCheck(index)).toBeTruthy()
-      }
-    })
+
+describe('sieveOfEratosthenes', () => {
+  test('returns an empty array for max < 2', () => {
+    expect(sieveOfEratosthenes(1)).toEqual([])
+  })
+
+  test('returns [2] for max = 2', () => {
+    expect(sieveOfEratosthenes(2)).toEqual([2])
+  })
+
+  test('returns [2, 3] for max = 3', () => {
+    expect(sieveOfEratosthenes(3)).toEqual([2, 3])
+  })
+
+  test('returns [2, 3, 5, 7] for max = 10', () => {
+    expect(sieveOfEratosthenes(10)).toEqual([2, 3, 5, 7])
+  })
+
+  test('returns [2, 3, 5, 7, 11, 13, 17, 19] for max = 20', () => {
+    expect(sieveOfEratosthenes(20)).toEqual([2, 3, 5, 7, 11, 13, 17, 19])
+  })
+
+  test('returns [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] for max = 30', () => {
+    expect(sieveOfEratosthenes(30)).toEqual([
+      2, 3, 5, 7, 11, 13, 17, 19, 23, 29
+    ])
   })
 })
diff --git a/Maths/test/SieveOfEratosthenesIntArray.test.js b/Maths/test/SieveOfEratosthenesIntArray.test.js
deleted file mode 100644
index e3a3be3002..0000000000
--- a/Maths/test/SieveOfEratosthenesIntArray.test.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { sieveOfEratosthenes } from '../SieveOfEratosthenesIntArray'
-import { PrimeCheck } from '../PrimeCheck'
-
-describe('should return an array of prime numbers', () => {
-  it('should have each element in the array as a prime numbers', () => {
-    const n = 100
-    const primes = sieveOfEratosthenes(n)
-    primes.forEach((prime) => {
-      expect(PrimeCheck(prime)).toBeTruthy()
-    })
-  })
-})
diff --git a/Project-Euler/Problem035.js b/Project-Euler/Problem035.js
index c877acba5a..0b11cd0357 100644
--- a/Project-Euler/Problem035.js
+++ b/Project-Euler/Problem035.js
@@ -9,7 +9,7 @@
  *
  * @author ddaniel27
  */
-import { sieveOfEratosthenes } from '../Maths/SieveOfEratosthenesIntArray'
+import { sieveOfEratosthenes } from '../Maths/SieveOfEratosthenes'
 
 function problem35(n) {
   if (n < 2) {

From 1d252d7acae4ac46a3fc5d972c068cb95688c2f7 Mon Sep 17 00:00:00 2001
From: Ridge Kimani <101694484+ridge-kimani@users.noreply.github.com>
Date: Wed, 15 Jan 2025 14:11:02 +0300
Subject: [PATCH 73/73] feat: add tests for binary search trees (#1769)

---
 Data-Structures/Tree/BinarySearchTree.js      | 17 +++--
 .../Tree/test/BinarySearchTree.test.js        | 66 +++++++++++++++++++
 2 files changed, 76 insertions(+), 7 deletions(-)
 create mode 100644 Data-Structures/Tree/test/BinarySearchTree.test.js

diff --git a/Data-Structures/Tree/BinarySearchTree.js b/Data-Structures/Tree/BinarySearchTree.js
index abbcc3fb62..8a65c8e650 100644
--- a/Data-Structures/Tree/BinarySearchTree.js
+++ b/Data-Structures/Tree/BinarySearchTree.js
@@ -36,13 +36,13 @@ const Node = (function Node() {
     visit(output = (value) => console.log(value)) {
       // Recursively go left
       if (this.left !== null) {
-        this.left.visit()
+        this.left.visit(output)
       }
       // Print out value
       output(this.value)
       // Recursively go right
       if (this.right !== null) {
-        this.right.visit()
+        this.right.visit(output)
       }
     }
 
@@ -116,20 +116,23 @@ const Tree = (function () {
     }
 
     // Inorder traversal
-    traverse() {
+    traverse(output = (value) => console.log(value)) {
       if (!this.root) {
         // No nodes are there in the tree till now
         return
       }
-      this.root.visit()
+      this.root.visit(output)
     }
 
     // Start by searching the root
     search(val) {
-      const found = this.root.search(val)
-      if (found !== null) {
-        return found.value
+      if (this.root) {
+        const found = this.root.search(val)
+        if (found !== null) {
+          return found.value
+        }
       }
+
       // not found
       return null
     }
diff --git a/Data-Structures/Tree/test/BinarySearchTree.test.js b/Data-Structures/Tree/test/BinarySearchTree.test.js
new file mode 100644
index 0000000000..4c6c353592
--- /dev/null
+++ b/Data-Structures/Tree/test/BinarySearchTree.test.js
@@ -0,0 +1,66 @@
+import { Tree } from '../BinarySearchTree.js'
+
+describe('Binary Search Tree', () => {
+  let tree
+
+  beforeEach(() => {
+    tree = new Tree()
+    tree.addValue(10)
+    tree.addValue(5)
+    tree.addValue(15)
+    tree.addValue(3)
+    tree.addValue(8)
+  })
+
+  test('should add values to the tree', () => {
+    tree.addValue(12)
+
+    expect(tree.search(12)).toBe(12)
+    expect(tree.search(5)).toBe(5)
+    expect(tree.search(15)).toBe(15)
+  })
+
+  test('should perform in-order traversal', () => {
+    const values = []
+    const output = (val) => values.push(val)
+    tree.traverse(output)
+    expect(values).toEqual([3, 5, 8, 10, 15])
+  })
+
+  test('should remove leaf nodes correctly', () => {
+    tree.removeValue(5)
+    expect(tree.search(5)).toBeNull()
+  })
+
+  test('should remove nodes with one child correctly', () => {
+    tree.addValue(12)
+    tree.removeValue(15)
+
+    expect(tree.search(15)).toBeNull()
+    expect(tree.search(12)).toBe(12)
+  })
+
+  test('should remove nodes with two children correctly', () => {
+    tree.addValue(18)
+    tree.removeValue(15)
+
+    expect(tree.search(15)).toBeNull()
+    expect(tree.search(18)).toBe(18)
+  })
+
+  test('should return null for non-existent values', () => {
+    expect(tree.search(20)).toBeNull()
+    expect(tree.search(0)).toBeNull()
+  })
+
+  test('should handle removal of root node correctly', () => {
+    tree.removeValue(10)
+    expect(tree.search(10)).toBeNull()
+  })
+
+  test('should handle empty tree gracefully', () => {
+    const newTree = new Tree()
+    newTree.removeValue(22) // Should not throw
+    expect(newTree.search(22)).toBeNull()
+  })
+})
