[
  {
    "path": ".github/CODEOWNERS",
    "content": "* @appgurueu\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug report\ndescription: 'Create a report to help us improve'\ntitle: '[BUG]: '\nlabels: ['bug']\nbody:\n  - type: markdown\n    attributes:\n      value: '### Before you open an issue, please verify if a similar one already exists or has been closed before. More details about the process of contributing can be found in [CONTRIBUTING.md](https://github.com/TheAlgorithms/JavaScript/blob/master/CONTRIBUTING.md).'\n  - type: textarea\n    id: description\n    attributes:\n      label: Description\n      description: Explain what the problem is.\n    validations:\n      required: true\n  - type: textarea\n    id: expectedbhv\n    attributes:\n      label: Expected Behavior\n      description: Describe what was the expected behavior.\n    validations:\n      required: true\n  - type: textarea\n    id: actualbhv\n    attributes:\n      label: Actual Behavior\n      description: Describe what actually happens.\n    validations:\n      required: true\n  - type: textarea\n    id: steps\n    attributes:\n      label: Steps to reproduce (if applicable)\n      description: List steps to reproduce the behavior.\n      placeholder: |\n        1.\n        2.\n        3.\n        4.\n    validations:\n      required: false\n  - type: textarea\n    id: extra_information\n    attributes:\n      label: Additional information\n      description: Is there anything else we should know about this bug report?\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Discord community\n    url: https://the-algorithms.com/discord/\n    about: Have any questions or found any bugs? Contact us via our Discord community.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: Feature request\ndescription: 'Suggest features, propose improvements, discuss new ideas'\ntitle: '[FEATURE]: '\nlabels: ['enhancement']\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        ## This issue template is not for requesting new algorithms. For new algorithms, PRs should be opened directly.\n        ## Make sure your issue isn't a duplicate and you follow our [contributing guidelines](https://github.com/TheAlgorithms/JavaScript/blob/master/CONTRIBUTING.md)\n  - type: textarea\n    id: description\n    attributes:\n      label: Motivation\n      description: Describe what is the motivation behind this feature.\n    validations:\n      required: true\n  - type: textarea\n    id: examples\n    attributes:\n      label: Examples\n      description: If possible, provide examples of how this feature can be used.\n    validations:\n      required: false\n  - type: textarea\n    id: workarounds\n    attributes:\n      label: Possible workarounds\n      description: If possible, describes possible workarounds to this feature.\n    validations:\n      required: false\n  - type: textarea\n    id: extra_information\n    attributes:\n      label: Additional information\n      description: Is there anything else we should know about this feature request?\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/other.yml",
    "content": "name: Other issue\ndescription: Use this for any other issues. Do NOT create blank issues\ntitle: \"[OTHER]: \"\nlabels: [\"awaiting triage\"]\nbody:\n  - type: textarea\n    id: description\n    attributes:\n      label: What would you like to share?\n      description: Provide a clear and concise explanation of your issue.\n    validations:\n      required: true\n  - type: textarea\n    id: extrainfo\n    attributes:\n      label: Additional information\n      description: Is there anything else we should know about this issue?\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# Keep GitHub Actions up to date with Dependabot...\n# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot\nversion: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/from-referrer/)&nbsp;[know more](https://www.gitpod.io/docs/pull-requests/)\n\n### Describe your change:\n\n- [ ] Add an algorithm?\n- [ ] Fix a bug or typo in an existing algorithm?\n- [ ] Documentation change?\n\n### Checklist:\n\n- [ ] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Javascript/blob/master/CONTRIBUTING.md).\n- [ ] This pull request is all my own work -- I have not plagiarized.\n- [ ] I know that pull requests will not be merged if they fail the automated tests.\n- [ ] This PR only changes one algorithm file. To ease review, please open separate PRs for separate algorithms.\n- [ ] All new JavaScript files are placed inside an existing directory.\n- [ ] All filenames should use the UpperCamelCase (PascalCase) style. There should be no spaces in filenames.\n      **Example:**`UserProfile.js` is allowed but `userprofile.js`,`Userprofile.js`,`user-Profile.js`,`userProfile.js` are not\n- [ ] All new algorithms have a URL in their comments that points to Wikipedia or another similar explanation.\n- [ ] If this pull request resolves one or more open issues then the commit message contains `Fixes: #{$ISSUE_NO}`.\n"
  },
  {
    "path": ".github/stale.yml",
    "content": "# Number of days of inactivity before an issue becomes stale (2 weeks)\ndaysUntilStale: 14\n# Number of days of inactivity before a stale issue is closed (a week)\ndaysUntilClose: 7\n# Issues with these labels will never be considered stale\nexemptLabels:\n  - bug\n  - help wanted\n  - OK to merge\n# Label to use when marking an issue as stale\nstaleLabel: stale\n# Comment to post when marking an issue as stale. Set to `false` to disable\nmarkComment: >\n  This issue has been automatically marked as stale because it has not had\n  recent activity. It will be closed if no further activity occurs. Thank you\n  for your contributions.\n# Comment to post when closing a stale issue. Set to `false` to disable\ncloseComment: >\n  Please reopen this issue once you commit the changes requested or\n  make improvements on the code. Thank you for your contributions.\n"
  },
  {
    "path": ".github/workflows/Ci.yml",
    "content": "name: Continuous Integration\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n\njobs:\n  build:\n    name: Code style and tests\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 22\n          cache: npm\n\n      - name: 📦 Install dependencies\n        run: npm ci\n\n      - name: 🧪 Run all tests\n        run: npm run test\n\n      - name: 💄 Code style\n        run: npm run check-style\n\n  codespell:\n    name: Check for spelling errors\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: codespell-project/actions-codespell@master\n        with:\n          # file types to ignore\n          skip: \"*.json,*.yml,DIRECTORY.md\"\n          ignore_words_list: \"ba,esy,yse,falsy,abd\"\n"
  },
  {
    "path": ".github/workflows/UpdateDirectory.js",
    "content": "import path from 'path'\nimport fs from 'fs'\nimport { globby } from 'globby'\n\nfunction pathPrefix (i) {\n  const res = '  '.repeat(i)\n  return res + '*'\n}\n\nfunction printPath (oldPath, newPath, output) {\n  const oldParts = oldPath.split(path.sep)\n  const newParts = newPath.split(path.sep)\n\n  for (let i = 0; i < newParts.length; ++i) {\n    const newPart = newParts[i]\n    if (i + 1 > oldParts.length || oldParts[i] !== newPart) {\n      if (newPart) {\n        output.push(`${pathPrefix(i)} **${newPart.replace('_', ' ')}**`)\n      }\n    }\n  }\n\n  return newPath\n}\n\nfunction pathsToMarkdown (filePaths) {\n  const output = []\n\n  let oldPath = ''\n  filePaths.sort(function (a, b) {\n    if (a.toLowerCase() < b.toLowerCase()) return -1\n    if (a.toLowerCase() > b.toLowerCase()) return 1\n    return 0\n  })\n\n  for (let filepath of filePaths) {\n    let filename = path.basename(filepath)\n    filepath = path.dirname(filepath)\n\n    if (filepath !== oldPath) {\n      oldPath = printPath(oldPath, filepath, output)\n    }\n\n    let indent = filepath.split(path.sep).length\n\n    // prepare the markdown-esque prefix to the file's line\n    const prefix = pathPrefix(indent)\n\n    // remove extension from filename\n    const name = path.basename(filename, \".js\")\n    const url = path.join(filepath, filename)\n\n    output.push(`${prefix} [${name}](${url})`)\n  }\n\n  return output.join('\\n')\n}\n\n// get paths of all .js files - excluding node_modules, the .github folder, tests and config stuff\nglobby([\n  '**/*.js',\n  '!(node_modules|.github)/**/*',\n  \"!**/test/**/*\",\n  '!**/*.test.js',\n  '!**/*.manual-test.js',\n  '!vitest.config.ts'\n])\n  // create markdown content\n  .then(pathsToMarkdown)\n  // write markdown to file\n  .then(markdown => fs.writeFileSync('DIRECTORY.md', markdown + '\\n', { encoding: 'utf8' }))\n"
  },
  {
    "path": ".github/workflows/UpdateDirectory.yml",
    "content": "# This GitHub Action updates the DIRECTORY.md file (if needed) when doing a git push\nname: Update Directory\n\non:\n  push:\n    branches-ignore:\n      \"master\"\n\njobs:\n  updateDirectory:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 22\n          cache: npm\n\n      - name: 📦 Install dependencies\n        run: npm ci\n\n      - name: 🗄️ Create Directory from JS files\n        run: node .github/workflows/UpdateDirectory.js\n\n      - name: Configure Github Action\n        run: |\n          git config --global user.name \"$GITHUB_ACTOR\"\n          git config --global user.email \"$GITHUB_ACTOR@users.noreply.github.com\"\n\n      - name: 🤓 Commit & push new Directory (if needed)\n        run: |\n          if [[ `git status --porcelain` ]]; then\n            git commit -am \"Updated Documentation in README.md\"\n            git push\n          else\n            echo \"NO CHANGES DETECTED\"\n          fi\n"
  },
  {
    "path": ".github/workflows/UploadCoverageReport.yml",
    "content": "---\nname: UploadCoverageReport\n\n'on':\n  workflow_dispatch:\n  push:\n    branches:\n      - master\n  pull_request:\n\nenv:\n  REPORT_PATH: \"coverage/coverage-final.json\"\n\njobs:\n  UploadCoverageReport:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 22\n          cache: npm\n\n      - name: Install dependencies\n        run: npm ci\n\n      - name: Generate coverage report\n        run: npm test -- --coverage\n\n      - name: Upload coverage to codecov (tokenless)\n        if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository\n        uses: codecov/codecov-action@v4\n        with:\n          files: \"${{ env.REPORT_PATH }}\"\n          fail_ci_if_error: true\n\n      - name: Upload coverage to codecov (with token)\n        if: \"! github.event.pull_request.head.repo.fork \"\n        uses: codecov/codecov-action@v4\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }}\n          files: \"${{ env.REPORT_PATH }}\"\n          fail_ci_if_error: true\n...\n"
  },
  {
    "path": ".gitignore",
    "content": "# dependencies\n/node_modules\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# intelliJ workspace folder\n.idea\n.vscode\n.trae\n\n/coverage\n"
  },
  {
    "path": ".gitpod.yml",
    "content": "github:\n  prebuilds:\n    addBadge: true\n    addComment: false\n    addCheck: false\n    master: true\n    branches: true\n    pullRequestsFromForks: true\n\ntasks:\n  - init: npm install\n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nnpm run check-style\nnpm run test\n"
  },
  {
    "path": ".prettierignore",
    "content": ".github\nDIRECTORY.md\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"arrowParens\": \"always\",\n  \"bracketSpacing\": true,\n  \"endOfLine\": \"lf\",\n  \"insertPragma\": false,\n  \"printWidth\": 80,\n  \"proseWrap\": \"preserve\",\n  \"quoteProps\": \"as-needed\",\n  \"requirePragma\": false,\n  \"semi\": false,\n  \"singleQuote\": true,\n  \"tabWidth\": 2,\n  \"trailingComma\": \"none\",\n  \"useTabs\": false\n}\n"
  },
  {
    "path": "Backtracking/AllCombinationsOfSizeK.js",
    "content": "function generateCombinations(n, k) {\n  let currentCombination = []\n  let allCombinations = [] // will be used for storing all combinations\n  let currentValue = 1\n\n  function findCombinations() {\n    if (currentCombination.length === k) {\n      // Add the array of size k to the allCombinations array\n      allCombinations.push([...currentCombination])\n      return\n    }\n    if (currentValue > n) {\n      // Check for exceeding the range\n      return\n    }\n    currentCombination.push(currentValue++)\n    findCombinations()\n    currentCombination.pop()\n    findCombinations()\n    currentValue--\n  }\n\n  findCombinations()\n\n  return allCombinations\n}\n\nexport { generateCombinations }\n"
  },
  {
    "path": "Backtracking/GeneratePermutations.js",
    "content": "/*\n * Problem Statement: Generate all distinct permutations of an array (all permutations should be in sorted order);\n *\n * What is permutations?\n * - Permutation means possible arrangements in a set (here it is an array);\n *\n * Reference to know more about permutations:\n * - https://www.britannica.com/science/permutation\n *\n */\n\nconst swap = (arr, i, j) => {\n  const newArray = [...arr]\n\n  ;[newArray[i], newArray[j]] = [newArray[j], newArray[i]] // Swapping elements ES6 way\n\n  return newArray\n}\n\nconst permutations = (arr) => {\n  const P = []\n  const permute = (arr, low, high) => {\n    if (low === high) {\n      P.push([...arr])\n      return P\n    }\n    for (let i = low; i <= high; i++) {\n      arr = swap(arr, low, i)\n      permute(arr, low + 1, high)\n    }\n    return P\n  }\n  return permute(arr, 0, arr.length - 1)\n}\n\nexport { permutations }\n"
  },
  {
    "path": "Backtracking/KnightTour.js",
    "content": "// Wikipedia: https://en.wikipedia.org/wiki/Knight%27s_tour\n\nclass OpenKnightTour {\n  constructor(size) {\n    // Constructor to initialize the chessboard and size\n    this.board = new Array(size).fill(0).map(() => new Array(size).fill(0))\n    this.size = size\n  }\n\n  getMoves([i, j]) {\n    // Helper function to get the valid moves of the knight from the current position\n    const moves = [\n      [i + 2, j - 1],\n      [i + 2, j + 1],\n      [i - 2, j - 1],\n      [i - 2, j + 1],\n      [i + 1, j - 2],\n      [i + 1, j + 2],\n      [i - 1, j - 2],\n      [i - 1, j + 2]\n    ]\n\n    // Filter out moves that are within the board boundaries\n    return moves.filter(\n      ([y, x]) => y >= 0 && y < this.size && x >= 0 && x < this.size\n    )\n  }\n\n  isComplete() {\n    // Helper function to check if the board is complete\n    return !this.board.map((row) => row.includes(0)).includes(true)\n  }\n\n  solve() {\n    // Function to find the solution for the given board\n    for (let i = 0; i < this.size; i++) {\n      for (let j = 0; j < this.size; j++) {\n        if (this.solveHelper([i, j], 0)) return true\n      }\n    }\n    return false\n  }\n\n  solveHelper([i, j], curr) {\n    // Helper function for the main computation\n    if (this.isComplete()) return true\n\n    // Iterate through possible moves and attempt to fill the board\n    for (const [y, x] of this.getMoves([i, j])) {\n      if (this.board[y][x] === 0) {\n        this.board[y][x] = curr + 1\n        if (this.solveHelper([y, x], curr + 1)) return true\n        // Backtracking: If the solution is not found, reset the cell to 0\n        this.board[y][x] = 0\n      }\n    }\n    return false\n  }\n\n  printBoard(output = (value) => console.log(value)) {\n    // Utility function to display the board\n    for (const row of this.board) {\n      let string = ''\n      for (const elem of row) {\n        string += elem + '\\t'\n      }\n      output(string)\n    }\n  }\n}\n\nexport { OpenKnightTour }\n"
  },
  {
    "path": "Backtracking/MColoringProblem.js",
    "content": "/**\n * Colors a graph using up to m colors such that no two adjacent vertices share the same color.\n * @param {number[][]} graph - Adjacency matrix of the graph, using 0 for no edge.\n * @param {number} m - The number of colors to use.\n * @returns {?Array.<number>} A valid M-coloring of the graph using colors 1 to m, or null if none exists.\n * @see https://en.wikipedia.org/wiki/Graph_coloring\n */\nfunction mColoring(graph, m) {\n  const colors = new Array(graph.length).fill(0)\n\n  // Check if it's safe to color a vertex with a given color.\n  function isSafe(vertex, color) {\n    for (let i = 0; i < graph.length; i++) {\n      if (graph[vertex][i] && colors[i] === color) {\n        return false\n      }\n    }\n    return true\n  }\n\n  // Use backtracking to try and color the graph.\n  function solveColoring(vertex = 0) {\n    if (vertex === graph.length) {\n      return true\n    }\n\n    for (let color = 1; color <= m; color++) {\n      if (isSafe(vertex, color)) {\n        colors[vertex] = color\n\n        if (solveColoring(vertex + 1)) {\n          return true\n        }\n\n        // If no solution, backtrack.\n        colors[vertex] = 0\n      }\n    }\n    return false\n  }\n\n  // If coloring is possible, return the colors.\n  if (solveColoring()) {\n    return colors\n  }\n  return null\n}\n\nexport { mColoring }\n"
  },
  {
    "path": "Backtracking/NQueens.js",
    "content": "class NQueens {\n  constructor(size) {\n    if (size < 0) {\n      throw RangeError('Invalid board size')\n    }\n    this.board = new Array(size).fill('.').map(() => new Array(size).fill('.'))\n    this.size = size\n    this.solutionCount = 0\n  }\n\n  isValid([row, col]) {\n    // function to check if the placement of the queen in the given location is valid\n\n    // checking the left of the current row\n    for (let i = 0; i < col; i++) {\n      if (this.board[row][i] === 'Q') return false\n    }\n\n    // checking the upper left diagonal\n    for (let i = row, j = col; i >= 0 && j >= 0; i--, j--) {\n      if (this.board[i][j] === 'Q') return false\n    }\n\n    // checking the lower left diagonal\n    for (let i = row, j = col; j >= 0 && i < this.size; i++, j--) {\n      if (this.board[i][j] === 'Q') return false\n    }\n\n    return true\n  }\n\n  placeQueen(row, col) {\n    this.board[row][col] = 'Q'\n  }\n\n  removeQueen(row, col) {\n    this.board[row][col] = '.'\n  }\n\n  solve(col = 0) {\n    if (col >= this.size) {\n      this.solutionCount++\n      return true\n    }\n\n    for (let i = 0; i < this.size; i++) {\n      if (this.isValid([i, col])) {\n        this.placeQueen(i, col)\n        this.solve(col + 1)\n        this.removeQueen(i, col)\n      }\n    }\n\n    return false\n  }\n\n  printBoard(output = (value) => console.log(value)) {\n    if (!output._isMockFunction) {\n      output('\\n')\n    }\n    for (const row of this.board) {\n      output(row)\n    }\n  }\n}\n\nexport { NQueens }\n"
  },
  {
    "path": "Backtracking/RatInAMaze.js",
    "content": "/*\n * Problem Statement:\n * - Given a NxN grid, find whether rat in cell [0, 0] can reach the target in cell [N-1, N-1]\n * - The grid is represented as an array of rows. Each row is represented as an array of 0 or 1 values.\n * - A cell with value 0 can not be moved through. Value 1 means the rat can move here.\n * - The rat can not move diagonally.\n *\n * Reference for this problem: https://www.geeksforgeeks.org/rat-in-a-maze-backtracking-2/\n *\n * Based on the original implementation contributed by Chiranjeev Thapliyal (https://github.com/chiranjeev-thapliyal).\n */\n\n/**\n * Checks if the given grid is valid.\n *\n * A grid needs to satisfy these conditions:\n * - must not be empty\n * - must be a square\n * - must not contain values other than {@code 0} and {@code 1}\n *\n * @param grid The grid to check.\n * @throws TypeError When the given grid is invalid.\n */\nfunction validateGrid(grid) {\n  if (!Array.isArray(grid) || grid.length === 0)\n    throw new TypeError('Grid must be a non-empty array')\n\n  const allRowsHaveCorrectLength = grid.every(\n    (row) => row.length === grid.length\n  )\n  if (!allRowsHaveCorrectLength) throw new TypeError('Grid must be a square')\n\n  const allCellsHaveValidValues = grid.every((row) => {\n    return row.every((cell) => cell === 0 || cell === 1)\n  })\n  if (!allCellsHaveValidValues)\n    throw new TypeError('Grid must only contain 0s and 1s')\n}\n\nfunction isSafe(grid, x, y) {\n  const n = grid.length\n  return x >= 0 && x < n && y >= 0 && y < n && grid[y][x] === 1\n}\n\n/**\n * Attempts to calculate the remaining path to the target.\n *\n * @param grid The full grid.\n * @param x The current X coordinate.\n * @param y The current Y coordinate.\n * @param solution The current solution matrix.\n * @param path The path we took to get from the source cell to the current location.\n * @returns {string|boolean} Either the path to the target cell or false.\n */\nfunction getPathPart(grid, x, y, solution, path) {\n  const n = grid.length\n\n  // are we there yet?\n  if (x === n - 1 && y === n - 1 && grid[y][x] === 1) {\n    solution[y][x] = 1\n    return path\n  }\n\n  // did we step on a 0 cell or outside the grid?\n  if (!isSafe(grid, x, y)) return false\n\n  // are we walking onto an already-marked solution coordinate?\n  if (solution[y][x] === 1) return false\n\n  // none of the above? let's dig deeper!\n\n  // mark the current coordinates on the solution matrix\n  solution[y][x] = 1\n\n  // attempt to move right\n  const right = getPathPart(grid, x + 1, y, solution, path + 'R')\n  if (right) return right\n\n  // right didn't work: attempt to move down\n  const down = getPathPart(grid, x, y + 1, solution, path + 'D')\n  if (down) return down\n\n  // down didn't work: attempt to move up\n  const up = getPathPart(grid, x, y - 1, solution, path + 'U')\n  if (up) return up\n\n  // up didn't work: attempt to move left\n  const left = getPathPart(grid, x - 1, y, solution, path + 'L')\n  if (left) return left\n\n  // no direction was successful: remove this cell from the solution matrix and backtrack\n  solution[y][x] = 0\n  return false\n}\n\nfunction getPath(grid) {\n  // grid dimensions\n  const n = grid.length\n\n  // prepare solution matrix\n  const solution = []\n  for (let i = 0; i < n; i++) {\n    const row = Array(n)\n    row.fill(0)\n    solution[i] = row\n  }\n\n  return getPathPart(grid, 0, 0, solution, '')\n}\n\n/**\n * Creates an instance of the \"rat in a maze\" based on a given grid (maze).\n */\nexport class RatInAMaze {\n  constructor(grid) {\n    // first, let's do some error checking on the input\n    validateGrid(grid)\n\n    // attempt to solve the maze now - all public methods only query the result state later\n    const solution = getPath(grid)\n\n    if (solution !== false) {\n      this.path = solution\n      this.solved = true\n    } else {\n      this.path = ''\n      this.solved = false\n    }\n  }\n}\n"
  },
  {
    "path": "Backtracking/Sudoku.js",
    "content": "class Sudoku {\n  // Sudoku Class to hold the board and related functions\n  constructor(board) {\n    this.board = board\n  }\n\n  findEmptyCell() {\n    // Find a empty cell in the board (returns [-1, -1] if all cells are filled)\n    for (let i = 0; i < 9; i++) {\n      for (let j = 0; j < 9; j++) {\n        if (this.board[i][j] === 0) return [i, j]\n      }\n    }\n    return [-1, -1]\n  }\n\n  check([y, x], value) {\n    // checks if the value to be added in the board is an acceptable value for the cell\n\n    // checking through the row\n    for (let i = 0; i < 9; i++) {\n      if (this.board[i][x] === value) return false\n    }\n    // checking through the column\n    for (let i = 0; i < 9; i++) {\n      if (this.board[y][i] === value) return false\n    }\n\n    // checking through the 3x3 block of the cell\n    const secRow = Math.floor(y / 3)\n    const secCol = Math.floor(x / 3)\n    for (let i = secRow * 3; i < secRow * 3 + 3; i++) {\n      for (let j = secCol * 3; j < secCol * 3 + 3; j++) {\n        if (y !== i && x !== j && this.board[i][j] === value) return false\n      }\n    }\n\n    return true\n  }\n\n  solve() {\n    const [y, x] = this.findEmptyCell()\n\n    // checking if the board is complete\n    if (y === -1 && x === -1) return true\n\n    for (let val = 1; val < 10; val++) {\n      if (this.check([y, x], val)) {\n        this.board[y][x] = val\n        if (this.solve()) return true\n        // backtracking if the board cannot be solved using current configuration\n        this.board[y][x] = 0\n      }\n    }\n    // returning false the board cannot be solved using current configuration\n    return false\n  }\n\n  getSection(row, [start, end]) {\n    return this.board[row].slice(start, end)\n  }\n\n  printBoard(output = (...v) => console.log(...v)) {\n    // helper function to display board\n    for (let i = 0; i < 9; i++) {\n      if (i % 3 === 0 && i !== 0) {\n        output('- - - - - - - - - - - -')\n      }\n      output(\n        ...this.getSection(i, [0, 3]),\n        ' | ',\n        ...this.getSection(i, [3, 6]),\n        ' | ',\n        ...this.getSection(i, [6, 9])\n      )\n    }\n  }\n}\n\nexport { Sudoku }\n"
  },
  {
    "path": "Backtracking/SumOfSubset.js",
    "content": "/*\n *\n *  Sum of Subset problem\n *\n *  Given an ordered set W of non-negative integers and a value K,\n *  determine all possible subsets from the given set W whose sum\n *  of its elements equals to the given value K.\n *\n *  More info: https://www.geeksforgeeks.org/subset-sum-backtracking-4/\n */\n\n/*\n * @param {number[]} set Original set of numbers\n * @param {number[]} subset Subset being evaluated\n * @param {number} setIndex Index from set of last element in subset\n * @param {number} Sum of elements from subset\n * @param {targetSum} The target sum on which the subset sum is compared to\n * @returns {number[][]} Subsets whose elements add up to targetSum\n */\nconst sumOfSubset = (set, subset, setindex, sum, targetSum) => {\n  // Base case where the subset sum is equal to target sum\n  // Evaluation of following subsets on this path will always add up to\n  // greater than targetSum, so no need to continue\n  if (sum === targetSum) return [subset]\n\n  // This and following subsets on this path will always add up to\n  // greater than targetSum, so no need to continue\n  if (sum > targetSum) return []\n\n  // Initialize results array. Will contain only valid subsets\n  let results = []\n\n  // Slice gets from the set all the elements at the right of the last element\n  // to be evaluated (last element of subset)\n  // forEach iterated on the resulting array\n  set.slice(setindex).forEach((num, index) => {\n    // The next subset to be evaluated, current subset plus next element\n    const nextSubset = [...subset, num]\n\n    // Next index from the set. Current set index plus iteration index\n    // index starts at 0, so a + 1 is required\n    const nextSetIndex = setindex + index + 1\n\n    // Sum of elements from the next subset to be evaluated\n    const nextSum = sum + num\n\n    // Call recursively the sumOfSubset for the nextSubset\n    const subsetResult = sumOfSubset(\n      set,\n      nextSubset,\n      nextSetIndex,\n      nextSum,\n      targetSum\n    )\n\n    // Concat the recursive result with current result array\n    results = [...results, ...subsetResult]\n  })\n\n  // Return results\n  return results\n}\n\nexport { sumOfSubset }\n"
  },
  {
    "path": "Backtracking/generateParentheses.js",
    "content": "/**\n * Problem Statement: Given a number n pairs of parentheses, try to Generate all combinations of valid parentheses;\n * @param {number} n - number of given parentheses\n * @return {string[]} res - array that contains all valid parentheses\n * @see https://leetcode.com/problems/generate-parentheses/\n */\n\nconst generateParentheses = (n) => {\n  const res = []\n\n  const solve = (chres, openParenthese, closedParenthese) => {\n    if (openParenthese === n && closedParenthese === n) {\n      res.push(chres)\n      return\n    }\n\n    if (openParenthese <= n) {\n      solve(chres + '(', openParenthese + 1, closedParenthese)\n    }\n\n    if (closedParenthese < openParenthese) {\n      solve(chres + ')', openParenthese, closedParenthese + 1)\n    }\n  }\n\n  solve('', 0, 0)\n\n  return res\n}\n\nexport { generateParentheses }\n"
  },
  {
    "path": "Backtracking/tests/AllCombinationsOfSizeK.test.js",
    "content": "import { generateCombinations } from '../AllCombinationsOfSizeK'\n\ndescribe('AllCombinationsOfSizeK', () => {\n  it('should return 3x2 matrix solution for n = 3 and k = 2', () => {\n    const res = generateCombinations(3, 2)\n    expect(res).toEqual([\n      [1, 2],\n      [1, 3],\n      [2, 3]\n    ])\n  })\n\n  it('should return 6x2 matrix solution for n = 4 and k = 2', () => {\n    const res = generateCombinations(4, 2)\n    expect(res).toEqual([\n      [1, 2],\n      [1, 3],\n      [1, 4],\n      [2, 3],\n      [2, 4],\n      [3, 4]\n    ])\n  })\n})\n"
  },
  {
    "path": "Backtracking/tests/GenerateParentheses.test.js",
    "content": "import { generateParentheses } from '../generateParentheses'\n\ntest('generate all valid parentheses of input 3', () => {\n  expect(generateParentheses(3)).toStrictEqual([\n    '((()))',\n    '(()())',\n    '(())()',\n    '()(())',\n    '()()()'\n  ])\n})\n"
  },
  {
    "path": "Backtracking/tests/GeneratePermutations.test.js",
    "content": "import { factorial } from '../../Recursive/Factorial'\nimport { permutations } from '../GeneratePermutations'\n\ndescribe('Permutations', () => {\n  it('Permutations of [a]', () => {\n    const perms = permutations(['a'])\n    expect(perms).toHaveLength(factorial(1))\n    expect(perms).toContainEqual(['a'])\n  })\n\n  it('Permutations of [true, false]', () => {\n    const perms = permutations([true, false])\n    expect(perms).toHaveLength(factorial(2))\n    expect(perms).toContainEqual([true, false])\n    expect(perms).toContainEqual([false, true])\n  })\n\n  it('Permutations of [1, 2, 3]', () => {\n    const perms = permutations([1, 2, 3])\n    expect(perms).toHaveLength(factorial(3))\n    expect(perms).toContainEqual([1, 2, 3])\n    expect(perms).toContainEqual([1, 3, 2])\n    expect(perms).toContainEqual([2, 1, 3])\n    expect(perms).toContainEqual([2, 3, 1])\n    expect(perms).toContainEqual([3, 1, 2])\n    expect(perms).toContainEqual([3, 2, 1])\n  })\n\n  it('Permutation counts across larger input arrays', () => {\n    expect(permutations([1, 2, 3, 4, 5, 6, 7, 8])).toHaveLength(factorial(8))\n    expect(permutations([1, 2, 3, 4, 5, 6, 7, 8, 9])).toHaveLength(factorial(9))\n  })\n})\n"
  },
  {
    "path": "Backtracking/tests/KnightTour.test.js",
    "content": "import { OpenKnightTour } from '../KnightTour'\n\ndescribe('OpenKnightTour', () => {\n  it('OpenKnightTour(5)', () => {\n    const KT = new OpenKnightTour(5)\n    expect(KT.board).toEqual([\n      [0, 0, 0, 0, 0],\n      [0, 0, 0, 0, 0],\n      [0, 0, 0, 0, 0],\n      [0, 0, 0, 0, 0],\n      [0, 0, 0, 0, 0]\n    ])\n\n    expect(KT.solve()).toBe(true)\n    expect(KT.board).toEqual([\n      [19, 4, 15, 10, 25],\n      [14, 9, 18, 5, 16],\n      [1, 20, 3, 24, 11],\n      [8, 13, 22, 17, 6],\n      [21, 2, 7, 12, 23]\n    ])\n  })\n\n  it('OpenKnightTour(2)', () => {\n    const KT = new OpenKnightTour(2)\n    expect(KT.board).toEqual([\n      [0, 0],\n      [0, 0]\n    ])\n\n    expect(KT.solve()).toBe(false)\n    expect(KT.board).toEqual([\n      [0, 0],\n      [0, 0]\n    ])\n  })\n})\n"
  },
  {
    "path": "Backtracking/tests/MColoringProblem.test.js",
    "content": "import { mColoring } from '../MColoringProblem'\n\ndescribe('MColoringProblem', () => {\n  it('should color a triangle with 3 colors', () => {\n    const graph = [\n      [0, 1, 1],\n      [1, 0, 1],\n      [1, 1, 0]\n    ]\n    const solution = mColoring(graph, 3)\n    expect(solution).not.toBeNull()\n  })\n\n  it('should not color a triangle with 2 colors', () => {\n    const graph = [\n      [0, 1, 1],\n      [1, 0, 1],\n      [1, 1, 0]\n    ]\n    const solution = mColoring(graph, 2)\n    expect(solution).toBeNull()\n  })\n})\n"
  },
  {
    "path": "Backtracking/tests/NQueens.test.js",
    "content": "import { NQueens } from '../NQueens'\n\ndescribe('NQueens', () => {\n  it('should return 2 solutions for 4x4 size board', () => {\n    const _4Queens = new NQueens(4)\n    _4Queens.solve()\n    expect(_4Queens.solutionCount).toEqual(2)\n  })\n\n  it('should return 92 solutions for 8x8 size board', () => {\n    const _8Queens = new NQueens(8)\n    _8Queens.solve()\n    expect(_8Queens.solutionCount).toEqual(92)\n  })\n\n  it('should throw RangeError for negative size board', () => {\n    expect(() => {\n      return new NQueens(-1)\n    }).toThrow(RangeError)\n  })\n})\n"
  },
  {
    "path": "Backtracking/tests/RatInAMaze.test.js",
    "content": "import { RatInAMaze } from '../RatInAMaze'\n\ndescribe('RatInAMaze', () => {\n  it('should fail for non-arrays', () => {\n    const values = [undefined, null, {}, 42, 'hello, world']\n\n    for (const value of values) {\n      // we deliberately want to check whether this constructor call fails or not\n      expect(() => {\n        new RatInAMaze(value)\n      }).toThrow()\n    }\n  })\n\n  it('should fail for an empty array', () => {\n    // we deliberately want to check whether this constructor call fails or not\n    expect(() => {\n      new RatInAMaze([])\n    }).toThrow()\n  })\n\n  it('should fail for a non-square array', () => {\n    const array = [\n      [0, 0, 0],\n      [0, 0]\n    ]\n\n    // we deliberately want to check whether this constructor call fails or not\n    expect(() => {\n      new RatInAMaze(array)\n    }).toThrow()\n  })\n\n  it('should fail for arrays containing invalid values', () => {\n    const values = [[[2]], [['a']]]\n\n    for (const value of values) {\n      // we deliberately want to check whether this constructor call fails or not\n      expect(() => {\n        new RatInAMaze(value)\n      }).toThrow()\n    }\n  })\n\n  it('should work for a single-cell maze', () => {\n    const maze = new RatInAMaze([[1]])\n    expect(maze.solved).toBe(true)\n    expect(maze.path).toBe('')\n  })\n\n  it('should work for a single-cell maze that can not be solved', () => {\n    const maze = new RatInAMaze([[0]])\n    expect(maze.solved).toBe(false)\n    expect(maze.path).toBe('')\n  })\n\n  it('should work for a simple 3x3 maze', () => {\n    const maze = new RatInAMaze([\n      [1, 1, 0],\n      [0, 1, 0],\n      [0, 1, 1]\n    ])\n    expect(maze.solved).toBe(true)\n    expect(maze.path).toBe('RDDR')\n  })\n\n  it('should work for a simple 2x2 that can not be solved', () => {\n    const maze = new RatInAMaze([\n      [1, 0],\n      [0, 1]\n    ])\n    expect(maze.solved).toBe(false)\n    expect(maze.path).toBe('')\n  })\n\n  it('should work for a more complex maze', () => {\n    const maze = new RatInAMaze([\n      [1, 1, 1, 1, 1, 0, 0],\n      [0, 0, 0, 0, 1, 0, 0],\n      [1, 1, 1, 0, 1, 0, 0],\n      [1, 0, 1, 0, 1, 0, 0],\n      [1, 0, 1, 1, 1, 0, 0],\n      [1, 0, 0, 0, 0, 0, 0],\n      [1, 1, 1, 1, 1, 1, 1]\n    ])\n    expect(maze.solved).toBe(true)\n    expect(maze.path).toBe('RRRRDDDDLLUULLDDDDRRRRRR')\n  })\n\n  it('should work for a more complex maze that can not be solved', () => {\n    const maze = new RatInAMaze([\n      [1, 1, 1, 1, 1, 0, 1],\n      [0, 0, 0, 0, 1, 0, 1],\n      [1, 1, 1, 0, 1, 0, 1],\n      [1, 0, 1, 0, 1, 0, 1],\n      [1, 0, 1, 0, 1, 1, 1],\n      [1, 0, 0, 0, 0, 0, 0],\n      [1, 1, 1, 1, 1, 1, 1]\n    ])\n    expect(maze.solved).toBe(false)\n    expect(maze.path).toBe('')\n  })\n})\n"
  },
  {
    "path": "Backtracking/tests/Sudoku.test.js",
    "content": "import { Sudoku } from '../Sudoku'\n\nconst data = [\n  [3, 0, 6, 5, 0, 8, 4, 0, 0],\n  [5, 2, 0, 0, 0, 0, 0, 0, 0],\n  [0, 8, 7, 0, 0, 0, 0, 3, 1],\n  [0, 0, 3, 0, 1, 0, 0, 8, 0],\n  [9, 0, 0, 8, 6, 3, 0, 0, 5],\n  [0, 5, 0, 0, 9, 0, 6, 0, 0],\n  [1, 3, 0, 0, 0, 0, 2, 5, 0],\n  [0, 0, 0, 0, 0, 0, 0, 7, 4],\n  [0, 0, 5, 2, 0, 6, 3, 0, 0]\n]\n\nconst solved = [\n  [3, 1, 6, 5, 7, 8, 4, 9, 2],\n  [5, 2, 9, 1, 3, 4, 7, 6, 8],\n  [4, 8, 7, 6, 2, 9, 5, 3, 1],\n  [2, 6, 3, 4, 1, 5, 9, 8, 7],\n  [9, 7, 4, 8, 6, 3, 1, 2, 5],\n  [8, 5, 1, 7, 9, 2, 6, 4, 3],\n  [1, 3, 8, 9, 4, 7, 2, 5, 6],\n  [6, 9, 2, 3, 5, 1, 8, 7, 4],\n  [7, 4, 5, 2, 8, 6, 3, 1, 9]\n]\n\ndescribe('Sudoku', () => {\n  it('should create a valid board successfully', () => {\n    // we deliberately want to check whether this constructor call fails or not\n    expect(() => {\n      new Sudoku(data)\n    }).not.toThrow()\n  })\n\n  it('should find an empty cell', () => {\n    const board = new Sudoku(data)\n    const emptyCell = board.findEmptyCell()\n    expect(emptyCell).not.toEqual([-1, -1])\n  })\n\n  it('should solve the board successfully', () => {\n    const board = new Sudoku(data)\n    board.solve()\n\n    // should not have empty cells anymore\n    const emptyCell = board.findEmptyCell()\n    expect(emptyCell).toEqual([-1, -1])\n\n    // solved board should match our expectation\n    for (let i = 0; i < 9; i++) {\n      const section = board.getSection(i, [0, 9])\n      expect(section).toEqual(solved[i])\n    }\n  })\n})\n"
  },
  {
    "path": "Backtracking/tests/SumOfSubset.test.js",
    "content": "import { sumOfSubset } from '../SumOfSubset'\n\ndescribe('SumOfSubset', () => {\n  it('should return the subsets that add up to the given number', () => {\n    // W = [2, 5, 7, 8, 12, 16, 23, 40]\n    // K = 25\n\n    const nums = [2, 5, 7, 8, 12, 16, 23, 40]\n\n    const subsets = sumOfSubset(nums, [], 0, 0, 25)\n\n    expect(subsets).toEqual([\n      [2, 7, 16],\n      [2, 23],\n      [5, 8, 12]\n    ])\n  })\n})\n"
  },
  {
    "path": "Bit-Manipulation/BinaryCountSetBits.js",
    "content": "/*\n    author: vivek9patel\n    license: GPL-3.0 or later\n\n    This script will find number of 1's\n    in binary representation of given number\n\n*/\n\nfunction BinaryCountSetBits(a) {\n  'use strict'\n\n  // check whether input is an integer, some non-integer number like, 21.1 have non-terminating binary expansions and hence their binary expansion will contain infinite ones, thus the handling of non-integers (including strings,objects etc. as it is meaningless) has been omitted\n\n  if (!Number.isInteger(a)) throw new TypeError('Argument not an Integer')\n\n  let count = 0\n  while (a) {\n    a &= a - 1\n    count++\n  }\n\n  return count\n}\n\nexport { BinaryCountSetBits }\n"
  },
  {
    "path": "Bit-Manipulation/GenerateSubSets.js",
    "content": "/**\n * @function generateSubSets\n * @param {Array} inputArray\n * @returns {Array}\n * @example [1,2] -> [[],[1],[2],[1,2]]\n */\n\n// The time complexity of this algorithm is BigO(2^n) where n is the length of array\nfunction generateSubSets(inputArray) {\n  if (!Array.isArray(inputArray)) {\n    throw new Error('Provided input is not an array')\n  }\n  if (inputArray.length > 32) {\n    throw new RangeError('Error size should be less than equal to 32')\n  }\n  let arrayLength = inputArray.length\n  let subSets = []\n  // loop till (2^n) - 1\n  for (let i = 0; i < 1 << arrayLength; i++) {\n    let subSet = []\n    for (let j = 0; j < arrayLength; j++) {\n      // 1 << j it shifts binary digit 1 by j positions and then we perform\n      // and by AND operation we are checking whetheer jth bit\n      // in i is set to 1 if result is non zero just add into set\n      if (i & (1 << j)) {\n        subSet.push(inputArray[j])\n      }\n    }\n    subSets.push(subSet)\n  }\n  return subSets\n}\n\nexport { generateSubSets }\n"
  },
  {
    "path": "Bit-Manipulation/GrayCodes.js",
    "content": "/**\n * Generates a Gray code sequence for the given number of bits.\n * @param {number} n - The number of bits in the Gray code sequence.\n * @returns {number[]} - An array of Gray codes in binary format.\n * @description\n * Gray codes are binary sequences in which two successive values differ in only one bit.\n * This function generates a Gray code sequence of length 2^n for the given number of bits.\n *\n * The algorithm follows these steps:\n *\n * 1. Initialize an array `grayCodes` to store the Gray codes. Start with [0, 1] for n = 1.\n * 2. Iterate from 1 to n:\n *    a. Calculate `highestBit` as 2^i, where `i` is the current iteration index.\n *    b. Iterate in reverse order through the existing Gray codes:\n *       - For each Gray code `code`, add `highestBit | code` to `grayCodes`.\n *       - This operation flips a single bit in each existing code, creating new codes.\n * 3. Return the `grayCodes` array containing the Gray codes in decimal representation.\n *\n *resources: [GFG](https://www.geeksforgeeks.org/generate-n-bit-gray-codes/)\n * @example\n * const n = 3;\n * const grayCodes = generateGrayCodes(n);\n * // grayCodes will be [0, 1, 3, 2, 6, 7, 5, 4] for n=3.\n */\nfunction generateGrayCodes(n) {\n  if (n <= 0) {\n    return [0]\n  }\n\n  const grayCodes = [0, 1]\n\n  for (let i = 1; i < n; i++) {\n    const highestBit = 1 << i\n    for (let j = grayCodes.length - 1; j >= 0; j--) {\n      grayCodes.push(highestBit | grayCodes[j])\n    }\n  }\n\n  return grayCodes\n}\n\nexport { generateGrayCodes }\n"
  },
  {
    "path": "Bit-Manipulation/IsPowerOfTwo.js",
    "content": "/*\n    author: @Aayushi-Mittal\n\n    This script will check whether the given\n    number is a power of two or not.\n\n    A number will be a power of two if only one bit is set and rest are unset.\n    This is true for all the cases except 01 because (2^0 = 1) which is not a power of 2.\n    For eg: 10 (2^1 = 2), 100 (2^2 = 4), 10000 (2^4 = 16)\n\n    Reference Link: https://www.hackerearth.com/practice/notes/round-a-number-to-the-next-power-of-2/\n\n    If we will subtract 1 from a number that is a power of 2 we will get it's 1's complement.\n    And we know that 1's complement is just opp. of that number.\n    So, (n & (n-1)) will be 0.\n\n    For eg:    (1000 & (1000-1))\n                1 0 0 0     // Original Number (8)\n                0 1 1 1     // After Subtracting 1 (8-1 = 7)\n                _______\n                0 0 0 0     // will become 0\n\n*/\n\nexport const IsPowerOfTwo = (n) => {\n  return n > 0 && (n & (n - 1)) === 0\n}\n"
  },
  {
    "path": "Bit-Manipulation/IsPowerofFour.js",
    "content": "/**\n * @author : dev-madhurendra\n * Checks whether the given number is a power of four or not.\n *\n * A number is considered a power of four if and only if there is a single '1' bit in its binary representation,\n * and that '1' bit is at the first position, followed by an even number of '0' bits.\n *\n * @param {number} n - The input number to check.\n * @returns {boolean} True if the number is a power of four, false otherwise.\n *\n * @example\n * const result = isPowerOfFour(16); // Returns true (16 is 4^2)\n * const result2 = isPowerOfFour(5);  // Returns false (5 is not a power of four)\n */\nconst isPowerOfFour = (n) => n > 0 && (n & (n - 1)) === 0 && n % 3 === 1\n\nexport { isPowerOfFour }\n"
  },
  {
    "path": "Bit-Manipulation/LogTwo.js",
    "content": "/**\n * https://handwiki.org/wiki/Binary_logarithm\n * Approximate log2 using only bitwise operators\n * @param {number} n\n * @returns {number} Log2 approximation equal to floor(log2(n))\n */\nexport const logTwo = (n) => {\n  let result = 0\n  while (n >> 1) {\n    n >>= 1\n    result++\n  }\n  return result\n}\n"
  },
  {
    "path": "Bit-Manipulation/NextPowerOfTwo.js",
    "content": "/**\n *\n *  This script will find next power of two\n *    of given number.\n *  More about it:\n *   https://www.techiedelight.com/round-next-highest-power-2/\n *\n */\n\nexport const nextPowerOfTwo = (n) => {\n  if (n > 0 && (n & (n - 1)) === 0) return n\n  let result = 1\n  while (n > 0) {\n    result = result << 1\n    n = n >> 1\n  }\n  return result\n}\n"
  },
  {
    "path": "Bit-Manipulation/SetBit.js",
    "content": "/*\n * Setting Bit: https://www.geeksforgeeks.org/set-k-th-bit-given-number/\n *\n * To set any bit we use bitwise OR (|) operator.\n *\n * Bitwise OR (|) compares the bits of the 32\n * bit binary representations of the number and\n * returns a number after comparing each bit.\n *\n * 0 | 0 -> 0\n * 0 | 1 -> 1\n * 1 | 0 -> 1\n * 1 | 1 -> 1\n *\n * In-order to set kth bit of a number (where k is the position where bit is to be changed)\n * we need to shift 1 k times to its left and then perform bitwise OR operation with the\n * number and result of left shift performed just before.\n *\n * References:\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_OR\n */\n\n/**\n * @param {number} number\n * @param {number} bitPosition - zero based.\n * @return {number}\n */\n\nexport const setBit = (number, bitPosition) => {\n  return number | (1 << bitPosition)\n}\n"
  },
  {
    "path": "Bit-Manipulation/UniqueElementInAnArray.js",
    "content": "/**\n * Finds the unique element in an array where all other elements are repeated twice.\n *\n * @param {number[]} arr - The input array of integers.\n * @returns {number} The unique element.\n *\n * @example\n * const arr = [1, 2, 1, 2, 3];\n * const uniqueElement = findUniqueElement(arr); // Returns 3\n */\nconst findUniqueElement = (arr) => arr.reduce((acc, val) => acc ^ val, 0)\n\nexport { findUniqueElement }\n"
  },
  {
    "path": "Bit-Manipulation/test/BinaryCountSetBits.test.js",
    "content": "import { BinaryCountSetBits } from '../BinaryCountSetBits'\n\ntest('check BinaryCountSetBits of 25 is 3', () => {\n  const res = BinaryCountSetBits(25)\n  expect(res).toBe(3)\n})\ntest('check BinaryCountSetBits of 36 is 2', () => {\n  const res = BinaryCountSetBits(36)\n  expect(res).toBe(2)\n})\ntest('check BinaryCountSetBits of 16 is 1', () => {\n  const res = BinaryCountSetBits(16)\n  expect(res).toBe(1)\n})\ntest('check BinaryCountSetBits of 58 is 4', () => {\n  const res = BinaryCountSetBits(58)\n  expect(res).toBe(4)\n})\ntest('check BinaryCountSetBits of 4294967295 is 32', () => {\n  const res = BinaryCountSetBits(4294967295)\n  expect(res).toBe(32)\n})\ntest('check BinaryCountSetBits of 0 is 0', () => {\n  const res = BinaryCountSetBits(0)\n  expect(res).toBe(0)\n})\ntest('check BinaryCountSetBits of 21.1 throws error', () => {\n  expect(() => BinaryCountSetBits(21.1)).toThrow()\n})\ntest('check BinaryCountSetBits of {} throws error', () => {\n  expect(() => BinaryCountSetBits({})).toThrow()\n})\n"
  },
  {
    "path": "Bit-Manipulation/test/GenerateSubSets.test.js",
    "content": "import { generateSubSets } from '../GenerateSubSets'\n\ndescribe('subSets', () => {\n  it('find the subsets', () => {\n    expect(generateSubSets([1, 2, 3])).toEqual([\n      [],\n      [1],\n      [2],\n      [1, 2],\n      [3],\n      [1, 3],\n      [2, 3],\n      [1, 2, 3]\n    ])\n    expect(generateSubSets([1, 2])).toEqual([[], [1], [2], [1, 2]])\n    expect(generateSubSets([1, 2, 3])).toEqual([\n      [],\n      [1],\n      [2],\n      [1, 2],\n      [3],\n      [1, 3],\n      [2, 3],\n      [1, 2, 3]\n    ])\n    expect(() => generateSubSets('invalid')).toThrow(\n      'Provided input is not an array'\n    )\n    expect(() =>\n      generateSubSets([\n        1, 2, 2, 1, 2, 3, 4, 3, 2, 3, 4, 3, 2, 2, 2, 3, 12, 11, 4, 2, 2, 2, 2,\n        1, 2, 3, 5, 6, 7, 7, 8, 6, 5, 6, 7, 8, 9, 8, 0, 6\n      ])\n    ).toThrow('Error size should be less than equal to 32')\n  })\n})\n"
  },
  {
    "path": "Bit-Manipulation/test/GrayCodes.test.js",
    "content": "import { generateGrayCodes } from '../GrayCodes.js'\n\ndescribe('Gray codes', () => {\n  test.each([\n    [0, [0b0]],\n    [1, [0b0, 0b1]],\n    [2, [0b00, 0b01, 0b11, 0b10]],\n    [3, [0b000, 0b001, 0b011, 0b010, 0b110, 0b111, 0b101, 0b100]],\n    [\n      4,\n      [\n        0b0000, 0b0001, 0b0011, 0b0010, 0b0110, 0b0111, 0b0101, 0b0100, 0b1100,\n        0b1101, 0b1111, 0b1110, 0b1010, 0b1011, 0b1001, 0b1000\n      ]\n    ]\n  ])('n = %i -> %j', (n, expected) => {\n    expect(generateGrayCodes(n)).toEqual(expected)\n  })\n})\n"
  },
  {
    "path": "Bit-Manipulation/test/IsPowerOfFour.test.js",
    "content": "import { isPowerOfFour } from '../IsPowerofFour'\n\ndescribe('IsPowerOfFour', () => {\n  it.each([\n    [0, false],\n    [4, true],\n    [16, true],\n    [12, false],\n    [64, true],\n    [-64, false]\n  ])('should return the number is power of four or not', (n, expected) => {\n    expect(isPowerOfFour(n)).toBe(expected)\n  })\n})\n"
  },
  {
    "path": "Bit-Manipulation/test/IsPowerOfTwo.test.js",
    "content": "import { IsPowerOfTwo } from '../IsPowerOfTwo'\n\ntest('Check if 0 is a power of 2 or not:', () => {\n  const res = IsPowerOfTwo(0)\n  expect(res).toBe(false)\n})\n\ntest('Check if 1 is a power of 2 or not:', () => {\n  const res = IsPowerOfTwo(1)\n  expect(res).toBe(true)\n})\n\ntest('Check if 4 is a power of 2 or not:', () => {\n  const res = IsPowerOfTwo(4)\n  expect(res).toBe(true)\n})\n\ntest('Check if 1024 is a power of 2 or not:', () => {\n  const res = IsPowerOfTwo(1024)\n  expect(res).toBe(true)\n})\n\ntest('Check if 1025 is a power of 2 or not:', () => {\n  const res = IsPowerOfTwo(1025)\n  expect(res).toBe(false)\n})\n"
  },
  {
    "path": "Bit-Manipulation/test/LogTwo.test.js",
    "content": "import { logTwo } from '../LogTwo'\n\nfor (let i = 1; i < 100; i++) {\n  test('log2(' + i + ')', () => {\n    expect(logTwo(i)).toBe(Math.floor(Math.log2(i)))\n  })\n}\n"
  },
  {
    "path": "Bit-Manipulation/test/NextPowerOfTwo.test.js",
    "content": "import { nextPowerOfTwo } from '../NextPowerOfTwo'\n\ndescribe('NextPowerOfTwo', () => {\n  it.each`\n    input    | result\n    ${0}     | ${1}\n    ${1}     | ${1}\n    ${2}     | ${2}\n    ${3}     | ${4}\n    ${5}     | ${8}\n    ${125}   | ${128}\n    ${1024}  | ${1024}\n    ${10000} | ${16384}\n  `('returns $result when is given $input', ({ input, result }) => {\n    const res = nextPowerOfTwo(input)\n    expect(res).toBe(result)\n  })\n})\n"
  },
  {
    "path": "Bit-Manipulation/test/SetBit.test.js",
    "content": "import { setBit } from '../SetBit'\n\ntest('Set bit number 0 in 1:', () => {\n  const setBitPos = setBit(1, 0)\n  expect(setBitPos).toBe(1)\n})\n\ntest('Set bit number 0 in 2:', () => {\n  const setBitPos = setBit(2, 0)\n  expect(setBitPos).toBe(3)\n})\n\ntest('Set bit number 1 in 10:', () => {\n  const setBitPos = setBit(10, 1)\n  expect(setBitPos).toBe(10)\n})\n\ntest('Set bit number 2 in 10:', () => {\n  const setBitPos = setBit(10, 2)\n  expect(setBitPos).toBe(14)\n})\n"
  },
  {
    "path": "Bit-Manipulation/test/UniqueElementInAnArray.test.js",
    "content": "import { findUniqueElement } from '../UniqueElementInAnArray'\n\ndescribe('UniqueElementInAnArray', () => {\n  it.each([\n    [[1, 2, 1, 3, 3], 2],\n    [[1, 2, 3, 4, 5, 4, 3, 2, 1], 5]\n  ])('should return an unique element from an array', (arr, expected) => {\n    expect(findUniqueElement(arr)).toBe(expected)\n  })\n})\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing guidelines\n\n## Before contributing\n\nWelcome to [TheAlgorithms/JavaScript](https://github.com/TheAlgorithms/JavaScript)! Before sending your pull requests,\nmake sure that you **read the whole guidelines**. If you have any doubts about the contributing guide, please feel free to\n[state them clearly in an issue](https://github.com/TheAlgorithms/JavaScript/issues/new) or by joining our [Discord community](https://the-algorithms.com/discord).\n\n## Contributing\n\n### Contributor\n\nWe are very happy that you consider implementing algorithms and data structures for others! This repository is\nreferenced and used by learners from around the globe. Being one of our contributors, you agree and confirm that:\n\n- You did your work - plagiarism is not allowed.\n  - Any plagiarized work will not be merged.\n- Your work will be distributed under the [GNU GPLv3.0](https://github.com/TheAlgorithms/JavaScript/blob/master/LICENSE) once your pull request is merged.\n- Your submitted work must fulfill our styles and standards.\n\n**New implementations** are welcome! For example, new solutions to a problem, different representations of a graph data\nstructure, or algorithm designs with different complexity.\n\n**Improving comments** and **writing proper tests** are also highly welcome.\n\n### Contribution\n\nWe appreciate any contribution, from fixing grammar mistakes to implementing complex algorithms. Please read this\nsection if you are contributing to your work.\n\nIf you submit a pull request that resolves an open issue, please help us to keep our issue list small by adding\n`fixes: #{$ISSUE_NO}` to your commit message. GitHub will use this tag to auto-close the issue if your PR is merged.\n\n#### What is an Algorithm?\n\nAn Algorithm is one or more functions (or classes) that:\n\n- take one or more inputs.\n- perform some internal calculations or data manipulations.\n- return one or more outputs.\n- have minimal side effects.\n\nAlgorithms should be packaged in a way that would make it easy for readers to put them into larger programs.\n\nAlgorithms should:\n\n- have intuitive class and function names that make their purpose clear to readers.\n- use JavaScript naming conventions and intuitive variable names to ease comprehension.\n- be flexible to take different input values.\n- raise JavaScript exceptions (RangeError, etc.) on erroneous input values.\n\nAlgorithms in this repo should not be how-to examples for existing JavaScript packages. Instead, they should perform\ninternal calculations or manipulations to convert input values into different output values. Those calculations or\nmanipulations can use data types, classes, or functions of existing JavaScript packages but each algorithm in this repo\nshould add a unique value.\n\n#### Commit guidelines\n\n- Follow [**Conventional Commits**](https://www.conventionalcommits.org/en/v1.0.0/) guidelines at all times.\n- Use one of the following prefixes (there might be other miscellaneous prefixes, though).\n  - fix: A bug fix in an algorithm, workflow, configuration/settings, etc..\n  - feat: A new feature, such as new algorithms, new workflows, etc..\n  - docs: Documentation changes or fixes, like improving the contributing guidelines, fixing a typo, etc..\n  - test: Correct existing tests or add new ones.\n  - chore: Miscellaneous changes that do not match any of the above.\n\nExamples of best commit messages.\n\n```txt\nfix: fixed error in XYZ algorithm\nfeat: re-work the CI workflow\ndocs: improve the contributing guidelines\ntest: add self-tests for XYZ algorithm\nchore: update readme badges\n```\n\n#### File Naming Convention\n\n- Filenames should use the UpperCamelCase (PascalCase) style.\n- There should be no spaces in filenames.\n- **Example:** `UserProfile.js` is allowed but `userprofile.js`,`Userprofile.js`,`user-Profile.js`,`userProfile.js` are\n  not.\n\n#### Module System\n\nWe use the [ES Module](https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/) system, which brings an\nofficial, standardized module system to JavaScript.\n\nIt roughly means you will need to use `export` and `import` statements instead of `module.exports` and `require()`.\n\n#### Testing\n\nBe confident that your code works. When was the last time you committed a code change, your build failed, and half of\nyour app stopped working? Mine was last week. Writing tests for our Algorithms will help us ensure the implementations\nare airtight even after multiple fixes and code changes.\n\nWe use [Vitest](https://vitest.dev/) to run unit tests on our algorithms. It provides a very readable and expressive\nway to structure your test code.\n\nIt is advised that the algorithm file (module) does not contain any \"live\" code but rather just exports the function(s)\nneeded to execute the algorithm. Your test code can import those function(s), call them with the appropriate parameters\nand inspect the outcome. Example: [RatInAMaze.test.js](Backtracking/tests/RatInAMaze.test.js).\n\nPlease refrain from using `console` in your implementation AND test code.\n\nFirst, you should install all dependencies using:\n\n```bash\nnpm install\n```\n\nYou can (and should!) run all tests locally before committing your changes:\n\n```bash\nnpm test\n```\n\nIf you want to save some time and just run a specific test:\n\n```bash\n# This will run any test file where the filename contains \"koch\" (no need to specify folder path)\nnpm test -- koch\n```\n\nYou can also start Vitest in \"watch\" mode:\n\n```bash\nnpm run test-watch\n```\n\nThis will run all tests and watch source and test files for changes. When a change is made, the tests will run again.\n\n#### Coding Style\n\nFor consistency and readability, we require that new submissions follow the [Prettier Style](https://prettier.io/).\nBefore committing, please format your code automatically using Prettier by running the following command:\n\n```bash\nnpm run style\n```\n\nA few (but not all) of the things to keep in mind:\n\n- Use camelCase with the leading character as lowercase for identifier names (variables and functions).\n- Names start with a letter.\n- Follow code indentation: Always use 2 spaces for code-block indentation.\n\n```js\nfunction sumOfArray(arrayOfNumbers) {\n  let sum = 0\n\n  for (let i = 0; i < arrayOfNumbers.length; i++) {\n    sum += arrayOfNumbers[i]\n  }\n\n  return sum\n}\n```\n\n- Avoid using global variables and avoid `==`.\n- Please use `let` over `var`.\n- Please refrain from using `console.log` or any other console methods.\n- **Absolutely** don't use `alert`.\n- We strongly recommend the use of ECMAScript 6.\n- Avoid importing external libraries for basic algorithms. Only use those libraries for complicated algorithms.\n- Most importantly:\n  - **Be consistent in the use of these guidelines when submitting.**\n  - Happy coding!\n\nWriter [@itsvinayak](https://github.com/itsvinayak) and contributors, May 2020.\n"
  },
  {
    "path": "Cache/LFUCache.js",
    "content": "class CacheNode {\n  constructor(key, value, frequency) {\n    this.key = key\n    this.value = value\n    this.frequency = frequency\n\n    return Object.seal(this)\n  }\n}\n\n// This frequency map class will act like javascript Map DS with more two custom method refresh & insert\nclass FrequencyMap extends Map {\n  static get [Symbol.species]() {\n    return Map\n  } // for using Symbol.species we can access Map constructor  @see -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/@@species\n  get [Symbol.toStringTag]() {\n    return ''\n  }\n\n  /**\n   * @method refresh\n   * @description - It's revive a CacheNode, increment of this nodes frequency and refresh the frequencyMap via new incremented nodes frequency\n   * @param {CacheNode} node\n   */\n  refresh(node) {\n    const { frequency } = node\n    const freqSet = this.get(frequency)\n    freqSet.delete(node)\n\n    node.frequency++\n\n    this.insert(node)\n  }\n\n  /**\n   * @method insert\n   * @description - Add new CacheNode into HashSet by the frequency\n   * @param {CacheNode} node\n   */\n  insert(node) {\n    const { frequency } = node\n\n    if (!this.has(frequency)) {\n      this.set(frequency, new Set())\n    }\n\n    this.get(frequency).add(node)\n  }\n}\n\nclass LFUCache {\n  #capacity\n  #frequencyMap\n\n  /**\n   * @param {number} capacity - The range of LFUCache\n   * @returns {LFUCache} - sealed\n   */\n  constructor(capacity) {\n    this.#capacity = capacity\n    this.#frequencyMap = new FrequencyMap()\n    this.misses = 0\n    this.hits = 0\n    this.cache = new Map()\n\n    return Object.seal(this)\n  }\n\n  /**\n   * Get the capacity of the LFUCache\n   * @returns {number}\n   */\n  get capacity() {\n    return this.#capacity\n  }\n\n  /**\n   * Get the current size of LFUCache\n   * @returns {number}\n   */\n  get size() {\n    return this.cache.size\n  }\n\n  /**\n   * Set the capacity of the LFUCache if you decrease the capacity its removed CacheNodes following the LFU - least frequency used\n   */\n  set capacity(newCapacity) {\n    if (this.#capacity > newCapacity) {\n      let diff = this.#capacity - newCapacity // get the decrement number of capacity\n\n      while (diff--) {\n        this.#removeCacheNode()\n      }\n\n      this.cache.size === 0 && this.#frequencyMap.clear()\n    }\n\n    this.#capacity = newCapacity\n  }\n\n  get info() {\n    return Object.freeze({\n      misses: this.misses,\n      hits: this.hits,\n      capacity: this.capacity,\n      currentSize: this.size,\n      leastFrequency: this.leastFrequency\n    })\n  }\n\n  get leastFrequency() {\n    const freqCacheIterator = this.#frequencyMap.keys()\n    let leastFrequency = freqCacheIterator.next().value || null\n\n    // select the non-empty frequency Set\n    while (this.#frequencyMap.get(leastFrequency)?.size === 0) {\n      leastFrequency = freqCacheIterator.next().value\n    }\n\n    return leastFrequency\n  }\n\n  #removeCacheNode() {\n    const leastFreqSet = this.#frequencyMap.get(this.leastFrequency)\n    // Select the least recently used node from the least Frequency set\n    const LFUNode = leastFreqSet.values().next().value\n\n    leastFreqSet.delete(LFUNode)\n    this.cache.delete(LFUNode.key)\n  }\n\n  /**\n   * if key exist then return true otherwise false\n   * @param {any} key\n   * @returns {boolean}\n   */\n  has(key) {\n    key = String(key) // converted to string\n\n    return this.cache.has(key)\n  }\n\n  /**\n   * @method get\n   * @description - This method return the value of key & refresh the frequencyMap by the oldNode\n   * @param {string} key\n   * @returns {any}\n   */\n  get(key) {\n    key = String(key) // converted to string\n\n    if (this.cache.has(key)) {\n      const oldNode = this.cache.get(key)\n      this.#frequencyMap.refresh(oldNode)\n\n      this.hits++\n\n      return oldNode.value\n    }\n\n    this.misses++\n    return null\n  }\n\n  /**\n   * @method set\n   * @description - This method stored the value by key & add frequency if it doesn't exist\n   * @param {string} key\n   * @param {any} value\n   * @param {number} frequency\n   * @returns {LFUCache}\n   */\n  set(key, value, frequency = 1) {\n    key = String(key) // converted to string\n\n    if (this.#capacity === 0) {\n      throw new RangeError('LFUCache ERROR: The Capacity is 0')\n    }\n\n    if (this.cache.has(key)) {\n      const node = this.cache.get(key)\n      node.value = value\n\n      this.#frequencyMap.refresh(node)\n\n      return this\n    }\n\n    // if the cache size is full, then it's delete the Least Frequency Used node\n    if (this.#capacity === this.cache.size) {\n      this.#removeCacheNode()\n    }\n\n    const newNode = new CacheNode(key, value, frequency)\n\n    this.cache.set(key, newNode)\n    this.#frequencyMap.insert(newNode)\n\n    return this\n  }\n\n  /**\n   * @method parse\n   * @description - This method receive a valid LFUCache JSON & run JSON.prase() method and merge with existing LFUCache\n   * @param {JSON} json\n   * @returns {LFUCache} - merged\n   */\n  parse(json) {\n    const { misses, hits, cache } = JSON.parse(json)\n\n    this.misses += misses ?? 0\n    this.hits += hits ?? 0\n\n    for (const key in cache) {\n      const { value, frequency } = cache[key]\n      this.set(key, value, frequency)\n    }\n\n    return this\n  }\n\n  /**\n   * @method clear\n   * @description - This method cleared the whole LFUCache\n   * @returns {LFUCache}\n   */\n  clear() {\n    this.cache.clear()\n    this.#frequencyMap.clear()\n\n    return this\n  }\n\n  /**\n   * @method toString\n   * @description - This method generate a JSON format of LFUCache & return it.\n   * @param {number} indent\n   * @returns {string} - JSON\n   */\n  toString(indent) {\n    const replacer = (_, value) => {\n      if (value instanceof Set) {\n        return [...value]\n      }\n\n      if (value instanceof Map) {\n        return Object.fromEntries(value)\n      }\n\n      return value\n    }\n\n    return JSON.stringify(this, replacer, indent)\n  }\n}\n\nexport default LFUCache\n"
  },
  {
    "path": "Cache/LRUCache.js",
    "content": "class LRUCache {\n  // LRU Cache to store a given capacity of data\n  #capacity\n\n  /**\n   * @param {number} capacity - the capacity of LRUCache\n   * @returns {LRUCache} - sealed\n   */\n  constructor(capacity) {\n    if (!Number.isInteger(capacity) || capacity < 0) {\n      throw new TypeError('Invalid capacity')\n    }\n\n    this.#capacity = ~~capacity\n    this.misses = 0\n    this.hits = 0\n    this.cache = new Map()\n\n    return Object.seal(this)\n  }\n\n  get info() {\n    return Object.freeze({\n      misses: this.misses,\n      hits: this.hits,\n      capacity: this.capacity,\n      size: this.size\n    })\n  }\n\n  get size() {\n    return this.cache.size\n  }\n\n  get capacity() {\n    return this.#capacity\n  }\n\n  set capacity(newCapacity) {\n    if (newCapacity < 0) {\n      throw new RangeError('Capacity should be greater than 0')\n    }\n\n    if (newCapacity < this.capacity) {\n      let diff = this.capacity - newCapacity\n\n      while (diff--) {\n        this.#removeLeastRecentlyUsed()\n      }\n    }\n\n    this.#capacity = newCapacity\n  }\n\n  /**\n   * delete oldest key existing in map by the help of iterator\n   */\n  #removeLeastRecentlyUsed() {\n    this.cache.delete(this.cache.keys().next().value)\n  }\n\n  /**\n   * @param {string} key\n   * @returns {*}\n   */\n  has(key) {\n    key = String(key)\n\n    return this.cache.has(key)\n  }\n\n  /**\n   * @param {string} key\n   * @param {*} value\n   */\n  set(key, value) {\n    key = String(key)\n    // Sets the value for the input key and if the key exists it updates the existing key\n    if (this.size === this.capacity) {\n      this.#removeLeastRecentlyUsed()\n    }\n\n    this.cache.set(key, value)\n  }\n\n  /**\n   * @param {string} key\n   * @returns {*}\n   */\n  get(key) {\n    key = String(key)\n    // Returns the value for the input key. Returns null if key is not present in cache\n    if (this.cache.has(key)) {\n      const value = this.cache.get(key)\n\n      // refresh the cache to update the order of key\n      this.cache.delete(key)\n      this.cache.set(key, value)\n\n      this.hits++\n      return value\n    }\n\n    this.misses++\n    return null\n  }\n\n  /**\n   * @param {JSON} json\n   * @returns {LRUCache}\n   */\n  parse(json) {\n    const { misses, hits, cache } = JSON.parse(json)\n\n    this.misses += misses ?? 0\n    this.hits += hits ?? 0\n\n    for (const key in cache) {\n      this.set(key, cache[key])\n    }\n\n    return this\n  }\n\n  /**\n   * @param {number} indent\n   * @returns {JSON} - string\n   */\n  toString(indent) {\n    const replacer = (_, value) => {\n      if (value instanceof Set) {\n        return [...value]\n      }\n\n      if (value instanceof Map) {\n        return Object.fromEntries(value)\n      }\n\n      return value\n    }\n\n    return JSON.stringify(this, replacer, indent)\n  }\n}\n\nexport default LRUCache\n"
  },
  {
    "path": "Cache/Memoize.js",
    "content": "/**\n * @function memoize\n * @description ->\n * From [Wikipedia](https://en.wikipedia.org/wiki/Memoization),\n * memoization is an optimization technique\n * used primarily to speed up computer programs,\n * by storing the results of expensive function calls\n * and returning the cached result when the same inputs occur again\n * This function is a first class objects,\n * which lets us use it as [Higher-Order Function](https://eloquentjavascript.net/05_higher_order.html)\n * and return another function\n * @param {Function} func Original function\n * @param {Map} cache - it's receive any cache DS which have get, set & has method\n * @returns {Function} Memoized function\n */\nconst memoize = (func, cache = new Map()) => {\n  const jsonReplacer = (_, value) => {\n    if (value instanceof Set) {\n      // if the value is Set it's converted to Array cause JSON.stringify can't convert Set\n      return [...value]\n    }\n\n    if (value instanceof Map) {\n      // if the value is Map it's converted to Object cause JSON.stringify can't convert Map\n      return Object.fromEntries(value)\n    }\n\n    return value\n  }\n\n  return (...args) => {\n    /**\n     * Arguments converted to JSON string for use as a key of Map - it's easy to detect collections like -> Object and Array\n     * If the args input is -> [new Set([1, 2, 3, 4]), {name: 'myName', age: 23}]\n     * Then the argsKey generate to -> '[[1,2,3,4],{\"name\":\"myName\",\"age\":23}]' which is JSON mean string\n     * Now it's ready to be a perfect key for Map\n     */\n    const argsKey = JSON.stringify(args, jsonReplacer)\n\n    /**\n     * Checks if the argument is already present in the cache,\n     * then return the associated value / result\n     */\n    if (cache.has(argsKey)) {\n      return cache.get(argsKey)\n    }\n\n    /**\n     * If the argument is not yet present in the cache,\n     * execute original function and save its value / result in cache,\n     * finally return it\n     */\n    const result = func(...args) // spread all args\n    cache.set(argsKey, result)\n\n    return result\n  }\n}\n\nexport { memoize }\n"
  },
  {
    "path": "Cache/test/LFUCache.test.js",
    "content": "import LFUCache from '../LFUCache'\nimport { fibonacciCache } from './cacheTest'\n\ndescribe('Testing LFUCache class', () => {\n  it('Example 1 (Small Cache, size = 2)', () => {\n    const cache = new LFUCache(1) // initially capacity 1\n\n    cache.capacity = 2 // increase the capacity\n\n    expect(cache.capacity).toBe(2)\n\n    cache.set(1, 1) // frequency = 1\n    cache.set(2, 2) // frequency = 1\n\n    expect(cache.get(1)).toBe(1) // frequency = 2\n    expect(cache.get(2)).toBe(2) // frequency = 2\n\n    // Additional entries triggers cache rotate\n    cache.set(3, 3) // frequency = 1 & key 1 removed from the cached, cause now it's tie and followed the LRU system\n\n    expect(cache.get(1)).toBe(null) // misses = 1\n    expect(cache.get(2)).toBe(2) // frequency = 3\n    expect(cache.get(3)).toBe(3) // frequency = 2\n\n    cache.set(4, 4) // frequency = 1 & key 3 removed cause the frequency of 3 is 2 which is least frequency\n    expect(cache.get(1)).toBe(null) // misses = 2\n    expect(cache.get(2)).toBe(2) // frequency = 4\n    expect(cache.get(3)).toBe(null) // misses = 3\n    expect(cache.get(4)).toBe(4) // frequency = 2 which is least\n\n    expect(cache.info).toEqual({\n      misses: 3,\n      hits: 6,\n      capacity: 2,\n      currentSize: 2,\n      leastFrequency: 2\n    })\n\n    const json =\n      '{\"misses\":3,\"hits\":6,\"cache\":{\"2\":{\"key\":\"2\",\"value\":2,\"frequency\":4},\"4\":{\"key\":\"4\",\"value\":4,\"frequency\":2}}}'\n    expect(cache.toString()).toBe(json)\n\n    const cacheInstance = cache.parse(json) // again merge the json\n\n    expect(cacheInstance).toBe(cache) // return the same cache\n\n    cache.capacity = 1 // decrease the capacity\n\n    expect(cache.info).toEqual({\n      // after merging the info\n      misses: 6,\n      hits: 12,\n      capacity: 1,\n      currentSize: 1,\n      leastFrequency: 5\n    })\n\n    const clearedCache = cache.clear() // clear the cache\n    expect(clearedCache.size).toBe(0)\n  })\n\n  it('Example 2 (Computing Fibonacci Series, size = 100)', () => {\n    const cache = new LFUCache(100)\n\n    for (let i = 1; i <= 100; i++) {\n      fibonacciCache(i, cache)\n    }\n\n    expect(cache.info).toEqual({\n      misses: 103,\n      hits: 193,\n      capacity: 100,\n      currentSize: 98,\n      leastFrequency: 1\n    })\n  })\n})\n"
  },
  {
    "path": "Cache/test/LRUCache.test.js",
    "content": "import LRUCache from '../LRUCache'\nimport { fibonacciCache } from './cacheTest'\n\ndescribe('Testing LRUCache', () => {\n  it('Testing with invalid capacity', () => {\n    expect(() => new LRUCache()).toThrow()\n    expect(() => new LRUCache('Invalid')).toThrow()\n    expect(() => new LRUCache(-1)).toThrow()\n    expect(() => new LRUCache(Infinity)).toThrow()\n  })\n\n  it('Example 1 (Small Cache, size = 2)', () => {\n    const cache = new LRUCache(1) // initially capacity\n\n    cache.capacity++ // now the capacity is increasing by one\n\n    cache.set(1, 1)\n    cache.set(2, 2)\n\n    expect(cache.get(1)).toBe(1)\n    expect(cache.get(2)).toBe(2)\n\n    // Additional entries triggers cache rotate\n    cache.set(3, 3)\n\n    // Then we should have a cache miss for the first entry added\n    expect(cache.get(1)).toBe(null)\n    expect(cache.get(2)).toBe(2)\n    expect(cache.get(3)).toBe(3)\n\n    cache.set(4, 4)\n    expect(cache.get(1)).toBe(null) // cache miss\n    expect(cache.get(2)).toBe(null) // cache miss\n    expect(cache.get(3)).toBe(3)\n    expect(cache.get(4)).toBe(4)\n\n    expect(cache.info).toEqual({\n      misses: 3,\n      hits: 6,\n      capacity: 2,\n      size: 2\n    })\n\n    const json = '{\"misses\":3,\"hits\":6,\"cache\":{\"3\":3,\"4\":4}}'\n    expect(cache.toString()).toBe(json)\n\n    // merge with json\n    cache.parse(json)\n\n    cache.capacity-- // now the capacity decreasing by one\n\n    expect(cache.info).toEqual({\n      misses: 6,\n      hits: 12,\n      capacity: 1,\n      size: 1\n    })\n  })\n\n  it('Example 2 (Computing Fibonacci Series, size = 100)', () => {\n    const cache = new LRUCache(100)\n\n    for (let i = 1; i <= 100; i++) {\n      fibonacciCache(i, cache)\n    }\n\n    expect(cache.info).toEqual({\n      misses: 103,\n      hits: 193,\n      capacity: 100,\n      size: 98\n    })\n  })\n})\n"
  },
  {
    "path": "Cache/test/Memoize.test.js",
    "content": "import { memoize } from '../Memoize'\nimport { union } from './cacheTest'\nimport { fibonacci } from '../../Dynamic-Programming/FibonacciNumber'\nimport { factorial } from '../../Recursive/Factorial'\nimport LFUCache from '../LFUCache'\n\nconst multipleFactorials = (arr) => arr.map(factorial)\n\ndescribe('Testing Memoize', () => {\n  it('expects the fibonacci function to use the cache on the second call', () => {\n    const memoFibonacci = memoize(fibonacci)\n\n    expect(memoFibonacci(5)).toEqual(fibonacci(5))\n    expect(memoFibonacci(5)).toEqual(5)\n    expect(memoFibonacci(10)).toEqual(fibonacci(10))\n    expect(memoFibonacci(10)).toEqual(55)\n  })\n\n  it('expects the factorial function to use the cache on the second call', () => {\n    const memoFactorial = memoize(factorial)\n\n    expect(memoFactorial(5)).toEqual(factorial(5))\n    expect(memoFactorial(5)).toEqual(120)\n    expect(memoFactorial(10)).toEqual(factorial(10))\n    expect(memoFactorial(10)).toEqual(3628800)\n  })\n\n  it('expects the multipleFactorials function to use the cache on the second call', () => {\n    const memoMultipleFactorials = memoize(multipleFactorials)\n    const input = [2, 3, 4, 5]\n\n    expect(memoMultipleFactorials(input)).toEqual([2, 6, 24, 120])\n    expect(memoMultipleFactorials(input)).toEqual(multipleFactorials(input))\n  })\n\n  it('expects the multipleFactorials function to use the cache on the second call', () => {\n    const memoMultipleFactorials = memoize(multipleFactorials)\n    const input = [2, 3, 4, 5]\n\n    expect(memoMultipleFactorials(input)).toEqual([2, 6, 24, 120])\n    expect(memoMultipleFactorials(input)).toEqual(multipleFactorials(input))\n  })\n\n  it('expects the union function to use the cache on the second call', () => {\n    const memoUnion = memoize(union)\n    const inputs = [new Set([1, 2, 3]), new Set([4, 3, 2]), new Set([5, 3, 6])]\n\n    expect(memoUnion(...inputs)).toEqual(new Set([1, 2, 3, 4, 5, 6]))\n    expect(memoUnion(...inputs)).toEqual(union(...inputs))\n  })\n\n  it('Testing with explicit cache -> LFUCache', () => {\n    const LFU = new LFUCache(2)\n\n    const memoizeFibonacci = memoize(fibonacci, LFU) // added LFU cache explicitly\n    const fibOfFiveHundred = memoizeFibonacci(500)\n    const fibOfOneHundred = memoizeFibonacci(100)\n\n    expect(memoizeFibonacci(500)).toBe(fibOfFiveHundred)\n    expect(memoizeFibonacci(100)).toBe(fibOfOneHundred)\n\n    expect(LFU.leastFrequency).toBe(2)\n  })\n})\n"
  },
  {
    "path": "Cache/test/cacheTest.js",
    "content": "/**\n * @function fibonacciCache\n * @description - this is a cached variant of fib number\n * @param {number} n  - Real number (n > -1)\n * @param {Object} cache\n * @returns {number}\n */\nexport const fibonacciCache = (n, cache = null) => {\n  if (cache) {\n    const value = cache.get(n)\n\n    if (value !== null) {\n      return value\n    }\n  }\n\n  if (n === 1 || n === 2) {\n    return 1\n  }\n\n  const result = fibonacciCache(n - 1, cache) + fibonacciCache(n - 2, cache)\n\n  cache && cache.set(n, result)\n\n  return result\n}\n\n/**\n * @title implementation of union function\n * @param {Set} sets\n * @return {new Set}\n */\nexport const union = (...sets) => {\n  return new Set(sets.reduce((flatArray, set) => [...flatArray, ...set], []))\n}\n"
  },
  {
    "path": "Cellular-Automata/ConwaysGameOfLife.js",
    "content": "/*\nConway's Game of Life\nThe Game of Life is a cellular automaton devised by the British mathematician John Horton Conway in 1970. The universe of the Game of Life is an infinite, two-dimensional orthogonal grid of square cells, each of which is in one of two possible states, live or dead, (or populated and unpopulated, respectively). Every cell interacts with its eight neighbours, which are the cells that are horizontally, vertically, or diagonally adjacent. At each step in time, the following transitions occur:\n  1. Any live cell with two or three live neighbours survives.\n  2. Any dead cell with three live neighbours becomes a live cell.\n  3. All other live cells die in the next generation. Similarly, all other dead cells stay dead.\n(description adapted from https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life )\n(example adapted from https://github.com/TheAlgorithms/Python/blob/master/cellular_automata/conways_game_of_life.py )\n*/\n\n/**\n * Generates the next generation for a given state of Conway's Game of Life.\n */\nexport function newGeneration(cells) {\n  const nextGeneration = []\n  for (let i = 0; i < cells.length; i++) {\n    const nextGenerationRow = []\n    for (let j = 0; j < cells[i].length; j++) {\n      // Get the number of living neighbours\n      let neighbourCount = 0\n      if (i > 0 && j > 0) neighbourCount += cells[i - 1][j - 1]\n      if (i > 0) neighbourCount += cells[i - 1][j]\n      if (i > 0 && j < cells[i].length - 1)\n        neighbourCount += cells[i - 1][j + 1]\n      if (j > 0) neighbourCount += cells[i][j - 1]\n      if (j < cells[i].length - 1) neighbourCount += cells[i][j + 1]\n      if (i < cells.length - 1 && j > 0) neighbourCount += cells[i + 1][j - 1]\n      if (i < cells.length - 1) neighbourCount += cells[i + 1][j]\n      if (i < cells.length - 1 && j < cells[i].length - 1)\n        neighbourCount += cells[i + 1][j + 1]\n\n      // Decide whether the cell is alive or dead\n      const alive = cells[i][j] === 1\n\n      const cellIsAlive =\n        (alive && neighbourCount >= 2 && neighbourCount <= 3) ||\n        (!alive && neighbourCount === 3)\n\n      nextGenerationRow.push(cellIsAlive ? 1 : 0)\n    }\n    nextGeneration.push(nextGenerationRow)\n  }\n  return nextGeneration\n}\n"
  },
  {
    "path": "Cellular-Automata/Elementary.js",
    "content": "/**\n * Author: Jacoby Johnson (cobyj33)\n *\n * Generates generations of Elementary 1D cellular automata\n *\n * Wikipedia: https://en.wikipedia.org/wiki/Elementary_cellular_automaton\n * See all 255 possible rules and find another explanation here: https://mathworld.wolfram.com/ElementaryCellularAutomaton.html\n *\n * My personal take on the explanation of Elementary Cellular Automata:\n *\n * Elementary 1D cellular automata defines the growth and decay of populations of \"cells\" according to a specific rule, where the population is a line (array) and each cell is in either an \"alive\" (1) or a \"dead\" (0) state.\n *\n * The next generation of for a cell in the simulation ONLY depends on the state of its neighborhood (the state of the cell itself as well as the states of the cells to the immediate right and the immediate left)\n * Therefore, since each neighborhood consists of 3 cells each with 2 states there are 2^3 possibilities that determine a cell's next state, where each possible neighborhood could be represented in binary as\n *\n * 111\n * 110\n * 101\n * 100\n * 011\n * 010\n * 001\n * 000\n *\n * Where \"1\" represents the cell being alive and \"0\" represents the cell being dead. The leftmost bit represents the left neighbor of the currently analyzed cell, the middle bit represents the currently analyzed cell, and the rightmost bit represents the right neighbor of the currently analyzed cell.\n *\n * Rules are represented between 0 and 255 (0 and 255 inclusive), or more conceptually is seen as an 8 bit binary number. Each bit represents whether a cell should survive according to one of the 8 states of a cell's neighborhood. In this way, the number can act like an array of data of length 8.\n * The most significant bit (ex: ->10100100 ) represents the output for the \"all on\" state while the least significant bit (ex: 10100100<- ) represents the output for the \"all off\" state\n * In other words, all of the 8 possible neighborhood configurations map toward the 8 bits in a rule's output values\n *\n * Therefore, to find whether the a cell is born, survives, or dies, one could convert the state of a cell and it's neighbors into a binary number, then use the numerical value of that binary number as an index to find the corresponding rule's output, which is what has been implemented below\n * This analysis of a cell's neighborhood is performed on each cell in a generation until a new generation is created and returned.\n *\n * Rules are usually demonstrated visually by how a single cell grows independently according to that rule\n *\n * Example: First generations of Rule 94                    First Generations of Rule 126\n * 000000000000000000000000001000000000000000000000000      000000000000000000000000001000000000000000000000000\n * 000000000000000000000000011100000000000000000000000      000000000000000000000000011100000000000000000000000\n * 000000000000000000000000110110000000000000000000000      000000000000000000000000110110000000000000000000000\n * 000000000000000000000001110111000000000000000000000      000000000000000000000001111111000000000000000000000\n * 000000000000000000000011010101100000000000000000000      000000000000000000000011000001100000000000000000000\n * 000000000000000000000111010101110000000000000000000      000000000000000000000111100011110000000000000000000\n * 000000000000000000001101010101011000000000000000000      000000000000000000001100110110011000000000000000000\n * 000000000000000000011101010101011100000000000000000      000000000000000000011111111111111100000000000000000\n * 000000000000000000110101010101010110000000000000000      000000000000000000110000000000000110000000000000000\n * 000000000000000001110101010101010111000000000000000      000000000000000001111000000000001111000000000000000\n * 000000000000000011010101010101010101100000000000000      000000000000000011001100000000011001100000000000000\n * 000000000000000111010101010101010101110000000000000      000000000000000111111110000000111111110000000000000\n * 000000000000001101010101010101010101011000000000000      000000000000001100000011000001100000011000000000000\n * 000000000000011101010101010101010101011100000000000      000000000000011110000111100011110000111100000000000\n * 000000000000110101010101010101010101010110000000000      000000000000110011001100110110011001100110000000000\n * 000000000001110101010101010101010101010111000000000      000000000001111111111111111111111111111111000000000\n * 000000000011010101010101010101010101010101100000000      000000000011000000000000000000000000000001100000000\n * 000000000111010101010101010101010101010101110000000      000000000111100000000000000000000000000011110000000\n * 000000001101010101010101010101010101010101011000000      000000001100110000000000000000000000000110011000000\n * 000000011101010101010101010101010101010101011100000      000000011111111000000000000000000000001111111100000\n *\n * DEV NOTE: This implementation assumes that cells on the edge (who only have 1 neighbor) have 1 neighbor and a permanently \"dead\" neighbor, which is technically correct in a finite space. However, most diagrams of these elementary cellular automata rules assume a infinite line of cells. Therefore, the edges of the array may not evolve perfectly in line with pictured diagrams which assume infinite space.\n */\n\n/**\n * Find the next Elementary Cell Automata Generation given the previous generation and the rule [0-255] to follow\n * @param {(0 | 1)[]} generation The current generation of the Elementary Cellular Automata simulation\n * @param {number} rule The current rule of the Elementary Cellular Automata simulation. Must be an integer between 0 and 255 inclusive\n * @returns {(0 | 1)[]} The next generation according to the inputted rule\n */\nexport function getNextElementaryGeneration(generation, rule) {\n  const NUM_ELEMENTARY_NEIGHBORHOOD_STATES = 8\n  const MIN_RULE = 0\n  const MAX_RULE = 255\n\n  if (!Number.isInteger(rule)) {\n    throw new Error(\n      `Rule must be an integer between the values 0 and 255 (got ${rule})`\n    )\n  }\n  if (rule < MIN_RULE || rule > MAX_RULE) {\n    throw new RangeError(\n      `Rule must be an integer between the values 0 and 255 (got ${rule})`\n    )\n  }\n\n  const binaryRule = rule\n    .toString(2)\n    .padStart(NUM_ELEMENTARY_NEIGHBORHOOD_STATES, '0')\n  const ruleData = binaryRule.split('').map((bit) => Number.parseInt(bit)) // note that ruleData[0] represents \"all alive\" while ruleData[7] represents \"all dead\"\n  const output = new Array(generation.length)\n  const LEFT_DEAD = 4 // 100 in binary\n  const MIDDLE_DEAD = 2 // 010 in binary\n  const RIGHT_DEAD = 1 // 001 in binary\n\n  for (let i = 0; i < generation.length; i++) {\n    let neighborhoodValue = LEFT_DEAD | MIDDLE_DEAD | RIGHT_DEAD\n\n    if (i - 1 > 0 && generation[i - 1] === 1) {\n      neighborhoodValue ^= LEFT_DEAD\n    }\n\n    if (generation[i] === 1) {\n      neighborhoodValue ^= MIDDLE_DEAD\n    }\n\n    if (i + 1 < generation.length && generation[i + 1] === 1) {\n      neighborhoodValue ^= RIGHT_DEAD\n    }\n\n    output[i] = ruleData[neighborhoodValue]\n  }\n\n  return output\n}\n"
  },
  {
    "path": "Cellular-Automata/test/ConwaysGameOfLife.test.js",
    "content": "import { newGeneration } from '../ConwaysGameOfLife'\n\ndescribe('newGeneration', () => {\n  it('should produce the next generation according to the rules', () => {\n    expect(\n      newGeneration([\n        [0, 1, 0],\n        [0, 1, 0],\n        [0, 1, 0]\n      ])\n    ).toEqual([\n      [0, 0, 0],\n      [1, 1, 1],\n      [0, 0, 0]\n    ])\n  })\n})\n"
  },
  {
    "path": "Cellular-Automata/test/Elementary.test.js",
    "content": "import { getNextElementaryGeneration } from '../Elementary'\n\ndescribe('Elementary Cellular Automata', () => {\n  describe('Rule Errors', () => {\n    it('Correct', () => {\n      expect(() =>\n        getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 128)\n      ).not.toThrow()\n    })\n\n    it('Less than 0', () => {\n      expect(() =>\n        getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], -1)\n      ).toThrow()\n    })\n\n    it('Greater than 255', () => {\n      expect(() =>\n        getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 256)\n      ).toThrow()\n    })\n\n    it('Decimal', () => {\n      expect(() =>\n        getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 100.4)\n      ).toThrow()\n    })\n  })\n\n  describe('Rule 54 Iterations', () => {\n    it('Generation 1', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 54)\n      ).toEqual([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0])\n    })\n    it('Generation 2', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 54)\n      ).toEqual([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0])\n    })\n    it('Generation 3', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0], 54)\n      ).toEqual([0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0])\n    })\n    it('Generation 4', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0], 54)\n      ).toEqual([0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0])\n    })\n  })\n\n  describe('Rule 222 Iterations', () => {\n    it('Generation 1', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 222)\n      ).toEqual([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0])\n    })\n    it('Generation 2', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 222)\n      ).toEqual([0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0])\n    })\n    it('Generation 3', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], 222)\n      ).toEqual([0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0])\n    })\n    it('Generation 4', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0], 222)\n      ).toEqual([0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0])\n    })\n  })\n\n  describe('Rule 60 Iterations', () => {\n    it('Generation 1', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 60)\n      ).toEqual([0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0])\n    })\n    it('Generation 2', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0], 60)\n      ).toEqual([0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0])\n    })\n    it('Generation 3', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0], 60)\n      ).toEqual([0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0])\n    })\n    it('Generation 4', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0], 60)\n      ).toEqual([0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0])\n    })\n  })\n\n  describe('Rule 90 Iterations', () => {\n    it('Generation 1', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 90)\n      ).toEqual([0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0])\n    })\n    it('Generation 2', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0], 90)\n      ).toEqual([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0])\n    })\n    it('Generation 3', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0], 90)\n      ).toEqual([0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0])\n    })\n    it('Generation 4', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0], 90)\n      ).toEqual([0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0])\n    })\n  })\n\n  describe('Rule 30 Iterations', () => {\n    it('Generation 1', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 30)\n      ).toEqual([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0])\n    })\n    it('Generation 2', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 30)\n      ).toEqual([0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0])\n    })\n    it('Generation 3', () => {\n      expect(\n        getNextElementaryGeneration([0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0], 30)\n      ).toEqual([0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0])\n    })\n  })\n})\n"
  },
  {
    "path": "Ciphers/AffineCipher.js",
    "content": "/**\n * @description - The affine cipher is a type of monoalphabetic substitution cipher, where each letter in an alphabet is mapped to its numeric equivalent, encrypted using a simple mathematical function, and converted back to a letter\n * @see - [wiki](https://en.wikipedia.org/wiki/Affine_cipher)\n */\n\nimport { CoPrimeCheck } from '../Maths/CoPrimeCheck'\n// Default key for Affine Cipher\nconst key = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'\n\n/**\n * Fix result for negative value in modulas equation\n * @param {Number} n - Constant number\n * @param {Number} m - Modulos value\n * @return {Number} Return n mod m\n */\nfunction mod(n, m) {\n  return ((n % m) + m) % m\n}\n\n/**\n * Modular multiplicative inverse\n * @param {Number} a - A coefficient\n * @param {Number} m - Modulos value\n * @return {Number} Return modular multiplicative inverse of coefficient a and modulos m\n */\nfunction inverseMod(a, m) {\n  for (let x = 1; x < m; x++) {\n    if (mod(a * x, m) === 1) return x\n  }\n}\n\n/**\n * Argument validation\n * @param {String} str - String to be checked\n * @param {Number} a - A coefficient to be checked\n * @param {Number} b - B coefficient to be checked\n * @return {Boolean} Result of the checking\n */\nfunction isCorrectFormat(str, a, b) {\n  if (typeof a !== 'number' || typeof b !== 'number') {\n    throw new TypeError('Coefficient a, b should be number')\n  }\n\n  if (typeof str !== 'string') {\n    throw new TypeError('Argument str should be String')\n  }\n\n  if (!CoPrimeCheck(a, 26)) {\n    throw new Error(a + ' is not coprime of 26')\n  }\n\n  return true\n}\n\n/**\n * Find character index based on ASCII order\n * @param {String} char - Character index to be found\n * @return {Boolean} Character index\n */\nfunction findCharIndex(char) {\n  return char.toUpperCase().charCodeAt(0) - 'A'.charCodeAt(0)\n}\n\n/**\n * Encrypt a Affine Cipher\n * @param {String} str - String to be encrypted\n * @param {Number} a - A coefficient\n * @param {Number} b - B coefficient\n * @return {String} result - Encrypted string\n */\n\nfunction encrypt(str, a, b) {\n  let result = ''\n  if (isCorrectFormat(str, a, b)) {\n    for (let x = 0; x < str.length; x++) {\n      const charIndex = findCharIndex(str[x])\n      if (charIndex < 0) result += '-1' + ' '\n      else result += key.charAt(mod(a * charIndex + b, 26)) + ' '\n    }\n  }\n  return result.trim()\n}\n\n/**\n * Decrypt a Affine Cipher\n * @param {String} str - String to be decrypted\n * @param {Number} a - A coefficient\n * @param {Number} b - B coefficient\n * @return {String} result - Decrypted string\n */\nfunction decrypt(str, a, b) {\n  let result = ''\n  if (isCorrectFormat(str, a, b)) {\n    str = str.split(' ')\n    for (let x = 0; x < str.length; x++) {\n      if (str[x] === '-1') result += ' '\n      else {\n        const charIndex = findCharIndex(str[x])\n        result += key[mod(inverseMod(a, 26) * (charIndex - b), 26)]\n      }\n    }\n    return result\n  }\n}\nexport { encrypt, decrypt }\n"
  },
  {
    "path": "Ciphers/Atbash.js",
    "content": "/**\n * @function Atbash - Decrypt a Atbash cipher\n * @description - The Atbash cipher is a particular type of monoalphabetic cipher formed by taking the alphabet and mapping it to its reverse, so that the first letter becomes the last letter, the second letter becomes the second to last letter, and so on.\n * @param {string} str - string to be decrypted/encrypt\n * @return {string} decrypted/encrypted string\n * @see - [wiki](https://en.wikipedia.org/wiki/Atbash)\n */\nconst Atbash = (str) => {\n  if (typeof str !== 'string') {\n    throw new TypeError('Argument should be string')\n  }\n\n  return str.replace(/[a-z]/gi, (char) => {\n    const charCode = char.charCodeAt()\n\n    if (/[A-Z]/.test(char)) {\n      return String.fromCharCode(90 + 65 - charCode)\n    }\n\n    return String.fromCharCode(122 + 97 - charCode)\n  })\n}\n\nexport default Atbash\n"
  },
  {
    "path": "Ciphers/CaesarCipher.js",
    "content": "/**\n * @function caesarsCipher\n * @description - In cryptography, a Caesar cipher, also known as Caesar's cipher, the shift cipher, Caesar's code or Caesar shift, is one of the simplest and most widely known encryption techniques. It is a type of substitution cipher in which each letter in the plaintext is replaced by a letter some fixed number of positions down the alphabet. For example, with a left shift of 3, D would be replaced by A, E would become B, and so on. The method is named after Julius Caesar, who used it in his private correspondence.\n * @see - [wiki](https://en.wikipedia.org/wiki/Caesar_cipher)\n * @param  {string} str - string to be encrypted\n * @param {number} rotation - the number of rotation, expect real number ( > 0)\n * @return {string} - decrypted string\n */\nconst caesarCipher = (str, rotation) => {\n  if (typeof str !== 'string' || !Number.isInteger(rotation) || rotation < 0) {\n    throw new TypeError('Arguments are invalid')\n  }\n\n  const alphabets = new Array(26)\n    .fill()\n    .map((_, index) => String.fromCharCode(97 + index)) // generate all lower alphabets array a-z\n\n  const cipherMap = alphabets.reduce(\n    (map, char, index) => map.set(char, alphabets[(rotation + index) % 26]),\n    new Map()\n  )\n\n  return str.replace(/[a-z]/gi, (char) => {\n    if (/[A-Z]/.test(char)) {\n      return cipherMap.get(char.toLowerCase()).toUpperCase()\n    }\n\n    return cipherMap.get(char)\n  })\n}\n\nexport default caesarCipher\n"
  },
  {
    "path": "Ciphers/KeyFinder.js",
    "content": "/**\n * Find and retrieve the encryption key automatically.\n * @param {string} str - The input encrypted string.\n * @returns {number} - The encryption key found, or 0 if not found.\n */\nfunction keyFinder(str) {\n  // str is used to get the input of encrypted string\n  const wordBank = [\n    'I ',\n    'You ',\n    'We ',\n    'They ',\n    'He ',\n    'She ',\n    'It ',\n    ' the ',\n    'The ',\n    ' of ',\n    ' is ',\n    'Is ',\n    ' am ',\n    'Am ',\n    ' are ',\n    'Are ',\n    ' have ',\n    'Have ',\n    ' has ',\n    'Has ',\n    ' may ',\n    'May ',\n    ' be ',\n    'Be '\n  ]\n  const inStr = str.toString() // convert the input to String\n  let outStr = '' // store the output value\n  let outStrElement = '' // temporary store the word inside the outStr, it is used for comparison\n  for (let k = 0; k < 26; k++) {\n    // try the number of key shifted, the sum of character from a-z or A-Z is 26\n    outStr = caesarCipherEncodeAndDecodeEngine(inStr, k) // use the encryption engine to decrypt the input string\n\n    // loop through the whole input string\n    for (let s = 0; s < outStr.length; s++) {\n      for (let i = 0; i < wordBank.length; i++) {\n        // initialize the outStrElement which is a temp output string for comparison,\n        // use a loop to find the next digit of wordBank element and compare with outStr's digit\n        for (let w = 0; w < wordBank[i].length; w++) {\n          outStrElement += outStr[s + w]\n        }\n        // this part need to be optimize with the calculation of the number of occurrence of word's probabilities\n        // linked list will be used in the next stage of development to calculate the number of occurrence of the key\n        if (wordBank[i] === outStrElement) {\n          return k // return the key number if founded\n        }\n        outStrElement = '' // reset the temp word\n      } // end for (let i=0; i < wordBank.length; i++)\n    }\n  }\n  return 0 // return 0 if found nothing\n}\n\n/**\n * This sub-function is used to assist the keyFinder in finding the key.\n * @param {string} inStr - The input string.\n * @param {number} numShifted - The number of characters to shift in the Caesar cipher.\n * @returns {string} - The decrypted string.\n */\nfunction caesarCipherEncodeAndDecodeEngine(inStr, numShifted) {\n  const shiftNum = numShifted\n  let charCode = 0\n  let shiftedCharCode = 0\n  let result = 0\n\n  return inStr\n    .split('')\n    .map((char) => {\n      charCode = char.charCodeAt()\n      shiftedCharCode = charCode + shiftNum\n      result = charCode\n\n      if (charCode >= 48 && charCode <= 57) {\n        if (shiftedCharCode < 48) {\n          let diff = Math.abs(48 - 1 - shiftedCharCode) % 10\n\n          while (diff >= 10) {\n            diff = diff % 10\n          }\n          document.getElementById('diffID').innerHTML = diff\n\n          shiftedCharCode = 57 - diff\n\n          result = shiftedCharCode\n        } else if (shiftedCharCode >= 48 && shiftedCharCode <= 57) {\n          result = shiftedCharCode\n        } else if (shiftedCharCode > 57) {\n          let diff = Math.abs(57 + 1 - shiftedCharCode) % 10\n\n          while (diff >= 10) {\n            diff = diff % 10\n          }\n          document.getElementById('diffID').innerHTML = diff\n\n          shiftedCharCode = 48 + diff\n\n          result = shiftedCharCode\n        }\n      } else if (charCode >= 65 && charCode <= 90) {\n        if (shiftedCharCode <= 64) {\n          let diff = Math.abs(65 - 1 - shiftedCharCode) % 26\n\n          while (diff % 26 >= 26) {\n            diff = diff % 26\n          }\n          shiftedCharCode = 90 - diff\n          result = shiftedCharCode\n        } else if (shiftedCharCode >= 65 && shiftedCharCode <= 90) {\n          result = shiftedCharCode\n        } else if (shiftedCharCode > 90) {\n          let diff = Math.abs(shiftedCharCode - 1 - 90) % 26\n\n          while (diff % 26 >= 26) {\n            diff = diff % 26\n          }\n          shiftedCharCode = 65 + diff\n          result = shiftedCharCode\n        }\n      } else if (charCode >= 97 && charCode <= 122) {\n        if (shiftedCharCode <= 96) {\n          let diff = Math.abs(97 - 1 - shiftedCharCode) % 26\n\n          while (diff % 26 >= 26) {\n            diff = diff % 26\n          }\n          shiftedCharCode = 122 - diff\n          result = shiftedCharCode\n        } else if (shiftedCharCode >= 97 && shiftedCharCode <= 122) {\n          result = shiftedCharCode\n        } else if (shiftedCharCode > 122) {\n          let diff = Math.abs(shiftedCharCode - 1 - 122) % 26\n\n          while (diff % 26 >= 26) {\n            diff = diff % 26\n          }\n          shiftedCharCode = 97 + diff\n          result = shiftedCharCode\n        }\n      }\n      return String.fromCharCode(parseInt(result))\n    })\n    .join('')\n}\n\nexport { keyFinder }\n\n// > keyFinder('test')\n// 0\n"
  },
  {
    "path": "Ciphers/KeywordShiftedAlphabet.js",
    "content": "/**\n * Keyword shifted alphabet is a simple cipher using a translation table created with a help of a keyword.\n * Keyword must be a word where each character can occur only once.\n * To create the translation table, we write all the alphabet characters to the first.\n * Second row start with the keyword, then we continue with the rest of the characters that are missing in alphabetical order.\n *\n * |A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|\n * |K|E|Y|W|O|R|D|A|B|C|F|G|H|I|J|L|M|N|P|Q|S|T|U|V|W|Z|\n *\n * Encryption is then just a matter of writing the matching (same index) letter from the second row instead of the first row:\n * 'Hello world' -> 'Aoggj ujngw'\n *\n * Decryption is then just the reverse process of writing the matching (same index) letter from the first row instead of the second row\n * 'Aogg ujngw' -> 'Hello world'\n *\n * Non alphabetical characters (space, exclamation mark, ...) are kept as they are\n */\n\nconst alphabet = [\n  'a',\n  'b',\n  'c',\n  'd',\n  'e',\n  'f',\n  'g',\n  'h',\n  'i',\n  'j',\n  'k',\n  'l',\n  'm',\n  'n',\n  'o',\n  'p',\n  'q',\n  'r',\n  's',\n  't',\n  'u',\n  'v',\n  'w',\n  'x',\n  'y',\n  'z'\n]\n\nfunction checkKeywordValidity(keyword) {\n  keyword.split('').forEach((char, index) => {\n    const rest = keyword.slice(0, index) + keyword.slice(index + 1)\n    if (rest.indexOf(char) !== -1) {\n      return false\n    }\n  })\n  return true\n}\n\nfunction getEncryptedAlphabet(keyword) {\n  const encryptedAlphabet = keyword.split('')\n  alphabet.forEach((char) => {\n    if (encryptedAlphabet.indexOf(char) === -1) {\n      encryptedAlphabet.push(char)\n    }\n  })\n  return encryptedAlphabet\n}\n\nfunction translate(sourceAlphabet, targetAlphabet, message) {\n  return message.split('').reduce((encryptedMessage, char) => {\n    const isUpperCase = char === char.toUpperCase()\n    const encryptedCharIndex = sourceAlphabet.indexOf(char.toLowerCase())\n    const encryptedChar =\n      encryptedCharIndex !== -1 ? targetAlphabet[encryptedCharIndex] : char\n    encryptedMessage += isUpperCase\n      ? encryptedChar.toUpperCase()\n      : encryptedChar\n    return encryptedMessage\n  }, '')\n}\n\nfunction checkInputs(keyword, message) {\n  if (!keyword || !message) {\n    throw new Error('Both keyword and message must be specified')\n  }\n\n  if (!checkKeywordValidity(keyword)) {\n    throw new Error('Invalid keyword!')\n  }\n}\n\nfunction encrypt(keyword, message) {\n  checkInputs(keyword, message)\n  return translate(\n    alphabet,\n    getEncryptedAlphabet(keyword.toLowerCase()),\n    message\n  )\n}\n\nfunction decrypt(keyword, message) {\n  checkInputs(keyword, message)\n  return translate(\n    getEncryptedAlphabet(keyword.toLowerCase()),\n    alphabet,\n    message\n  )\n}\n\nexport { encrypt, decrypt }\n\n// encrypt('keyword', 'Hello world!') // Prints 'Aoggj ujngw!'\n// decrypt('keyword', 'Aoggj ujngw!') // Prints 'Hello world!\n"
  },
  {
    "path": "Ciphers/MorseCode.js",
    "content": "/**\n * @author mrmagic2020\n * @description Enciphers a combination of letters, numbers and symbols into morse code.\n * @see https://en.wikipedia.org/wiki/Morse_code\n * @param {string} msg The message to be enciphered.\n * @param {string} dot Symbol representing the dots.\n * @param {string} dash Symbol representing the dash.\n * @returns {string} Enciphered morse code.\n * @example morse('Hello World!') = '**** * *-** *-** ---   *-- --- *-* *-** -** -*-*--'\n */\nconst morse = (msg, dot = '*', dash = '-') => {\n  const key = {\n    A: '*-',\n    B: '-***',\n    C: '-*-*',\n    D: '-**',\n    E: '*',\n    F: '**-*',\n    G: '--*',\n    H: '****',\n    I: '**',\n    J: '*---',\n    K: '-*-',\n    L: '*-**',\n    M: '--',\n    N: '-*',\n    O: '---',\n    P: '*--*',\n    Q: '--*-',\n    R: '*-*',\n    S: '***',\n    T: '-',\n    U: '**-',\n    V: '***-',\n    W: '*--',\n    X: '-**-',\n    Y: '-*--',\n    Z: '--**',\n    1: '*----',\n    2: '**---',\n    3: '***--',\n    4: '****-',\n    5: '*****',\n    6: '-****',\n    7: '--***',\n    8: '---**',\n    9: '----*',\n    0: '-----',\n    '.': '*-*-*-',\n    ',': '--**--',\n    '?': '**--**',\n    '!': '-*-*--',\n    \"'\": '*----*',\n    '\"': '*-**-*',\n    '(': '-*--*',\n    ')': '-*--*-',\n    '&': '*-***',\n    ':': '---***',\n    ';': '-*-*-*',\n    '/': '-**-*',\n    _: '**--*-',\n    '=': '-***-',\n    '+': '*-*-*',\n    '-': '-****-',\n    $: '***-**-',\n    '@': '*--*-*'\n  }\n\n  let newMsg = ''\n\n  msg\n    .toString()\n    .split('')\n    .forEach((e) => {\n      if (/[a-zA-Z]/.test(e)) {\n        newMsg += key[e.toUpperCase()]\n          .replaceAll('*', dot)\n          .replaceAll('-', dash)\n      } else if (Object.keys(key).includes(e)) {\n        newMsg += key[e].replaceAll('*', dot).replaceAll('-', dash)\n      } else {\n        newMsg += e\n      }\n      newMsg += ' '\n    })\n\n  return newMsg.trim()\n}\n\nexport { morse }\n"
  },
  {
    "path": "Ciphers/ROT13.js",
    "content": "/**\n * @function ROT13\n * @description - ROT13 (\"rotate by 13 places\", sometimes hyphenated ROT-13) is a simple letter substitution cipher that replaces a letter with the 13th letter after it in the alphabet. ROT13 is a special case of the Caesar cipher which was developed in ancient Rome. Because there are 26 letters (2×13) in the basic Latin alphabet, ROT13 is its own inverse; that is, to undo ROT13, the same algorithm is applied, so the same action can be used for encoding and decoding. The algorithm provides virtually no cryptographic security, and is often cited as a canonical example of weak encryption.\n * @see - [wiki](https://en.wikipedia.org/wiki/ROT13)\n * @param {String} str - string to be decrypted\n * @return {String} decrypted string\n */\nfunction ROT13(str) {\n  if (typeof str !== 'string') {\n    throw new TypeError('Argument should be string')\n  }\n\n  return str.replace(/[a-z]/gi, (char) => {\n    const charCode = char.charCodeAt()\n\n    if (/[n-z]/i.test(char)) {\n      return String.fromCharCode(charCode - 13)\n    }\n\n    return String.fromCharCode(charCode + 13)\n  })\n}\n\nexport default ROT13\n"
  },
  {
    "path": "Ciphers/VigenereCipher.js",
    "content": "/**\n * Check if the Character is letter or not\n * @param {String} str - character to check\n * @return {object} An array with the character or null if isn't a letter\n */\nfunction isLetter(str) {\n  return str.length === 1 && str.match(/[a-zA-Z]/i)\n}\n\n/**\n * Check if is Uppercase or Lowercase\n * @param {String} character - character to check\n * @return {Boolean} result of the checking\n */\nfunction isUpperCase(character) {\n  if (character === character.toUpperCase()) {\n    return true\n  }\n  if (character === character.toLowerCase()) {\n    return false\n  }\n}\n\n/**\n * Encrypt a Vigenere cipher\n * @param {String} message - string to be encrypted\n * @param {String} key - key for encrypt\n * @return {String} result - encrypted string\n */\nfunction encrypt(message, key) {\n  let result = ''\n\n  for (let i = 0, j = 0; i < message.length; i++) {\n    const c = message.charAt(i)\n    if (isLetter(c)) {\n      if (isUpperCase(c)) {\n        result += String.fromCharCode(\n          ((c.charCodeAt(0) + key.toUpperCase().charCodeAt(j) - 2 * 65) % 26) +\n            65\n        ) // A: 65\n      } else {\n        result += String.fromCharCode(\n          ((c.charCodeAt(0) + key.toLowerCase().charCodeAt(j) - 2 * 97) % 26) +\n            97\n        ) // a: 97\n      }\n    } else {\n      result += c\n    }\n    j = ++j % key.length\n  }\n  return result\n}\n\n/**\n * Decrypt a Vigenere cipher\n * @param {String} message - string to be decrypted\n * @param {String} key - key for decrypt\n * @return {String} result - decrypted string\n */\nfunction decrypt(message, key) {\n  let result = ''\n\n  for (let i = 0, j = 0; i < message.length; i++) {\n    const c = message.charAt(i)\n    if (isLetter(c)) {\n      if (isUpperCase(c)) {\n        result += String.fromCharCode(\n          90 - ((25 - (c.charCodeAt(0) - key.toUpperCase().charCodeAt(j))) % 26)\n        )\n      } else {\n        result += String.fromCharCode(\n          122 -\n            ((25 - (c.charCodeAt(0) - key.toLowerCase().charCodeAt(j))) % 26)\n        )\n      }\n    } else {\n      result += c\n    }\n    j = ++j % key.length\n  }\n  return result\n}\n\nexport { encrypt, decrypt }\n\n// > encrypt('Hello World!', 'code')\n// 'Jsopq Zstzg!'\n\n// > decrypt('Jsopq Zstzg!', 'code')\n// 'Hello World!'\n"
  },
  {
    "path": "Ciphers/XORCipher.js",
    "content": "/**\n * @function XORCipher\n * @description - Encrypt using an XOR cipher\n * The XOR cipher is a type of additive cipher.\n * Each character is bitwise XORed with the key.\n * We loop through the input string, XORing each\n * character with the key.\n * @param {string} str - string to be encrypted\n * @param {number} key - key for encryption\n * @return {string} encrypted string\n */\nconst XORCipher = (str, key) => {\n  if (typeof str !== 'string' || !Number.isInteger(key)) {\n    throw new TypeError('Arguments type are invalid')\n  }\n\n  return str.replace(/./g, (char) =>\n    String.fromCharCode(char.charCodeAt() ^ key)\n  )\n}\n\nexport default XORCipher\n"
  },
  {
    "path": "Ciphers/test/AffineCipher.test.js",
    "content": "import { encrypt, decrypt } from '../AffineCipher'\n\ndescribe('Test Affine Cipher', () => {\n  it('Test - 1, Pass invalid input to encrypt function', () => {\n    expect(() => encrypt(null, null, null)).toThrow()\n    expect(() => encrypt('null', null, null)).toThrow()\n    expect(() => encrypt('null', 1, null)).toThrow()\n    expect(() => encrypt('null', null, 1)).toThrow()\n    expect(() => encrypt('null', 2, 1)).toThrow()\n    expect(() => encrypt('null', 4, 1)).toThrow()\n  })\n\n  it('Test - 2, Pass invalid input to decrypt function', () => {\n    expect(() => decrypt(null, null, null)).toThrow()\n    expect(() => decrypt('null', null, null)).toThrow()\n    expect(() => decrypt('null', 1, null)).toThrow()\n    expect(() => decrypt('null', null, 1)).toThrow()\n    expect(() => encrypt('null', 2, 1)).toThrow()\n    expect(() => encrypt('null', 4, 1)).toThrow()\n  })\n\n  it('Test - 3 Pass string value to encrypt and decrypt function', () => {\n    expect(decrypt(encrypt('HELLO WORLD', 5, 8), 5, 8)).toBe('HELLO WORLD')\n    expect(decrypt(encrypt('ABC DEF', 3, 5), 3, 5)).toBe('ABC DEF')\n    expect(decrypt(encrypt('Brown fox jump over the fence', 7, 3), 7, 3)).toBe(\n      'BROWN FOX JUMP OVER THE FENCE'\n    )\n  })\n})\n"
  },
  {
    "path": "Ciphers/test/Atbash.test.js",
    "content": "import Atbash from '../Atbash'\n\ndescribe('Testing Atbash function', () => {\n  it('Test - 1, passing a non-string as an argument', () => {\n    expect(() => Atbash(0x345)).toThrow()\n    expect(() => Atbash(123)).toThrow()\n    expect(() => Atbash(123n)).toThrow()\n    expect(() => Atbash(false)).toThrow()\n    expect(() => Atbash({})).toThrow()\n    expect(() => Atbash([])).toThrow()\n  })\n\n  it('Test - 2, passing a string as an argument', () => {\n    const clearText = 'The quick brown fox jumps over the lazy dog'\n    const cryptText = Atbash(clearText)\n    expect(Atbash(cryptText)).toBe(clearText)\n  })\n})\n"
  },
  {
    "path": "Ciphers/test/CaesarCipher.test.js",
    "content": "import caesarCipher from '../CaesarCipher'\n\ndescribe('Testing the caesarsCipher function', () => {\n  it('Test - 1, Testing for invalid types', () => {\n    expect(() => caesarCipher(false, 3)).toThrow()\n    expect(() => caesarCipher('false', -1)).toThrow()\n    expect(() => caesarCipher('true', null)).toThrow()\n  })\n\n  it('Test - 2, Testing for valid string and rotation', () => {\n    expect(caesarCipher('middle-Outz', 2)).toBe('okffng-Qwvb')\n    expect(caesarCipher('abcdefghijklmnopqrstuvwxyz', 3)).toBe(\n      'defghijklmnopqrstuvwxyzabc'\n    )\n    expect(caesarCipher('Always-Look-on-the-Bright-Side-of-Life', 5)).toBe(\n      'Fqbfdx-Qttp-ts-ymj-Gwnlmy-Xnij-tk-Qnkj'\n    )\n    expect(\n      caesarCipher('THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG', 23)\n    ).toBe('QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD')\n  })\n})\n"
  },
  {
    "path": "Ciphers/test/KeywordShiftedAlphabet.test.js",
    "content": "import { encrypt, decrypt } from '../KeywordShiftedAlphabet'\n\ntest('Hello world! === decrypt(encrypt(Hello world!))', () => {\n  const word = 'Hello world!'\n  const result = decrypt('keyword', encrypt('keyword', word))\n  expect(result).toMatch(word)\n})\n\ntest('The Algorithms === decrypt(encrypt(The Algorithms))', () => {\n  const word = 'The Algorithms'\n  const result = decrypt('keyword', encrypt('keyword', word))\n  expect(result).toMatch(word)\n})\n"
  },
  {
    "path": "Ciphers/test/MorseCode.test.js",
    "content": "import { morse } from '../MorseCode'\n\ndescribe('Testing morse function', () => {\n  it('should return an enciphered string with a given input string', () => {\n    expect(morse('Hello World!')).toBe(\n      '**** * *-** *-** ---   *-- --- *-* *-** -** -*-*--'\n    )\n    expect(morse('1+1=2')).toBe('*---- *-*-* *---- -***- **---')\n  })\n\n  it('should leave symbols that does not have its corresponding morse representation', () => {\n    expect(morse('© 2023 GitHub, Inc.')).toBe(\n      '©   **--- ----- **--- ***--   --* ** - **** **- -*** --**--   ** -* -*-* *-*-*-'\n    )\n  })\n\n  it('should be able to accept custom morse code symbols', () => {\n    expect(morse('Nodejs', '.', '|')).toBe('|. ||| |.. . .||| ...')\n  })\n})\n"
  },
  {
    "path": "Ciphers/test/ROT13.test.js",
    "content": "import ROT13 from '../ROT13'\n\ndescribe('Testing ROT13 function', () => {\n  it('Test - 1, passing a non-string as an argument', () => {\n    expect(() => ROT13(0x345)).toThrow()\n    expect(() => ROT13(123)).toThrow()\n    expect(() => ROT13(123n)).toThrow()\n    expect(() => ROT13(false)).toThrow()\n    expect(() => ROT13({})).toThrow()\n    expect(() => ROT13([])).toThrow()\n  })\n\n  it('Test - 2, passing a string as an argument', () => {\n    expect(ROT13('Uryyb Jbeyq')).toBe('Hello World')\n    expect(ROT13('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz')).toBe(\n      'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'\n    )\n    expect(ROT13('The quick brown fox jumps over the lazy dog')).toBe(\n      'Gur dhvpx oebja sbk whzcf bire gur ynml qbt'\n    )\n  })\n})\n"
  },
  {
    "path": "Ciphers/test/VigenereCipher.test.js",
    "content": "import { encrypt, decrypt } from '../VigenereCipher'\n\ntest('Hello world! === decrypt(encrypt(Hello world!))', () => {\n  const word = 'Hello world!'\n  const result = decrypt(encrypt(word, 'code'), 'code')\n  expect(result).toMatch(word)\n})\n\ntest('The Algorithms === decrypt(encrypt(The Algorithms))', () => {\n  const word = 'The Algorithms'\n  const result = decrypt(encrypt(word, 'code'), 'code')\n  expect(result).toMatch(word)\n})\n"
  },
  {
    "path": "Ciphers/test/XORCipher.test.js",
    "content": "import XORCipher from '../XORCipher'\n\ndescribe('Testing XORCipher function', () => {\n  it('Test - 1, passing a non-string as an argument', () => {\n    expect(() => XORCipher(false, 0x345)).toThrow()\n    expect(() => XORCipher(true, 123)).toThrow()\n    expect(() => XORCipher(1n, 123n)).toThrow()\n    expect(() => XORCipher(false, 0.34)).toThrow()\n    expect(() => XORCipher({})).toThrow()\n    expect(() => XORCipher([])).toThrow()\n  })\n\n  it('Test - 2, passing a string & number as an argument', () => {\n    // NB: Node REPL might not output the null char '\\x00' (charcode 0)\n    expect(XORCipher('test string', 32)).toBe('TEST\\x00STRING')\n    expect(XORCipher('TEST\\x00STRING', 32)).toBe('test string')\n  })\n})\n"
  },
  {
    "path": "Compression/RLE.js",
    "content": "/*\n * RLE (Run Length Encoding) is a simple form of data compression.\n * The basic idea is to represent repeated successive characters as a single count and character.\n * For example, the string \"AAAABBBCCDAA\" would be encoded as \"4A3B2C1D2A\".\n *\n * @author - [ddaniel27](https://github.com/ddaniel27)\n */\n\nfunction Compress(str) {\n  let compressed = ''\n  let count = 1\n\n  for (let i = 0; i < str.length; i++) {\n    if (str[i] !== str[i + 1]) {\n      compressed += count + str[i]\n      count = 1\n      continue\n    }\n\n    count++\n  }\n\n  return compressed\n}\n\nfunction Decompress(str) {\n  let decompressed = ''\n  let match = [...str.matchAll(/(\\d+)(\\D)/g)] // match all groups of digits followed by a non-digit character\n\n  match.forEach((item) => {\n    let [count, char] = [item[1], item[2]]\n    decompressed += char.repeat(count)\n  })\n\n  return decompressed\n}\n\nexport { Compress, Decompress }\n"
  },
  {
    "path": "Compression/test/RLE.test.js",
    "content": "import { Compress, Decompress } from '../RLE'\n\ndescribe('Test RLE Compressor/Decompressor', () => {\n  it('Test - 1, Pass long repetitive strings', () => {\n    expect(Compress('AAAAAAAAAAAAAA')).toBe('14A')\n    expect(Compress('AAABBQQQQQFG')).toBe('3A2B5Q1F1G')\n  })\n\n  it('Test - 2, Pass compressed strings', () => {\n    expect(Decompress('14A')).toBe('AAAAAAAAAAAAAA')\n    expect(Decompress('3A2B5Q1F1G')).toBe('AAABBQQQQQFG')\n  })\n})\n"
  },
  {
    "path": "Conversions/ArbitraryBase.js",
    "content": "/**\n * Divide two numbers and get the result of floor division and remainder\n * @param {number} dividend\n * @param {number} divisor\n * @returns {[result: number, remainder: number]}\n */\nconst floorDiv = (dividend, divisor) => {\n  const remainder = dividend % divisor\n  const result = Math.floor(dividend / divisor)\n\n  return [result, remainder]\n}\n\n/**\n * Converts a string from one base to other. Loses accuracy above the value of `Number.MAX_SAFE_INTEGER`.\n * @param {string} stringInBaseOne String in input base\n * @param {string} baseOneCharacters Character set for the input base\n * @param {string} baseTwoCharacters Character set for the output base\n * @returns {string}\n */\nconst convertArbitraryBase = (\n  stringInBaseOne,\n  baseOneCharacterString,\n  baseTwoCharacterString\n) => {\n  if (\n    [stringInBaseOne, baseOneCharacterString, baseTwoCharacterString]\n      .map((arg) => typeof arg)\n      .some((type) => type !== 'string')\n  ) {\n    throw new TypeError('Only string arguments are allowed')\n  }\n\n  const baseOneCharacters = [...baseOneCharacterString]\n  const baseTwoCharacters = [...baseTwoCharacterString]\n\n  for (const charactersInBase of [baseOneCharacters, baseTwoCharacters]) {\n    if (charactersInBase.length !== new Set(charactersInBase).size) {\n      throw new TypeError(\n        'Duplicate characters in character set are not allowed'\n      )\n    }\n  }\n  const reversedStringOneChars = [...stringInBaseOne].reverse()\n  const stringOneBase = baseOneCharacters.length\n  let value = 0\n  let placeValue = 1\n  for (const digit of reversedStringOneChars) {\n    const digitNumber = baseOneCharacters.indexOf(digit)\n    if (digitNumber === -1) {\n      throw new TypeError(`Not a valid character: ${digit}`)\n    }\n    value += digitNumber * placeValue\n    placeValue *= stringOneBase\n  }\n  const outputChars = []\n  const stringTwoBase = baseTwoCharacters.length\n  while (value > 0) {\n    const [divisionResult, remainder] = floorDiv(value, stringTwoBase)\n    outputChars.push(baseTwoCharacters[remainder])\n    value = divisionResult\n  }\n  return outputChars.reverse().join('') || baseTwoCharacters[0]\n}\n\n/**\n * Converts a arbitrary-length string from one base to other. Doesn't lose accuracy.\n * @param {string} stringInBaseOne String in input base\n * @param {string} baseOneCharacters Character set for the input base\n * @param {string} baseTwoCharacters Character set for the output base\n * @returns {string}\n */\nconst convertArbitraryBaseBigIntVersion = (\n  stringInBaseOne,\n  baseOneCharacterString,\n  baseTwoCharacterString\n) => {\n  if (\n    [stringInBaseOne, baseOneCharacterString, baseTwoCharacterString]\n      .map((arg) => typeof arg)\n      .some((type) => type !== 'string')\n  ) {\n    throw new TypeError('Only string arguments are allowed')\n  }\n\n  const baseOneCharacters = [...baseOneCharacterString]\n  const baseTwoCharacters = [...baseTwoCharacterString]\n\n  for (const charactersInBase of [baseOneCharacters, baseTwoCharacters]) {\n    if (charactersInBase.length !== new Set(charactersInBase).size) {\n      throw new TypeError(\n        'Duplicate characters in character set are not allowed'\n      )\n    }\n  }\n  const reversedStringOneChars = [...stringInBaseOne].reverse()\n  const stringOneBase = BigInt(baseOneCharacters.length)\n  let value = 0n\n  let placeValue = 1n\n  for (const digit of reversedStringOneChars) {\n    const digitNumber = BigInt(baseOneCharacters.indexOf(digit))\n    if (digitNumber === -1n) {\n      throw new TypeError(`Not a valid character: ${digit}`)\n    }\n    value += digitNumber * placeValue\n    placeValue *= stringOneBase\n  }\n  const outputChars = []\n  const stringTwoBase = BigInt(baseTwoCharacters.length)\n  while (value > 0n) {\n    const divisionResult = value / stringTwoBase\n    const remainder = value % stringTwoBase\n    outputChars.push(baseTwoCharacters[remainder])\n    value = divisionResult\n  }\n  return outputChars.reverse().join('') || baseTwoCharacters[0]\n}\n\nexport { convertArbitraryBase, convertArbitraryBaseBigIntVersion }\n"
  },
  {
    "path": "Conversions/ArrayBufferToBase64.js",
    "content": "// About base64: https://en.wikipedia.org/wiki/Base64\n\n/**\n * Converts an array of bytes to base64 encoding\n * @param {ArrayBuffer} binaryData An ArrayBuffer which represents an array of bytes\n * @returns {string} A string containing the base64 encoding of `binaryData`\n */\nfunction bufferToBase64(binaryData) {\n  // The base64 encoding uses the following set of characters to encode any binary data as text\n  const base64Table =\n    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n  // Every 3 bytes translates to 4 base64 characters, if we have less than 3 bytes we must append '=' chars as padding\n  const padding = 3 - (binaryData.byteLength % 3)\n  // Create an instance of Uint8Array, to read from the binaryData array buffer\n  const byteView = new Uint8Array(binaryData)\n  let result = ''\n\n  // Loop through all bytes in the buffer, in increments of 3 bytes\n  for (let i = 0; i < byteView.byteLength; i += 3) {\n    // Get the index for the next 4 base64 chars\n    const char1 = (byteView[i] & 252) >> 2\n    const char2 = ((byteView[i] & 3) << 4) + ((byteView[i + 1] & 240) >> 4)\n    const char3 = ((byteView[i + 1] & 15) << 2) + ((byteView[i + 2] & 192) >> 6)\n    const char4 = byteView[i + 2] & 63\n\n    result +=\n      base64Table[char1] +\n      base64Table[char2] +\n      base64Table[char3] +\n      base64Table[char4]\n  }\n\n  // Add padding '=' chars if needed\n  if (padding !== 3) {\n    const paddedResult =\n      result.slice(0, result.length - padding) + '='.repeat(padding)\n    return paddedResult\n  }\n\n  return result\n}\n\nexport { bufferToBase64 }\n"
  },
  {
    "path": "Conversions/Base64ToArrayBuffer.js",
    "content": "// About base64: https://en.wikipedia.org/wiki/Base64\n\n/**\n * Converts a base64 string to an array of bytes\n * @param {string} b64 A base64 string\n * @returns {ArrayBuffer} An ArrayBuffer representing the bytes encoded by the base64 string\n */\nfunction base64ToBuffer(b64) {\n  // The base64 encoding uses the following set of characters to encode any binary data as text\n  const base64Table =\n    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n  // Find the index of char '=' first occurrence\n  const paddingIdx = b64.indexOf('=')\n  // Remove padding chars from base64 string, if there are any\n  const b64NoPadding = paddingIdx !== -1 ? b64.slice(0, paddingIdx) : b64\n  // Calculate the length of the result buffer\n  const bufferLength = Math.floor((b64NoPadding.length * 6) / 8)\n  // Create the result buffer\n  const result = new ArrayBuffer(bufferLength)\n  // Create an instance of Uint8Array, to write to the `result` buffer\n  const byteView = new Uint8Array(result)\n\n  // Loop through all chars in the base64 string, in increments of 4 chars, and in increments of 3 bytes\n  for (let i = 0, j = 0; i < b64NoPadding.length; i += 4, j += 3) {\n    // Get the index of the next 4 base64 chars\n    const b64Char1 = base64Table.indexOf(b64NoPadding[i])\n    const b64Char2 = base64Table.indexOf(b64NoPadding[i + 1])\n    let b64Char3 = base64Table.indexOf(b64NoPadding[i + 2])\n    let b64Char4 = base64Table.indexOf(b64NoPadding[i + 3])\n\n    // If base64 chars 3 and 4 don't exit, then set them to 0\n    if (b64Char3 === -1) b64Char3 = 0\n    if (b64Char4 === -1) b64Char4 = 0\n\n    // Calculate the next 3 bytes\n    const byte1 = (b64Char1 << 2) + ((b64Char2 & 48) >> 4)\n    const byte2 = ((b64Char2 & 15) << 4) + ((b64Char3 & 60) >> 2)\n    const byte3 = ((b64Char3 & 3) << 6) + b64Char4\n\n    byteView[j] = byte1\n    byteView[j + 1] = byte2\n    byteView[j + 2] = byte3\n  }\n\n  return result\n}\n\nexport { base64ToBuffer }\n"
  },
  {
    "path": "Conversions/BinaryToDecimal.js",
    "content": "export default function binaryToDecimal(binaryString) {\n  let decimalNumber = 0\n  const binaryDigits = binaryString.split('').reverse() // Splits the binary number into reversed single digits\n  binaryDigits.forEach((binaryDigit, index) => {\n    decimalNumber += binaryDigit * Math.pow(2, index) // Summation of all the decimal converted digits\n  })\n  return decimalNumber\n}\n"
  },
  {
    "path": "Conversions/BinaryToHex.js",
    "content": "const pad = (num, padlen) => {\n  const pad = new Array(1 + padlen).join(0)\n  return (pad + num).slice(-pad.length)\n}\n\nconst hexLookup = (bin) => {\n  let binary = bin\n  if (binary.length < 4) {\n    binary = pad(binary, 4)\n  }\n  switch (binary) {\n    case '0000':\n      return '0'\n    case '0001':\n      return '1'\n    case '0010':\n      return '2'\n    case '0011':\n      return '3'\n    case '0100':\n      return '4'\n    case '0101':\n      return '5'\n    case '0110':\n      return '6'\n    case '0111':\n      return '7'\n    case '1000':\n      return '8'\n    case '1001':\n      return '9'\n    case '1010':\n      return 'A'\n    case '1011':\n      return 'B'\n    case '1100':\n      return 'C'\n    case '1101':\n      return 'D'\n    case '1110':\n      return 'E'\n    case '1111':\n      return 'F'\n  }\n}\nconst binaryToHex = (binaryString) => {\n  /*\n  Function for converting Binary to Hex\n\n  1. The conversion will start from Least Significant Digit (LSB) to the Most Significant Bit (MSB).\n  2. We divide the bits into sections of 4-bits starting from LSB to MSB.\n  3. If the MSB get less than 4 bits, then we pad 0s to the front of it.\n\n  For Example:\n  Binary String = '1001101'\n\n  1. Divide it to 2 parts => ['100', '1101']\n  2. Pad 0s the MSB so it'll be => ['0100', '1101']\n  3. Use the lookup table and merge them, therefore the result is 4D.\n\n  */\n\n  let result = ''\n  binaryString = binaryString.split('')\n  for (let i = binaryString.length - 1; i >= 0; i = i - 4) {\n    if (i >= 3) {\n      result += hexLookup(binaryString.slice(i - 3, i + 1).join(''))\n    } else {\n      result += hexLookup(binaryString.slice(0, i + 1).join(''))\n    }\n  }\n  return result.split('').reverse().join('')\n}\n\nexport default binaryToHex\n"
  },
  {
    "path": "Conversions/DateDayDifference.js",
    "content": "/*\n    DateDayDifference Method\n    ------------------------\n    DateDayDifference method calculates the number of days between two dates.\n\n    Algorithm & Explanation : https://ncalculators.com/time-date/date-difference-calculator.htm\n*/\n\nimport { isLeapYear } from '../Maths/LeapYear'\nimport { parseDate } from '../Timing-Functions/ParseDate'\n\nconst DateToDay = (dd, mm, yyyy) => {\n  return (\n    365 * (yyyy - 1) +\n    Math.floor((yyyy - 1) / 4) -\n    Math.floor((yyyy - 1) / 100) +\n    Math.floor((yyyy - 1) / 400) +\n    dd +\n    Math.floor((367 * mm - 362) / 12) +\n    (mm <= 2 ? 0 : isLeapYear(yyyy) ? -1 : -2)\n  )\n}\n\nconst DateDayDifference = (date1, date2) => {\n  const firstDate = parseDate(date1)\n  const secondDate = parseDate(date2)\n\n  return Math.abs(\n    DateToDay(secondDate.day, secondDate.month, secondDate.year) -\n      DateToDay(firstDate.day, firstDate.month, firstDate.year)\n  )\n}\n\n// Example : DateDayDifference('17/08/2002', '10/10/2020') => 6630\n\nexport { DateDayDifference }\n"
  },
  {
    "path": "Conversions/DateToDay.js",
    "content": "/*\n                    DateToDay Method\n                    ----------------\n    The DateToDay method takes a date in string format and\n    returns the name of a day. The approach behind this method\n    is very simple, we first take a string date and check\n    whether their date is valid or not, if the date is valid\n    then we do this But apply the algorithm shown below. The\n    algorithm shown below gives us the number of the day and\n    finally converts it to the name of the day.\n\n    Algorithm & Explanation : https://en.wikipedia.org/wiki/Zeller%27s_congruence\n*/\n\nimport { parseDate } from '../Timing-Functions/ParseDate'\n\n// Array holding name of the day: Saturday - Sunday - Friday => 0 - 1 - 6\nconst daysNameArr = [\n  'Saturday',\n  'Sunday',\n  'Monday',\n  'Tuesday',\n  'Wednesday',\n  'Thursday',\n  'Friday'\n]\n\nconst DateToDay = (date) => {\n  // firstly, check that input is a string or not.\n  const dateStruct = parseDate(date)\n  let year = dateStruct.year\n  let month = dateStruct.month\n  let day = dateStruct.day\n\n  // In case of Jan and Feb:\n  // Year: we consider it as previous year\n  // e.g., 1/1/1987 here year is 1986 (-1)\n  // Month: we consider value as 13 & 14 respectively\n  if (month < 3) {\n    year--\n    month += 12\n  }\n\n  // divide year into century and the last two digits of the century\n  const yearDigits = year % 100\n  const century = Math.floor(year / 100)\n\n  /*\n  In mathematics, remainders of divisions are usually defined to always be positive;\n  As an example, -2 mod 7 = 5.\n  Many programming languages including JavaScript implement the remainder of `n % m` as `sign(n) * (abs(n) % m)`.\n  This means the result has the same sign as the numerator. Here, `-2 % 7 = -1 * (2 % 7) = -2`.\n\n  To ensure a positive numerator, the formula is adapted: `- 2 * century` is replaced with `+ 5 * century`\n  which does not alter the resulting numbers mod 7 since `7 - 2 = 5`\n\n  The following example shows the issue with modulo division:\n  Without the adaption, the formula yields `weekDay = -6` for the date 2/3/2014;\n  With the adaption, it yields the positive result `weekDay = 7 - 6 = 1` (Sunday), which is what we need to index the array\n  */\n  const weekDay =\n    (day +\n      Math.floor((month + 1) * 2.6) +\n      yearDigits +\n      Math.floor(yearDigits / 4) +\n      Math.floor(century / 4) +\n      5 * century) %\n    7\n  return daysNameArr[weekDay] // name of the weekday\n}\n\n// Example : DateToDay(\"18/12/2020\") => Friday\n\nexport { DateToDay }\n"
  },
  {
    "path": "Conversions/DecimalToBinary.js",
    "content": "function decimalToBinary(num) {\n  const bin = []\n  while (num > 0) {\n    bin.unshift(num % 2)\n    num >>= 1 // basically /= 2 without remainder if any\n  }\n  return bin.join('')\n}\n\nexport { decimalToBinary }\n\n// > decimalToBinary(2)\n// '10'\n\n// > decimalToBinary(7)\n// '111'\n\n// > decimalToBinary(35)\n// '100011'\n"
  },
  {
    "path": "Conversions/DecimalToHex.js",
    "content": "function intToHex(num) {\n  switch (num) {\n    case 10:\n      return 'A'\n    case 11:\n      return 'B'\n    case 12:\n      return 'C'\n    case 13:\n      return 'D'\n    case 14:\n      return 'E'\n    case 15:\n      return 'F'\n  }\n  return num\n}\n\nfunction decimalToHex(num) {\n  const hexOut = []\n  while (num > 15) {\n    hexOut.unshift(intToHex(num % 16))\n    num = Math.floor(num / 16)\n  }\n  return intToHex(num) + hexOut.join('')\n}\n\nexport { decimalToHex }\n"
  },
  {
    "path": "Conversions/DecimalToOctal.js",
    "content": "function decimalToOctal(num) {\n  let oct = 0\n  let c = 0\n  while (num > 0) {\n    const r = num % 8\n    oct = oct + r * Math.pow(10, c++)\n    num = Math.floor(num / 8) // basically /= 8 without remainder if any\n  }\n  return oct\n}\n\nexport { decimalToOctal }\n\n// > decimalToOctal(2)\n// 2\n\n// > decimalToOctal(8)\n// 10\n\n// > decimalToOctal(65)\n// 101\n\n// > decimalToOctal(216)\n// 330\n\n// > decimalToOctal(512)\n// 1000\n"
  },
  {
    "path": "Conversions/DecimalToRoman.js",
    "content": "/*\n    Decimal To Roman\n\n    This algorithm take decimal number and convert to roman numeral according to standard form (https://en.wikipedia.org/wiki/Roman_numerals#Description)\n\n    Algorithm & Explanation : https://www.rapidtables.com/convert/number/how-number-to-roman-numerals.html\n*/\n\nconst values = {\n  M: 1000,\n  CM: 900,\n  D: 500,\n  CD: 400,\n  C: 100,\n  XC: 90,\n  L: 50,\n  XL: 40,\n  X: 10,\n  IX: 9,\n  V: 5,\n  IV: 4,\n  I: 1\n}\n\nconst orders = [\n  'M',\n  'CM',\n  'D',\n  'CD',\n  'C',\n  'XC',\n  'L',\n  'XL',\n  'X',\n  'IX',\n  'V',\n  'IV',\n  'I'\n]\n\nfunction decimalToRoman(num) {\n  let roman = ''\n  for (const symbol of orders) {\n    while (num >= values[symbol]) {\n      roman += symbol\n      num -= values[symbol]\n    }\n  }\n  return roman\n}\n\nexport { decimalToRoman }\n"
  },
  {
    "path": "Conversions/HexToBinary.js",
    "content": "const binLookup = (key) =>\n  ({\n    0: '0000',\n    1: '0001',\n    2: '0010',\n    3: '0011',\n    4: '0100',\n    5: '0101',\n    6: '0110',\n    7: '0111',\n    8: '1000',\n    9: '1001',\n    a: '1010',\n    b: '1011',\n    c: '1100',\n    d: '1101',\n    e: '1110',\n    f: '1111'\n  })[key.toLowerCase()] // select the binary number by valid hex key with the help javascript object\n\nconst hexToBinary = (hexString) => {\n  if (typeof hexString !== 'string') {\n    throw new TypeError('Argument is not a string type')\n  }\n\n  if (/[^\\da-f]/gi.test(hexString)) {\n    throw new Error('Argument is not a valid HEX code!')\n  }\n  /*\n    Function for converting Hex to Binary\n\n    1. We convert every hexadecimal bit to 4 binary bits\n    2. Conversion goes by searching in the lookup table\n  */\n\n  return hexString.replace(/[0-9a-f]/gi, (lexeme) => binLookup(lexeme))\n}\n\nexport default hexToBinary\n"
  },
  {
    "path": "Conversions/HexToDecimal.js",
    "content": "function hexToInt(hexNum) {\n  if (!/^[0-9A-F]+$/.test(hexNum)) {\n    throw new Error('Invalid hex string.')\n  }\n  const numArr = hexNum.split('') // converts number to array\n  return numArr.map((item, index) => {\n    switch (item) {\n      case 'A':\n        return 10\n      case 'B':\n        return 11\n      case 'C':\n        return 12\n      case 'D':\n        return 13\n      case 'E':\n        return 14\n      case 'F':\n        return 15\n      default:\n        return parseInt(item)\n    }\n  })\n}\n\nfunction hexToDecimal(hexNum) {\n  const intItemsArr = hexToInt(hexNum)\n  return intItemsArr.reduce((accumulator, current, index) => {\n    return (\n      accumulator + current * Math.pow(16, intItemsArr.length - (1 + index))\n    )\n  }, 0)\n}\n\nexport { hexToDecimal }\n"
  },
  {
    "path": "Conversions/HexToRGB.js",
    "content": "function hexStringToRGB(hexString) {\n  let r = hexString.substring(0, 2)\n  let g = hexString.substring(2, 4)\n  let b = hexString.substring(4, 6)\n\n  r = parseInt(r, 16)\n  g = parseInt(g, 16)\n  b = parseInt(b, 16)\n  const obj = { r, g, b }\n\n  return obj\n}\n\nexport { hexStringToRGB }\n\n// > hexStringToRGB('ffffff')\n// { r: 255, g: 255, b: 255 }\n"
  },
  {
    "path": "Conversions/LengthConversion.js",
    "content": "/**\n * Converts a length from one unit to another.\n *\n * @param {number} length - The length to convert.\n * @param {string} fromUnit - The unit to convert from (e.g., \"km\", \"m\", \"cm\").\n * @param {string} toUnit - The unit to convert to (e.g., \"km\", \"m\", \"cm\").\n * @returns {number} The converted length.\n * @throws {Error} If the units are invalid or not found in the conversion dictionary.\n */\n\nconst lengthConversion = (length, fromUnit, toUnit) => {\n  // Define a dictionary to map units to meters\n  const meters = {\n    mm: 0.001,\n    cm: 0.01,\n    m: 1,\n    km: 1000,\n    inch: 0.0254,\n    ft: 0.3048,\n    yd: 0.9144,\n    mi: 1609.34\n  }\n\n  // Check if the units are in the dictionary, otherwise, throw an error\n  if (!(fromUnit in meters) || !(toUnit in meters)) {\n    throw new Error('Invalid units')\n  }\n\n  // Perform the conversion\n  const metersFrom = length * meters[fromUnit]\n  const convertedLength = metersFrom / meters[toUnit]\n\n  return convertedLength\n}\n\nexport { lengthConversion }\n"
  },
  {
    "path": "Conversions/LitersToImperialGallons.js",
    "content": "/**\n * This function converts liters to imperial gallons\n * @constructor\n * @param {number} liters - Amount of liters to convert to gallons\n * @see https://en.wikipedia.org/wiki/Gallon\n */\nconst litersToImperialGallons = (liters) => {\n  return liters / 4.54609\n}\n\nexport default litersToImperialGallons\n"
  },
  {
    "path": "Conversions/LitersToUSGallons.js",
    "content": "/**\n * This function converts liters to US gallons\n * https://en.wikipedia.org/wiki/Gallon\n * @constructor\n * @param {number} liters - Amount of liters to convert to gallons\n */\nconst litersToUSGallons = (liters) => {\n  return liters / 3.785411784\n}\n\nexport default litersToUSGallons\n"
  },
  {
    "path": "Conversions/LowerCaseConversion.js",
    "content": "/*\n    Explanation :- a user gives a String (it can be incomplete uppercase or\n        partial uppercase) and then the program would convert it into a\n        complete(all characters in lower case) lower case string. The\n        logic we have used in the following program is: All the upper case\n        characters (A-Z) has ASCII value ranging from 65 to 90 and their\n        corresponding lower case characters (a-z) have ASCII values 32\n        greater than them. For example ‘A‘ has an ASCII value of 65\n        and ‘a‘ has an ASCII value of 97 (65+32). The same applies to other\n        characters.\n*/\n\n/**\n * LowerCaseConversion takes any case-style string and converts it to the lower case-style string.\n * @param {String} inputString any case style string\n * @returns {String} lower case string\n */\nconst LowerCaseConversion = (inputString) => {\n  // Take a string and split it into characters.\n  const newString = inputString.split('').map((char) => {\n    // Get a character code by the use charCodeAt method.\n    const presentCharCode = char.charCodeAt()\n    // If the character code lies between 65 to 90 it means they are in the upper case so convert it.\n    if (presentCharCode >= 65 && presentCharCode <= 90) {\n      // Convert the case by use of the above explanation.\n      return String.fromCharCode(presentCharCode + 32)\n    }\n    // Else return the characters without any modification.\n    return char\n  })\n  // After modification, with the help of the join method, join all the characters and return them.\n  return newString.join('')\n}\n\nexport { LowerCaseConversion }\n"
  },
  {
    "path": "Conversions/MeterToFeetConversion.js",
    "content": "// Foot: https://en.wikipedia.org/wiki/Foot_(unit)\nconst feetToMeter = (feet) => {\n  return feet * 0.3048\n}\n\nconst meterToFeet = (meter) => {\n  return meter / 0.3048\n}\n\nexport { feetToMeter, meterToFeet }\n"
  },
  {
    "path": "Conversions/OctToDecimal.js",
    "content": "function octalToDecimal(num) {\n  let dec = 0\n  let base = 1\n  while (num > 0) {\n    const r = num % 10\n    num = Math.floor(num / 10)\n    dec = dec + r * base\n    base = base * 8\n  }\n  return dec\n}\n\nexport { octalToDecimal }\n\n// > octalToDecimal(56)\n// 46\n\n// > octalToDecimal(2365)\n// 1269\n"
  },
  {
    "path": "Conversions/OuncesToKilograms.js",
    "content": "/**\n * This function converts ounces to kilograms\n * https://en.wikipedia.org/wiki/Ounce\n * @constructor\n * @param {number} oz - Amount of ounces to convert to kilograms\n */\nconst ouncesToKilograms = (oz) => {\n  return (oz * 28.3498) / 1000\n}\n\nexport default ouncesToKilograms\n"
  },
  {
    "path": "Conversions/RGBToHex.js",
    "content": "function RGBToHex(r, g, b) {\n  if (typeof r !== 'number' || typeof g !== 'number' || typeof b !== 'number') {\n    throw new TypeError('argument is not a Number')\n  }\n\n  const toHex = (n) => (n || '0').toString(16).padStart(2, '0')\n\n  return `#${toHex(r)}${toHex(g)}${toHex(b)}`\n}\n\nexport { RGBToHex }\n\n// > RGBToHex(255, 255, 255)\n// '#ffffff'\n\n// > RGBToHex(255, 99, 71)\n// '#ff6347'\n"
  },
  {
    "path": "Conversions/RailwayTimeConversion.js",
    "content": "/*\n    The time conversion of normalized time to the railway is a simple algorithm\n    because we know that if the time is in 'AM' value it means they only want\n    some changes on hours and minutes and if the time in 'PM' it means the only\n    want some changes in hour value.\n\n    Input Format -> 07:05:45PM\n    Output Format -> 19:05:45\n\n    Problem & Explanation Source : https://www.mathsisfun.com/time.html\n*/\n\n/**\n * RailwayTimeConversion method converts normalized time string to Railway time string.\n * @param {String} timeString Normalized time string.\n * @returns {String} Railway time string.\n */\nconst RailwayTimeConversion = (timeString) => {\n  // firstly, check that input is a string or not.\n  if (typeof timeString !== 'string') {\n    throw new TypeError('Argument is not a string.')\n  }\n  // split the string by ':' character.\n  const [hour, minute, secondWithShift] = timeString.split(':')\n  // split second and shift value.\n  const [second, shift] = [\n    secondWithShift.substring(0, 2),\n    secondWithShift.substring(2)\n  ]\n  // convert shifted time to not-shift time(Railway time) by using the above explanation.\n  if (shift === 'PM') {\n    if (parseInt(hour) === 12) {\n      return `${hour}:${minute}:${second}`\n    } else {\n      return `${parseInt(hour) + 12}:${minute}:${second}`\n    }\n  } else {\n    if (parseInt(hour) === 12) {\n      return `00:${minute}:${second}`\n    } else {\n      return `${hour}:${minute}:${second}`\n    }\n  }\n}\n\nexport { RailwayTimeConversion }\n"
  },
  {
    "path": "Conversions/RgbHslConversion.js",
    "content": "/**\n * Given a color in RGB format, convert it to HSL format.\n *\n * For more info: https://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/\n *\n * @param {number[]} colorRgb - One dimensional array of integers (RGB color format).\n * @returns {number[]} - One dimensional array of integers (HSL color format).\n *\n * @example\n * const colorRgb = [24, 98, 118]\n *\n * const result = rgbToHsl(colorRgb)\n *\n * // The function returns the corresponding color in HSL format:\n * // result = [193, 66, 28]\n */\n\nconst checkRgbFormat = (colorRgb) => colorRgb.every((c) => c >= 0 && c <= 255)\n\nconst rgbToHsl = (colorRgb) => {\n  if (!checkRgbFormat(colorRgb)) {\n    throw new Error('Input is not a valid RGB color.')\n  }\n\n  let colorHsl = colorRgb\n\n  let red = Math.round(colorRgb[0])\n  let green = Math.round(colorRgb[1])\n  let blue = Math.round(colorRgb[2])\n\n  const limit = 255\n\n  colorHsl[0] = red / limit\n  colorHsl[1] = green / limit\n  colorHsl[2] = blue / limit\n\n  let minValue = Math.min(...colorHsl)\n  let maxValue = Math.max(...colorHsl)\n\n  let channel = 0\n\n  if (maxValue === colorHsl[1]) {\n    channel = 1\n  } else if (maxValue === colorHsl[2]) {\n    channel = 2\n  }\n\n  let luminance = (minValue + maxValue) / 2\n\n  let saturation = 0\n\n  if (minValue !== maxValue) {\n    if (luminance <= 0.5) {\n      saturation = (maxValue - minValue) / (maxValue + minValue)\n    } else {\n      saturation = (maxValue - minValue) / (2 - maxValue - minValue)\n    }\n  }\n\n  let hue = 0\n\n  if (saturation !== 0) {\n    if (channel === 0) {\n      hue = (colorHsl[1] - colorHsl[2]) / (maxValue - minValue)\n    } else if (channel === 1) {\n      hue = 2 + (colorHsl[2] - colorHsl[0]) / (maxValue - minValue)\n    } else {\n      hue = 4 + (colorHsl[0] - colorHsl[1]) / (maxValue - minValue)\n    }\n  }\n\n  hue *= 60\n\n  if (hue < 0) {\n    hue += 360\n  }\n\n  colorHsl[0] = Math.round(hue)\n  colorHsl[1] = Math.round(saturation * 100)\n  colorHsl[2] = Math.round(luminance * 100)\n\n  return colorHsl\n}\n\nexport { rgbToHsl }\n"
  },
  {
    "path": "Conversions/RgbHsvConversion.js",
    "content": "/*\n * The RGB color model is an additive color model in which red, green, and blue light are added\n * together in various ways to reproduce a broad array of colors. The name of the model comes from\n * the initials of the three additive primary colors, red, green, and blue. Meanwhile, the HSV\n * representation models how colors appear under light. In it, colors are represented using three\n * components: hue, saturation and (brightness-)value. This file provides functions for converting\n * colors from one representation to the other. (description adapted from\n * https://en.wikipedia.org/wiki/RGB_color_model and https://en.wikipedia.org/wiki/HSL_and_HSV).\n */\n\n/**\n * Conversion from the HSV-representation to the RGB-representation.\n *\n * @param hue Hue of the color.\n * @param saturation Saturation of the color.\n * @param value Brightness-value of the color.\n * @return The tuple of RGB-components.\n */\nexport function hsvToRgb(hue, saturation, value) {\n  if (hue < 0 || hue > 360) {\n    throw new Error('hue should be between 0 and 360')\n  }\n\n  if (saturation < 0 || saturation > 1) {\n    throw new Error('saturation should be between 0 and 1')\n  }\n\n  if (value < 0 || value > 1) {\n    throw new Error('value should be between 0 and 1')\n  }\n\n  const chroma = value * saturation\n  const hueSection = hue / 60\n  const secondLargestComponent = chroma * (1 - Math.abs((hueSection % 2) - 1))\n  const matchValue = value - chroma\n\n  return getRgbBySection(hueSection, chroma, matchValue, secondLargestComponent)\n}\n\n/**\n * Conversion from the RGB-representation to the HSV-representation.\n *\n * @param red Red-component of the color.\n * @param green Green-component of the color.\n * @param blue Blue-component of the color.\n * @return The tuple of HSV-components.\n */\nexport function rgbToHsv(red, green, blue) {\n  if (red < 0 || red > 255) {\n    throw new Error('red should be between 0 and 255')\n  }\n\n  if (green < 0 || green > 255) {\n    throw new Error('green should be between 0 and 255')\n  }\n\n  if (blue < 0 || blue > 255) {\n    throw new Error('blue should be between 0 and 255')\n  }\n\n  const dRed = red / 255\n  const dGreen = green / 255\n  const dBlue = blue / 255\n  const value = Math.max(Math.max(dRed, dGreen), dBlue)\n  const chroma = value - Math.min(Math.min(dRed, dGreen), dBlue)\n  const saturation = value === 0 ? 0 : chroma / value\n  let hue\n\n  if (chroma === 0) {\n    hue = 0\n  } else if (value === dRed) {\n    hue = 60 * ((dGreen - dBlue) / chroma)\n  } else if (value === dGreen) {\n    hue = 60 * (2 + (dBlue - dRed) / chroma)\n  } else {\n    hue = 60 * (4 + (dRed - dGreen) / chroma)\n  }\n\n  hue = (hue + 360) % 360\n\n  return [hue, saturation, value]\n}\n\nexport function approximatelyEqualHsv(hsv1, hsv2) {\n  const bHue = Math.abs(hsv1[0] - hsv2[0]) < 0.2\n  const bSaturation = Math.abs(hsv1[1] - hsv2[1]) < 0.002\n  const bValue = Math.abs(hsv1[2] - hsv2[2]) < 0.002\n\n  return bHue && bSaturation && bValue\n}\n\nfunction getRgbBySection(\n  hueSection,\n  chroma,\n  matchValue,\n  secondLargestComponent\n) {\n  function convertToInt(input) {\n    return Math.round(255 * input)\n  }\n\n  let red\n  let green\n  let blue\n\n  if (hueSection >= 0 && hueSection <= 1) {\n    red = convertToInt(chroma + matchValue)\n    green = convertToInt(secondLargestComponent + matchValue)\n    blue = convertToInt(matchValue)\n  } else if (hueSection > 1 && hueSection <= 2) {\n    red = convertToInt(secondLargestComponent + matchValue)\n    green = convertToInt(chroma + matchValue)\n    blue = convertToInt(matchValue)\n  } else if (hueSection > 2 && hueSection <= 3) {\n    red = convertToInt(matchValue)\n    green = convertToInt(chroma + matchValue)\n    blue = convertToInt(secondLargestComponent + matchValue)\n  } else if (hueSection > 3 && hueSection <= 4) {\n    red = convertToInt(matchValue)\n    green = convertToInt(secondLargestComponent + matchValue)\n    blue = convertToInt(chroma + matchValue)\n  } else if (hueSection > 4 && hueSection <= 5) {\n    red = convertToInt(secondLargestComponent + matchValue)\n    green = convertToInt(matchValue)\n    blue = convertToInt(chroma + matchValue)\n  } else {\n    red = convertToInt(chroma + matchValue)\n    green = convertToInt(matchValue)\n    blue = convertToInt(secondLargestComponent + matchValue)\n  }\n\n  return [red, green, blue]\n}\n"
  },
  {
    "path": "Conversions/RomanToDecimal.js",
    "content": "const values = {\n  I: 1,\n  V: 5,\n  X: 10,\n  L: 50,\n  C: 100,\n  D: 500,\n  M: 1000\n}\n\nexport function romanToDecimal(romanNumber) {\n  let prev = ' '\n\n  let sum = 0\n\n  let newPrev = 0\n  for (let i = romanNumber.length - 1; i >= 0; i--) {\n    const c = romanNumber.charAt(i)\n\n    if (prev !== ' ') {\n      newPrev = values[prev] > newPrev ? values[prev] : newPrev\n    }\n\n    const currentNum = values[c]\n    if (currentNum >= newPrev) {\n      sum += currentNum\n    } else {\n      sum -= currentNum\n    }\n\n    prev = c\n  }\n  return sum\n}\n"
  },
  {
    "path": "Conversions/TemperatureConversion.js",
    "content": "// This files has functions to convert different temperature units\n// Functions take temperature value as a argument and returns corresponding converted value\n\nconst celsiusToFahrenheit = (celsius) => {\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Celsius\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit\n  return Math.round((celsius * 9) / 5 + 32)\n}\n\nconst celsiusToKelvin = (celsius) => {\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Celsius\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin\n  return Math.round(celsius + 273.15)\n}\n\nconst celsiusToRankine = (celsius) => {\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Celsius\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale\n  return Math.round((celsius * 9) / 5 + 491.67)\n}\n\nconst fahrenheitToCelsius = (fahrenheit) => {\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Celsius\n  return Math.round(((fahrenheit - 32) * 5) / 9)\n}\n\nconst fahrenheitToKelvin = (fahrenheit) => {\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin\n  return Math.round(((fahrenheit - 32) * 5) / 9 + 273.15)\n}\n\nconst fahrenheitToRankine = (fahrenheit) => {\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale\n  return Math.round(fahrenheit + 459.67)\n}\n\nconst kelvinToCelsius = (kelvin) => {\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Celsius\n  return Math.round(kelvin - 273.15)\n}\n\nconst kelvinToFahrenheit = (kelvin) => {\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit\n  return Math.round(((kelvin - 273.15) * 9) / 5 + 32)\n}\n\nconst kelvinToRankine = (kelvin) => {\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale\n  return Math.round((kelvin * 9) / 5)\n}\n\nconst rankineToCelsius = (rankine) => {\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Celsius\n  return Math.round(((rankine - 491.67) * 5) / 9)\n}\n\nconst rankineToFahrenheit = (rankine) => {\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit\n  return Math.round(rankine - 459.67)\n}\n\nconst rankineToKelvin = (rankine) => {\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale\n  // Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin\n  return Math.round((rankine * 5) / 9)\n}\n\nconst reaumurToKelvin = (reaumur) => {\n  // Reference:- http://www.csgnetwork.com/temp2conv.html\n  return Math.round(reaumur * 1.25 + 273.15)\n}\n\nconst reaumurToFahrenheit = (reaumur) => {\n  // Reference:- http://www.csgnetwork.com/temp2conv.html\n  return Math.round(reaumur * 2.25 + 32)\n}\n\nconst reaumurToCelsius = (reaumur) => {\n  // Reference:- http://www.csgnetwork.com/temp2conv.html\n  return Math.round(reaumur * 1.25)\n}\n\nconst reaumurToRankine = (reaumur) => {\n  // Reference:- http://www.csgnetwork.com/temp2conv.html\n  return Math.round(reaumur * 2.25 + 32 + 459.67)\n}\n\nexport {\n  celsiusToFahrenheit,\n  celsiusToKelvin,\n  celsiusToRankine,\n  fahrenheitToCelsius,\n  fahrenheitToKelvin,\n  fahrenheitToRankine,\n  kelvinToCelsius,\n  kelvinToFahrenheit,\n  kelvinToRankine,\n  rankineToCelsius,\n  rankineToFahrenheit,\n  rankineToKelvin,\n  reaumurToCelsius,\n  reaumurToFahrenheit,\n  reaumurToKelvin,\n  reaumurToRankine\n}\n"
  },
  {
    "path": "Conversions/TitleCaseConversion.js",
    "content": "/*\n    Problem statement and Explanation : https://www.codeproject.com/Tips/162540/Letter-Case-Conversion-Algorithms-Title-Case-Toggl.\n    [Title case](https://en.wikipedia.org/wiki/Title_case) is a style where all words are capitalized. Officially, title case\n    does not capitalize some words, such as very short words like \"a\" or \"is\", but for the purposes of this function, a general approach\n    is taken where all words are capitalized regardless of length.\n*/\n\n/**\n * The titleCaseConversion function converts a string into a title case string.\n * @param {string} inputString The input string which can have any types of letter casing.\n * @returns {string} A string that is in title case.\n */\nconst titleCaseConversion = (inputString) => {\n  if (inputString === '') return ''\n  // Extract all space separated string.\n  const stringCollections = inputString.split(' ').map((word) => {\n    let firstChar = ''\n    // Get the [ASCII](https://en.wikipedia.org/wiki/ASCII) character code by the use charCodeAt method.\n    const firstCharCode = word[0].charCodeAt()\n    // If the ASCII character code lies between 97 to 122 it means they are in the lowercase so convert it.\n    if (firstCharCode >= 97 && firstCharCode <= 122) {\n      // Convert the case by use of the above explanation.\n      firstChar += String.fromCharCode(firstCharCode - 32)\n    } else {\n      // Else store the characters without any modification.\n      firstChar += word[0]\n    }\n    const newWordChar = word\n      .slice(1)\n      .split('')\n      .map((char) => {\n        // Get the ASCII character code by the use charCodeAt method.\n        const presentCharCode = char.charCodeAt()\n        // If the ASCII character code lies between 65 to 90, it means they are in the uppercase so convert it.\n        if (presentCharCode >= 65 && presentCharCode <= 90) {\n          // Convert the case by use of the above explanation.\n          return String.fromCharCode(presentCharCode + 32)\n        }\n        // Else return the characters without any modification.\n        return char\n      })\n    // Return the first converted character and remaining character string.\n    return firstChar + newWordChar.join('')\n  })\n  // Convert all words in a string and return it.\n  return stringCollections.join(' ')\n}\n\nexport { titleCaseConversion }\n"
  },
  {
    "path": "Conversions/UpperCaseConversion.js",
    "content": "/*\n    Explanation :- A user gives a string (it can be incomplete lowercase or\n        partially in lowercase) and then the program converts it into a\n        completely (all characters in uppercase) uppercase string. The\n        logic we have used in the following program is: All the lowercase\n        characters (a-z) has [ASCII](https://en.wikipedia.org/wiki/ASCII) value ranging from 97 to 122 and their\n        corresponding uppercase characters (A-Z) have ASCII values 32\n        lesser than them. For example ‘a‘ has an ASCII value of 97\n        and ‘A‘ has an ASCII value of 65 (97 - 32). The same applies to other\n        characters.\n*/\n\n/**\n * upperCaseConversion takes any case-style string and converts it to the uppercase-style string.\n * @param {string} inputString Any case style string\n * @returns {string} Uppercase string\n */\nconst upperCaseConversion = (inputString) => {\n  // Take a string and split it into characters.\n  const newString = inputString.split('').map((char) => {\n    // Get a character code by the use charCodeAt method.\n    const presentCharCode = char.charCodeAt()\n    // If the character code lies between 97 to 122, it means they are in the lowercase so convert it.\n    if (presentCharCode >= 97 && presentCharCode <= 122) {\n      // Convert the case by use of the above explanation.\n      return String.fromCharCode(presentCharCode - 32)\n    }\n    // Else return the characters without any modification.\n    return char\n  })\n  // After modification, with the help of the join method, join all the characters and return them.\n  return newString.join('')\n}\n\nexport { upperCaseConversion }\n"
  },
  {
    "path": "Conversions/test/ArbitraryBase.test.js",
    "content": "import {\n  convertArbitraryBase,\n  convertArbitraryBaseBigIntVersion\n} from '../ArbitraryBase'\n\ntest('Check the answer of convertArbitraryBase(98, 0123456789, 01234567) is 142', () => {\n  const res = convertArbitraryBase('98', '0123456789', '01234567')\n  expect(res).toBe('142')\n})\n\ntest('Check the answer of convertArbitraryBase(98, 0123456789, abcdefgh) is bec', () => {\n  const res = convertArbitraryBase('98', '0123456789', 'abcdefgh')\n  expect(res).toBe('bec')\n})\n\ntest('Check the answer of convertArbitraryBase(98, 0123456789, 98765432) is 857', () => {\n  const res = convertArbitraryBase('98', '0123456789', '98765432')\n  expect(res).toBe('857')\n})\n\ntest('Check the answer of convertArbitraryBase(129, 0123456789, 01234567) is 201', () => {\n  const res = convertArbitraryBase('129', '0123456789', '01234567')\n  expect(res).toBe('201')\n})\n\ntest('Check the answer of convertArbitraryBase(112, 0123456789, 12345678) is 271', () => {\n  const res = convertArbitraryBase('112', '0123456789', '12345678')\n  expect(res).toBe('271')\n})\n\ntest('Check the answer of convertArbitraryBase(112, 0123456789, 123456789) is 245', () => {\n  const res = convertArbitraryBase('112', '0123456789', '123456789')\n  expect(res).toBe('245')\n})\n\ntest('Check the answer of convertArbitraryBase(111, 0123456789, abcdefgh) is bfh', () => {\n  const res = convertArbitraryBase('111', '0123456789', 'abcdefgh')\n  expect(res).toBe('bfh')\n})\n\ntest('Unicode awareness', () => {\n  const res = convertArbitraryBase('98', '0123456789', '💝🎸🦄')\n  expect(res).toBe('🎸💝🎸🦄🦄')\n})\n\ntest('zero', () => {\n  const res = convertArbitraryBase('0', '0123456789', 'abc')\n  expect(res).toBe('a')\n})\n\ntest('BigInt version with input string of arbitrary length', () => {\n  const resBigIntVersion = convertArbitraryBaseBigIntVersion(\n    String(10n ** 100n),\n    '0123456789',\n    '0123456789abcdefghijklmnopqrstuvwxyz'\n  )\n\n  expect(resBigIntVersion).toBe((10n ** 100n).toString(36))\n})\n"
  },
  {
    "path": "Conversions/test/ArrayBufferToBase64.test.js",
    "content": "import { bufferToBase64 } from '../ArrayBufferToBase64'\nimport { TextEncoder } from 'util'\n\ndescribe('ArrayBufferToBase64', () => {\n  it('should encode \"Hello, world!\" as \"SGVsbG8sIHdvcmxkIQ==\"', () => {\n    const testString = 'Hello, world!'\n    const encoder = new TextEncoder()\n    const helloWorldBuffer = encoder.encode(testString)\n    const result = bufferToBase64(helloWorldBuffer)\n    expect(result).toBe('SGVsbG8sIHdvcmxkIQ==')\n  })\n\n  it('should encode binary buffer [55,23,177,234,68,26,90] as \"Nxex6kQaWg==\"', () => {\n    const testBuffer = new Uint8Array([55, 23, 177, 234, 68, 26, 90])\n    const result = bufferToBase64(testBuffer)\n    expect(result).toBe('Nxex6kQaWg==')\n  })\n\n  it('should encode binary buffer [0,1,2,3,4,5,6,7,8,9] as \"AAECAwQFBgcICQ==\"', () => {\n    const testBuffer = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])\n    const result = bufferToBase64(testBuffer)\n    expect(result).toBe('AAECAwQFBgcICQ==')\n  })\n})\n"
  },
  {
    "path": "Conversions/test/Base64ToArrayBuffer.test.js",
    "content": "import { base64ToBuffer } from '../Base64ToArrayBuffer'\nimport { TextDecoder } from 'util'\n\ndescribe('Base64ToArrayBuffer', () => {\n  it('should decode \"SGVsbG8sIHdvcmxkIQ==\" as \"Hello, world!\"', () => {\n    const testBase64String = 'SGVsbG8sIHdvcmxkIQ=='\n    const buffer = base64ToBuffer(testBase64String)\n    const decoder = new TextDecoder()\n    const helloWorldString = decoder.decode(buffer)\n    expect(helloWorldString).toBe('Hello, world!')\n  })\n\n  it('should decode base64 \"Nxex6kQaWg==\" as binary buffer [55,23,177,234,68,26,90]', () => {\n    const testBase64String = 'Nxex6kQaWg=='\n    const buffer = base64ToBuffer(testBase64String)\n    const array = [...new Uint8Array(buffer)]\n    expect(array).toEqual([55, 23, 177, 234, 68, 26, 90])\n  })\n\n  it('should decode base64 \"AAECAwQFBgcICQ==\" as binary buffer [0,1,2,3,4,5,6,7,8,9]', () => {\n    const testBase64String = 'AAECAwQFBgcICQ=='\n    const buffer = base64ToBuffer(testBase64String)\n    const array = [...new Uint8Array(buffer)]\n    expect(array).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])\n  })\n})\n"
  },
  {
    "path": "Conversions/test/BinaryToDecimal.test.js",
    "content": "import binaryToDecimal from '../BinaryToDecimal'\n\ndescribe('BinaryToDecimal', () => {\n  it('expects to return correct decimal value', () => {\n    expect(binaryToDecimal('1000')).toBe(8)\n  })\n\n  it('expects to return correct hexadecimal value for more than one hex digit', () => {\n    expect(binaryToDecimal('01101000')).toBe(104)\n  })\n\n  it('expects to return correct hexadecimal value for padding-required binary', () => {\n    expect(binaryToDecimal('1000101')).toBe(69)\n  })\n})\n"
  },
  {
    "path": "Conversions/test/BinaryToHex.test.js",
    "content": "import binaryToHex from '../BinaryToHex'\n\ndescribe('BinaryToHex', () => {\n  it('expects to return correct hexadecimal value', () => {\n    expect(binaryToHex('1000')).toBe('8')\n  })\n\n  it('expects to return correct hexadecimal value for more than one hex digit', () => {\n    expect(binaryToHex('11101010')).toBe('EA')\n  })\n\n  it('expects to return correct hexadecimal value for padding-required binary', () => {\n    expect(binaryToHex('1001101')).toBe('4D')\n  })\n\n  it('expects to return correct hexadecimal value, matching (num).toString(16)', () => {\n    expect(binaryToHex('1111')).toBe(\n      parseInt('1111', 2).toString(16).toUpperCase()\n    )\n  })\n})\n"
  },
  {
    "path": "Conversions/test/DateDayDiffernce.test.js",
    "content": "import { DateDayDifference } from '../DateDayDifference'\n\ndescribe('DateDayDifference', () => {\n  it.each([\n    ['17/08/2002', '10/10/2020', 6629],\n    ['18/02/2001', '16/03/2022', 7696],\n    ['11/11/2011', '12/12/2012', 397],\n    ['01/01/2001', '16/03/2011', 3726],\n    ['04/03/2024', '04/03/2024', 0],\n    ['03/03/2024', '04/03/2024', 1],\n    ['02/03/2024', '04/03/2024', 2],\n    ['01/03/2024', '04/03/2024', 3],\n    ['29/02/2024', '04/03/2024', 4],\n    ['04/03/2024', '04/03/2025', 365],\n    ['04/03/2023', '04/03/2024', 366]\n  ])(\n    'The difference between %s and %s is %i',\n    (firstDate, secondDate, expected) => {\n      expect(DateDayDifference(firstDate, secondDate)).toBe(expected)\n      expect(DateDayDifference(secondDate, firstDate)).toBe(expected)\n    }\n  )\n\n  it('should throw when any input is not a string', () => {\n    expect(() => DateDayDifference(10102024, '11/10/2024')).toThrowError()\n    expect(() => DateDayDifference('11/10/2024', 10102024)).toThrowError()\n  })\n\n  it.each(['32/01/2000', '00/01/2000', '15/00/2000', '15/13/2000'])(\n    'should throw when input is not a correct date %s',\n    (wrongDate) => {\n      expect(() => DateDayDifference(wrongDate, '04/03/2024')).toThrowError()\n      expect(() => DateDayDifference('04/03/2024', wrongDate)).toThrowError()\n    }\n  )\n})\n"
  },
  {
    "path": "Conversions/test/DateToDay.test.js",
    "content": "import { DateToDay } from '../DateToDay'\n\ndescribe('DateToDay', () => {\n  it.each([\n    ['18/02/2001', 'Sunday'],\n    ['18/12/2020', 'Friday'],\n    ['12/12/2012', 'Wednesday'],\n    ['01/01/2001', 'Monday'],\n    ['1/1/2020', 'Wednesday'],\n    ['2/3/2014', 'Sunday'],\n    ['28/2/2017', 'Tuesday'],\n    ['02/03/2024', 'Saturday'],\n    ['29/02/2024', 'Thursday']\n  ])('%s is %s', (date, day) => {\n    expect(DateToDay(date)).toBe(day)\n  })\n\n  it('should throw when input is not a string', () => {\n    expect(() => DateToDay(100)).toThrowError()\n  })\n\n  it.each(['32/01/2000', '00/01/2000', '15/00/2000', '15/13/2000'])(\n    'should throw when input is not a correct date %s',\n    (wrongDate) => {\n      expect(() => DateToDay(wrongDate)).toThrowError()\n    }\n  )\n})\n"
  },
  {
    "path": "Conversions/test/DecimalToBinary.test.js",
    "content": "import { decimalToBinary } from '../DecimalToBinary'\n\ntest('The Binary representation of 35 is 100011', () => {\n  const res = decimalToBinary(35)\n  expect(res).toBe('100011')\n})\n\ntest('The Binary representation of 1 is 1', () => {\n  const res = decimalToBinary(1)\n  expect(res).toBe('1')\n})\n\ntest('The Binary representation of 1000 is 1111101000', () => {\n  const res = decimalToBinary(1000)\n  expect(res).toBe('1111101000')\n})\n\ntest('The Binary representation of 2 is 10', () => {\n  const res = decimalToBinary(2)\n  expect(res).toBe('10')\n})\n\ntest('The Binary representation of 17 is 10001', () => {\n  const res = decimalToBinary(17)\n  expect(res).toBe('10001')\n})\n"
  },
  {
    "path": "Conversions/test/DecimalToHex.test.js",
    "content": "import { decimalToHex } from '../DecimalToHex'\n\ndescribe('DecimalToHex', () => {\n  it('expects to return correct hexadecimal value', () => {\n    expect(decimalToHex(255)).toBe('FF')\n  })\n\n  it('expects to return correct hexadecimal value, matching (num).toString(16)', () => {\n    expect(decimalToHex(32768)).toBe((32768).toString(16).toUpperCase())\n  })\n\n  it('expects to not handle negative numbers', () => {\n    expect(decimalToHex(-32768)).not.toBe((-32768).toString(16).toUpperCase())\n  })\n})\n"
  },
  {
    "path": "Conversions/test/DecimalToOctal.test.js",
    "content": "import { decimalToOctal } from '../DecimalToOctal'\n\ntest('The Octal representation of 8 is 10', () => {\n  const res = decimalToOctal(8)\n  expect(res).toBe(10)\n})\n\ntest('The Octal representation of 1 is 1', () => {\n  const res = decimalToOctal(1)\n  expect(res).toBe(1)\n})\n\ntest('The Octal representation of 0 is 0', () => {\n  const res = decimalToOctal(0)\n  expect(res).toBe(0)\n})\n\ntest('The Octal representation of 100 is 144', () => {\n  const res = decimalToOctal(100)\n  expect(res).toBe(144)\n})\n\ntest('The Octal representation of 111 is 157', () => {\n  const res = decimalToOctal(111)\n  expect(res).toBe(157)\n})\n"
  },
  {
    "path": "Conversions/test/DecimalToRoman.test.js",
    "content": "import { decimalToRoman } from '../DecimalToRoman'\n\ndescribe('decimalToRoman', () => {\n  it('expects to return correct roman numeral of given number', () => {\n    expect(decimalToRoman(34)).toBe('XXXIV')\n  })\n  it('expects to return correct roman numeral of given number', () => {\n    expect(decimalToRoman(28)).toBe('XXVIII')\n  })\n  it('expects to return correct roman numeral of given number', () => {\n    expect(decimalToRoman(2021)).toBe('MMXXI')\n  })\n})\n"
  },
  {
    "path": "Conversions/test/HexToBinary.test.js",
    "content": "import hexToBinary from '../HexToBinary'\n\ndescribe('Testing hexToBinary', () => {\n  it('expects throw error in invalid types', () => {\n    expect(() => hexToBinary(false)).toThrowError()\n    expect(() => hexToBinary(null)).toThrowError()\n    expect(() => hexToBinary(23464)).toThrowError()\n  })\n\n  it('expects throw error in invalid hex', () => {\n    expect(() => hexToBinary('Hello i am not a valid Hex')).toThrowError()\n    expect(() => hexToBinary('Gf46f')).toThrowError()\n    expect(() => hexToBinary('M')).toThrowError()\n  })\n\n  it('expects to return correct hexadecimal value', () => {\n    expect(hexToBinary('8')).toBe('1000')\n  })\n\n  it('expects to return correct binary value for more than one hex digit', () => {\n    expect(hexToBinary('EA')).toBe('11101010')\n  })\n\n  it('expects to test its robustness as it should be case-insensitive', () => {\n    expect(hexToBinary('4d')).toBe('01001101')\n  })\n\n  it('expects to return correct hexadecimal value, matching (num).toString(2)', () => {\n    expect(hexToBinary('F')).toBe(parseInt('F', 16).toString(2))\n  })\n})\n"
  },
  {
    "path": "Conversions/test/HexToDecimal.test.js",
    "content": "import { hexToDecimal } from '../HexToDecimal'\n\ndescribe('Testing HexToDecimal', () => {\n  it.each([\n    ['0', 0],\n    ['1', 1],\n    ['A', 10],\n    ['B', 11],\n    ['C', 12],\n    ['D', 13],\n    ['E', 14],\n    ['F', 15],\n    ['10', 16],\n    ['859', 2137],\n    ['4D2', 1234],\n    ['81323ABD92', 554893491602]\n  ])('check with %s', (hexStr, expected) => {\n    expect(hexToDecimal(hexStr)).toBe(expected)\n  })\n\n  it.each(['a', '-1', 'G', ''])('throws for %s', (hexStr) => {\n    expect(() => hexToDecimal(hexStr)).toThrowError()\n  })\n})\n"
  },
  {
    "path": "Conversions/test/HexToRGB.test.js",
    "content": "import { hexStringToRGB } from '../HexToRGB'\n\ntest('The RGB form of Hex String E1E1E1 is {r: 225, g: 225, b: 225}', () => {\n  const res = hexStringToRGB('E1E1E1')\n  expect(res).toEqual({ r: 225, g: 225, b: 225 })\n})\n\ntest('The RGB form of Hex String 000000 is {r: 0, g: 0, b: 0}', () => {\n  const res = hexStringToRGB('000000')\n  expect(res).toEqual({ r: 0, g: 0, b: 0 })\n})\n\ntest('The RGB form of Hex String 6CE1CD is {r: 108, g: 225, b: 205}', () => {\n  const res = hexStringToRGB('6CE1CD')\n  expect(res).toEqual({ r: 108, g: 225, b: 205 })\n})\n"
  },
  {
    "path": "Conversions/test/LengthConversion.test.js",
    "content": "import { lengthConversion } from '../LengthConversion.js'\n\ndescribe('LengthConversion', () => {\n  it.each`\n    length | fromUnit | toUnit    | expected\n    ${10}  | ${'km'}  | ${'m'}    | ${10000}\n    ${100} | ${'m'}   | ${'km'}   | ${0.1}\n    ${5}   | ${'cm'}  | ${'mm'}   | ${50}\n    ${12}  | ${'ft'}  | ${'inch'} | ${144.00000000000003}\n  `(\n    'converts $length $fromUnit to $toUnit',\n    ({ length, fromUnit, toUnit, expected }) => {\n      try {\n        const result = lengthConversion(length, fromUnit, toUnit)\n        expect(result).toBe(expected)\n      } catch (error) {\n        expect(error).toBeUndefined()\n      }\n    }\n  )\n\n  it.each`\n    length  | fromUnit  | toUnit  | expected\n    ${10}   | ${'m'}    | ${'km'} | ${0.01}\n    ${1000} | ${'mm'}   | ${'cm'} | ${100}\n    ${1}    | ${'inch'} | ${'ft'} | ${0.08333333333}\n  `(\n    'converts $length $fromUnit to $toUnit (vice versa)',\n    ({ length, fromUnit, toUnit, expected }) => {\n      try {\n        const result = lengthConversion(length, fromUnit, toUnit)\n        expect(result).toBeCloseTo(expected, 10) // Close comparison due to floating-point precision\n      } catch (error) {\n        expect(error).toBeUndefined()\n      }\n    }\n  )\n\n  it.each`\n    length | fromUnit     | toUnit       | expectedError\n    ${10}  | ${'km'}      | ${'invalid'} | ${'Invalid units'}\n    ${5}   | ${'invalid'} | ${'m'}       | ${'Invalid units'}\n  `(\n    'returns error message for invalid units: $fromUnit to $toUnit',\n    ({ length, fromUnit, toUnit, expectedError }) => {\n      try {\n        lengthConversion(length, fromUnit, toUnit)\n      } catch (error) {\n        expect(error.message).toBe(expectedError)\n      }\n    }\n  )\n})\n"
  },
  {
    "path": "Conversions/test/LitersToImperialGallons.test.js",
    "content": "import litersToImperialGallons from '../LitersToImperialGallons'\n\ntest('Convert 25 liters to imperial gallons', () => {\n  expect(parseFloat(litersToImperialGallons(25).toFixed(2))).toBe(5.5)\n})\n"
  },
  {
    "path": "Conversions/test/LitersToUSGallons.test.js",
    "content": "import litersToUSGallons from '../LitersToUSGallons'\n\ntest('Convert 50 liters to US gallons', () => {\n  expect(parseFloat(litersToUSGallons(50).toFixed(2))).toBe(13.21)\n})\n"
  },
  {
    "path": "Conversions/test/LowerCaseConversion.test.js",
    "content": "import { LowerCaseConversion } from '../LowerCaseConversion'\n\ntest('The LowerCaseConversion of ApoLO is apolo', () => {\n  const res = LowerCaseConversion('ApoLO')\n  expect(res).toBe('apolo')\n})\n\ntest('The LowerCaseConversion of WEB is web', () => {\n  const res = LowerCaseConversion('WEB')\n  expect(res).toBe('web')\n})\n\ntest('The LowerCaseConversion of EaRTh is earth', () => {\n  const res = LowerCaseConversion('EaRTh')\n  expect(res).toBe('earth')\n})\n\ntest('The LowerCaseConversion of TiGER is tiger', () => {\n  const res = LowerCaseConversion('TiGER')\n  expect(res).toBe('tiger')\n})\n\ntest('The LowerCaseConversion of Cricket is cricket', () => {\n  const res = LowerCaseConversion('Cricket')\n  expect(res).toBe('cricket')\n})\n"
  },
  {
    "path": "Conversions/test/MeterToFeetConversion.test.js",
    "content": "import { meterToFeet, feetToMeter } from '../MeterToFeetConversion'\n\ndescribe('Testing conversion of Meter to Feet', () => {\n  it('with feet value', () => {\n    expect(meterToFeet(30.48)).toBe(100)\n  })\n})\n\ndescribe('Testing conversion of Feet to Meter', () => {\n  it('with feet value', () => {\n    expect(feetToMeter(10)).toBe(3.048)\n  })\n})\n"
  },
  {
    "path": "Conversions/test/OctToDecimal.test.js",
    "content": "import { octalToDecimal } from '../OctToDecimal'\n\ntest('The Decimal representation of Octal number 56 is 46', () => {\n  const res = octalToDecimal(56)\n  expect(res).toBe(46)\n})\n\ntest('The Decimal representation of Octal number 99 is 81', () => {\n  const res = octalToDecimal(99)\n  expect(res).toBe(81)\n})\n\ntest('The Decimal representation of Octal number 17 is 15', () => {\n  const res = octalToDecimal(17)\n  expect(res).toBe(15)\n})\n\ntest('The Decimal representation of Octal number 100 is 64', () => {\n  const res = octalToDecimal(100)\n  expect(res).toBe(64)\n})\n\ntest('The Decimal representation of Octal number 0 is 0', () => {\n  const res = octalToDecimal(0)\n  expect(res).toBe(0)\n})\n"
  },
  {
    "path": "Conversions/test/OuncesToKilogram.test.js",
    "content": "import ouncesToKilograms from '../OuncesToKilograms'\n\ntest('Convert 60 ounces to kilograms', () => {\n  expect(parseFloat(ouncesToKilograms(60).toFixed(3))).toBe(1.701)\n})\n"
  },
  {
    "path": "Conversions/test/RGBToHex.test.js",
    "content": "import { RGBToHex } from '../RGBToHex'\n\ntest('The Hex format of RGB (225, 225, 225) is #ffffff', () => {\n  const res = RGBToHex(255, 255, 255)\n  expect(res).toBe('#ffffff')\n})\n\ntest('The Hex format of RGB (190, 108, 217) is #be6cd9', () => {\n  const res = RGBToHex(190, 108, 217)\n  expect(res).toBe('#be6cd9')\n})\n\ntest('The Hex format of RGB (255, 99, 71) is #ff6347', () => {\n  const res = RGBToHex(255, 99, 71)\n  expect(res).toBe('#ff6347')\n})\n\ntest('The Hex format of RGB (100, 108, 217) is #646cd9', () => {\n  const res = RGBToHex(100, 108, 217)\n  expect(res).toBe('#646cd9')\n})\n"
  },
  {
    "path": "Conversions/test/RailwayTimeConversion.test.js",
    "content": "import { RailwayTimeConversion } from '../RailwayTimeConversion'\n\ntest('The RailwayTimeConversion of 07:05:45AM is 07:05:45', () => {\n  const res = RailwayTimeConversion('07:05:45AM')\n  expect(res).toEqual('07:05:45')\n})\n\ntest('The RailwayTimeConversion of 07:05:45PM is 19:05:45', () => {\n  const res = RailwayTimeConversion('07:05:45PM')\n  expect(res).toEqual('19:05:45')\n})\n\ntest('The RailwayTimeConversion of 10:20:00AM is 10:20:00', () => {\n  const res = RailwayTimeConversion('10:20:00AM')\n  expect(res).toEqual('10:20:00')\n})\n\ntest('The RailwayTimeConversion of 11:20:00PM is 23:20:00', () => {\n  const res = RailwayTimeConversion('11:20:00PM')\n  expect(res).toEqual('23:20:00')\n})\n\ntest('The RailwayTimeConversion throws when input is not a string', () => {\n  expect(() => RailwayTimeConversion(1120)).toThrowError()\n})\n"
  },
  {
    "path": "Conversions/test/RgbHslConversion.test.js",
    "content": "import { rgbToHsl } from '../RgbHslConversion'\ndescribe('RgbHslConversion', () => {\n  test.each([\n    [\n      [215, 19, 180],\n      [311, 84, 46]\n    ],\n    [\n      [21, 190, 18],\n      [119, 83, 41]\n    ],\n    [\n      [80, 100, 160],\n      [225, 33, 47]\n    ],\n    [\n      [80, 1, 16],\n      [349, 98, 16]\n    ],\n    [\n      [8, 20, 0],\n      [96, 100, 4]\n    ],\n    [\n      [0, 0, 0],\n      [0, 0, 0]\n    ],\n    [\n      [255, 255, 255],\n      [0, 0, 100]\n    ]\n  ])('Should return the color in HSL format.', (colorRgb, expected) => {\n    expect(rgbToHsl(colorRgb)).toEqual(expected)\n  })\n\n  test.each([\n    [[256, 180, 9], 'Input is not a valid RGB color.'],\n    [[-90, 46, 8], 'Input is not a valid RGB color.'],\n    [[1, 39, 900], 'Input is not a valid RGB color.']\n  ])('Should return the error message.', (colorRgb, expected) => {\n    expect(() => rgbToHsl(colorRgb)).toThrowError(expected)\n  })\n})\n"
  },
  {
    "path": "Conversions/test/RgbHsvConversion.test.js",
    "content": "import { approximatelyEqualHsv, hsvToRgb, rgbToHsv } from '../RgbHsvConversion'\n\ndescribe('hsvToRgb', () => {\n  // Expected RGB-values taken from https://www.rapidtables.com/convert/color/hsv-to-rgb.html\n  it('should calculate the correct RGB values', () => {\n    expect(hsvToRgb(0, 0, 0)).toEqual([0, 0, 0])\n    expect(hsvToRgb(0, 0, 1)).toEqual([255, 255, 255])\n    expect(hsvToRgb(0, 1, 1)).toEqual([255, 0, 0])\n    expect(hsvToRgb(60, 1, 1)).toEqual([255, 255, 0])\n    expect(hsvToRgb(120, 1, 1)).toEqual([0, 255, 0])\n    expect(hsvToRgb(240, 1, 1)).toEqual([0, 0, 255])\n    expect(hsvToRgb(300, 1, 1)).toEqual([255, 0, 255])\n    expect(hsvToRgb(180, 0.5, 0.5)).toEqual([64, 128, 128])\n    expect(hsvToRgb(234, 0.14, 0.88)).toEqual([193, 196, 224])\n    expect(hsvToRgb(330, 0.75, 0.5)).toEqual([128, 32, 80])\n  })\n})\n\ndescribe('rgbToHsv', () => {\n  // \"approximatelyEqualHsv\" needed because of small deviations due to rounding for the RGB-values\n  it('should calculate the correct HSV values', () => {\n    expect(approximatelyEqualHsv(rgbToHsv(0, 0, 0), [0, 0, 0])).toEqual(true)\n    expect(approximatelyEqualHsv(rgbToHsv(255, 255, 255), [0, 0, 1])).toEqual(\n      true\n    )\n    expect(approximatelyEqualHsv(rgbToHsv(255, 0, 0), [0, 1, 1])).toEqual(true)\n    expect(approximatelyEqualHsv(rgbToHsv(255, 255, 0), [60, 1, 1])).toEqual(\n      true\n    )\n    expect(approximatelyEqualHsv(rgbToHsv(0, 255, 0), [120, 1, 1])).toEqual(\n      true\n    )\n    expect(approximatelyEqualHsv(rgbToHsv(0, 0, 255), [240, 1, 1])).toEqual(\n      true\n    )\n    expect(approximatelyEqualHsv(rgbToHsv(255, 0, 255), [300, 1, 1])).toEqual(\n      true\n    )\n    expect(\n      approximatelyEqualHsv(rgbToHsv(64, 128, 128), [180, 0.5, 0.5])\n    ).toEqual(true)\n    expect(\n      approximatelyEqualHsv(rgbToHsv(193, 196, 224), [234, 0.14, 0.88])\n    ).toEqual(true)\n    expect(\n      approximatelyEqualHsv(rgbToHsv(128, 32, 80), [330, 0.75, 0.5])\n    ).toEqual(true)\n  })\n})\n"
  },
  {
    "path": "Conversions/test/RomanToDecimal.test.js",
    "content": "import { romanToDecimal } from '../RomanToDecimal'\n\ndescribe('romanToDecimal', () => {\n  it('XXIIVV', () => {\n    expect(romanToDecimal('XXIIVV')).toBe(28)\n  })\n\n  it('MDCCCIV', () => {\n    expect(romanToDecimal('MDCCCIV')).toBe(1804)\n  })\n\n  it('XXIVI', () => {\n    expect(romanToDecimal('XXIVI')).toBe(25)\n  })\n})\n"
  },
  {
    "path": "Conversions/test/TemperatureConversion.test.js",
    "content": "import * as tc from '../TemperatureConversion.js'\n\ndescribe('Testing Conversion of Celsius to fahrenheit', () => {\n  it('with celsius value', () => {\n    const test1 = tc.celsiusToFahrenheit(10)\n    expect(test1).toBe(50)\n  })\n})\n\ndescribe('Testing Conversion of Celsius to kelvin', () => {\n  it('with celsius value', () => {\n    const test1 = tc.celsiusToKelvin(15)\n    expect(test1).toBe(288)\n  })\n})\n\ndescribe('Testing Conversion of Celsius to Rankine', () => {\n  it('with celsius value', () => {\n    const test1 = tc.celsiusToRankine(28)\n    expect(test1).toBe(542)\n  })\n})\n\ndescribe('Testing Conversion of Fahrenheit to Celsius', () => {\n  it('with Fahrenheit value', () => {\n    const test1 = tc.fahrenheitToCelsius(134)\n    expect(test1).toBe(57)\n  })\n})\n\ndescribe('Testing Conversion of Fahrenheit to Kelvin', () => {\n  it('with Fahrenheit value', () => {\n    const test1 = tc.fahrenheitToKelvin(125)\n    expect(test1).toBe(325)\n  })\n})\n\ndescribe('Testing Conversion of Fahrenheit to Rankine', () => {\n  it('with Fahrenheit value', () => {\n    const test1 = tc.fahrenheitToRankine(10)\n    expect(test1).toBe(470)\n  })\n})\n\ndescribe('Testing Conversion of Kelvin to Celsius', () => {\n  it('with Kelvin value', () => {\n    const test1 = tc.kelvinToCelsius(100)\n    expect(test1).toBe(-173)\n  })\n})\n\ndescribe('Testing Conversion of Kelvin to Fahrenheit', () => {\n  it('with Kelvin value', () => {\n    const test1 = tc.kelvinToFahrenheit(20)\n    expect(test1).toBe(-424)\n  })\n})\n\ndescribe('Testing Conversion of Kelvin to Rankine', () => {\n  it('with kelvin value', () => {\n    const test1 = tc.kelvinToRankine(69)\n    expect(test1).toBe(124)\n  })\n})\ndescribe('Testing Conversion of Rankine to Celsius', () => {\n  it('with Rankine value', () => {\n    const test1 = tc.rankineToCelsius(234)\n    expect(test1).toBe(-143)\n  })\n})\ndescribe('Testing Conversion of Rankine to Fahrenheit', () => {\n  it('with Rankine value', () => {\n    const test1 = tc.rankineToFahrenheit(98)\n    expect(test1).toBe(-362)\n  })\n})\ndescribe('Testing Conversion of Rankine to Kelvin', () => {\n  it('with Rankine value', () => {\n    const test1 = tc.rankineToKelvin(10)\n    expect(test1).toBe(6)\n  })\n})\ndescribe('Testing Conversion of Reaumur to Celsius', () => {\n  it('with Reaumur value', () => {\n    const test1 = tc.reaumurToCelsius(100)\n    expect(test1).toBe(125)\n  })\n})\ndescribe('Testing Conversion of Reaumur to Fahrenheit', () => {\n  it('with Reaumur value', () => {\n    const test1 = tc.reaumurToFahrenheit(100)\n    expect(test1).toBe(257)\n  })\n})\ndescribe('Testing Conversion of Reaumur to Kelvin', () => {\n  it('with Reamur value', () => {\n    const test1 = tc.reaumurToKelvin(100)\n    expect(test1).toBe(398)\n  })\n})\ndescribe('Testing Conversion of Reamur to Rankine', () => {\n  it('with Reamur value', () => {\n    const test1 = tc.reaumurToRankine(100)\n    expect(test1).toBe(717)\n  })\n})\n"
  },
  {
    "path": "Conversions/test/TitleCaseConversion.test.js",
    "content": "import { titleCaseConversion } from '../TitleCaseConversion'\n\ndescribe('Tests for the titleCaseConversion function', () => {\n  it('should return an empty string when the input is an empty string', () => {\n    expect(titleCaseConversion('')).toEqual('')\n  })\n\n  it('should return the input string when the input string is a title case string', () => {\n    expect(titleCaseConversion('A Proper Title Case String')).toEqual(\n      'A Proper Title Case String'\n    )\n  })\n\n  it('should return a title case string when input is an all-uppercase string', () => {\n    expect(titleCaseConversion('ALL UPPER CASE')).toEqual('All Upper Case')\n  })\n\n  it('should return a title case string when input is a title case string of with spaces', () => {\n    expect(titleCaseConversion('ALL UPPERCASE')).toEqual('All Uppercase')\n  })\n\n  it('should return a title case string when input is a title case string of with no spaces', () => {\n    expect(titleCaseConversion('ALLUPPERCASE')).toEqual('Alluppercase')\n  })\n\n  it('should return a title case string when input is a title case string with punctuation', () => {\n    expect(titleCaseConversion('All Title Case!')).toEqual('All Title Case!')\n  })\n\n  it('should return a title case string when input is an all-lowercase string with no spaces', () => {\n    expect(titleCaseConversion('lowercaseinput')).toEqual('Lowercaseinput')\n  })\n\n  it('should return a title case string when input is an all-lowercase string with spaces', () => {\n    expect(titleCaseConversion('lowercase input')).toEqual('Lowercase Input')\n  })\n\n  it('should return a title case string when input is an all-lowercase string with punctuation', () => {\n    expect(titleCaseConversion('lower, case, input.')).toEqual(\n      'Lower, Case, Input.'\n    )\n  })\n\n  it('should return a title case string when input is an mixed-case string', () => {\n    expect(titleCaseConversion('mixeD CaSe INPuT')).toEqual('Mixed Case Input')\n  })\n\n  it('should return a title case string when input is an mixed-case string with no spaces', () => {\n    expect(titleCaseConversion('mixeDCaSeINPuT')).toEqual('Mixedcaseinput')\n  })\n\n  it('should return a title case string when input is an mixed-case string with punctuation', () => {\n    expect(titleCaseConversion('mixeD, CaSe, INPuT!')).toEqual(\n      'Mixed, Case, Input!'\n    )\n  })\n})\n"
  },
  {
    "path": "Conversions/test/UpperCaseConverstion.test.js",
    "content": "import { upperCaseConversion } from '../UpperCaseConversion'\n\ndescribe('Test the upperCaseConversion function', () => {\n  it('should return an empty string when the input is an empty string', () => {\n    expect(upperCaseConversion('')).toEqual('')\n  })\n\n  it('should return an all-uppercase string when input is an all-uppercase string', () => {\n    expect(upperCaseConversion('ALLUPPERCASE')).toEqual('ALLUPPERCASE')\n  })\n\n  it('should return an all-uppercase string when input is an all-uppercase string with spaces', () => {\n    expect(upperCaseConversion('ALL UPPERCASE')).toEqual('ALL UPPERCASE')\n  })\n\n  it('should return an all-uppercase string when input is an all-uppercase string with punctuation', () => {\n    expect(upperCaseConversion('ALL UPPER-CASE!')).toEqual('ALL UPPER-CASE!')\n  })\n\n  it('should return an all-uppercase string when input is an all-lowercase string', () => {\n    expect(upperCaseConversion('lowercaseinput')).toEqual('LOWERCASEINPUT')\n  })\n\n  it('should return an all-uppercase string when input is an all-lowercase string with spaces', () => {\n    expect(upperCaseConversion('lowercase input')).toEqual('LOWERCASE INPUT')\n  })\n\n  it('should return an all-uppercase string when input is an all-lowercase string with punctuation', () => {\n    expect(upperCaseConversion('lower-case, input.')).toEqual(\n      'LOWER-CASE, INPUT.'\n    )\n  })\n\n  it('should return an all-uppercase string when input is an mixed-case string', () => {\n    expect(upperCaseConversion('mixeDCaSeINPuT')).toEqual('MIXEDCASEINPUT')\n  })\n\n  it('should return an all-uppercase string when input is an mixed-case string with spaces', () => {\n    expect(upperCaseConversion('mixeD CaSe INPuT')).toEqual('MIXED CASE INPUT')\n  })\n\n  it('should return an all-uppercase string when input is an mixed-case string with punctuation', () => {\n    expect(upperCaseConversion('mixeD-CaSe INPuT!')).toEqual(\n      'MIXED-CASE INPUT!'\n    )\n  })\n})\n"
  },
  {
    "path": "DIRECTORY.md",
    "content": "* **Backtracking**\n  * [AllCombinationsOfSizeK](Backtracking/AllCombinationsOfSizeK.js)\n  * [generateParentheses](Backtracking/generateParentheses.js)\n  * [GeneratePermutations](Backtracking/GeneratePermutations.js)\n  * [KnightTour](Backtracking/KnightTour.js)\n  * [MColoringProblem](Backtracking/MColoringProblem.js)\n  * [NQueens](Backtracking/NQueens.js)\n  * [RatInAMaze](Backtracking/RatInAMaze.js)\n  * [Sudoku](Backtracking/Sudoku.js)\n  * [SumOfSubset](Backtracking/SumOfSubset.js)\n* **Bit-Manipulation**\n  * [BinaryCountSetBits](Bit-Manipulation/BinaryCountSetBits.js)\n  * [GenerateSubSets](Bit-Manipulation/GenerateSubSets.js)\n  * [GrayCodes](Bit-Manipulation/GrayCodes.js)\n  * [IsPowerofFour](Bit-Manipulation/IsPowerofFour.js)\n  * [IsPowerOfTwo](Bit-Manipulation/IsPowerOfTwo.js)\n  * [LogTwo](Bit-Manipulation/LogTwo.js)\n  * [NextPowerOfTwo](Bit-Manipulation/NextPowerOfTwo.js)\n  * [SetBit](Bit-Manipulation/SetBit.js)\n  * [UniqueElementInAnArray](Bit-Manipulation/UniqueElementInAnArray.js)\n* **Cache**\n  * [LFUCache](Cache/LFUCache.js)\n  * [LRUCache](Cache/LRUCache.js)\n  * [Memoize](Cache/Memoize.js)\n* **Cellular-Automata**\n  * [ConwaysGameOfLife](Cellular-Automata/ConwaysGameOfLife.js)\n  * [Elementary](Cellular-Automata/Elementary.js)\n* **Ciphers**\n  * [AffineCipher](Ciphers/AffineCipher.js)\n  * [Atbash](Ciphers/Atbash.js)\n  * [CaesarCipher](Ciphers/CaesarCipher.js)\n  * [KeyFinder](Ciphers/KeyFinder.js)\n  * [KeywordShiftedAlphabet](Ciphers/KeywordShiftedAlphabet.js)\n  * [MorseCode](Ciphers/MorseCode.js)\n  * [ROT13](Ciphers/ROT13.js)\n  * [VigenereCipher](Ciphers/VigenereCipher.js)\n  * [XORCipher](Ciphers/XORCipher.js)\n* **Compression**\n  * [RLE](Compression/RLE.js)\n* **Conversions**\n  * [ArbitraryBase](Conversions/ArbitraryBase.js)\n  * [ArrayBufferToBase64](Conversions/ArrayBufferToBase64.js)\n  * [Base64ToArrayBuffer](Conversions/Base64ToArrayBuffer.js)\n  * [BinaryToDecimal](Conversions/BinaryToDecimal.js)\n  * [BinaryToHex](Conversions/BinaryToHex.js)\n  * [DateDayDifference](Conversions/DateDayDifference.js)\n  * [DateToDay](Conversions/DateToDay.js)\n  * [DecimalToBinary](Conversions/DecimalToBinary.js)\n  * [DecimalToHex](Conversions/DecimalToHex.js)\n  * [DecimalToOctal](Conversions/DecimalToOctal.js)\n  * [DecimalToRoman](Conversions/DecimalToRoman.js)\n  * [HexToBinary](Conversions/HexToBinary.js)\n  * [HexToDecimal](Conversions/HexToDecimal.js)\n  * [HexToRGB](Conversions/HexToRGB.js)\n  * [LengthConversion](Conversions/LengthConversion.js)\n  * [LitersToImperialGallons](Conversions/LitersToImperialGallons.js)\n  * [LitersToUSGallons](Conversions/LitersToUSGallons.js)\n  * [LowerCaseConversion](Conversions/LowerCaseConversion.js)\n  * [MeterToFeetConversion](Conversions/MeterToFeetConversion.js)\n  * [OctToDecimal](Conversions/OctToDecimal.js)\n  * [OuncesToKilograms](Conversions/OuncesToKilograms.js)\n  * [RailwayTimeConversion](Conversions/RailwayTimeConversion.js)\n  * [RgbHslConversion](Conversions/RgbHslConversion.js)\n  * [RgbHsvConversion](Conversions/RgbHsvConversion.js)\n  * [RGBToHex](Conversions/RGBToHex.js)\n  * [RomanToDecimal](Conversions/RomanToDecimal.js)\n  * [TemperatureConversion](Conversions/TemperatureConversion.js)\n  * [TitleCaseConversion](Conversions/TitleCaseConversion.js)\n  * [UpperCaseConversion](Conversions/UpperCaseConversion.js)\n* **Data-Structures**\n  * **Array**\n    * [LocalMaximumPoint](Data-Structures/Array/LocalMaximumPoint.js)\n    * [NumberOfLocalMaximumPoints](Data-Structures/Array/NumberOfLocalMaximumPoints.js)\n    * [QuickSelect](Data-Structures/Array/QuickSelect.js)\n    * [Reverse](Data-Structures/Array/Reverse.js)\n  * **Graph**\n    * [Graph](Data-Structures/Graph/Graph.js)\n    * [Graph2](Data-Structures/Graph/Graph2.js)\n    * [Graph3](Data-Structures/Graph/Graph3.js)\n  * **Heap**\n    * [BinaryHeap](Data-Structures/Heap/BinaryHeap.js)\n    * [KeyPriorityQueue](Data-Structures/Heap/KeyPriorityQueue.js)\n    * [MinPriorityQueue](Data-Structures/Heap/MinPriorityQueue.js)\n  * **Linked-List**\n    * [AddTwoNumbers](Data-Structures/Linked-List/AddTwoNumbers.js)\n    * [CycleDetection](Data-Structures/Linked-List/CycleDetection.js)\n    * [CycleDetectionII](Data-Structures/Linked-List/CycleDetectionII.js)\n    * [DoublyLinkedList](Data-Structures/Linked-List/DoublyLinkedList.js)\n    * [MergeTwoSortedLinkedLists](Data-Structures/Linked-List/MergeTwoSortedLinkedLists.js)\n    * [ReverseSinglyLinkedList](Data-Structures/Linked-List/ReverseSinglyLinkedList.js)\n    * [SinglyCircularLinkedList](Data-Structures/Linked-List/SinglyCircularLinkedList.js)\n    * [SinglyLinkedList](Data-Structures/Linked-List/SinglyLinkedList.js)\n  * **Queue**\n    * [CircularQueue](Data-Structures/Queue/CircularQueue.js)\n    * [Queue](Data-Structures/Queue/Queue.js)\n    * [QueueUsing2Stacks](Data-Structures/Queue/QueueUsing2Stacks.js)\n  * **Stack**\n    * [EvaluateExpression](Data-Structures/Stack/EvaluateExpression.js)\n    * [Stack](Data-Structures/Stack/Stack.js)\n    * [StackES6](Data-Structures/Stack/StackES6.js)\n  * **Tree**\n    * [AVLTree](Data-Structures/Tree/AVLTree.js)\n    * [BinarySearchTree](Data-Structures/Tree/BinarySearchTree.js)\n    * [SegmentTree](Data-Structures/Tree/SegmentTree.js)\n    * [Trie](Data-Structures/Tree/Trie.js)\n  * **Vectors**\n    * [Vector2](Data-Structures/Vectors/Vector2.js)\n* **Dynamic-Programming**\n  * [Abbreviation](Dynamic-Programming/Abbreviation.js)\n  * [CatalanNumbers](Dynamic-Programming/CatalanNumbers.js)\n  * [ClimbingStairs](Dynamic-Programming/ClimbingStairs.js)\n  * [CoinChange](Dynamic-Programming/CoinChange.js)\n  * [EditDistance](Dynamic-Programming/EditDistance.js)\n  * [FastFibonacciNumber](Dynamic-Programming/FastFibonacciNumber.js)\n  * [FibonacciNumber](Dynamic-Programming/FibonacciNumber.js)\n  * [FindMonthCalendar](Dynamic-Programming/FindMonthCalendar.js)\n  * [KadaneAlgo](Dynamic-Programming/KadaneAlgo.js)\n  * [LevenshteinDistance](Dynamic-Programming/LevenshteinDistance.js)\n  * [LongestCommonSubsequence](Dynamic-Programming/LongestCommonSubsequence.js)\n  * [LongestIncreasingSubsequence](Dynamic-Programming/LongestIncreasingSubsequence.js)\n  * [LongestPalindromicSubsequence](Dynamic-Programming/LongestPalindromicSubsequence.js)\n  * [LongestValidParentheses](Dynamic-Programming/LongestValidParentheses.js)\n  * [MaxNonAdjacentSum](Dynamic-Programming/MaxNonAdjacentSum.js)\n  * [MaxProductOfThree](Dynamic-Programming/MaxProductOfThree.js)\n  * [MinimumCostPath](Dynamic-Programming/MinimumCostPath.js)\n  * [NumberOfSubsetEqualToGivenSum](Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js)\n  * [RodCutting](Dynamic-Programming/RodCutting.js)\n  * [Shuf](Dynamic-Programming/Shuf.js)\n  * [SieveOfEratosthenes](Dynamic-Programming/SieveOfEratosthenes.js)\n  * **Sliding-Window**\n    * [HouseRobber](Dynamic-Programming/Sliding-Window/HouseRobber.js)\n    * [LongestSubstringWithoutRepeatingCharacters](Dynamic-Programming/Sliding-Window/LongestSubstringWithoutRepeatingCharacters.js)\n    * [MaxConsecutiveOnes](Dynamic-Programming/Sliding-Window/MaxConsecutiveOnes.js)\n    * [MaxConsecutiveOnesIII](Dynamic-Programming/Sliding-Window/MaxConsecutiveOnesIII.js)\n    * [PermutationinString](Dynamic-Programming/Sliding-Window/PermutationinString.js)\n  * [SudokuSolver](Dynamic-Programming/SudokuSolver.js)\n  * [TrappingRainWater](Dynamic-Programming/TrappingRainWater.js)\n  * [TribonacciNumber](Dynamic-Programming/TribonacciNumber.js)\n  * [UniquePaths](Dynamic-Programming/UniquePaths.js)\n  * [UniquePaths2](Dynamic-Programming/UniquePaths2.js)\n  * [ZeroOneKnapsack](Dynamic-Programming/ZeroOneKnapsack.js)\n* **Geometry**\n  * [Circle](Geometry/Circle.js)\n  * [Cone](Geometry/Cone.js)\n  * [ConvexHullGraham](Geometry/ConvexHullGraham.js)\n  * [Pyramid](Geometry/Pyramid.js)\n  * [Sphere](Geometry/Sphere.js)\n* **Graphs**\n  * [BellmanFord](Graphs/BellmanFord.js)\n  * [BinaryLifting](Graphs/BinaryLifting.js)\n  * [BreadthFirstSearch](Graphs/BreadthFirstSearch.js)\n  * [BreadthFirstShortestPath](Graphs/BreadthFirstShortestPath.js)\n  * [ConnectedComponents](Graphs/ConnectedComponents.js)\n  * [Density](Graphs/Density.js)\n  * [DepthFirstSearchIterative](Graphs/DepthFirstSearchIterative.js)\n  * [DepthFirstSearchRecursive](Graphs/DepthFirstSearchRecursive.js)\n  * [Dijkstra](Graphs/Dijkstra.js)\n  * [DijkstraSmallestPath](Graphs/DijkstraSmallestPath.js)\n  * [FloydWarshall](Graphs/FloydWarshall.js)\n  * [Kosaraju](Graphs/Kosaraju.js)\n  * [KruskalMST](Graphs/KruskalMST.js)\n  * [LCABinaryLifting](Graphs/LCABinaryLifting.js)\n  * [NodeNeighbors](Graphs/NodeNeighbors.js)\n  * [NumberOfIslands](Graphs/NumberOfIslands.js)\n  * [PrimMST](Graphs/PrimMST.js)\n* **Hashes**\n  * [MD5](Hashes/MD5.js)\n  * [SHA1](Hashes/SHA1.js)\n  * [SHA256](Hashes/SHA256.js)\n* **Maths**\n  * [Abs](Maths/Abs.js)\n  * [AliquotSum](Maths/AliquotSum.js)\n  * [Area](Maths/Area.js)\n  * [ArithmeticGeometricMean](Maths/ArithmeticGeometricMean.js)\n  * [ArmstrongNumber](Maths/ArmstrongNumber.js)\n  * [AutomorphicNumber](Maths/AutomorphicNumber.js)\n  * [AverageMean](Maths/AverageMean.js)\n  * [AverageMedian](Maths/AverageMedian.js)\n  * [BinaryConvert](Maths/BinaryConvert.js)\n  * [BinaryExponentiationIterative](Maths/BinaryExponentiationIterative.js)\n  * [BinaryExponentiationRecursive](Maths/BinaryExponentiationRecursive.js)\n  * [BinomialCoefficient](Maths/BinomialCoefficient.js)\n  * [BisectionMethod](Maths/BisectionMethod.js)\n  * [CheckKishnamurthyNumber](Maths/CheckKishnamurthyNumber.js)\n  * [CircularArc](Maths/CircularArc.js)\n  * [CollatzSequence](Maths/CollatzSequence.js)\n  * [Coordinate](Maths/Coordinate.js)\n  * [CoPrimeCheck](Maths/CoPrimeCheck.js)\n  * [CountNumbersDivisible](Maths/CountNumbersDivisible.js)\n  * [DecimalExpansion](Maths/DecimalExpansion.js)\n  * [DecimalIsolate](Maths/DecimalIsolate.js)\n  * [DegreeToRadian](Maths/DegreeToRadian.js)\n  * [Determinant](Maths/Determinant.js)\n  * [EuclideanDistance](Maths/EuclideanDistance.js)\n  * [EulerMethod](Maths/EulerMethod.js)\n  * [EulersTotient](Maths/EulersTotient.js)\n  * [EulersTotientFunction](Maths/EulersTotientFunction.js)\n  * [ExponentialFunction](Maths/ExponentialFunction.js)\n  * [ExtendedEuclideanGCD](Maths/ExtendedEuclideanGCD.js)\n  * [Factorial](Maths/Factorial.js)\n  * [Factors](Maths/Factors.js)\n  * [FareyApproximation](Maths/FareyApproximation.js)\n  * [FermatPrimalityTest](Maths/FermatPrimalityTest.js)\n  * [Fibonacci](Maths/Fibonacci.js)\n  * [FigurateNumber](Maths/FigurateNumber.js)\n  * [FindHcf](Maths/FindHcf.js)\n  * [FindLcm](Maths/FindLcm.js)\n  * [FindMaxRecursion](Maths/FindMaxRecursion.js)\n  * [FindMin](Maths/FindMin.js)\n  * [FindMinIterator](Maths/FindMinIterator.js)\n  * [FriendlyNumbers](Maths/FriendlyNumbers.js)\n  * [GetEuclidGCD](Maths/GetEuclidGCD.js)\n  * [GridGet](Maths/GridGet.js)\n  * [HexagonalNumber](Maths/HexagonalNumber.js)\n  * [IntToBase](Maths/IntToBase.js)\n  * [IsDivisible](Maths/IsDivisible.js)\n  * [IsEven](Maths/IsEven.js)\n  * [IsOdd](Maths/IsOdd.js)\n  * [isPalindromeIntegerNumber](Maths/isPalindromeIntegerNumber.js)\n  * [IsPronic](Maths/IsPronic.js)\n  * [IsSquareFree](Maths/IsSquareFree.js)\n  * [JugglerSequence](Maths/JugglerSequence.js)\n  * [LeapYear](Maths/LeapYear.js)\n  * [LinearSieve](Maths/LinearSieve.js)\n  * [LiouvilleFunction](Maths/LiouvilleFunction.js)\n  * [LucasSeries](Maths/LucasSeries.js)\n  * [Mandelbrot](Maths/Mandelbrot.js)\n  * [MatrixExponentiationRecursive](Maths/MatrixExponentiationRecursive.js)\n  * [MatrixMultiplication](Maths/MatrixMultiplication.js)\n  * [MeanAbsoluteDeviation](Maths/MeanAbsoluteDeviation.js)\n  * [MeanSquareError](Maths/MeanSquareError.js)\n  * [MidpointIntegration](Maths/MidpointIntegration.js)\n  * [MobiusFunction](Maths/MobiusFunction.js)\n  * [ModularArithmetic](Maths/ModularArithmetic.js)\n  * [ModularBinaryExponentiationRecursive](Maths/ModularBinaryExponentiationRecursive.js)\n  * [NumberOfDigits](Maths/NumberOfDigits.js)\n  * [Palindrome](Maths/Palindrome.js)\n  * [ParityOutlier](Maths/ParityOutlier.js)\n  * [PascalTriangle](Maths/PascalTriangle.js)\n  * [PerfectCube](Maths/PerfectCube.js)\n  * [PerfectNumber](Maths/PerfectNumber.js)\n  * [PerfectSquare](Maths/PerfectSquare.js)\n  * [PermutationAndCombination](Maths/PermutationAndCombination.js)\n  * [PiApproximationMonteCarlo](Maths/PiApproximationMonteCarlo.js)\n  * [Polynomial](Maths/Polynomial.js)\n  * [Pow](Maths/Pow.js)\n  * [PowLogarithmic](Maths/PowLogarithmic.js)\n  * [PrimeCheck](Maths/PrimeCheck.js)\n  * [PrimeFactors](Maths/PrimeFactors.js)\n  * [QuadraticRoots](Maths/QuadraticRoots.js)\n  * [RadianToDegree](Maths/RadianToDegree.js)\n  * [ReverseNumber](Maths/ReverseNumber.js)\n  * [ReversePolishNotation](Maths/ReversePolishNotation.js)\n  * [RowEchelon](Maths/RowEchelon.js)\n  * [ShorsAlgorithm](Maths/ShorsAlgorithm.js)\n  * [SieveOfEratosthenes](Maths/SieveOfEratosthenes.js)\n  * [Signum](Maths/Signum.js)\n  * [SimpsonIntegration](Maths/SimpsonIntegration.js)\n  * [Softmax](Maths/Softmax.js)\n  * [SquareRoot](Maths/SquareRoot.js)\n  * [SquareRootLogarithmic](Maths/SquareRootLogarithmic.js)\n  * [SumOfDigits](Maths/SumOfDigits.js)\n  * [SumOfGeometricProgression](Maths/SumOfGeometricProgression.js)\n  * [TwoSum](Maths/TwoSum.js)\n  * [Volume](Maths/Volume.js)\n  * [WhileLoopFactorial](Maths/WhileLoopFactorial.js)\n  * [ZellersCongruenceAlgorithm](Maths/ZellersCongruenceAlgorithm.js)\n* **Navigation**\n  * [Haversine](Navigation/Haversine.js)\n* **Project-Euler**\n  * [Problem001](Project-Euler/Problem001.js)\n  * [Problem002](Project-Euler/Problem002.js)\n  * [Problem003](Project-Euler/Problem003.js)\n  * [Problem004](Project-Euler/Problem004.js)\n  * [Problem005](Project-Euler/Problem005.js)\n  * [Problem006](Project-Euler/Problem006.js)\n  * [Problem007](Project-Euler/Problem007.js)\n  * [Problem008](Project-Euler/Problem008.js)\n  * [Problem009](Project-Euler/Problem009.js)\n  * [Problem010](Project-Euler/Problem010.js)\n  * [Problem011](Project-Euler/Problem011.js)\n  * [Problem012](Project-Euler/Problem012.js)\n  * [Problem013](Project-Euler/Problem013.js)\n  * [Problem014](Project-Euler/Problem014.js)\n  * [Problem015](Project-Euler/Problem015.js)\n  * [Problem016](Project-Euler/Problem016.js)\n  * [Problem017](Project-Euler/Problem017.js)\n  * [Problem018](Project-Euler/Problem018.js)\n  * [Problem019](Project-Euler/Problem019.js)\n  * [Problem020](Project-Euler/Problem020.js)\n  * [Problem021](Project-Euler/Problem021.js)\n  * [Problem023](Project-Euler/Problem023.js)\n  * [Problem025](Project-Euler/Problem025.js)\n  * [Problem028](Project-Euler/Problem028.js)\n  * [Problem035](Project-Euler/Problem035.js)\n  * [Problem044](Project-Euler/Problem044.js)\n* **Recursive**\n  * [BinaryEquivalent](Recursive/BinaryEquivalent.js)\n  * [BinarySearch](Recursive/BinarySearch.js)\n  * [Factorial](Recursive/Factorial.js)\n  * [FibonacciNumberRecursive](Recursive/FibonacciNumberRecursive.js)\n  * [FloodFill](Recursive/FloodFill.js)\n  * [KochSnowflake](Recursive/KochSnowflake.js)\n  * [LetterCombination](Recursive/LetterCombination.js)\n  * [Palindrome](Recursive/Palindrome.js)\n  * [PalindromePartitioning](Recursive/PalindromePartitioning.js)\n  * [Partition](Recursive/Partition.js)\n  * [SubsequenceRecursive](Recursive/SubsequenceRecursive.js)\n  * [TowerOfHanoi](Recursive/TowerOfHanoi.js)\n* **Search**\n  * [BinarySearch](Search/BinarySearch.js)\n  * [ExponentialSearch](Search/ExponentialSearch.js)\n  * [FibonacciSearch](Search/FibonacciSearch.js)\n  * [InterpolationSearch](Search/InterpolationSearch.js)\n  * [JumpSearch](Search/JumpSearch.js)\n  * [LinearSearch](Search/LinearSearch.js)\n  * [Minesweeper](Search/Minesweeper.js)\n  * [QuickSelectSearch](Search/QuickSelectSearch.js)\n  * [RabinKarp](Search/RabinKarp.js)\n  * [SlidingWindow](Search/SlidingWindow.js)\n  * [StringSearch](Search/StringSearch.js)\n  * [TernarySearch](Search/TernarySearch.js)\n  * [UnionFind](Search/UnionFind.js)\n* **Sliding-Windows**\n  * [MaxSumSubarrayFixed](Sliding-Windows/MaxSumSubarrayFixed.js)\n  * [LongestSubarrayWithSumAtMost](Sliding-Windows/LongestSubarrayWithSumAtMost.js)\n* **Sorts**\n  * [AlphaNumericalSort](Sorts/AlphaNumericalSort.js)\n  * [BeadSort](Sorts/BeadSort.js)\n  * [BinaryInsertionSort](Sorts/BinaryInsertionSort.js)\n  * [BogoSort](Sorts/BogoSort.js)\n  * [BubbleSort](Sorts/BubbleSort.js)\n  * [BucketSort](Sorts/BucketSort.js)\n  * [CocktailShakerSort](Sorts/CocktailShakerSort.js)\n  * [CombSort](Sorts/CombSort.js)\n  * [CountingSort](Sorts/CountingSort.js)\n  * [CycleSort](Sorts/CycleSort.js)\n  * [DutchNationalFlagSort](Sorts/DutchNationalFlagSort.js)\n  * [FindSecondLargestElement](Sorts/FindSecondLargestElement.js)\n  * [FisherYatesShuffle](Sorts/FisherYatesShuffle.js)\n  * [FlashSort](Sorts/FlashSort.js)\n  * [GnomeSort](Sorts/GnomeSort.js)\n  * [HeapSort](Sorts/HeapSort.js)\n  * [HeapSortV2](Sorts/HeapSortV2.js)\n  * [InsertionSort](Sorts/InsertionSort.js)\n  * [IntroSort](Sorts/IntroSort.js)\n  * [MergeSort](Sorts/MergeSort.js)\n  * [OddEvenSort](Sorts/OddEvenSort.js)\n  * [PancakeSort](Sorts/PancakeSort.js)\n  * [PigeonHoleSort](Sorts/PigeonHoleSort.js)\n  * [QuickSort](Sorts/QuickSort.js)\n  * [QuickSortRecursive](Sorts/QuickSortRecursive.js)\n  * [RadixSort](Sorts/RadixSort.js)\n  * [SelectionSort](Sorts/SelectionSort.js)\n  * [ShellSort](Sorts/ShellSort.js)\n  * [SimplifiedWiggleSort](Sorts/SimplifiedWiggleSort.js)\n  * [StoogeSort](Sorts/StoogeSort.js)\n  * [SwapSort](Sorts/SwapSort.js)\n  * [TimSort](Sorts/TimSort.js)\n  * [TopologicalSort](Sorts/TopologicalSort.js)\n* **String**\n  * [AlphaNumericPalindrome](String/AlphaNumericPalindrome.js)\n  * [AlternativeStringArrange](String/AlternativeStringArrange.js)\n  * [BoyerMoore](String/BoyerMoore.js)\n  * [CheckAnagram](String/CheckAnagram.js)\n  * [CheckCamelCase](String/CheckCamelCase.js)\n  * [CheckExceeding](String/CheckExceeding.js)\n  * [CheckFlatCase](String/CheckFlatCase.js)\n  * [CheckKebabCase](String/CheckKebabCase.js)\n  * [CheckPalindrome](String/CheckPalindrome.js)\n  * [CheckPangram](String/CheckPangram.js)\n  * [CheckPascalCase](String/CheckPascalCase.js)\n  * [CheckRearrangePalindrome](String/CheckRearrangePalindrome.js)\n  * [CheckSnakeCase](String/CheckSnakeCase.js)\n  * [CheckWordOccurrence](String/CheckWordOccurrence.js)\n  * [CountLetters](String/CountLetters.js)\n  * [CountSubstrings](String/CountSubstrings.js)\n  * [CountVowels](String/CountVowels.js)\n  * [CreatePermutations](String/CreatePermutations.js)\n  * [DiceCoefficient](String/DiceCoefficient.js)\n  * [FirstUniqueCharacter](String/FirstUniqueCharacter.js)\n  * [FormatPhoneNumber](String/FormatPhoneNumber.js)\n  * [GenerateGUID](String/GenerateGUID.js)\n  * [HammingDistance](String/HammingDistance.js)\n  * [IsPalindrome](String/IsPalindrome.js)\n  * [KMPPatternSearching](String/KMPPatternSearching.js)\n  * [LengthofLongestSubstringWithoutRepetition](String/LengthofLongestSubstringWithoutRepetition.js)\n  * [LevenshteinDistance](String/LevenshteinDistance.js)\n  * [Lower](String/Lower.js)\n  * [MaxCharacter](String/MaxCharacter.js)\n  * [MaxWord](String/MaxWord.js)\n  * [PatternMatching](String/PatternMatching.js)\n  * [PercentageOfLetters](String/PercentageOfLetters.js)\n  * [PermutateString](String/PermutateString.js)\n  * [ReverseString](String/ReverseString.js)\n  * [ReverseWords](String/ReverseWords.js)\n  * [ScrambleStrings](String/ScrambleStrings.js)\n  * [Upper](String/Upper.js)\n  * [ValidateCreditCard](String/ValidateCreditCard.js)\n  * [ValidateEmail](String/ValidateEmail.js)\n  * [ZFunction](String/ZFunction.js)\n* **Timing-Functions**\n  * [GetMonthDays](Timing-Functions/GetMonthDays.js)\n  * [IntervalTimer](Timing-Functions/IntervalTimer.js)\n  * [ParseDate](Timing-Functions/ParseDate.js)\n* **Trees**\n  * [BreadthFirstTreeTraversal](Trees/BreadthFirstTreeTraversal.js)\n  * [DepthFirstSearch](Trees/DepthFirstSearch.js)\n  * [FenwickTree](Trees/FenwickTree.js)\n"
  },
  {
    "path": "Data-Structures/Array/LocalMaximumPoint.js",
    "content": "/**\n * [LocalMaxima](https://www.geeksforgeeks.org/find-indices-of-all-local-maxima-and-local-minima-in-an-array/) is an algorithm to find relative bigger numbers compared to their neighbors\n *\n * Notes:\n * - works by using divide and conquer\n * - the function gets the array A with n Real numbers and returns the index of local max point (if more than one exists return the first one)\n *\n * @complexity: O(log(n)) (on average )\n * @complexity: O(log(n)) (worst case)\n * @flow\n */\nconst findMaxPointIndex = (\n  array,\n  rangeStartIndex,\n  rangeEndIndex,\n  originalLength\n) => {\n  // find index range middle point\n  const middleIndex =\n    rangeStartIndex + parseInt((rangeEndIndex - rangeStartIndex) / 2)\n\n  // handle array bounds\n  if (\n    (middleIndex === 0 || array[middleIndex - 1] <= array[middleIndex]) &&\n    (middleIndex === originalLength - 1 ||\n      array[middleIndex + 1] <= array[middleIndex])\n  ) {\n    return middleIndex\n  } else if (middleIndex > 0 && array[middleIndex - 1] > array[middleIndex]) {\n    return findMaxPointIndex(\n      array,\n      rangeStartIndex,\n      middleIndex - 1,\n      originalLength\n    )\n  } else {\n    // regular local max\n    return findMaxPointIndex(\n      array,\n      middleIndex + 1,\n      rangeEndIndex,\n      originalLength\n    )\n  }\n}\n\nconst LocalMaximumPoint = (A) => findMaxPointIndex(A, 0, A.length - 1, A.length)\n\nexport { LocalMaximumPoint }\n"
  },
  {
    "path": "Data-Structures/Array/NumberOfLocalMaximumPoints.js",
    "content": "/**\n * [NumberOfLocalMaximumPoints](https://www.geeksforgeeks.org/find-indices-of-all-local-maxima-and-local-minima-in-an-array/) is an algorithm to find relative bigger numbers compared to their neighbors\n *\n * Notes:\n * - like the other similar local maxima search function find relative maxima points in array but doesn't stop at one but returns total point count\n * - runs on array A of size n and returns the local maxima count using divide and conquer methodology\n *\n * @complexity: O(n) (on average )\n * @complexity: O(n) (worst case)\n * @flow\n */\n\n// check if returned index is a local maxima\nconst IsMaximumPoint = (array, index) => {\n  // handle array bounds\n  // array start\n  if (index === 0) {\n    return array[index] > array[index + 1]\n    // array end\n  } else if (index === array.length - 1) {\n    return array[index] > array[index - 1]\n    // handle index inside array bounds\n  } else {\n    return array[index] > array[index + 1] && array[index] > array[index - 1]\n  }\n}\n\nconst CountLocalMaximumPoints = (array, startIndex, endIndex) => {\n  // stop check in divide and conquer recursion\n  if (startIndex === endIndex) {\n    return IsMaximumPoint(array, startIndex) ? 1 : 0\n  }\n\n  // handle the two halves\n  const middleIndex = parseInt((startIndex + endIndex) / 2)\n  return (\n    CountLocalMaximumPoints(array, startIndex, middleIndex) +\n    CountLocalMaximumPoints(array, middleIndex + 1, endIndex)\n  )\n}\n\nconst NumberOfLocalMaximumPoints = (A) =>\n  CountLocalMaximumPoints(A, 0, A.length - 1)\n\nexport { NumberOfLocalMaximumPoints }\n"
  },
  {
    "path": "Data-Structures/Array/QuickSelect.js",
    "content": "/**\n * [QuickSelect](https://www.geeksforgeeks.org/quickselect-algorithm/) is an algorithm to find the kth smallest number\n *\n * Notes:\n * -QuickSelect is related to QuickSort, thus has optimal best and average\n * -case (O(n)) but unlikely poor worst case (O(n^2))\n * -This implementation uses randomly selected pivots for better performance\n *\n * @complexity: O(n) (on average )\n * @complexity: O(n^2) (worst case)\n * @flow\n */\n\nfunction QuickSelect(items, kth) {\n  if (kth < 1 || kth > items.length) {\n    throw new RangeError('Index Out of Bound')\n  }\n\n  return RandomizedSelect(items, 0, items.length - 1, kth)\n}\n\nfunction RandomizedSelect(items, left, right, i) {\n  if (left === right) return items[left]\n\n  const pivotIndex = RandomizedPartition(items, left, right)\n  const k = pivotIndex - left + 1\n\n  if (i === k) return items[pivotIndex]\n  if (i < k) return RandomizedSelect(items, left, pivotIndex - 1, i)\n\n  return RandomizedSelect(items, pivotIndex + 1, right, i - k)\n}\n\nfunction RandomizedPartition(items, left, right) {\n  const rand = getRandomInt(left, right)\n  Swap(items, rand, right)\n  return Partition(items, left, right)\n}\n\nfunction Partition(items, left, right) {\n  const x = items[right]\n  let pivotIndex = left - 1\n\n  for (let j = left; j < right; j++) {\n    if (items[j] <= x) {\n      pivotIndex++\n      Swap(items, pivotIndex, j)\n    }\n  }\n\n  Swap(items, pivotIndex + 1, right)\n\n  return pivotIndex + 1\n}\n\nfunction getRandomInt(min, max) {\n  return Math.floor(Math.random() * (max - min + 1)) + min\n}\n\nfunction Swap(arr, x, y) {\n  ;[arr[x], arr[y]] = [arr[y], arr[x]]\n}\n\nexport { QuickSelect }\n"
  },
  {
    "path": "Data-Structures/Array/Reverse.js",
    "content": "/** https://www.geeksforgeeks.org/write-a-program-to-Reverse-an-array-or-string/\n * This function will accept an array and\n * Reverse its elements and returns the inverted array\n * @param {Array} arr array with elements of any data type\n * @returns {Array} array with inverted elements\n */\n\nconst Reverse = (arr) => {\n  // limit specifies the amount of Reverse actions\n  for (let i = 0, j = arr.length - 1; i < arr.length / 2; i++, j--)\n    [arr[i], arr[j]] = [arr[j], arr[i]]\n\n  return arr\n}\nexport { Reverse }\n"
  },
  {
    "path": "Data-Structures/Array/test/LocalMaximumPoint.test.js",
    "content": "import { LocalMaximumPoint } from '../LocalMaximumPoint'\n\ndescribe('LocalMaximumPoint tests', () => {\n  it('test boundary maximum points - last element', () => {\n    const Array = [1, 2, 3, 4, 5, 6, 12]\n    expect(LocalMaximumPoint(Array)).toEqual(6)\n  })\n\n  it('test boundary maximum points - first element', () => {\n    const Array2 = [13, 6, 5, 4, 3, 2, 1]\n    expect(LocalMaximumPoint(Array2)).toEqual(0)\n  })\n\n  it('test boundary maximum points - should find first maximum point from the top', () => {\n    // Test a mix of number types (i.e., positive/negative, numbers with decimals, fractions)\n    const Array = [13, 2, 3, 4, 5, 6, 12]\n    expect(LocalMaximumPoint(Array)).toEqual(6)\n  })\n\n  it('test inner points - second element', () => {\n    const Array2 = [13, 16, 5, 4, 3, 2, 1]\n    expect(LocalMaximumPoint(Array2)).toEqual(1)\n  })\n\n  it('test inner points - element some where in the middle', () => {\n    const Array2 = [13, 16, 5, 41, 3, 2, 1]\n    expect(LocalMaximumPoint(Array2)).toEqual(3)\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Array/test/NumberOfLocalMaximumPoints.test.js",
    "content": "import { NumberOfLocalMaximumPoints } from '../NumberOfLocalMaximumPoints'\n\ndescribe('LocalMaximumPoint tests', () => {\n  it('test boundary maximum points - last element', () => {\n    const Array = [1, 2, 3, 4, 5, 6, 12]\n    expect(NumberOfLocalMaximumPoints(Array)).toEqual(1)\n  })\n\n  it('test boundary maximum points - first element', () => {\n    const Array = [13, 6, 5, 4, 3, 2, 1]\n    expect(NumberOfLocalMaximumPoints(Array)).toEqual(1)\n  })\n\n  it('test boundary maximum points - both boundaries have maximum points', () => {\n    // Test a mix of number types (i.e., positive/negative, numbers with decimals, fractions)\n    const Array = [13, 2, 3, 4, 5, 6, 12]\n    expect(NumberOfLocalMaximumPoints(Array)).toEqual(2)\n  })\n\n  it('multiple maximum points in the middle', () => {\n    // Test a mix of number types (i.e., positive/negative, numbers with decimals, fractions)\n    const Array = [1, 3, 2, 5, 6, 9, 2, 7, 12, 1, 0]\n    expect(NumberOfLocalMaximumPoints(Array)).toEqual(3)\n  })\n\n  it('multiple maximum points in the middle with one at end', () => {\n    // Test a mix of number types (i.e., positive/negative, numbers with decimals, fractions)\n    const Array = [1, 3, 2, 5, 6, 9, 2, 7, 12, 1, 10]\n    expect(NumberOfLocalMaximumPoints(Array)).toEqual(4)\n  })\n\n  it('multiple maximum points in the middle with one at start', () => {\n    // Test a mix of number types (i.e., positive/negative, numbers with decimals, fractions)\n    const Array = [10, 3, 2, 5, 6, 9, 2, 7, 12, 1, 0]\n    expect(NumberOfLocalMaximumPoints(Array)).toEqual(3)\n  })\n\n  it('multiple maximum points in the middle with two more at both ends', () => {\n    // Test a mix of number types (i.e., positive/negative, numbers with decimals, fractions)\n    const Array = [10, 3, 11, 5, 6, 9, 2, 7, 12, 1, 10]\n    expect(NumberOfLocalMaximumPoints(Array)).toEqual(5)\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Array/test/QuickSelect.test.js",
    "content": "import { QuickSelect } from '../QuickSelect'\n\ndescribe('QuickSelect tests', () => {\n  it('should return the only element of a list of length 1', () => {\n    // Test a mix of number types (i.e., positive/negative, numbers with decimals, fractions)\n    expect(QuickSelect([100], 1)).toEqual(100)\n    expect(QuickSelect([-23], 1)).toEqual(-23)\n    expect(QuickSelect([2007.102], 1)).toEqual(2007.102)\n    expect(QuickSelect([0.9], 1)).toEqual(0.9)\n    expect(QuickSelect([-0.075], 1)).toEqual(-0.075)\n    expect(QuickSelect([0], 1)).toEqual(0)\n    expect(QuickSelect([1], 1)).toEqual(1)\n  })\n\n  it('should throw an Error when k is greater than the length of the list', () => {\n    expect(() => QuickSelect([100, 2], 5)).toThrow('Index Out of Bound')\n  })\n\n  it('should throw an Error when k is less than 1', () => {\n    expect(() => QuickSelect([100, 2], 0)).toThrow('Index Out of Bound')\n    expect(() => QuickSelect([100, 2], -1)).toThrow('Index Out of Bound')\n  })\n\n  describe('varieties of list composition', () => {\n    it('should return the kth smallest element of a list that is in increasing order', () => {\n      expect(QuickSelect([10, 22, 33, 44, 55], 1)).toEqual(10)\n      expect(QuickSelect([10, 22, 33, 44, 55], 2)).toEqual(22)\n      expect(QuickSelect([10, 22, 33, 44, 55], 3)).toEqual(33)\n      expect(QuickSelect([10, 22, 33, 44, 55], 4)).toEqual(44)\n      expect(QuickSelect([10, 22, 33, 44, 55], 5)).toEqual(55)\n    })\n\n    it('should return the kth smallest element of an input list that is in decreasing order', () => {\n      expect(QuickSelect([82, 33.12, 4.0, 1], 1)).toEqual(1)\n      expect(QuickSelect([82, 33.12, 4.0, 1], 2)).toEqual(4.0)\n      expect(QuickSelect([82, 33.12, 4.0, 1], 2)).toEqual(4)\n      expect(QuickSelect([82, 33.12, 4.0, 1], 3)).toEqual(33.12)\n      expect(QuickSelect([82, 33.12, 4.0, 1], 4)).toEqual(82)\n    })\n\n    it('should return the kth smallest element of an input list that is no particular order', () => {\n      expect(QuickSelect([123, 14231, -10, 0, 15], 3)).toEqual(15)\n      expect(QuickSelect([0, 15, 123, 14231, -10], 3)).toEqual(15)\n      expect(QuickSelect([-10, 15, 123, 14231, 0], 3)).toEqual(15)\n      expect(QuickSelect([14231, 0, 15, 123, -10], 3)).toEqual(15)\n      expect(QuickSelect([14231, 0, 15, -10, 123], 3)).toEqual(15)\n    })\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Array/test/Reverse.test.js",
    "content": "import { Reverse } from '../Reverse.js'\n\ndescribe('reverse elements in an array', () => {\n  it.each([\n    [[], []],\n    [[1], [1]],\n    [\n      [1, 2, 3, 4],\n      [4, 3, 2, 1]\n    ]\n  ])('returns %j when given %j', (array, expected) => {\n    expect(Reverse(array)).toEqual(expected)\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Graph/Graph.js",
    "content": "class Graph {\n  constructor() {\n    this.adjacencyMap = {}\n  }\n\n  addVertex(vertex) {\n    this.adjacencyMap[vertex] = []\n  }\n\n  containsVertex(vertex) {\n    return typeof this.adjacencyMap[vertex] !== 'undefined'\n  }\n\n  addEdge(vertex1, vertex2) {\n    if (this.containsVertex(vertex1) && this.containsVertex(vertex2)) {\n      this.adjacencyMap[vertex1].push(vertex2)\n      this.adjacencyMap[vertex2].push(vertex1)\n    }\n  }\n\n  printGraph(output = (value) => console.log(value)) {\n    const keys = Object.keys(this.adjacencyMap)\n    for (const i of keys) {\n      const values = this.adjacencyMap[i]\n      let vertex = ''\n      for (const j of values) {\n        vertex += j + ' '\n      }\n      output(i + ' -> ' + vertex)\n    }\n  }\n\n  /**\n   * Prints the Breadth first traversal of the graph from source.\n   * @param {number} source The source vertex to start BFS.\n   */\n  bfs(source, output = (value) => console.log(value)) {\n    const queue = [[source, 0]] // level of source is 0\n    const visited = new Set()\n\n    while (queue.length) {\n      const [node, level] = queue.shift() // remove the front of the queue\n      if (visited.has(node)) {\n        // visited\n        continue\n      }\n\n      visited.add(node)\n      output(`Visited node ${node} at level ${level}.`)\n      for (const next of this.adjacencyMap[node]) {\n        queue.push([next, level + 1]) // level 1 more than current\n      }\n    }\n  }\n\n  /**\n   * Prints the Depth first traversal of the graph from source.\n   * @param {number} source The source vertex to start DFS.\n   */\n  dfs(source, visited = new Set(), output = (value) => console.log(value)) {\n    if (visited.has(source)) {\n      // visited\n      return\n    }\n\n    output(`Visited node ${source}`)\n    visited.add(source)\n    for (const neighbour of this.adjacencyMap[source]) {\n      this.dfs(neighbour, visited, output)\n    }\n  }\n}\n\nconst example = () => {\n  const g = new Graph()\n  g.addVertex(1)\n  g.addVertex(2)\n  g.addVertex(3)\n  g.addVertex(4)\n  g.addVertex(5)\n  g.addEdge(1, 2)\n  g.addEdge(1, 3)\n  g.addEdge(2, 4)\n  g.addEdge(2, 5)\n\n  // Graph\n  // 1 -> 2 3\n  // 2 -> 1 4 5\n  // 3 -> 1\n  // 4 -> 2\n  // 5 -> 2\n\n  // Printing the adjacency list\n  // g.printGraph()\n\n  // Breadth first search at node 1\n  g.bfs(1)\n\n  // Depth first search at node 1\n  g.dfs(1)\n}\n\nexport { Graph, example }\n"
  },
  {
    "path": "Data-Structures/Graph/Graph2.js",
    "content": "// create a graph class\nclass Graph {\n  // defining vertex array and\n  // adjacent list\n  constructor(noOfVertices) {\n    this.noOfVertices = noOfVertices\n    this.AdjList = new Map()\n  }\n\n  // functions to be implemented\n\n  // addVertex(v)\n  // addEdge(v, w)\n  // printGraph()\n\n  // bfs(v)\n  // dfs(v)\n\n  // add vertex to the graph\n  addVertex(v) {\n    // initialize the adjacent list with a\n    // null array\n\n    this.AdjList.set(v, [])\n  }\n\n  // add edge to the graph\n  addEdge(v, w) {\n    // get the list for vertex v and put the\n    // vertex w denoting edge between v and w\n    this.AdjList.get(v).push(w)\n\n    // Since graph is undirected,\n    // add an edge from w to v also\n    this.AdjList.get(w).push(v)\n  }\n\n  // Prints the vertex and adjacency list\n  printGraph(output = (value) => console.log(value)) {\n    // get all the vertices\n    const getKeys = this.AdjList.keys()\n\n    // iterate over the vertices\n    for (const i of getKeys) {\n      // get the corresponding adjacency list\n      // for the vertex\n      const getValues = this.AdjList.get(i)\n      let conc = ''\n\n      // iterate over the adjacency list\n      // concatenate the values into a string\n      for (const j of getValues) {\n        conc += j + ' '\n      }\n\n      // print the vertex and its adjacency list\n      output(i + ' -> ' + conc)\n    }\n  }\n}\n\nexport { Graph }\n"
  },
  {
    "path": "Data-Structures/Graph/Graph3.js",
    "content": "class Graph {\n  constructor() {\n    this.adjacencyObject = {}\n  }\n\n  addVertex(vertex) {\n    if (!this.adjacencyObject[vertex]) this.adjacencyObject[vertex] = []\n  }\n\n  addEdge(vertex1, vertex2) {\n    this.adjacencyObject[vertex1].push(vertex2)\n    this.adjacencyObject[vertex2].push(vertex1)\n  }\n\n  removeEdge(vertex1, vertex2) {\n    this.adjacencyObject[vertex1] = this.adjacencyObject[vertex1].filter(\n      (v) => v !== vertex2\n    )\n    this.adjacencyObject[vertex2] = this.adjacencyObject[vertex2].filter(\n      (v) => v !== vertex1\n    )\n  }\n\n  removeVertex(vertex) {\n    while (this.adjacencyObject[vertex].length) {\n      const adjacentVertex = this.adjacencyObject[vertex].pop()\n      this.removeEdge(vertex, adjacentVertex)\n    }\n  }\n\n  /**\n   * Return DFS (Depth First Search) List Using Recursive Method\n   */\n  DFS(start) {\n    if (!start) return null\n\n    const result = []\n    const visited = {}\n    const adjacencyObject = this.adjacencyObject\n\n    function dfs(vertex) {\n      if (!vertex) return null\n      visited[vertex] = true\n      result.push(vertex)\n      adjacencyObject[vertex].forEach((neighbor) => {\n        if (!visited[neighbor]) {\n          dfs(neighbor)\n        }\n      })\n    }\n\n    dfs(start)\n    return result\n  }\n\n  /**\n   * Return DFS(Depth First Search) List Using Iteration\n   */\n  DFSIterative(start) {\n    if (!start) return null\n\n    const stack = [start]\n    const visited = {}\n    visited[start] = true\n\n    const result = []\n    let currentVertex\n\n    while (stack.length) {\n      currentVertex = stack.pop()\n      result.push(currentVertex)\n\n      this.adjacencyObject[currentVertex].forEach((neighbor) => {\n        if (!visited[neighbor]) {\n          visited[neighbor] = true\n          stack.push(neighbor)\n        }\n      })\n    }\n    return result\n  }\n\n  BFS(start) {\n    if (!start) return null\n\n    const queue = [start]\n    const visited = {}\n    visited[start] = true\n\n    let currentVertex\n    const result = []\n\n    while (queue.length) {\n      currentVertex = queue.shift()\n      result.push(currentVertex)\n\n      this.adjacencyObject[currentVertex].forEach((neighbor) => {\n        if (!visited[neighbor]) {\n          visited[neighbor] = true\n          queue.push(neighbor)\n        }\n      })\n    }\n    return result\n  }\n}\n\nexport { Graph }\n"
  },
  {
    "path": "Data-Structures/Graph/test/Graph2.test.js",
    "content": "import { Graph } from '../Graph2'\n\ndescribe('Test Graph2', () => {\n  const vertices = ['A', 'B', 'C', 'D', 'E', 'F']\n  const graph = new Graph(vertices.length)\n\n  // adding vertices\n  vertices.forEach((vertice) => graph.addVertex(vertice))\n\n  // adding edges\n  graph.addEdge('A', 'B')\n  graph.addEdge('A', 'D')\n  graph.addEdge('A', 'E')\n  graph.addEdge('B', 'C')\n  graph.addEdge('D', 'E')\n  graph.addEdge('E', 'F')\n  graph.addEdge('E', 'C')\n  graph.addEdge('C', 'F')\n\n  it('Check adjacency lists', () => {\n    const mockFn = vi.fn()\n    graph.printGraph(mockFn)\n\n    // Expect one call per vertex\n    expect(mockFn.mock.calls.length).toBe(vertices.length)\n\n    // Collect adjacency lists from output (call args)\n    const adjListArr = mockFn.mock.calls.map((v) => v[0])\n\n    expect(adjListArr).toEqual([\n      'A -> B D E ',\n      'B -> A C ',\n      'C -> B E F ',\n      'D -> A E ',\n      'E -> A D F C ',\n      'F -> E C '\n    ])\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Graph/test/Graph3.test.js",
    "content": "import { Graph } from '../Graph3'\n\ndescribe('Test Graph3', () => {\n  const g = new Graph()\n\n  // Add Vertices\n  g.addVertex('A')\n  g.addVertex('B')\n  g.addVertex('C')\n  g.addVertex('D')\n  g.addVertex('E')\n  g.addVertex('F')\n\n  // Add Edges\n  g.addEdge('A', 'B')\n  g.addEdge('A', 'C')\n  g.addEdge('B', 'D')\n  g.addEdge('C', 'E')\n  g.addEdge('D', 'E')\n  g.addEdge('D', 'F')\n  g.addEdge('E', 'F')\n\n  /**\n   * A - B - D\n   * |      / \\\n   * C - - E - F\n   *\n   * DFS(Iterative): A-C-E-F-D-B\n   * DFS(Recursive): A-B-D-E-C-F\n   * BFS: A-B-C-D-E-F\n   */\n  it('Check iterative DFS List', () => {\n    const iterativeDFSList = g.DFSIterative('A')\n    expect(iterativeDFSList).toEqual(['A', 'C', 'E', 'F', 'D', 'B'])\n  })\n\n  it('Check recursive DFS List', () => {\n    const recursiveDFSList = g.DFS('A')\n    expect(recursiveDFSList).toEqual(['A', 'B', 'D', 'E', 'C', 'F'])\n  })\n\n  it('Check BFS List', () => {\n    const BFSList = g.BFS('A')\n    expect(BFSList).toEqual(['A', 'B', 'C', 'D', 'E', 'F'])\n  })\n\n  /**\n   * Test After Remove 'B' Vertex\n   * A       D\n   * |      / \\\n   * C - - E - F\n   *\n   * DFS(Iterative): A-C-E-F-D\n   * DFS(Recursive): A-C-E-D-F\n   * BFS: A-C-E-D-F\n   */\n\n  it('Check iterative DFS List After Removing Vertex B', () => {\n    g.removeVertex('B')\n    const iterativeDFSList = g.DFSIterative('A')\n    expect(iterativeDFSList).toEqual(['A', 'C', 'E', 'F', 'D'])\n  })\n\n  it('Check recursive DFS List After Removing Vertex B', () => {\n    g.removeVertex('B')\n    const recursiveDFSList = g.DFS('A')\n    expect(recursiveDFSList).toEqual(['A', 'C', 'E', 'D', 'F'])\n  })\n\n  it('Check BFS List After Removing Vertex B', () => {\n    g.removeVertex('B')\n    const BFSList = g.BFS('A')\n    expect(BFSList).toEqual(['A', 'C', 'E', 'D', 'F'])\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Heap/BinaryHeap.js",
    "content": "/**\n * BinaryHeap class represents a binary heap data structure that can be configured as a Min Heap or Max Heap.\n *\n * Binary heaps are binary trees that are filled level by level and from left to right inside each level.\n * They have the property that any parent node has a smaller (for Min Heap) or greater (for Max Heap) priority\n * than its children, ensuring that the root of the tree always holds the extremal value.\n */\nclass BinaryHeap {\n  /**\n   * Creates a new BinaryHeap instance.\n   * @constructor\n   * @param {Function} comparatorFunction - The comparator function used to determine the order of elements (e.g., minHeapComparator or maxHeapComparator).\n   */\n  constructor(comparatorFunction) {\n    /**\n     * The heap array that stores elements.\n     * @member {Array}\n     */\n    this.heap = []\n\n    /**\n     * The comparator function used for ordering elements in the heap.\n     * @member {Function}\n     */\n    this.comparator = comparatorFunction\n  }\n\n  /**\n   * Inserts a new value into the heap.\n   * @param {*} value - The value to be inserted into the heap.\n   */\n  insert(value) {\n    this.heap.push(value)\n    this.#bubbleUp(this.heap.length - 1)\n  }\n\n  /**\n   * Returns the number of elements in the heap.\n   * @returns {number} - The number of elements in the heap.\n   */\n  size() {\n    return this.heap.length\n  }\n\n  /**\n   * Checks if the heap is empty.\n   * @returns {boolean} - True if the heap is empty, false otherwise.\n   */\n  empty() {\n    return this.size() === 0\n  }\n\n  /**\n   * Bubbles up a value from the specified index to maintain the heap property.\n   * @param {number} currIdx - The index of the value to be bubbled up.\n   * @private\n   */\n  #bubbleUp(currIdx) {\n    let parentIdx = Math.floor((currIdx - 1) / 2)\n\n    while (\n      currIdx > 0 &&\n      this.comparator(this.heap[currIdx], this.heap[parentIdx])\n    ) {\n      this.#swap(currIdx, parentIdx)\n      currIdx = parentIdx\n      parentIdx = Math.floor((currIdx - 1) / 2)\n    }\n  }\n\n  /**\n   * Sinks down a value from the specified index to maintain the heap property.\n   * @param {number} currIdx - The index of the value to be sunk down.\n   * @private\n   */\n  #sinkDown(currIdx) {\n    let childOneIdx = currIdx * 2 + 1\n\n    while (childOneIdx < this.size()) {\n      const childTwoIdx = childOneIdx + 1 < this.size() ? childOneIdx + 1 : -1\n      const swapIdx =\n        childTwoIdx !== -1 &&\n        this.comparator(this.heap[childTwoIdx], this.heap[childOneIdx])\n          ? childTwoIdx\n          : childOneIdx\n\n      if (this.comparator(this.heap[swapIdx], this.heap[currIdx])) {\n        this.#swap(currIdx, swapIdx)\n        currIdx = swapIdx\n        childOneIdx = currIdx * 2 + 1\n      } else {\n        return\n      }\n    }\n  }\n\n  /**\n   * Retrieves the top element of the heap without removing it.\n   * @returns {*} - The top element of the heap.\n   */\n  peek() {\n    return this.heap[0]\n  }\n\n  /**\n   * Removes and returns the top element of the heap.\n   * @returns {*} - The top element of the heap.\n   */\n  extractTop() {\n    const top = this.peek()\n    const last = this.heap.pop()\n\n    if (!this.empty()) {\n      this.heap[0] = last\n      this.#sinkDown(0)\n    }\n\n    return top\n  }\n\n  /**\n   * Swaps elements at two specified indices in the heap.\n   * @param {number} index1 - The index of the first element to be swapped.\n   * @param {number} index2 - The index of the second element to be swapped.\n   * @private\n   */\n  #swap(index1, index2) {\n    ;[this.heap[index1], this.heap[index2]] = [\n      this.heap[index2],\n      this.heap[index1]\n    ]\n  }\n}\n\n/**\n * Comparator function for creating a Min Heap.\n * @param {*} a - The first element to compare.\n * @param {*} b - The second element to compare.\n * @returns {boolean} - True if 'a' should have higher priority than 'b' in the Min Heap, false otherwise.\n */\nconst minHeapComparator = (a, b) => a < b\n\n/**\n * Comparator function for creating a Max Heap.\n * @param {*} a - The first element to compare.\n * @param {*} b - The second element to compare.\n * @returns {boolean} - True if 'a' should have higher priority than 'b' in the Max Heap, false otherwise.\n */\nconst maxHeapComparator = (a, b) => a > b\n\nexport { BinaryHeap, minHeapComparator, maxHeapComparator }\n"
  },
  {
    "path": "Data-Structures/Heap/KeyPriorityQueue.js",
    "content": "/**\n * KeyPriorityQueue is a priority queue based on a Minimum Binary Heap.\n *\n * Minimum Binary Heaps are binary trees which are filled level by level\n * and then from left to right inside a depth level.\n * Their main property is that any parent node has a smaller or equal priority to all of its children,\n * hence the root of the tree always has the smallest priority of all nodes.\n *\n * This implementation of the Minimum Binary Heap allows for nodes to be associated to both a key,\n * which can be any datatype, and a priority.\n *\n * The heap is represented by an array with nodes ordered\n * from root-to-leaf, left-to-right.\n * Therefore, the parent-child node relationship is such that\n *      * the children nodes positions relative to their parent are: (parentPos * 2 + 1) and (parentPos * 2 + 2)\n *      * the parent node position relative to either of its children is: Math.floor((childPos - 1) / 2)\n *\n * More information and visuals on Binary Heaps can be found here: https://www.geeksforgeeks.org/binary-heap/\n */\n\n// Priority Queue Helper functions\nconst getParentPosition = (position) => Math.floor((position - 1) / 2)\nconst getChildrenPositions = (position) => [2 * position + 1, 2 * position + 2]\n\nclass KeyPriorityQueue {\n  // Priority Queue class using Minimum Binary Heap\n  constructor() {\n    this._heap = []\n    this.priorities = new Map()\n  }\n\n  /**\n   * Checks if the heap is empty\n   * @returns boolean\n   */\n  isEmpty() {\n    return this._heap.length === 0\n  }\n\n  /**\n   * Adds an element to the queue\n   * @param {*} key\n   * @param {number} priority\n   */\n  push(key, priority) {\n    this._heap.push(key)\n    this.priorities.set(key, priority)\n    this._shiftUp(this._heap.length - 1)\n  }\n\n  /**\n   * Removes the element with least priority\n   * @returns the key of the element with least priority\n   */\n  pop() {\n    this._swap(0, this._heap.length - 1)\n    const key = this._heap.pop()\n    this.priorities.delete(key)\n    this._shiftDown(0)\n    return key\n  }\n\n  /**\n   * Checks whether a given key is present in the queue\n   * @param {*} key\n   * @returns boolean\n   */\n  contains(key) {\n    return this.priorities.has(key)\n  }\n\n  /**\n   * Updates the priority of the given element.\n   * Adds the element if it is not in the queue.\n   * @param {*} key the element to change\n   * @param {number} priority new priority of the element\n   */\n  update(key, priority) {\n    const currPos = this._heap.indexOf(key)\n    // if the key does not exist yet, add it\n    if (currPos === -1) return this.push(key, priority)\n    // else update priority\n    this.priorities.set(key, priority)\n    const parentPos = getParentPosition(currPos)\n    const currPriority = this._getPriorityOrInfinite(currPos)\n    const parentPriority = this._getPriorityOrInfinite(parentPos)\n    const [child1Pos, child2Pos] = getChildrenPositions(currPos)\n    const child1Priority = this._getPriorityOrInfinite(child1Pos)\n    const child2Priority = this._getPriorityOrInfinite(child2Pos)\n\n    if (parentPos >= 0 && parentPriority > currPriority) {\n      this._shiftUp(currPos)\n    } else if (child1Priority < currPriority || child2Priority < currPriority) {\n      this._shiftDown(currPos)\n    }\n  }\n\n  _getPriorityOrInfinite(position) {\n    // Helper function, returns priority of the node, or Infinite if no node corresponds to this position\n    if (position >= 0 && position < this._heap.length)\n      return this.priorities.get(this._heap[position])\n    else return Infinity\n  }\n\n  _shiftUp(position) {\n    // Helper function to shift up a node to proper position (equivalent to bubbleUp)\n    let currPos = position\n    let parentPos = getParentPosition(currPos)\n    let currPriority = this._getPriorityOrInfinite(currPos)\n    let parentPriority = this._getPriorityOrInfinite(parentPos)\n\n    while (parentPos >= 0 && parentPriority > currPriority) {\n      this._swap(currPos, parentPos)\n      currPos = parentPos\n      parentPos = getParentPosition(currPos)\n      currPriority = this._getPriorityOrInfinite(currPos)\n      parentPriority = this._getPriorityOrInfinite(parentPos)\n    }\n  }\n\n  _shiftDown(position) {\n    // Helper function to shift down a node to proper position (equivalent to bubbleDown)\n    let currPos = position\n    let [child1Pos, child2Pos] = getChildrenPositions(currPos)\n    let child1Priority = this._getPriorityOrInfinite(child1Pos)\n    let child2Priority = this._getPriorityOrInfinite(child2Pos)\n    let currPriority = this._getPriorityOrInfinite(currPos)\n\n    if (currPriority === Infinity) {\n      return\n    }\n\n    while (child1Priority < currPriority || child2Priority < currPriority) {\n      if (child1Priority < currPriority && child1Priority < child2Priority) {\n        this._swap(child1Pos, currPos)\n        currPos = child1Pos\n      } else {\n        this._swap(child2Pos, currPos)\n        currPos = child2Pos\n      }\n      ;[child1Pos, child2Pos] = getChildrenPositions(currPos)\n      child1Priority = this._getPriorityOrInfinite(child1Pos)\n      child2Priority = this._getPriorityOrInfinite(child2Pos)\n      currPriority = this._getPriorityOrInfinite(currPos)\n    }\n  }\n\n  _swap(position1, position2) {\n    // Helper function to swap 2 nodes\n    ;[this._heap[position1], this._heap[position2]] = [\n      this._heap[position2],\n      this._heap[position1]\n    ]\n  }\n}\n\nexport { KeyPriorityQueue }\n"
  },
  {
    "path": "Data-Structures/Heap/MinPriorityQueue.js",
    "content": "/* Minimum Priority Queue\n * It is a part of heap data structure\n * A heap is a specific tree based data structure\n * in which all the nodes of tree are in a specific order.\n * that is the children are arranged in some\n * respect of their parents, can either be greater\n * or less than the parent. This makes it a min priority queue\n * or max priority queue.\n */\n\n// Functions: insert, delete, peek, isEmpty, print, heapSort, sink\n\nclass MinPriorityQueue {\n  // calls the constructor and initializes the capacity\n  constructor(c) {\n    this.heap = []\n    this.capacity = c\n    this.size = 0\n  }\n\n  // inserts the key at the end and rearranges it\n  // so that the binary heap is in appropriate order\n  insert(key) {\n    if (this.isFull()) return\n    this.heap[this.size + 1] = key\n    let k = this.size + 1\n    while (k > 1) {\n      if (this.heap[k] < this.heap[Math.floor(k / 2)]) {\n        const temp = this.heap[k]\n        this.heap[k] = this.heap[Math.floor(k / 2)]\n        this.heap[Math.floor(k / 2)] = temp\n      }\n      k = Math.floor(k / 2)\n    }\n    this.size++\n  }\n\n  // returns the highest priority value\n  peek() {\n    return this.heap[1]\n  }\n\n  // returns boolean value whether the heap is empty or not\n  isEmpty() {\n    return this.size === 0\n  }\n\n  // returns boolean value whether the heap is full or not\n  isFull() {\n    return this.size === this.capacity\n  }\n\n  // prints the heap\n  print(output = (value) => console.log(value)) {\n    output(this.heap.slice(1))\n  }\n\n  // heap reverse can be done by performing swapping the first\n  // element with the last, removing the last element to\n  // new array and calling sink function.\n  heapReverse() {\n    const heapSort = []\n    while (this.size > 0) {\n      // swap first element with last element\n      ;[this.heap[1], this.heap[this.size]] = [\n        this.heap[this.size],\n        this.heap[1]\n      ]\n      heapSort.push(this.heap.pop())\n      this.size--\n      this.sink()\n    }\n    // first value from heap it's empty to respect\n    // structure with 1 as index of the first element\n    this.heap = [undefined, ...heapSort.reverse()]\n    this.size = heapSort.length\n  }\n\n  // this function reorders the heap after every delete function\n  sink() {\n    let k = 1\n    while (2 * k <= this.size || 2 * k + 1 <= this.size) {\n      let minIndex\n      if (this.heap[2 * k] >= this.heap[k]) {\n        if (2 * k + 1 <= this.size && this.heap[2 * k + 1] >= this.heap[k]) {\n          break\n        } else if (2 * k + 1 > this.size) {\n          break\n        }\n      }\n      if (2 * k + 1 > this.size) {\n        minIndex = this.heap[2 * k] < this.heap[k] ? 2 * k : k\n      } else {\n        if (\n          this.heap[k] > this.heap[2 * k] ||\n          this.heap[k] > this.heap[2 * k + 1]\n        ) {\n          minIndex = this.heap[2 * k] < this.heap[2 * k + 1] ? 2 * k : 2 * k + 1\n        } else {\n          minIndex = k\n        }\n      }\n      const temp = this.heap[k]\n      this.heap[k] = this.heap[minIndex]\n      this.heap[minIndex] = temp\n      k = minIndex\n    }\n  }\n\n  // deletes the highest priority value from the heap. The last\n  // element goes to ahead to first position and reorder heap\n  delete() {\n    // checks empty and one element array conditions\n    if (this.isEmpty()) return\n    if (this.size === 1) {\n      this.size--\n      return this.heap.pop()\n    }\n    const min = this.heap[1]\n    this.heap[1] = this.heap.pop()\n    this.size--\n    this.sink()\n    return min\n  }\n}\n\nexport { MinPriorityQueue }\n"
  },
  {
    "path": "Data-Structures/Heap/test/BinaryHeap.test.js",
    "content": "import { BinaryHeap, minHeapComparator } from '../BinaryHeap'\n\ndescribe('BinaryHeap', () => {\n  describe('MinHeap', () => {\n    let minHeap\n\n    beforeEach(() => {\n      // Initialize a MinHeap\n      minHeap = new BinaryHeap(minHeapComparator)\n      minHeap.insert(4)\n      minHeap.insert(3)\n      minHeap.insert(6)\n      minHeap.insert(1)\n      minHeap.insert(8)\n      minHeap.insert(2)\n    })\n\n    it('should initialize a heap from an input array', () => {\n      // Check if the heap is initialized correctly\n      expect(minHeap.heap).toEqual([1, 3, 2, 4, 8, 6])\n    })\n\n    it('should show the top value in the heap', () => {\n      // Check if the top value is as expected\n      const minValue = minHeap.peek()\n      expect(minValue).toEqual(1)\n    })\n\n    it('should remove and return the top value in the heap', () => {\n      // Check if the top value is removed correctly\n      const minValue = minHeap.extractTop()\n      expect(minValue).toEqual(1)\n      expect(minHeap.heap).toEqual([2, 3, 6, 4, 8])\n    })\n\n    it('should handle insertion of duplicate values', () => {\n      // Check if the heap handles duplicate values correctly\n      minHeap.insert(2)\n      expect(minHeap.heap).toEqual([1, 3, 2, 4, 8, 6, 2])\n    })\n\n    it('should handle an empty heap', () => {\n      // Check if an empty heap behaves as expected\n      const emptyHeap = new BinaryHeap(minHeapComparator)\n      expect(emptyHeap.peek()).toBeUndefined()\n      expect(emptyHeap.extractTop()).toBeUndefined()\n    })\n\n    it('should handle extracting all elements from the heap', () => {\n      // Check if all elements can be extracted in the correct order\n      const extractedValues = []\n      while (!minHeap.empty()) {\n        extractedValues.push(minHeap.extractTop())\n      }\n      expect(extractedValues).toEqual([1, 2, 3, 4, 6, 8])\n    })\n\n    it('should insert elements in ascending order', () => {\n      // Check if elements are inserted in ascending order\n      const ascendingHeap = new BinaryHeap(minHeapComparator)\n      ascendingHeap.insert(4)\n      ascendingHeap.insert(3)\n      ascendingHeap.insert(2)\n      ascendingHeap.insert(1)\n      expect(ascendingHeap.extractTop()).toEqual(1)\n      expect(ascendingHeap.extractTop()).toEqual(2)\n      expect(ascendingHeap.extractTop()).toEqual(3)\n      expect(ascendingHeap.extractTop()).toEqual(4)\n    })\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Heap/test/KeyPriorityQueue.test.js",
    "content": "import { KeyPriorityQueue } from '../KeyPriorityQueue.js'\n\ndescribe('Key Priority Queue', () => {\n  describe('Method isEmpty', () => {\n    test('Check heap is empty', () => {\n      const queue = new KeyPriorityQueue()\n      const res = queue.isEmpty()\n      expect(res).toEqual(true)\n    })\n\n    test('Check heap is not empty', () => {\n      const queue = new KeyPriorityQueue()\n      queue.push(0, 2)\n      const res = queue.isEmpty()\n      expect(res).toEqual(false)\n    })\n  })\n\n  describe('Methods push and pop', () => {\n    test('Test Case 1', () => {\n      // create queue\n      const queue = new KeyPriorityQueue()\n      queue.push(0, 3)\n      queue.push(1, 7)\n      queue.push(2, 9)\n      queue.push(3, 13)\n      // create expected queue\n      const expectedQueue = new KeyPriorityQueue()\n      expectedQueue.push(1, 7)\n      expectedQueue.push(3, 13)\n      expectedQueue.push(2, 9)\n      // result from popping element from the queue\n      queue.pop()\n      expect(queue).toEqual(expectedQueue)\n    })\n\n    test('Test Case 2', () => {\n      // create queue\n      const queue = new KeyPriorityQueue()\n      queue.push(0, 3)\n      queue.push(1, 9)\n      queue.push(2, 7)\n      queue.push(3, 13)\n      // create expected queue\n      const expectedQueue = new KeyPriorityQueue()\n      expectedQueue.push(2, 7)\n      expectedQueue.push(1, 9)\n      expectedQueue.push(3, 13)\n      // result from popping element from the queue\n      queue.pop()\n      expect(queue).toEqual(expectedQueue)\n    })\n\n    test('Test Case 3', () => {\n      // create queue\n      const queue = new KeyPriorityQueue()\n      queue.push(0, 3)\n      queue.push(1, 7)\n      queue.push(2, 9)\n      queue.push(3, 12)\n      queue.push(4, 13)\n      // create expected queue\n      const expectedQueue = new KeyPriorityQueue()\n      expectedQueue.push(1, 7)\n      expectedQueue.push(3, 12)\n      expectedQueue.push(2, 9)\n      expectedQueue.push(4, 13)\n      // result from popping element from the queue\n      queue.pop()\n      expect(queue).toEqual(expectedQueue)\n    })\n  })\n\n  describe('Method contains', () => {\n    test('Check heap does not contain element', () => {\n      const queue = new KeyPriorityQueue()\n      const res = queue.contains(0)\n      expect(res).toEqual(false)\n    })\n\n    test('Check heap contains element', () => {\n      const queue = new KeyPriorityQueue()\n      queue.push(0, 2)\n      const res = queue.contains(0)\n      expect(res).toEqual(true)\n    })\n  })\n\n  describe('Method update', () => {\n    test('Update without change in position', () => {\n      // create queue\n      const queue = new KeyPriorityQueue()\n      queue.push(0, 3)\n      queue.push(1, 5)\n      queue.push(2, 7)\n      queue.push(3, 11)\n      // create expected queue\n      const expectedQueue = new KeyPriorityQueue()\n      expectedQueue.push(0, 2)\n      expectedQueue.push(1, 5)\n      expectedQueue.push(2, 7)\n      expectedQueue.push(3, 11)\n      // result from updating to similar priority\n      queue.update(0, 2)\n      expect(queue).toEqual(expectedQueue)\n    })\n\n    test('Update with change in position', () => {\n      // create queue\n      const queue = new KeyPriorityQueue()\n      queue.push(0, 3)\n      queue.push(1, 5)\n      queue.push(2, 7)\n      queue.push(3, 11)\n      // create expected queue\n      const expectedQueue = new KeyPriorityQueue()\n      expectedQueue.push(1, 5)\n      expectedQueue.push(3, 11)\n      expectedQueue.push(2, 7)\n      expectedQueue.push(0, 9)\n      // result from updating to similar priority\n      queue.update(0, 9)\n      expect(queue).toEqual(expectedQueue)\n    })\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Heap/test/MinPriorityQueue.test.js",
    "content": "import { MinPriorityQueue } from '../MinPriorityQueue'\n\ndescribe('MinPriorityQueue', () => {\n  const values = [5, 2, 4, 1, 7, 6, 3, 8]\n  const capacity = values.length\n  let queue\n\n  beforeEach(() => {\n    queue = new MinPriorityQueue(capacity)\n    values.forEach((v) => queue.insert(v))\n  })\n\n  it('Check heap ordering', () => {\n    const mockFn = vi.fn()\n    queue.print(mockFn)\n\n    expect(mockFn.mock.calls.length).toBe(1) // Expect one call\n    expect(mockFn.mock.calls[0].length).toBe(1) // Expect one argument\n\n    const heap = mockFn.mock.calls[0][0]\n    expect(heap.length).toBe(capacity)\n    expect(heap).toStrictEqual([1, 2, 3, 5, 7, 6, 4, 8])\n  })\n\n  it('heapSort() expected to reverse the heap ordering', () => {\n    queue.heapReverse()\n    const mockFn = vi.fn()\n    queue.print(mockFn)\n\n    expect(mockFn.mock.calls.length).toBe(1)\n    expect(mockFn.mock.calls[0].length).toBe(1)\n\n    const heap = mockFn.mock.calls[0][0]\n    expect(heap.length).toBe(capacity)\n    expect(heap).toStrictEqual([8, 7, 6, 5, 4, 3, 2, 1])\n  })\n\n  describe('delete() function work properly', () => {\n    it('return undefined if heap is empty', () => {\n      const minqueue = new MinPriorityQueue(capacity)\n      const min = minqueue.delete()\n      expect(min).toBe(undefined)\n    })\n    it('return min value and remove it', () => {\n      const sortedValues = values.sort()\n      let initialSize = queue.size\n      sortedValues.forEach((minValue, index) => {\n        const min = queue.delete()\n        expect(min).toBe(minValue)\n        expect(queue.size).toBe(--initialSize)\n      })\n      expect(queue.size).toBe(0)\n    })\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Linked-List/AddTwoNumbers.js",
    "content": "/**\n * A LinkedList based solution for Add Two Numbers\n *\n */\nimport { Node } from './SinglyLinkedList.js'\n\n/*\nProblem Statement:\nGiven two non-empty linked lists representing two non-negative integers.\nThe digits are stored in reverse order and each of their nodes contain a single digit.\nAdd the two numbers and return it as a linked list.\n\nLink for the Problem: https://leetcode.com/problems/add-two-numbers/\n*/\n\nclass AddTwoNumbers {\n  constructor() {\n    this.dummyNode = new Node(0)\n  }\n\n  solution(firstList, secondList) {\n    let firstRunner = firstList\n    let secondRunner = secondList\n    let tail = this.dummyNode\n    let carry = 0\n    while (firstRunner != null || secondRunner != null) {\n      const firstNumber = firstRunner ? firstRunner.data : 0\n      const secondNumber = secondRunner ? secondRunner.data : 0\n      const sum = carry + firstNumber + secondNumber\n      carry = parseInt(sum / 10)\n      tail.next = new Node(sum % 10)\n      tail = tail.next\n      if (firstRunner) {\n        firstRunner = firstRunner.next\n      }\n      if (secondRunner) {\n        secondRunner = secondRunner.next\n      }\n    }\n    if (carry > 0) {\n      tail.next = new Node(carry % 10)\n    }\n\n    return this.dummyNode.next\n  }\n\n  solutionToArray() {\n    const list = []\n    let currentNode = this.dummyNode.next\n    while (currentNode) {\n      list.push(currentNode.data)\n      currentNode = currentNode.next\n    }\n\n    return list\n  }\n}\n\nexport { AddTwoNumbers }\n"
  },
  {
    "path": "Data-Structures/Linked-List/CycleDetection.js",
    "content": "/**\n * A LinkedList based solution for Detecting a Cycle in a list.\n * https://en.wikipedia.org/wiki/Cycle_detection\n */\n\nfunction detectCycle(head) {\n  /*\n  Problem Statement:\n  Given head, the head of a linked list, determine if the linked list has a cycle in it.\n  Link for the Problem: https://leetcode.com/problems/linked-list-cycle/\n  */\n  if (!head) {\n    return false\n  }\n\n  let slow = head\n  let fast = head.next\n  while (fast && fast.next) {\n    if (fast === slow) {\n      return true\n    }\n    fast = fast.next.next\n    slow = slow.next\n  }\n  return false\n}\n\nexport { detectCycle }\n"
  },
  {
    "path": "Data-Structures/Linked-List/CycleDetectionII.js",
    "content": "/**\n * A LinkedList based solution for finding the starting node of the cycle in a list.\n * @returns the node where cycle begins in the linked list. If there is no cycle present, returns null.\n * @see https://en.wikipedia.org/wiki/Cycle_detection\n * @see https://leetcode.com/problems/linked-list-cycle-ii/\n */\n\nfunction findCycleStart(head) {\n  let length = 0\n  let fast = head\n  let slow = head\n\n  while (fast !== null && fast.next !== null) {\n    fast = fast.next.next\n    slow = slow.next\n    if (fast === slow) {\n      length = cycleLength(slow)\n      break\n    }\n  }\n\n  if (length === 0) {\n    // If there is no cycle, return null.\n    return null\n  }\n\n  let ahead = head\n  let behind = head\n  // Move slow pointer ahead 'length' of cycle times\n  while (length > 0) {\n    ahead = ahead.next\n    length--\n  }\n\n  // Now move both pointers until they meet - this will be the start of cycle\n  while (ahead !== behind) {\n    ahead = ahead.next\n    behind = behind.next\n  }\n\n  // return the meeting node\n  return ahead\n}\n\n// head is a node on a cycle\nfunction cycleLength(head) {\n  // How long until we visit head again?\n  let cur = head\n  let len = 0\n  do {\n    cur = cur.next\n    len++\n  } while (cur != head)\n  return len\n}\n\nexport { findCycleStart }\n"
  },
  {
    "path": "Data-Structures/Linked-List/DoublyLinkedList.js",
    "content": "class Node {\n  constructor(element) {\n    this.element = element\n    this.next = null\n    this.prev = null\n  }\n}\n\nclass DoubleLinkedList {\n  constructor() {\n    this.length = 0\n    this.head = null\n    this.tail = null\n  }\n\n  // Add new element\n  append(element) {\n    const node = new Node(element)\n\n    if (!this.head) {\n      this.head = node\n      this.tail = node\n    } else {\n      node.prev = this.tail\n      this.tail.next = node\n      this.tail = node\n    }\n\n    this.length++\n  }\n\n  // Add element\n  insert(position, element) {\n    // Check of out-of-bound values\n    if (position >= 0 && position <= this.length) {\n      const node = new Node(element)\n      let current = this.head\n      let previous = 0\n      let index = 0\n\n      if (position === 0) {\n        if (!this.head) {\n          this.head = node\n          this.tail = node\n        } else {\n          node.next = current\n          current.prev = node\n          this.head = node\n        }\n      } else if (position === this.length) {\n        current = this.tail\n        current.next = node\n        node.prev = current\n        this.tail = node\n      } else {\n        while (index++ < position) {\n          previous = current\n          current = current.next\n        }\n\n        node.next = current\n        previous.next = node\n\n        // New\n        current.prev = node\n        node.prev = previous\n      }\n\n      this.length++\n      return true\n    } else {\n      return false\n    }\n  }\n\n  // Remove element at any position\n  removeAt(position) {\n    // look for out-of-bounds value\n    if (position > -1 && position < this.length) {\n      let current = this.head\n      let previous = 0\n      let index = 0\n\n      // Removing first item\n      if (position === 0) {\n        this.head = current.next\n\n        // if there is only one item, update this.tail //NEW\n        if (this.length === 1) {\n          this.tail = null\n        } else {\n          this.head.prev = null\n        }\n      } else if (position === this.length - 1) {\n        current = this.tail\n        this.tail = current.prev\n        this.tail.next = null\n      } else {\n        while (index++ < position) {\n          previous = current\n          current = current.next\n        }\n\n        // link previous with current's next - skip it\n        previous.next = current.next\n        current.next.prev = previous\n      }\n\n      this.length--\n      return current.element\n    } else {\n      return null\n    }\n  }\n\n  // Get the indexOf item\n  indexOf(elm) {\n    let current = this.head\n    let index = -1\n\n    // If element found then return its position\n    while (current) {\n      if (elm === current.element) {\n        return ++index\n      }\n\n      index++\n      current = current.next\n    }\n\n    // Else return -1\n    return -1\n  }\n\n  // Find the item in the list\n  isPresent(elm) {\n    return this.indexOf(elm) !== -1\n  }\n\n  // Delete an item from the list\n  delete(elm) {\n    return this.removeAt(this.indexOf(elm))\n  }\n\n  // Delete first item from the list\n  deleteHead() {\n    this.removeAt(0)\n  }\n\n  // Delete last item from the list\n  deleteTail() {\n    this.removeAt(this.length - 1)\n  }\n\n  // Print item of the string\n  toString() {\n    let current = this.head\n    let string = ''\n\n    while (current) {\n      string += current.element + (current.next ? '\\n' : '')\n      current = current.next\n    }\n\n    return string\n  }\n\n  // Convert list to array\n  toArray() {\n    const arr = []\n    let current = this.head\n\n    while (current) {\n      arr.push(current.element)\n      current = current.next\n    }\n\n    return arr\n  }\n\n  // Check if list is empty\n  isEmpty() {\n    return this.length === 0\n  }\n\n  // Get the size of the list\n  size() {\n    return this.length\n  }\n\n  // Get the this.head\n  getHead() {\n    return this.head\n  }\n\n  // Get the this.tail\n  getTail() {\n    return this.tail\n  }\n\n  // Method to iterate over the LinkedList\n  iterator() {\n    let currentNode = this.getHead()\n    if (currentNode === null) return -1\n\n    const iterate = function* () {\n      while (currentNode) {\n        yield currentNode.element\n        currentNode = currentNode.next\n      }\n    }\n    return iterate()\n  }\n\n  // Method to log the LinkedList, for debugging\n  // it' a circular structure, so can't use stringify to debug the whole structure\n  log() {\n    let currentNode = this.getHead()\n    while (currentNode) {\n      console.log(currentNode.element)\n      currentNode = currentNode.next\n    }\n  }\n}\n\n// Example\n\n// const newDoubleLinkedList = new DoubleLinkedList()\n// newDoubleLinkedList.append(1)\n// newDoubleLinkedList.append(2)\n// newDoubleLinkedList.size() // returns 2\n// const iterate = newDoubleLinkedList.iterator()\n// console.log(iterate.next().value) // 1\n// console.log(iterate.next().value) // 2\n// console.log(newDoubleLinkedList.log())\n\nexport { DoubleLinkedList }\n"
  },
  {
    "path": "Data-Structures/Linked-List/MergeTwoSortedLinkedLists.js",
    "content": "import { LinkedList } from './SinglyLinkedList.js'\n/**\n * A LinkedList-based solution for merging two sorted linked lists into one sorted list.\n *\n * @param {LinkedList} list1 - The the first sorted linked list.\n * @param {LinkedList} list2 - The second sorted linked list.\n * @returns {LinkedList} - The merged sorted linked list.\n *\n * @example\n * const list1 = new LinkedList([1,2,4]);\n *\n * const list2 = new LinkedList([1,3,4]);\n *\n * const result = mergeLinkedLists(list1, list2);\n * // Returns the merged linked list representing 1 -> 1 -> 2 -> 3 -> 4 -> 4\n */\n\nfunction mergeLinkedLists(list1, list2) {\n  const mergedList = new LinkedList()\n\n  let current1 = list1.headNode\n  let current2 = list2.headNode\n\n  while (current1 || current2) {\n    if (!current1) {\n      mergedList.addLast(current2.data)\n      current2 = current2.next\n    } else if (!current2) {\n      mergedList.addLast(current1.data)\n      current1 = current1.next\n    } else {\n      if (current1.data < current2.data) {\n        mergedList.addLast(current1.data)\n        current1 = current1.next\n      } else {\n        mergedList.addLast(current2.data)\n        current2 = current2.next\n      }\n    }\n  }\n\n  return mergedList\n}\n\nexport { mergeLinkedLists }\n"
  },
  {
    "path": "Data-Structures/Linked-List/ReverseSinglyLinkedList.js",
    "content": "/** A LinkedList based solution to reverse a number\nProblem Statement: Given a number such that each of its digit is stored in a singly linked list. Reverse the linked list and return the head of the linked list Link for the Problem: https://leetcode.com/problems/reverse-linked-list/ */\nclass ReverseSinglyLinkedList {\n  solution(head) {\n    let prev = null\n    let next = null\n    while (head) {\n      next = head.next\n      head.next = prev\n      prev = head\n      head = next\n    }\n    return prev\n  }\n}\nexport { ReverseSinglyLinkedList }\n"
  },
  {
    "path": "Data-Structures/Linked-List/SinglyCircularLinkedList.js",
    "content": "// Methods - size, head, isEmpty, getElementAt, addAtFirst, add, clean, insertAt, remove, removeData, printData, get, clear\nimport { Node } from './SinglyLinkedList.js'\n\nclass SinglyCircularLinkedList {\n  constructor() {\n    this.headNode = null\n    this.length = 0\n  }\n\n  // Get size of the linkedList\n  size = () => this.length\n  // Get the headNode data\n  head = () => this.headNode?.data || null\n  // Check if the linkedList is empty\n  isEmpty = () => this.length === 0\n\n  // initiate the node and index\n  initiateNodeAndIndex() {\n    return { currentNode: this.headNode, currentIndex: 0 }\n  }\n\n  // get the data specific to an index\n  getElementAt(index) {\n    if (this.length !== 0 && index >= 0 && index <= this.length) {\n      let { currentNode } = this.initiateNodeAndIndex()\n      for (let i = 0; i < index && currentNode !== null; i++) {\n        currentNode = currentNode.next\n      }\n      return currentNode\n    }\n    return undefined\n  }\n\n  // Add the element in the first position\n  addAtFirst(data) {\n    const node = new Node(data)\n    node.next = this.headNode\n    this.headNode = node\n    this.length++\n    return this.length\n  }\n\n  // Add any data to the end of the linkedList\n  add(data) {\n    if (!this.headNode) {\n      return this.addAtFirst(data)\n    }\n    const node = new Node(data)\n    // Getting the last node\n    const currentNode = this.getElementAt(this.length - 1)\n    currentNode.next = node\n    node.next = this.headNode\n    this.length++\n    return this.length\n  }\n\n  // insert data at a specific position\n  insertAt(index, data) {\n    if (index === 0) return this.addAtFirst(data)\n    if (index === this.length) return this.add(data)\n    if (index < 0 || index > this.length)\n      throw new RangeError(`Index is out of range max ${this.length}`)\n    const node = new Node(data)\n    const previousNode = this.getElementAt(index - 1)\n    node.next = previousNode.next\n    previousNode.next = node\n    this.length++\n    return this.length\n  }\n\n  // find the first index of the data\n  indexOf(data) {\n    let { currentNode } = this.initiateNodeAndIndex()\n    // initializing currentIndex as -1\n    let currentIndex = -1\n    while (currentNode) {\n      if (currentNode.data === data) {\n        return currentIndex + 1\n      }\n      currentIndex++\n      currentNode = currentNode.next\n    }\n    return -1\n  }\n\n  // remove the data from the end of the list\n  remove() {\n    if (this.isEmpty()) return null\n    const secondLastNode = this.getElementAt(this.length - 2)\n    const removedNode = secondLastNode.next\n    secondLastNode.next = this.headNode\n    this.length--\n    return removedNode.data || null\n  }\n\n  // remove the data from the first of the list\n  removeFirst() {\n    if (this.isEmpty()) return null\n    const removedNode = this.headNode\n    if (this.length === 1) {\n      this.clear()\n      return removedNode.data\n    }\n    const lastNode = this.getElementAt(this.length - 1)\n    this.headNode = this.headNode.next\n    lastNode.next = this.headNode\n    this.length--\n    return removedNode.data || null\n  }\n\n  // remove the data from the index\n  removeAt(index) {\n    if (this.isEmpty()) return null\n    if (index === 0) return this.removeFirst()\n    if (index === this.length) return this.remove()\n    if (index < 0 && index > this.length) return null\n    const previousNode = this.getElementAt(index - 1)\n    const currentNode = previousNode.next\n    previousNode.next = currentNode.next\n    this.length--\n    return currentNode.data || null\n  }\n\n  // remove if the data is present\n  removeData(data) {\n    if (this.isEmpty()) return null\n    const index = this.indexOf(data)\n    return this.removeAt(index)\n  }\n\n  // logs the data\n  printData(output = (value) => console.log(value)) {\n    let { currentIndex, currentNode } = this.initiateNodeAndIndex()\n\n    while (currentNode !== null && currentIndex < this.length) {\n      output(currentNode.data)\n      currentNode = currentNode.next\n      currentIndex++\n    }\n  }\n\n  // get the data from the linkedList\n  get() {\n    let { currentIndex, currentNode } = this.initiateNodeAndIndex()\n    const list = []\n    while (currentNode !== null && currentIndex < this.length) {\n      list.push(currentNode.data)\n      currentNode = currentNode.next\n      currentIndex++\n    }\n    return list\n  }\n\n  clear() {\n    this.headNode = null\n    this.length = 0\n  }\n}\n\nexport { SinglyCircularLinkedList }\n"
  },
  {
    "path": "Data-Structures/Linked-List/SinglyLinkedList.js",
    "content": "/* SinglyLinkedList!!\n * A linked list is similar to an array, it holds a list of values.\n * However, links in a linked list do not have indexes. With\n * a linked list you do not need to predetermine its size as\n * it grows and shrinks as it is edited. This is an example of\n * a singly linked list.\n */\n\n// Methods - size, head, addLast, addFirst, addAt, removeFirst, removeLast, remove, removeAt, indexOf, isEmpty,  elementAt, findMiddle, get, clean, rotateListRight\n\nclass Node {\n  constructor(data) {\n    this.data = data\n    this.next = null\n  }\n}\n\nclass LinkedList {\n  constructor(listOfValues) {\n    this.headNode = null\n    this.tailNode = null\n    this.length = 0\n\n    if (listOfValues instanceof Array) {\n      for (const value of listOfValues) {\n        this.addLast(value)\n      }\n    }\n  }\n\n  // initiates the currentNode and currentIndex and return as an object\n  initiateNodeAndIndex() {\n    return { currentNode: this.headNode, currentIndex: 0 }\n  }\n\n  // Returns length\n  size() {\n    return this.length\n  }\n\n  // Returns the head\n  head() {\n    return this.headNode?.data ?? null\n  }\n\n  // Returns the tail\n  tail() {\n    return this.tailNode?.data ?? null\n  }\n\n  // Return if the list is empty\n  isEmpty() {\n    return this.length === 0\n  }\n\n  // add a node at last it to linklist\n  addLast(element) {\n    // Check if its the first element\n    if (this.headNode === null) {\n      return this.addFirst(element)\n    }\n    const node = new Node(element)\n    // Adding node at the end of the list and increase the length\n    this.tailNode.next = node\n    this.tailNode = node\n    this.length++\n    return this.size()\n  }\n\n  // add a node at first it to linklist\n  addFirst(element) {\n    const node = new Node(element)\n    // Check if its the first element\n    if (this.headNode === null) {\n      this.tailNode = node\n    }\n    // Adding node at the start of the list and increase the length\n    node.next = this.headNode\n    this.headNode = node\n    this.length++\n    return this.size()\n  }\n\n  // remove the first from the linklist\n  removeFirst() {\n    // Check if head is null\n    if (this.headNode === null) {\n      return null\n    }\n    // Removing node at the start of the list and decrease the length\n    const removedNode = this.headNode\n    this.headNode = this.headNode.next\n    this.length--\n    // Check if the list is empty\n    if (this.isEmpty()) {\n      this.tailNode = null\n    }\n    return removedNode?.data\n  }\n\n  // remove the last from the linklist\n  removeLast() {\n    if (this.isEmpty()) return null\n    // Check if there is only one element\n    if (this.length === 1) {\n      return this.removeFirst()\n    }\n    // Removing node at the end of the list and decrease the length\n    const removedNode = this.tailNode\n    let { currentNode } = this.initiateNodeAndIndex()\n    while (currentNode.next.next) {\n      currentNode = currentNode.next\n    }\n    currentNode.next = null\n    this.tailNode = currentNode\n    this.length--\n    return removedNode.data\n  }\n\n  // Removes the node with the value as param\n  remove(element) {\n    if (this.isEmpty()) return null\n    let { currentNode } = this.initiateNodeAndIndex()\n    let removedNode = null\n    // Check if the head node is the element to remove\n    if (currentNode.data === element) {\n      return this.removeFirst()\n    }\n    // Check if the tail node is the element to remove\n    if (this.tailNode.data === element) {\n      return this.removeLast()\n    }\n    // Check which node is the node to remove\n    while (currentNode.next) {\n      if (currentNode.next.data === element) {\n        removedNode = currentNode.next\n        currentNode.next = currentNode.next.next\n        this.length--\n        return removedNode.data\n      }\n      currentNode = currentNode.next\n    }\n    return removedNode?.data || null\n  }\n\n  // Returns the index of the element passed as param otherwise -1\n  indexOf(element) {\n    if (this.isEmpty()) return -1\n    let { currentNode, currentIndex } = this.initiateNodeAndIndex()\n    while (currentNode) {\n      if (currentNode.data === element) {\n        return currentIndex\n      }\n      currentNode = currentNode.next\n      currentIndex++\n    }\n    return -1\n  }\n\n  // Returns the element at an index\n  elementAt(index) {\n    if (index >= this.length || index < 0) {\n      throw new RangeError('Out of Range index')\n    }\n    let { currentIndex, currentNode } = this.initiateNodeAndIndex()\n    while (currentIndex < index) {\n      currentIndex++\n      currentNode = currentNode.next\n    }\n    return currentNode.data\n  }\n\n  // Adds the element at specified index\n  addAt(index, element) {\n    // Check if index is out of bounds of list\n    if (index > this.length || index < 0) {\n      throw new RangeError('Out of Range index')\n    }\n    if (index === 0) return this.addFirst(element)\n    if (index === this.length) return this.addLast(element)\n    let { currentIndex, currentNode } = this.initiateNodeAndIndex()\n    const node = new Node(element)\n\n    while (currentIndex !== index - 1) {\n      currentIndex++\n      currentNode = currentNode.next\n    }\n\n    // Adding the node at specified index\n    const tempNode = currentNode.next\n    currentNode.next = node\n    node.next = tempNode\n    // Incrementing the length\n    this.length++\n    return this.size()\n  }\n\n  // Removes the node at specified index\n  removeAt(index) {\n    // Check if index is present in list\n    if (index < 0 || index >= this.length) {\n      throw new RangeError('Out of Range index')\n    }\n    if (index === 0) return this.removeFirst()\n    if (index === this.length - 1) return this.removeLast()\n\n    let { currentIndex, currentNode } = this.initiateNodeAndIndex()\n    while (currentIndex !== index - 1) {\n      currentIndex++\n      currentNode = currentNode.next\n    }\n    const removedNode = currentNode.next\n    currentNode.next = currentNode.next.next\n    this.length--\n    return removedNode.data\n  }\n\n  // Returns a reference to middle node of linked list\n  findMiddle() {\n    // If there are two middle nodes, return the second middle node.\n    let fast = this.headNode\n    let slow = this.headNode\n\n    while (fast !== null && fast.next !== null) {\n      fast = fast.next.next\n      slow = slow.next\n    }\n    return slow\n  }\n\n  // make the linkedList Empty\n  clean() {\n    this.headNode = null\n    this.tailNode = null\n    this.length = 0\n  }\n\n  // Method to get the LinkedList\n  get() {\n    const list = []\n    let { currentNode } = this.initiateNodeAndIndex()\n    while (currentNode) {\n      list.push(currentNode.data)\n      currentNode = currentNode.next\n    }\n    return list\n  }\n\n  // Method for Rotating a List to the right by k places\n  rotateListRight(k) {\n    if (!this.headNode) return\n    let current = this.headNode\n    let tail = this.tailNode\n    let count = 1\n    while (current.next) {\n      count++\n      current = current.next\n    }\n    current.next = this.headNode\n    tail = current\n    k %= count\n    while (count - k > 0) {\n      tail = tail.next\n      count--\n    }\n    this.headNode = tail.next\n    tail.next = null\n  }\n\n  // Method to iterate over the LinkedList\n  iterator() {\n    let { currentNode } = this.initiateNodeAndIndex()\n    if (currentNode === null) return -1\n\n    const iterate = function* () {\n      while (currentNode) {\n        yield currentNode.data\n        currentNode = currentNode.next\n      }\n    }\n    return iterate()\n  }\n\n  // Method to log the LinkedList\n  log() {\n    console.log(JSON.stringify(this.headNode, null, 2))\n  }\n\n  // Method to reverse the LinkedList\n  reverse() {\n    let head = this.headNode\n    let prev = null\n    let next = null\n    while (head) {\n      next = head.next\n      head.next = prev\n      prev = head\n      head = next\n    }\n    this.tailNode = this.headNode\n    this.headNode = prev\n  }\n}\n\nexport { Node, LinkedList }\n"
  },
  {
    "path": "Data-Structures/Linked-List/test/AddTwoNumbers.test.js",
    "content": "import { AddTwoNumbers } from '../AddTwoNumbers.js'\nimport { LinkedList } from '../SinglyLinkedList'\n\ndescribe('AddTwoNumbers', () => {\n  it('Check Sum Of Two Linked List', () => {\n    const list1 = new LinkedList()\n    list1.addFirst(2)\n    list1.addLast(4)\n    list1.addLast(3)\n\n    const list2 = new LinkedList()\n    list2.addFirst(5)\n    list2.addLast(6)\n    list2.addLast(4)\n\n    const expected = new LinkedList()\n    expected.addFirst(7)\n    expected.addLast(0)\n    expected.addLast(8)\n\n    const addTwoLinkedList = new AddTwoNumbers()\n    addTwoLinkedList.solution(list1.headNode, list2.headNode)\n\n    expect(addTwoLinkedList.solutionToArray()).toEqual(expected.get())\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Linked-List/test/CycleDetection.test.js",
    "content": "import { detectCycle } from '../CycleDetection'\nimport { Node } from '../SinglyLinkedList'\n\ndescribe('Detect Cycle', () => {\n  it('should detect loop and return true', () => {\n    // Creating list and making a loop\n    const headNode = new Node(10)\n    headNode.next = new Node(20)\n    headNode.next.next = new Node(30)\n    headNode.next.next.next = new Node(40)\n    headNode.next.next.next.next = headNode\n    expect(detectCycle(headNode)).toEqual(true)\n  })\n\n  it('should not detect a loop and return false', () => {\n    // Case 0: When head is null, there is no loop.\n    expect(detectCycle(null)).toEqual(false)\n    const headNode = new Node(10)\n\n    // Case 1: List with single node doesn't have any loop\n    expect(detectCycle(headNode)).toEqual(false)\n\n    headNode.next = new Node(20)\n    headNode.next.next = new Node(30)\n    headNode.next.next.next = new Node(40)\n    headNode.next.next.next.next = new Node(50)\n\n    // Case 2: List not having any loops\n    expect(detectCycle(headNode)).toEqual(false)\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Linked-List/test/CycleDetectionII.test.js",
    "content": "import { findCycleStart } from '../CycleDetectionII'\nimport { Node } from '../SinglyLinkedList'\n\ndescribe('Detect Cycle', () => {\n  it('no cycle', () => {\n    const head = new Node(1)\n    head.next = new Node(2)\n\n    expect(findCycleStart(head)).toBeNull()\n  })\n\n  it('simple cycle', () => {\n    const head = new Node(1)\n    head.next = new Node(2)\n    head.next.next = new Node(3)\n    head.next.next.next = head.next // Creates a cycle\n\n    expect(findCycleStart(head)).toBe(head.next)\n  })\n\n  it('long list with cycle', () => {\n    const head = new Node(1)\n    head.next = new Node(2)\n    head.next.next = new Node(3)\n    head.next.next.next = new Node(4)\n    head.next.next.next.next = new Node(5)\n    head.next.next.next.next.next = head.next.next // Cycle\n\n    expect(findCycleStart(head)).toBe(head.next.next)\n  })\n\n  it('cycle on last node', () => {\n    const head = new Node(1)\n    head.next = new Node(2)\n    head.next.next = head\n\n    expect(findCycleStart(head)).toBe(head)\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Linked-List/test/DoublyLinkedList.test.js",
    "content": "import { DoubleLinkedList } from '../DoublyLinkedList'\n\ndescribe('DoubleLinkedList', () => {\n  it('Check append', () => {\n    const list = new DoubleLinkedList()\n\n    list.append(1)\n    expect(list.getHead().element).toEqual(1)\n\n    list.append(2)\n    expect(list.getTail().element).toEqual(2)\n  })\n\n  it('Check insert', () => {\n    const list = new DoubleLinkedList()\n\n    list.insert(0, 1)\n    expect(list.getHead().element).toEqual(1)\n\n    list.insert(1, 20)\n    expect(list.getTail().element).toEqual(20)\n  })\n\n  it('Check removeAt', () => {\n    const list = new DoubleLinkedList()\n\n    list.insert(0, 10)\n    list.insert(1, 40)\n    list.insert(2, 30)\n\n    list.removeAt(0)\n    expect(list.getHead().element).toEqual(40)\n\n    list.removeAt(1)\n    expect(list.getTail().element).toEqual(40)\n  })\n\n  it('Check delete', () => {\n    const list = new DoubleLinkedList()\n\n    list.insert(0, 10)\n    list.insert(1, 40)\n\n    list.delete(10)\n    expect(list.getHead().element).toEqual(40)\n  })\n\n  it('Check deleteTail', () => {\n    const list = new DoubleLinkedList()\n\n    list.insert(0, 10)\n    list.insert(1, 40)\n\n    list.deleteTail()\n    expect(list.getTail().element).toEqual(10)\n  })\n\n  it('Check toString', () => {\n    const list = new DoubleLinkedList()\n\n    list.insert(0, 20)\n    expect(list.toString()).toEqual('20')\n  })\n\n  it('Check isEmpty', () => {\n    const list = new DoubleLinkedList()\n\n    expect(list.isEmpty()).toEqual(true)\n\n    list.insert(0, 'Hello')\n    expect(list.isEmpty()).toEqual(false)\n  })\n\n  it('Check size', () => {\n    const list = new DoubleLinkedList()\n    expect(list.size()).toBe(0)\n\n    list.append(10)\n    expect(list.size()).toBe(1)\n\n    list.removeAt(1)\n    expect(list.size()).toBe(1)\n  })\n\n  it('Check toArray', () => {\n    const list = new DoubleLinkedList()\n    list.append(1)\n    list.append(2)\n\n    const listArray = list.toArray()\n    expect(listArray).toEqual([1, 2])\n  })\n\n  it('Check getHead', () => {\n    const list = new DoubleLinkedList()\n    expect(list.getHead()).toEqual(null)\n\n    list.append(1)\n    list.append(2)\n    expect(list.getHead()).toBeInstanceOf(Object)\n  })\n\n  it('Check Iterator', () => {\n    const list = new DoubleLinkedList()\n\n    let iterate = list.iterator()\n    expect(iterate).toBe(-1)\n\n    const arr = [10, 20, 5]\n    list.append(arr[0])\n    list.append(arr[1])\n    list.append(arr[2])\n    iterate = list.iterator()\n\n    for (let i = 0; i < arr.length; i++) {\n      expect(iterate.next().value).toBe(arr[i])\n    }\n    expect(iterate.next().value).toBe(undefined)\n\n    iterate = list.iterator()\n    let count = 0\n    for (const item of iterate) {\n      expect(item).toBe(arr[count])\n      count++\n    }\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Linked-List/test/MergeTwoSortedLinkedLists.test.js",
    "content": "import { expect } from 'vitest'\nimport { mergeLinkedLists } from '../MergeTwoSortedLinkedLists.js'\nimport { LinkedList } from '../SinglyLinkedList.js'\n\ndescribe('MergeTwoSortedLinkedLists', () => {\n  it('Merges two sorted linked lists', () => {\n    const list1 = new LinkedList([1, 2, 4])\n\n    const list2 = new LinkedList([1, 3, 4])\n\n    const expectedResult = new LinkedList([1, 1, 2, 3, 4, 4])\n\n    const result = mergeLinkedLists(list1, list2)\n\n    expect(result).toEqual(expectedResult)\n  })\n\n  it('Merges two empty linked lists', () => {\n    const list1 = new LinkedList()\n    const list2 = new LinkedList()\n\n    const expectedResult = new LinkedList()\n\n    const result = mergeLinkedLists(list1, list2)\n\n    expect(result).toEqual(expectedResult)\n  })\n\n  it('Merges one empty linked list with a non-empty one', () => {\n    const list1 = new LinkedList()\n    const list2 = new LinkedList([1])\n\n    const expectedResult = new LinkedList([1])\n\n    const result = mergeLinkedLists(list1, list2)\n\n    expect(result).toEqual(expectedResult)\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Linked-List/test/ReverseSinglyLinkedList.test.js",
    "content": "import { ReverseSinglyLinkedList } from '../ReverseSinglyLinkedList'\nimport { Node } from '../SinglyLinkedList'\ndescribe('ReverseSinglyLinkedList', () => {\n  it('Reverse a Number Represented as Linked List', () => {\n    const headNode = new Node(3)\n    headNode.next = new Node(4)\n    headNode.next.next = new Node(1)\n    const expected = new Node(1)\n    expected.next = new Node(4)\n    expected.next.next = new Node(3)\n    const reverseSinglyLinkedList = new ReverseSinglyLinkedList()\n    expect(reverseSinglyLinkedList.solution(headNode)).toEqual(expected)\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Linked-List/test/SinglyCircularLinkedList.test.js",
    "content": "import { SinglyCircularLinkedList } from '../SinglyCircularLinkedList'\n\ndescribe('SinglyCircularLinkedList', () => {\n  let list\n  beforeEach(() => {\n    list = new SinglyCircularLinkedList()\n  })\n  it('Check get', () => {\n    expect(list.get()).toEqual([])\n    expect(list.add(1)).toEqual(1)\n    expect(list.get()).toEqual([1])\n    expect(list.add(5)).toEqual(2)\n    expect(list.get()).toEqual([1, 5])\n  })\n\n  it('Check size', () => {\n    expect(list.size()).toEqual(0)\n    expect(list.add(1)).toEqual(1)\n    expect(list.add(1)).toEqual(2)\n    expect(list.size()).toEqual(2)\n  })\n\n  it('Check head', () => {\n    expect(list.head()).toEqual(null)\n    expect(list.add(1)).toEqual(1)\n    expect(list.head()).toEqual(1)\n    expect(list.add(1)).toEqual(2)\n    expect(list.head()).toEqual(1)\n    expect(list.addAtFirst(100)).toEqual(3)\n    expect(list.head()).toEqual(100)\n    expect(list.insertAt(0, 500)).toEqual(4)\n    expect(list.head()).toEqual(500)\n    list.clear()\n    expect(list.head()).toEqual(null)\n  })\n\n  it('Check isEmpty', () => {\n    expect(list.isEmpty()).toEqual(true)\n    expect(list.add(1)).toEqual(1)\n    expect(list.add(1)).toEqual(2)\n    expect(list.isEmpty()).toEqual(false)\n  })\n\n  it('Check getElementAt', () => {\n    list.add(100)\n    list.add(200)\n    list.add(300)\n    list.add(500)\n    list.add(900)\n\n    expect(list.getElementAt(1).data).toEqual(200)\n    expect(list.getElementAt(3).data).toEqual(500)\n  })\n\n  it('Check addAtFirst', () => {\n    list.add(1)\n    list.add(5)\n    list.add(7)\n    list.add(9)\n    list.add(0)\n    expect(list.get()).toEqual([1, 5, 7, 9, 0])\n    list.addAtFirst(100)\n    expect(list.get()).toEqual([100, 1, 5, 7, 9, 0])\n  })\n\n  it('Check add', () => {\n    list.add(1)\n    list.add(5)\n    list.add(7)\n    list.add(9)\n    list.add(0)\n    expect(list.get()).toEqual([1, 5, 7, 9, 0])\n    list.add(100)\n    expect(list.get()).toEqual([1, 5, 7, 9, 0, 100])\n  })\n\n  it('Check insertAt', () => {\n    expect(list.insertAt(0, 100)).toEqual(1)\n    expect(list.get()).toEqual([100])\n    expect(list.insertAt(0, 200)).toEqual(2)\n    expect(list.get()).toEqual([200, 100])\n    expect(list.insertAt(2, 300)).toEqual(3)\n    expect(list.get()).toEqual([200, 100, 300])\n  })\n\n  it('Checks indexOf', () => {\n    expect(list.indexOf(200)).toEqual(-1)\n    list.add(100)\n    list.add(200)\n    list.add(300)\n    list.add(500)\n    list.add(900)\n    expect(list.indexOf(200)).toEqual(1)\n  })\n\n  it('Check remove', () => {\n    expect(list.remove()).toEqual(null)\n    list.add(100)\n    list.add(200)\n    list.add(300)\n    list.add(500)\n    list.add(900)\n    expect(list.get()).toEqual([100, 200, 300, 500, 900])\n    const removedData = list.remove()\n    expect(removedData).toEqual(900)\n    expect(list.get()).toEqual([100, 200, 300, 500])\n  })\n\n  it('Check removeFirst', () => {\n    expect(list.removeFirst()).toEqual(null)\n    list.add(100)\n    list.add(200)\n    list.add(300)\n    list.add(500)\n    list.add(900)\n    expect(list.get()).toEqual([100, 200, 300, 500, 900])\n    const removedData = list.removeFirst()\n    expect(removedData).toEqual(100)\n    expect(list.get()).toEqual([200, 300, 500, 900])\n  })\n\n  it('Check removeAt', () => {\n    expect(list.removeAt(1)).toEqual(null)\n    list.add(100)\n    list.add(200)\n    list.add(300)\n    list.add(500)\n    list.add(900)\n    expect(list.get()).toEqual([100, 200, 300, 500, 900])\n    const removedData = list.removeAt(2)\n    expect(removedData).toEqual(300)\n    expect(list.get()).toEqual([100, 200, 500, 900])\n  })\n\n  it('Check removeData', () => {\n    expect(list.removeData(100)).toEqual(null)\n    list.add(100)\n    list.add(200)\n    list.add(300)\n    list.add(500)\n    list.add(900)\n    expect(list.get()).toEqual([100, 200, 300, 500, 900])\n    const removedData = list.removeData(200)\n    expect(removedData).toEqual(200)\n    expect(list.get()).toEqual([100, 300, 500, 900])\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Linked-List/test/SinglyLinkedList.test.js",
    "content": "import { LinkedList } from '../SinglyLinkedList'\n\ndescribe('SinglyLinkedList', () => {\n  it('Check addLast', () => {\n    const list = new LinkedList()\n    expect(list.get()).toEqual([])\n\n    expect(list.addLast(1)).toEqual(1)\n    expect(list.get()).toEqual([1])\n\n    expect(list.addLast(5)).toEqual(2)\n    expect(list.get()).toEqual([1, 5])\n  })\n\n  it('Check addFirst', () => {\n    const list = new LinkedList()\n    expect(list.get()).toEqual([])\n\n    expect(list.addFirst(1)).toEqual(1)\n    expect(list.get()).toEqual([1])\n\n    expect(list.addFirst(5)).toEqual(2)\n    expect(list.get()).toEqual([5, 1])\n  })\n\n  it('Check addAt', () => {\n    const list = new LinkedList()\n    expect(list.get()).toEqual([])\n\n    expect(list.addAt(0, 10)).toEqual(1)\n    expect(list.get()).toEqual([10])\n\n    expect(list.addAt(1, 20)).toEqual(2)\n    expect(list.get()).toEqual([10, 20])\n\n    expect(list.addAt(1, 30)).toEqual(3)\n    expect(list.get()).toEqual([10, 30, 20])\n\n    expect(list.addAt(3, 40)).toEqual(4)\n    expect(list.get()).toEqual([10, 30, 20, 40])\n  })\n\n  it('Check removeLast', () => {\n    const list = new LinkedList()\n    list.addLast(1)\n    list.addLast(2)\n    expect(list.get()).toEqual([1, 2])\n\n    expect(list.removeLast()).toEqual(2)\n    expect(list.get()).toEqual([1])\n\n    expect(list.removeLast()).toEqual(1)\n    expect(list.get()).toEqual([])\n  })\n\n  it('Check removeFirst', () => {\n    const list = new LinkedList()\n    list.addLast(1)\n    list.addLast(2)\n    expect(list.get()).toEqual([1, 2])\n\n    expect(list.removeFirst()).toEqual(1)\n    expect(list.get()).toEqual([2])\n\n    expect(list.removeFirst()).toEqual(2)\n    expect(list.get()).toEqual([])\n  })\n\n  it('Check removeAt', () => {\n    const list = new LinkedList()\n    list.addLast(10)\n    list.addLast(20)\n    list.addLast(30)\n    list.addLast(40)\n    list.addLast(50)\n    expect(list.get()).toEqual([10, 20, 30, 40, 50])\n\n    expect(list.removeAt(0)).toEqual(10)\n    expect(list.get()).toEqual([20, 30, 40, 50])\n\n    expect(list.removeAt(3)).toEqual(50)\n    expect(list.get()).toEqual([20, 30, 40])\n\n    expect(list.removeAt(1)).toEqual(30)\n    expect(list.get()).toEqual([20, 40])\n  })\n\n  it('Check remove', () => {\n    const list = new LinkedList()\n    list.addLast(10)\n    list.addLast(20)\n    list.addLast(30)\n    expect(list.get()).toEqual([10, 20, 30])\n\n    expect(list.remove(10)).toEqual(10)\n    expect(list.get()).toEqual([20, 30])\n\n    expect(list.remove(100)).toEqual(null)\n    expect(list.get()).toEqual([20, 30])\n  })\n\n  it('Check indexOf', () => {\n    const list = new LinkedList()\n    list.addLast(10)\n    list.addLast(20)\n    list.addLast(30)\n    list.addLast(40)\n    list.addLast(50)\n    expect(list.indexOf(10)).toBe(0)\n    expect(list.indexOf(30)).toBe(2)\n    expect(list.indexOf(50)).toBe(4)\n    expect(list.indexOf(70)).toBe(-1)\n  })\n\n  it('Check elementAt', () => {\n    const list = new LinkedList()\n    list.addLast(10)\n    list.addLast(20)\n    list.addLast(30)\n    list.addLast(40)\n    list.addLast(50)\n    expect(list.elementAt(0)).toBe(10)\n    expect(list.elementAt(1)).toBe(20)\n    expect(list.elementAt(3)).toBe(40)\n    expect(list.elementAt(4)).toBe(50)\n  })\n\n  it('Check isEmpty', () => {\n    const list = new LinkedList()\n    expect(list.isEmpty()).toBe(true)\n    list.addLast(10)\n    list.addLast(20)\n    list.addLast(30)\n    list.addLast(40)\n    list.addLast(50)\n    expect(list.isEmpty()).toBe(false)\n  })\n\n  it('Check head', () => {\n    const list = new LinkedList()\n    expect(list.head()).toBe(null)\n\n    list.addLast(10)\n    expect(list.head()).toBe(10)\n\n    list.addLast(20)\n    expect(list.head()).toBe(10)\n\n    list.addFirst(30)\n    expect(list.head()).toBe(30)\n\n    // check for a falsy head data\n    list.addFirst(false)\n    expect(list.head()).toBe(false)\n  })\n\n  it('Check tail', () => {\n    const list = new LinkedList()\n    expect(list.tail()).toBe(null)\n\n    list.addLast(10)\n    expect(list.tail()).toBe(10)\n\n    list.addLast(20)\n    expect(list.tail()).toBe(20)\n\n    list.addFirst(30)\n    expect(list.tail()).toBe(20)\n\n    // check for a falsy tail data\n    list.addLast(false)\n    expect(list.tail()).toBe(false)\n  })\n\n  it('Check size', () => {\n    const list = new LinkedList()\n    expect(list.size()).toBe(0)\n\n    list.addLast(10)\n    expect(list.size()).toBe(1)\n\n    list.addLast(20)\n    expect(list.size()).toBe(2)\n\n    list.removeFirst()\n    expect(list.size()).toBe(1)\n  })\n\n  it('Middle node of linked list', () => {\n    const list = new LinkedList()\n    list.addFirst(1)\n\n    // Middle node for list having single node\n    expect(list.findMiddle().data).toEqual(1)\n\n    list.addLast(2)\n    list.addLast(3)\n    list.addLast(4)\n    list.addLast(5)\n    list.addLast(6)\n    list.addLast(7)\n\n    // Middle node for list having odd number of nodes\n    expect(list.findMiddle().data).toEqual(4)\n\n    list.addLast(10)\n\n    // Middle node for list having even number of nodes\n    expect(list.findMiddle().data).toEqual(5)\n  })\n\n  it('Check Iterator', () => {\n    const list = new LinkedList()\n\n    let iterate = list.iterator()\n    expect(iterate).toBe(-1)\n\n    const arr = [10, 20, 5]\n    list.addLast(arr[0])\n    list.addLast(arr[1])\n    list.addLast(arr[2])\n    iterate = list.iterator()\n\n    for (let i = 0; i < arr.length; i++) {\n      expect(iterate.next().value).toBe(arr[i])\n    }\n    expect(iterate.next().value).toBe(undefined)\n\n    iterate = list.iterator()\n    let count = 0\n    for (const item of iterate) {\n      expect(item).toBe(arr[count])\n      count++\n    }\n  })\n  it('Cleans the linkedList', () => {\n    const list = new LinkedList()\n    list.addLast(10)\n    list.addLast(20)\n    list.addLast(30)\n    list.addLast(40)\n    list.addLast(50)\n    expect(list.size()).toEqual(5)\n    list.clean()\n    expect(list.isEmpty()).toBe(true)\n  })\n\n  it('should shift every node by k steps towards right, shifts tail nodes towards the start and change head of the list', () => {\n    // Case 0: When head of list is null\n    const tempNode = new LinkedList()\n    expect(tempNode.get()).toEqual([])\n\n    // Creating list\n    const headNode = new LinkedList([10, 20, 30, 40, 50])\n\n    // Case 1: when k = 0 => List should be unaffected\n    headNode.rotateListRight(0)\n    expect(headNode.get()).toEqual([10, 20, 30, 40, 50])\n\n    // Case 2: Rotate right by 2 steps\n    headNode.rotateListRight(2)\n    expect(headNode.get()).toEqual([40, 50, 10, 20, 30])\n\n    // Case 3: Rotate right by 12 steps\n    headNode.rotateListRight(12)\n    expect(headNode.get()).toEqual([20, 30, 40, 50, 10])\n\n    // Case 4: when k = length of the list = 5 => List should be unaffected\n    headNode.rotateListRight(5)\n    expect(headNode.get()).toEqual([20, 30, 40, 50, 10])\n  })\n\n  it('Reverse a Linked List', () => {\n    const list = new LinkedList([4, 3, 1])\n    list.reverse()\n    expect(list.get()).toEqual([1, 3, 4])\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Queue/CircularQueue.js",
    "content": "// Circular Queues offer a quick to store FIFO data with a maximum size.\n// Conserves memory as we only store up to our capacity\n// It is opposed to a queue which could continue to grow if input outpaces output\n// Doesn’t use dynamic memory so No memory leaks\n\nclass CircularQueue {\n  constructor(maxLength) {\n    this.queue = []\n    this.front = 0\n    this.rear = 0\n    this.maxLength = maxLength\n  }\n\n  // ADD ELEMENTS TO QUEUE\n  enqueue(value) {\n    if (this.checkOverflow()) return\n    if (this.checkEmpty()) {\n      this.front += 1\n      this.rear += 1\n    } else {\n      if (this.rear === this.maxLength) {\n        this.rear = 1\n      } else this.rear += 1\n    }\n    this.queue[this.rear] = value\n  }\n\n  // REMOVES ELEMENTS\n  dequeue() {\n    if (this.checkEmpty()) {\n      // UNDERFLOW\n      return\n    }\n    const y = this.queue[this.front]\n    this.queue[this.front] = '*'\n    if (!this.checkSingleelement()) {\n      if (this.front === this.maxLength) this.front = 1\n      else {\n        this.front += 1\n      }\n    }\n\n    return y // Returns the removed element and replaces it with a star\n  }\n\n  // checks if the queue is empty or not\n  checkEmpty() {\n    if (this.front === 0 && this.rear === 0) {\n      return true\n    }\n  }\n\n  checkSingleelement() {\n    if (this.front === this.rear && this.rear !== 0) {\n      this.front = this.rear = 0\n      return true\n    }\n  }\n\n  // Checks if max capacity of queue has been reached or not\n  checkOverflow() {\n    if (\n      (this.front === 1 && this.rear === this.maxLength) ||\n      this.front === this.rear + 1\n    ) {\n      // CIRCULAR QUEUE OVERFLOW\n      return true\n    }\n  }\n\n  // Prints the entire array ('*' represents blank space)\n  display(output = (value) => console.log(value)) {\n    for (let index = 1; index < this.queue.length; index++) {\n      output(this.queue[index])\n    }\n  }\n\n  // Displays the length of queue\n  length() {\n    return this.checkEmpty() ? 0 : this.queue.length - 1\n  }\n\n  // Display the top most value of queue\n  peek() {\n    return this.queue[this.front]\n  }\n}\n\nexport { CircularQueue }\n"
  },
  {
    "path": "Data-Structures/Queue/Queue.js",
    "content": "/* Queue\n * A Queue is a data structure that allows you to add an element to the end of\n * a list and remove the item at the front. A queue follows a FIFO (First In First Out)\n * system, where the first item to enter the queue is the first to be removed,\n * All these operation complexities are O(1).\n * This implementation following the linked list structure.\n */\n\nclass Queue {\n  #size\n\n  constructor() {\n    this.head = null\n    this.tail = null\n    this.#size = 0\n\n    return Object.seal(this)\n  }\n\n  get length() {\n    return this.#size\n  }\n\n  /**\n   * @description - Add a value to the end of the queue\n   * @param {*} data\n   * @returns {number} - The current size of queue\n   */\n  enqueue(data) {\n    const node = { data, next: null }\n\n    if (!this.head && !this.tail) {\n      this.head = node\n      this.tail = node\n    } else {\n      this.tail.next = node\n      this.tail = node\n    }\n\n    return ++this.#size\n  }\n\n  /**\n   * @description - Removes the value at the front of the queue\n   * @returns {*} - The first data of the queue\n   */\n  dequeue() {\n    if (this.isEmpty()) {\n      throw new Error('Queue is Empty')\n    }\n\n    const firstData = this.peekFirst()\n\n    this.head = this.head.next\n\n    if (!this.head) {\n      this.tail = null\n    }\n\n    this.#size--\n\n    return firstData\n  }\n\n  /**\n   * @description - Return the item at the front of the queue\n   * @returns {*}\n   */\n  peekFirst() {\n    if (this.isEmpty()) {\n      throw new Error('Queue is Empty')\n    }\n\n    return this.head.data\n  }\n\n  /**\n   * @description - Return the item at the tail of the queue\n   * @returns {*}\n   */\n  peekLast() {\n    if (this.isEmpty()) {\n      throw new Error('Queue is Empty')\n    }\n\n    return this.tail.data\n  }\n\n  /**\n   * @description - Return the array of Queue\n   * @returns {Array<*>}\n   */\n  toArray() {\n    const array = []\n    let node = this.head\n\n    while (node) {\n      array.push(node.data)\n      node = node.next\n    }\n\n    return array\n  }\n\n  /**\n   * @description - Return is queue empty or not\n   * @returns {boolean}\n   */\n  isEmpty() {\n    return this.length === 0\n  }\n}\n\nexport default Queue\n"
  },
  {
    "path": "Data-Structures/Queue/QueueUsing2Stacks.js",
    "content": "// implementation of Queue using 2 stacks\n// contribution made by hamza chabchoub for a university project\n\nclass Queue {\n  constructor() {\n    this.inputStack = []\n    this.outputStack = []\n  }\n\n  // Push item into the inputstack\n  enqueue(item) {\n    this.inputStack.push(item)\n  }\n\n  dequeue() {\n    // push all items to outputstack\n    this.outputStack = []\n    while (this.inputStack.length > 0) {\n      this.outputStack.push(this.inputStack.pop())\n    }\n    // return the top element of the outputstack if any\n    if (this.outputStack.length > 0) {\n      const top = this.outputStack.pop()\n      // repush all the items to the inputstack\n      this.inputStack = []\n      while (this.outputStack.length > 0) {\n        this.inputStack.push(this.outputStack.pop())\n      }\n      return top\n    }\n  }\n}\n\nexport { Queue }\n"
  },
  {
    "path": "Data-Structures/Queue/test/Queue.test.js",
    "content": "import Queue from '../Queue'\n\ndescribe('Testing the Queue DS', () => {\n  const queue = new Queue()\n\n  it('Testing enqueue method', () => {\n    expect(queue.enqueue(1)).toBe(1)\n    expect(queue.enqueue(2)).toBe(2)\n    expect(queue.enqueue(8)).toBe(3)\n    expect(queue.enqueue(9)).toBe(4)\n  })\n\n  it('Testing length after enqueue', () => {\n    expect(queue.length).toBe(4)\n  })\n\n  it('Testing peekFirst & peekLast methods', () => {\n    expect(queue.peekFirst()).toBe(1)\n    expect(queue.peekLast()).toBe(9)\n  })\n\n  it('Testing toArray method', () => {\n    expect(queue.toArray()).toEqual([1, 2, 8, 9])\n  })\n\n  it('Testing dequeue method', () => {\n    expect(queue.dequeue()).toBe(1)\n    expect(queue.dequeue()).toBe(2)\n  })\n\n  it('Testing length after dequeue', () => {\n    expect(queue.length).toBe(2)\n  })\n\n  it('Testing isEmpty method', () => {\n    const queue = new Queue()\n    expect(queue.isEmpty()).toBeTruthy()\n\n    queue.enqueue(1)\n    queue.enqueue(2)\n    queue.enqueue(8)\n    queue.enqueue(9)\n\n    expect(queue.isEmpty()).toBeFalsy()\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Queue/test/QueueUsing2Stacks.test.js",
    "content": "import { Queue } from '../QueueUsing2Stacks'\n\ndescribe('QueueUsing2Stacks', () => {\n  const queue = new Queue()\n\n  it('Check enqueue/dequeue', () => {\n    queue.enqueue(1)\n    queue.enqueue(2)\n    queue.enqueue(8)\n    queue.enqueue(9)\n\n    expect(queue.dequeue()).toBe(1)\n    expect(queue.dequeue()).toBe(2)\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Stack/EvaluateExpression.js",
    "content": "/**\n * Evaluate a numeric operations string in postfix notation using a stack.\n * Supports basic arithmetic operations: +, -, *, /\n * @see https://www.geeksforgeeks.org/evaluation-of-postfix-expression/\n * @param {string} expression - Numeric operations expression to evaluate. Must be a valid postfix expression.\n * @returns {number|null} - Result of the expression evaluation, or null if the expression is invalid.\n */\nfunction evaluatePostfixExpression(expression) {\n  const stack = []\n\n  // Helper function to perform an operation and push the result to the stack. Returns success.\n  function performOperation(operator) {\n    const rightOp = stack.pop() // Right operand is the top of the stack\n    const leftOp = stack.pop() // Left operand is the next item on the stack\n\n    if (leftOp === undefined || rightOp === undefined) {\n      return false // Invalid expression\n    }\n    switch (operator) {\n      case '+':\n        stack.push(leftOp + rightOp)\n        break\n      case '-':\n        stack.push(leftOp - rightOp)\n        break\n      case '*':\n        stack.push(leftOp * rightOp)\n        break\n      case '/':\n        if (rightOp === 0) {\n          return false\n        }\n        stack.push(leftOp / rightOp)\n        break\n      default:\n        return false // Unknown operator\n    }\n    return true\n  }\n\n  const tokens = expression.split(/\\s+/)\n\n  for (const token of tokens) {\n    if (!isNaN(parseFloat(token))) {\n      // If the token is a number, push it to the stack\n      stack.push(parseFloat(token))\n    } else {\n      // If the token is an operator, perform the operation\n      if (!performOperation(token)) {\n        return null // Invalid expression\n      }\n    }\n  }\n\n  return stack.length === 1 ? stack[0] : null\n}\n\nexport { evaluatePostfixExpression }\n"
  },
  {
    "path": "Data-Structures/Stack/Stack.js",
    "content": "/* Stack!!\n * A stack is exactly what it sounds like. An element gets added to the top of\n * the stack and only the element on the top may be removed. This is an example\n * of an array implementation of a Stack. So an element can only be added/removed\n * from the end of the array.\n */\n\n// Functions: push, pop, peek, view, length\n\n// Creates a stack constructor\nclass Stack {\n  constructor() {\n    // The top of the Stack\n    this.top = 0\n    // The array representation of the stack\n    this.stack = []\n  }\n\n  // Adds a value onto the end of the stack\n  push(value) {\n    this.stack[this.top] = value\n    this.top++\n  }\n\n  // Removes and returns the value at the end of the stack\n  pop() {\n    if (this.top === 0) {\n      return 'Stack is Empty'\n    }\n\n    this.top--\n    const result = this.stack[this.top]\n    this.stack = this.stack.splice(0, this.top)\n    return result\n  }\n\n  // Returns the size of the stack\n  size() {\n    return this.top\n  }\n\n  // Returns the value at the end of the stack\n  peek() {\n    return this.stack[this.top - 1]\n  }\n\n  // To see all the elements in the stack\n  view(output = (value) => console.log(value)) {\n    for (let i = 0; i < this.top; i++) {\n      output(this.stack[i])\n    }\n  }\n}\n\nexport { Stack }\n"
  },
  {
    "path": "Data-Structures/Stack/StackES6.js",
    "content": "/* Stack data-structure. It's work is based on the LIFO method (last-IN-first-OUT).\n * It means that elements added to the stack are placed on the top and only the\n * last element (from the top) can be reached. After we get access to the last\n * element, he pops from the stack.\n * This is a class-based implementation of a Stack. It provides functions\n * 'push' - to add an element, 'pop' - to remove an element from the top.\n * Also it implements 'length', 'last' and 'isEmpty' properties and\n * static isStack method to check is an object the instance of Stack class.\n */\n\n// Class declaration\nclass Stack {\n  constructor() {\n    this.stack = []\n    this.top = 0\n  }\n\n  // Adds a value to the end of the Stack\n  push(newValue) {\n    this.stack.push(newValue)\n    this.top += 1\n  }\n\n  // Returns and removes the last element of the Stack\n  pop() {\n    if (this.top !== 0) {\n      this.top -= 1\n      return this.stack.pop()\n    }\n    throw new Error('Stack Underflow')\n  }\n\n  // Returns the number of elements in the Stack\n  get length() {\n    return this.top\n  }\n\n  // Returns true if stack is empty, false otherwise\n  get isEmpty() {\n    return this.top === 0\n  }\n\n  // Returns the last element without removing it\n  get last() {\n    if (this.top !== 0) {\n      return this.stack[this.stack.length - 1]\n    }\n    return null\n  }\n\n  // Checks if an object is the instance os the Stack class\n  static isStack(el) {\n    return el instanceof Stack\n  }\n}\n\nexport { Stack }\n"
  },
  {
    "path": "Data-Structures/Stack/test/EvaluateExpression.test.js",
    "content": "import { evaluatePostfixExpression } from '../EvaluateExpression.js'\n\ndescribe('evaluatePostfixExpression', () => {\n  it('should evaluate a valid expression', () => {\n    const expression = '3 4 * 2 / 5 +' // (3 * 4) / 2 + 5 = 11\n    const result = evaluatePostfixExpression(expression)\n    expect(result).toBe(11)\n  })\n\n  it('should handle division by zero', () => {\n    const expression = '3 0 /' // Division by zero\n    const result = evaluatePostfixExpression(expression)\n    expect(result).toBe(null)\n  })\n\n  it('should handle an invalid expression', () => {\n    const expression = '3 * 4 2 / +' // Invalid expression\n    const result = evaluatePostfixExpression(expression)\n    expect(result).toBe(null)\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Tree/AVLTree.js",
    "content": "/**\n * Adelson-Velsky and Landis Tree\n * [Wikipedia](https://en.wikipedia.org/wiki/AVL_tree)\n * [A video lecture](http://www.youtube.com/watch?v=TbvhGcf6UJU)\n */\n'use strict'\n\n/**\n * A utility class for comparator\n * A comparator is expected to have following structure\n *\n * comp(a, b) RETURN < 0 if a < b\n * RETURN > 0 if a > b\n * MUST RETURN 0 if a == b\n */\nlet utils\n;(function (_utils) {\n  function comparator() {\n    return function (v1, v2) {\n      if (v1 < v2) return -1\n      if (v2 < v1) return 1\n      return 0\n    }\n  }\n  _utils.comparator = comparator\n})(utils || (utils = {}))\n\n/**\n * @constructor\n * A class for AVL Tree\n * @argument comp - A function used by AVL Tree For Comparison\n * If no argument is sent it uses utils.comparator\n */\nclass AVLTree {\n  constructor(comp) {\n    /** @public comparator function */\n    this._comp = undefined\n    this._comp = comp !== undefined ? comp : utils.comparator()\n\n    /** @public root of the AVL Tree */\n    this.root = null\n    /** @public number of elements in AVL Tree */\n    this.size = 0\n  }\n\n  /* Public Functions */\n  /**\n   * For Adding Elements to AVL Tree\n   * @param {any} _val\n   * Since in AVL Tree an element can only occur once so\n   * if a element exists it return false\n   * @returns {Boolean} element added or not\n   */\n  add(_val) {\n    const prevSize = this.size\n    this.root = insert(this.root, _val, this)\n    return this.size !== prevSize\n  }\n\n  /**\n   * TO check is a particular element exists or not\n   * @param {any} _val\n   * @returns {Boolean} exists or not\n   */\n  find(_val) {\n    const temp = searchAVLTree(this.root, _val, this)\n    return temp != null\n  }\n\n  /**\n   *\n   * @param {any} _val\n   * It is possible that element doesn't exists in tree\n   * in that case it return false\n   * @returns {Boolean} if element was found and deleted\n   */\n  remove(_val) {\n    const prevSize = this.size\n    this.root = deleteElement(this.root, _val, this)\n    return prevSize !== this.size\n  }\n}\n\n// creates new Node Object\nclass Node {\n  constructor(val) {\n    this._val = val\n    this._left = null\n    this._right = null\n    this._height = 1\n  }\n}\n\n// get height of a node\nconst getHeight = function (node) {\n  if (node == null) {\n    return 0\n  }\n  return node._height\n}\n\n// height difference or balance factor of a node\nconst getHeightDifference = function (node) {\n  return node == null ? 0 : getHeight(node._left) - getHeight(node._right)\n}\n\n// update height of a node based on children's heights\nconst updateHeight = function (node) {\n  if (node == null) {\n    return\n  }\n  node._height = Math.max(getHeight(node._left), getHeight(node._right)) + 1\n}\n\n// Helper: To check if the balanceFactor is valid\nconst isValidBalanceFactor = (balanceFactor) =>\n  [0, 1, -1].includes(balanceFactor)\n\n// rotations of AVL Tree\nconst leftRotate = function (node) {\n  const temp = node._right\n  node._right = temp._left\n  temp._left = node\n  updateHeight(node)\n  updateHeight(temp)\n  return temp\n}\nconst rightRotate = function (node) {\n  const temp = node._left\n  node._left = temp._right\n  temp._right = node\n  updateHeight(node)\n  updateHeight(temp)\n  return temp\n}\n\n// check if tree is balanced else balance it for insertion\nconst insertBalance = function (node, _val, balanceFactor, tree) {\n  if (balanceFactor > 1 && tree._comp(_val, node._left._val) < 0) {\n    return rightRotate(node) // Left Left Case\n  }\n  if (balanceFactor < 1 && tree._comp(_val, node._right._val) > 0) {\n    return leftRotate(node) // Right Right Case\n  }\n  if (balanceFactor > 1 && tree._comp(_val, node._left._val) > 0) {\n    node._left = leftRotate(node._left) // Left Right Case\n    return rightRotate(node)\n  }\n  node._right = rightRotate(node._right)\n  return leftRotate(node)\n}\n\n// check if tree is balanced after deletion\nconst delBalance = function (node) {\n  const balanceFactor1 = getHeightDifference(node)\n  if (isValidBalanceFactor(balanceFactor1)) {\n    return node\n  }\n  if (balanceFactor1 > 1) {\n    if (getHeightDifference(node._left) >= 0) {\n      return rightRotate(node) // Left Left\n    }\n    node._left = leftRotate(node._left)\n    return rightRotate(node) // Left Right\n  }\n  if (getHeightDifference(node._right) > 0) {\n    node._right = rightRotate(node._right)\n    return leftRotate(node) // Right Left\n  }\n  return leftRotate(node) // Right Right\n}\n\n// implement avl tree insertion\nconst insert = function (root, val, tree) {\n  if (root == null) {\n    tree.size++\n    return new Node(val)\n  }\n  if (tree._comp(root._val, val) < 0) {\n    root._right = insert(root._right, val, tree)\n  } else if (tree._comp(root._val, val) > 0) {\n    root._left = insert(root._left, val, tree)\n  } else {\n    return root\n  }\n  updateHeight(root)\n  const balanceFactor = getHeightDifference(root)\n  return isValidBalanceFactor(balanceFactor)\n    ? root\n    : insertBalance(root, val, balanceFactor, tree)\n}\n\n// delete am element\nconst deleteElement = function (root, _val, tree) {\n  if (root == null) {\n    return root\n  }\n  if (tree._comp(root._val, _val) === 0) {\n    // key found case\n    if (root._left === null && root._right === null) {\n      root = null\n      tree.size--\n    } else if (root._left === null) {\n      root = root._right\n      tree.size--\n    } else if (root._right === null) {\n      root = root._left\n      tree.size--\n    } else {\n      let temp = root._right\n      while (temp._left != null) {\n        temp = temp._left\n      }\n      root._val = temp._val\n      root._right = deleteElement(root._right, temp._val, tree)\n    }\n  } else {\n    if (tree._comp(root._val, _val) < 0) {\n      root._right = deleteElement(root._right, _val, tree)\n    } else {\n      root._left = deleteElement(root._left, _val, tree)\n    }\n  }\n  updateHeight(root)\n  root = delBalance(root)\n  return root\n}\n// search tree for a element\nconst searchAVLTree = function (root, val, tree) {\n  if (root == null) {\n    return null\n  }\n  if (tree._comp(root._val, val) === 0) {\n    return root\n  }\n  if (tree._comp(root._val, val) < 0) {\n    return searchAVLTree(root._right, val, tree)\n  }\n  return searchAVLTree(root._left, val, tree)\n}\n\n/**\n * A Code for Testing the AVLTree\n */\n// (function test () {\n//   const newAVL = new AVLTree()\n//   const size = Math.floor(Math.random() * 1000000)\n//   let uniques = 0\n//   let i, temp, j\n//   const array = []\n//   for (i = 0; i < size; i++) {\n//     temp = Math.floor(Math.random() * Number.MAX_VALUE)\n//     if (newAVL.add(temp)) {\n//       uniques++\n//       array.push(temp)\n//     }\n//   }\n//   if (newAVL.size !== uniques) {\n//     throw new Error('elements not inserted properly')\n//   }\n//   const findTestSize = Math.floor(Math.random() * uniques)\n//   for (i = 0; i < findTestSize; i++) {\n//     j = Math.floor(Math.random() * uniques)\n//     if (!newAVL.find(array[j])) {\n//       throw new Error('inserted elements not found')\n//     }\n//   }\n//   const deleteTestSize = Math.floor(uniques * Math.random())\n//   for (i = 0; i < deleteTestSize; i++) {\n//     j = Math.floor(Math.random() * uniques)\n//     temp = array[j]\n//     if (newAVL.find(temp)) {\n//       if (!newAVL.remove(temp)) {\n//         throw new Error('delete not working properly')\n//       }\n//     }\n//   }\n// })()\n\nexport { AVLTree }\n"
  },
  {
    "path": "Data-Structures/Tree/BinarySearchTree.js",
    "content": "/* Binary Search Tree!!\n *\n * Nodes that will go on the Binary Tree.\n * They consist of the data in them, the node to the left, the node\n * to the right, and the parent from which they came from.\n *\n * A binary tree is a data structure in which an element\n * has two successors(children). The left child is usually\n * smaller than the parent, and the right child is usually\n * bigger.\n */\n\n// class Node\nconst Node = (function Node() {\n  // Node in the tree\n  class Node {\n    constructor(val) {\n      this.value = val\n      this.left = null\n      this.right = null\n    }\n\n    // Search the tree for a value\n    search(val) {\n      if (this.value === val) {\n        return this\n      } else if (val < this.value && this.left !== null) {\n        return this.left.search(val)\n      } else if (val > this.value && this.right !== null) {\n        return this.right.search(val)\n      }\n      return null\n    }\n\n    // Visit a node\n    visit(output = (value) => console.log(value)) {\n      // Recursively go left\n      if (this.left !== null) {\n        this.left.visit(output)\n      }\n      // Print out value\n      output(this.value)\n      // Recursively go right\n      if (this.right !== null) {\n        this.right.visit(output)\n      }\n    }\n\n    // Add a node\n    addNode(n) {\n      if (n.value < this.value) {\n        if (this.left === null) {\n          this.left = n\n        } else {\n          this.left.addNode(n)\n        }\n      } else if (n.value > this.value) {\n        if (this.right === null) {\n          this.right = n\n        } else {\n          this.right.addNode(n)\n        }\n      }\n    }\n\n    // remove a node\n    removeNode(val) {\n      if (val === this.value) {\n        if (!this.left && !this.right) {\n          return null\n        } else {\n          if (this.left) {\n            const leftMax = maxVal(this.left)\n            this.value = leftMax\n            this.left = this.left.removeNode(leftMax)\n          } else {\n            const rightMin = minVal(this.right)\n            this.value = rightMin\n            this.right = this.right.removeNode(rightMin)\n          }\n        }\n      } else if (val < this.value) {\n        this.left = this.left && this.left.removeNode(val)\n      } else if (val > this.value) {\n        this.right = this.right && this.right.removeNode(val)\n      }\n      return this\n    }\n  }\n\n  // find maximum value in the tree\n  const maxVal = function (node) {\n    if (!node.right) {\n      return node.value\n    }\n    return maxVal(node.right)\n  }\n\n  // find minimum value in the tree\n  const minVal = function (node) {\n    if (!node.left) {\n      return node.value\n    }\n    return minVal(node.left)\n  }\n  // returns the constructor\n  return Node\n})()\n\n// class Tree\nconst Tree = (function () {\n  class Tree {\n    constructor() {\n      // Just store the root\n      this.root = null\n    }\n\n    // Inorder traversal\n    traverse(output = (value) => console.log(value)) {\n      if (!this.root) {\n        // No nodes are there in the tree till now\n        return\n      }\n      this.root.visit(output)\n    }\n\n    // Start by searching the root\n    search(val) {\n      if (this.root) {\n        const found = this.root.search(val)\n        if (found !== null) {\n          return found.value\n        }\n      }\n\n      // not found\n      return null\n    }\n\n    // Add a new value to the tree\n    addValue(val) {\n      const n = new Node(val)\n      if (this.root === null) {\n        this.root = n\n      } else {\n        this.root.addNode(n)\n      }\n    }\n\n    // remove a value from the tree\n    removeValue(val) {\n      // remove something if root exists\n      this.root = this.root && this.root.removeNode(val)\n    }\n  }\n\n  // returns the constructor\n  return Tree\n})()\n\nexport { Tree }\n"
  },
  {
    "path": "Data-Structures/Tree/SegmentTree.js",
    "content": "/**\n * Segment Tree\n * concept : [Wikipedia](https://en.wikipedia.org/wiki/Segment_tree)\n * inspired by : https://www.geeksforgeeks.org/segment-tree-efficient-implementation/\n *\n * time complexity\n * - init : O(N)\n * - update : O(log(N))\n * - query : O(log(N))\n *\n * space complexity : O(N)\n */\nclass SegmentTree {\n  size\n  tree\n  constructor(arr) {\n    // we define tree like this\n    // tree[1] : root node of tree\n    // tree[i] : i'th node\n    // tree[i * 2] : i'th left child\n    // tree[i * 2 + 1] : i'th right child\n    // and we use bit, shift operation for index\n    this.size = arr.length\n    this.tree = new Array(2 * arr.length)\n    this.tree.fill(0)\n\n    this.build(arr)\n  }\n\n  // function to build the tree\n  build(arr) {\n    const { size, tree } = this\n    // insert leaf nodes in tree\n    // leaf nodes will start from index N\n    // in this array and will go up to index (2 * N – 1)\n    for (let i = 0; i < size; i++) {\n      tree[size + i] = arr[i]\n    }\n\n    // build the tree by calculating parents\n    // tree's root node will contain all leaf node's sum\n    for (let i = size - 1; i > 0; --i) {\n      // current node's value is the sum of left child, right child\n      tree[i] = tree[i * 2] + tree[i * 2 + 1]\n    }\n  }\n\n  update(index, value) {\n    const { size, tree } = this\n\n    // only update values in the parents of the given node being changed.\n    // to get the parent move to parent node (index / 2)\n\n    // set value at position index\n    index += size\n    // tree[index] is leaf node and index's value of array\n    tree[index] = value\n\n    // move upward and update parents\n    for (let i = index; i > 1; i >>= 1) {\n      // i ^ 1 turns (2 * i) to (2 * i + 1)\n      // i ^ 1 is second child\n      tree[i >> 1] = tree[i] + tree[i ^ 1]\n    }\n  }\n\n  // interval [L, R) with left index(L) included and right (R) excluded.\n  query(left, right) {\n    const { size, tree } = this\n    // cause R is excluded, increase right for convenient\n    right++\n    let res = 0\n\n    // loop to find the sum in the range\n    for (left += size, right += size; left < right; left >>= 1, right >>= 1) {\n      // L is the left border of an query interval\n\n      // if L is odd it means that it is the right child of its parent and our interval includes only L and not the parent.\n      // So we will simply include this node to sum and move to the parent of its next node by doing L = (L + 1) / 2.\n\n      // if L is even it is the left child of its parent\n      // and the interval includes its parent also unless the right borders interfere.\n      if ((left & 1) > 0) {\n        res += tree[left++]\n      }\n\n      // same in R (the right border of an query interval)\n      if ((right & 1) > 0) {\n        res += tree[--right]\n      }\n    }\n\n    return res\n  }\n}\n\nexport { SegmentTree }\n"
  },
  {
    "path": "Data-Structures/Tree/Trie.js",
    "content": "class TrieNode {\n  constructor(key, parent) {\n    this.key = key\n    this.count = 0\n    this.children = Object.create(null)\n    if (parent === undefined) {\n      this.parent = null\n    } else {\n      this.parent = parent\n    }\n  }\n}\n\nclass Trie {\n  constructor() {\n    // create only root with null key and parent\n    this.root = new TrieNode(null, null)\n  }\n\n  // Recursively finds the occurrence of all words in a given node\n  static findAllWords(root, word, output) {\n    if (root === null) return\n    if (root.count > 0) {\n      if (typeof output === 'object') {\n        output.push({ word, count: root.count })\n      }\n    }\n    let key\n    for (key in root.children) {\n      word += key\n      this.findAllWords(root.children[key], word, output)\n      word = word.slice(0, -1)\n    }\n  }\n\n  insert(word) {\n    if (typeof word !== 'string') return\n    if (word === '') {\n      this.root.count += 1\n      return\n    }\n    let node = this.root\n    const len = word.length\n    let i\n    for (i = 0; i < len; i++) {\n      if (node.children[word.charAt(i)] === undefined) {\n        node.children[word.charAt(i)] = new TrieNode(word.charAt(i), node)\n      }\n      node = node.children[word.charAt(i)]\n    }\n    node.count += 1\n  }\n\n  findPrefix(word) {\n    if (typeof word !== 'string') return null\n    let node = this.root\n    const len = word.length\n    let i\n    // After end of this loop node will be at desired prefix\n    for (i = 0; i < len; i++) {\n      if (node.children[word.charAt(i)] === undefined) return null // No such prefix exists\n      node = node.children[word.charAt(i)]\n    }\n    return node\n  }\n\n  remove(word, count) {\n    if (typeof word !== 'string') return\n    if (typeof count !== 'number') count = 1\n    else if (count <= 0) return\n\n    // for empty string just delete count of root\n    if (word === '') {\n      if (this.root.count >= count) this.root.count -= count\n      else this.root.count = 0\n      return\n    }\n\n    let child = this.root\n    const len = word.length\n    let i, key\n    // child: node which is to be deleted\n    for (i = 0; i < len; i++) {\n      key = word.charAt(i)\n      if (child.children[key] === undefined) return\n      child = child.children[key]\n    }\n\n    // Delete no of occurrences specified\n    if (child.count >= count) child.count -= count\n    else child.count = 0\n\n    // If some occurrences are left we don't delete it or else\n    // if the object forms some other objects prefix we don't delete it\n    // For checking an empty object\n    // https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object\n    if (\n      child.count <= 0 &&\n      Object.keys(child.children).length &&\n      child.children.constructor === Object\n    ) {\n      child.parent.children[child.key] = undefined\n    }\n  }\n\n  findAllWords(prefix) {\n    const output = []\n    // find the node with provided prefix\n    const node = this.findPrefix(prefix)\n    // No such prefix exists\n    if (node === null) return output\n    Trie.findAllWords(node, prefix, output)\n    return output\n  }\n\n  contains(word) {\n    // find the node with given prefix\n    const node = this.findPrefix(word)\n    // No such word exists\n    return node !== null && node.count !== 0\n  }\n\n  findOccurrences(word) {\n    // find the node with given prefix\n    const node = this.findPrefix(word)\n    // No such word exists\n    if (node === null) return 0\n    return node.count\n  }\n}\n\nexport { Trie }\n"
  },
  {
    "path": "Data-Structures/Tree/test/AVLTree.test.js",
    "content": "import { AVLTree } from '../AVLTree'\n\ndescribe('AVLTree Implementation: ', () => {\n  const avlTree = new AVLTree()\n  const dataList = []\n  const demoData = [1, 4, 6, 22, 7, 99, 4, 66, 77, 98, 87, 54, 32, 15]\n\n  const avlStringTree = new AVLTree()\n  const collator = new Intl.Collator()\n  const stringData = ['S', 'W', 'z', 'B', 'a']\n\n  const emptyTree = new AVLTree(collator.compare)\n\n  beforeAll(() => {\n    demoData.forEach((item) => {\n      if (avlTree.add(item)) {\n        dataList.push(item)\n      }\n    })\n\n    avlStringTree._comp = collator.compare\n    stringData.forEach((item) => avlStringTree.add(item))\n  })\n\n  it('delete and search from empty tree', () => {\n    expect(emptyTree.remove(0)).toBeFalsy()\n    expect(emptyTree.find(0)).toBeFalsy()\n  })\n\n  it('checks if element is inserted properly', () => {\n    expect(dataList.length).toEqual(avlTree.size)\n    expect(stringData.length).toEqual(avlStringTree.size)\n  })\n\n  it('search if inserted element is present', () => {\n    demoData.forEach((data) => {\n      expect(avlTree.find(data)).toBeTruthy()\n    })\n    stringData.forEach((data) => {\n      expect(avlStringTree.find(data)).toBeTruthy()\n    })\n  })\n\n  it('delete element with two valid children', () => {\n    expect(avlTree.remove(77)).toBeTruthy()\n  })\n\n  it('delete element missing L-child', () => {\n    expect(avlTree.remove(98)).toBeTruthy()\n  })\n\n  it('delete elements forcing single R-rotation', () => {\n    expect(avlTree.remove(99)).toBeTruthy()\n    expect(avlTree.remove(87)).toBeTruthy()\n  })\n\n  it('delete elements forcing R-rotation and L-rotation', () => {\n    expect(avlTree.remove(1)).toBeTruthy()\n    expect(avlTree.remove(4)).toBeTruthy()\n  })\n\n  it('delete elements forcing single L-rotation', () => {\n    expect(avlTree.remove(7)).toBeTruthy()\n    expect(avlTree.remove(15)).toBeTruthy()\n    expect(avlTree.remove(6)).toBeTruthy()\n  })\n\n  it('delete element forcing single L-rotation and R-rotation', () => {\n    expect(avlTree.remove(66)).toBeTruthy()\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Tree/test/BinarySearchTree.test.js",
    "content": "import { Tree } from '../BinarySearchTree.js'\n\ndescribe('Binary Search Tree', () => {\n  let tree\n\n  beforeEach(() => {\n    tree = new Tree()\n    tree.addValue(10)\n    tree.addValue(5)\n    tree.addValue(15)\n    tree.addValue(3)\n    tree.addValue(8)\n  })\n\n  test('should add values to the tree', () => {\n    tree.addValue(12)\n\n    expect(tree.search(12)).toBe(12)\n    expect(tree.search(5)).toBe(5)\n    expect(tree.search(15)).toBe(15)\n  })\n\n  test('should perform in-order traversal', () => {\n    const values = []\n    const output = (val) => values.push(val)\n    tree.traverse(output)\n    expect(values).toEqual([3, 5, 8, 10, 15])\n  })\n\n  test('should remove leaf nodes correctly', () => {\n    tree.removeValue(5)\n    expect(tree.search(5)).toBeNull()\n  })\n\n  test('should remove nodes with one child correctly', () => {\n    tree.addValue(12)\n    tree.removeValue(15)\n\n    expect(tree.search(15)).toBeNull()\n    expect(tree.search(12)).toBe(12)\n  })\n\n  test('should remove nodes with two children correctly', () => {\n    tree.addValue(18)\n    tree.removeValue(15)\n\n    expect(tree.search(15)).toBeNull()\n    expect(tree.search(18)).toBe(18)\n  })\n\n  test('should return null for non-existent values', () => {\n    expect(tree.search(20)).toBeNull()\n    expect(tree.search(0)).toBeNull()\n  })\n\n  test('should handle removal of root node correctly', () => {\n    tree.removeValue(10)\n    expect(tree.search(10)).toBeNull()\n  })\n\n  test('should handle empty tree gracefully', () => {\n    const newTree = new Tree()\n    newTree.removeValue(22) // Should not throw\n    expect(newTree.search(22)).toBeNull()\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Tree/test/SegmentTree.test.js",
    "content": "import { SegmentTree } from '../SegmentTree'\n\ndescribe('SegmentTree sum test', () => {\n  const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]\n\n  const segment = new SegmentTree(a)\n\n  it('init sum check', () => {\n    expect(segment.query(0, 2)).toBe(6)\n  })\n\n  it('init sum check', () => {\n    segment.update(2, 1)\n    expect(segment.query(0, 2)).toBe(4)\n  })\n})\n"
  },
  {
    "path": "Data-Structures/Vectors/Vector2.js",
    "content": "/**\n * In mathematics and physics, a vector is an element of a vector space.\n *\n * The Vector2-class implements 2-dimensional vectors together with various vector-operations.\n * @see https://en.wikipedia.org/wiki/Vector_(mathematics_and_physics).\n */\n\nclass Vector2 {\n  constructor(x, y) {\n    this.x = x\n    this.y = y\n  }\n\n  /**\n   * Check for exact vector equality.\n   *\n   * @param vector The vector to compare to.\n   * @returns Whether they are exactly equal or not.\n   */\n  equalsExactly(vector) {\n    return this.x === vector.x && this.y === vector.y\n  }\n\n  /**\n   * Check for approximate vector equality.\n   *\n   * @param vector The vector to compare to.\n   * @param epsilon The allowed discrepancy for the x-values and the y-values.\n   * @returns Whether they are approximately equal or not.\n   */\n  equalsApproximately(vector, epsilon) {\n    return (\n      Math.abs(this.x - vector.x) < epsilon &&\n      Math.abs(this.y - vector.y) < epsilon\n    )\n  }\n\n  /**\n   * Vector length.\n   *\n   * @returns The length of the vector.\n   */\n  length() {\n    return Math.sqrt(this.x * this.x + this.y * this.y)\n  }\n\n  /**\n   * Normalization sets the vector to length 1 while maintaining its direction.\n   *\n   * @returns The normalized vector.\n   */\n  normalize() {\n    const length = this.length()\n    if (length === 0) {\n      throw new Error('Cannot normalize vectors of length 0')\n    }\n    return new Vector2(this.x / length, this.y / length)\n  }\n\n  /**\n   * Vector addition\n   *\n   * @param vector The vector to be added.\n   * @returns The sum-vector.\n   */\n  add(vector) {\n    const x = this.x + vector.x\n    const y = this.y + vector.y\n    return new Vector2(x, y)\n  }\n\n  /**\n   * Vector subtraction\n   *\n   * @param vector The vector to be subtracted.\n   * @returns The difference-vector.\n   */\n  subtract(vector) {\n    const x = this.x - vector.x\n    const y = this.y - vector.y\n    return new Vector2(x, y)\n  }\n\n  /**\n   * Vector scalar multiplication\n   *\n   * @param scalar The factor by which to multiply the vector.\n   * @returns The scaled vector.\n   */\n  multiply(scalar) {\n    const x = this.x * scalar\n    const y = this.y * scalar\n    return new Vector2(x, y)\n  }\n\n  /**\n   * Distance between this vector and another vector.\n   *\n   * @param vector The vector to which to calculate the distance.\n   * @returns The distance.\n   */\n  distance(vector) {\n    const difference = vector.subtract(this)\n    return difference.length()\n  }\n\n  /**\n   * Vector dot product\n   *\n   * @param vector The vector used for the multiplication.\n   * @returns The resulting dot product.\n   */\n  dotProduct(vector) {\n    return this.x * vector.x + this.y * vector.y\n  }\n\n  /**\n   * Vector rotation (see https://en.wikipedia.org/wiki/Rotation_matrix)\n   *\n   * @param angleInRadians The angle in radians by which to rotate the vector.\n   * @returns The rotated vector.\n   */\n  rotate(angleInRadians) {\n    const ca = Math.cos(angleInRadians)\n    const sa = Math.sin(angleInRadians)\n    const x = ca * this.x - sa * this.y\n    const y = sa * this.x + ca * this.y\n    return new Vector2(x, y)\n  }\n\n  /**\n   * Measure angle between two vectors\n   *\n   * @param vector The 2nd vector for the measurement.\n   * @returns The angle in radians.\n   */\n  angleBetween(vector) {\n    return Math.atan2(vector.y, vector.x) - Math.atan2(this.y, this.x)\n  }\n}\n\nexport { Vector2 }\n"
  },
  {
    "path": "Data-Structures/Vectors/test/Vector2.test.js",
    "content": "import { Vector2 } from '../Vector2.js'\n\ndescribe('Vector2', () => {\n  describe('#equalsExactly', () => {\n    it('should compare equality correctly', () => {\n      expect(new Vector2(1, 0).equalsExactly(new Vector2(1, 0))).toBe(true)\n\n      expect(new Vector2(1.23, 4.56).equalsExactly(new Vector2(0, 0))).toBe(\n        false\n      )\n    })\n  })\n\n  describe('#equalsApproximately', () => {\n    it('should compare equality (approximately) correctly', () => {\n      expect(\n        new Vector2(1, 0).equalsApproximately(\n          new Vector2(1, 0.0000001),\n          0.000001\n        )\n      ).toBe(true)\n\n      expect(\n        new Vector2(1.23, 4.56).equalsApproximately(\n          new Vector2(1.24, 4.56),\n          0.000001\n        )\n      ).toBe(false)\n    })\n  })\n\n  describe('#add', () => {\n    it('should add two vectors correctly', () => {\n      expect(\n        new Vector2(1, 0)\n          .add(new Vector2(0, 1))\n          .equalsApproximately(new Vector2(1, 1), 0.000001)\n      ).toBe(true)\n\n      expect(\n        new Vector2(-3.3, -9)\n          .add(new Vector2(-2.2, 3))\n          .equalsApproximately(new Vector2(-5.5, -6), 0.000001)\n      ).toBe(true)\n    })\n  })\n\n  describe('#subtract', () => {\n    it('should subtract two vectors correctly', () => {\n      expect(\n        new Vector2(1, 0)\n          .subtract(new Vector2(0, 1))\n          .equalsApproximately(new Vector2(1, -1), 0.000001)\n      ).toBe(true)\n\n      expect(\n        new Vector2(234.5, 1.7)\n          .subtract(new Vector2(3.3, 2.7))\n          .equalsApproximately(new Vector2(231.2, -1), 0.000001)\n      ).toBe(true)\n    })\n  })\n\n  describe('#multiply', () => {\n    it('should multiply two vectors correctly', () => {\n      expect(\n        new Vector2(1, 0)\n          .multiply(5)\n          .equalsApproximately(new Vector2(5, 0), 0.000001)\n      ).toBe(true)\n\n      expect(\n        new Vector2(3.41, -7.12)\n          .multiply(-3.1)\n          .equalsApproximately(new Vector2(-10.571, 22.072), 0.000001)\n      ).toBe(true)\n    })\n  })\n\n  describe('#length', () => {\n    it(\"should calculate it's length correctly\", () => {\n      expect(new Vector2(1, 0).length()).toBe(1)\n\n      expect(new Vector2(-1, 1).length()).toBe(Math.sqrt(2))\n    })\n  })\n\n  describe('#normalize', () => {\n    it('should normalize vectors correctly', () => {\n      expect(\n        new Vector2(1, 0)\n          .normalize()\n          .equalsApproximately(new Vector2(1, 0), 0.000001)\n      ).toBe(true)\n\n      expect(\n        new Vector2(1, -1)\n          .normalize()\n          .equalsApproximately(\n            new Vector2(Math.sqrt(2) / 2, -Math.sqrt(2) / 2),\n            0.000001\n          )\n      ).toBe(true)\n    })\n  })\n\n  describe('#distance', () => {\n    it('should calculate the distance between two vectors correctly', () => {\n      expect(new Vector2(0, 0).distance(new Vector2(0, -1))).toBe(1)\n\n      expect(new Vector2(1, 0).distance(new Vector2(0, 1))).toBe(Math.sqrt(2))\n    })\n  })\n\n  describe('#dotProduct', () => {\n    it('should calculate the dot product correctly', () => {\n      expect(new Vector2(1, 0).dotProduct(new Vector2(0, 1))).toBe(0)\n\n      expect(new Vector2(1, 2).dotProduct(new Vector2(3, 4))).toBe(11) // 1 * 3 + 2 * 4\n    })\n  })\n\n  describe('#rotate', () => {\n    it('should rotate a vector correctly', () => {\n      expect(\n        new Vector2(0, -1)\n          .rotate(Math.PI / 2)\n          .equalsApproximately(new Vector2(1, 0), 0.000001)\n      ).toBe(true)\n\n      expect(\n        new Vector2(1.23, -4.56)\n          .rotate(Math.PI)\n          .equalsApproximately(new Vector2(-1.23, 4.56), 0.000001)\n      ).toBe(true)\n    })\n  })\n\n  describe('#angleBetween', () => {\n    it('should calculate the angle between two vectors correctly', () => {\n      expect(new Vector2(1, 0).angleBetween(new Vector2(0, 1))).toBe(\n        Math.PI / 2\n      )\n\n      expect(new Vector2(1, 0).angleBetween(new Vector2(1, -1))).toBe(\n        -Math.PI / 4\n      )\n    })\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/Abbreviation.js",
    "content": "/**\n * @description\n * Given two strings, `source` and `target`, determine if it's possible to make `source` equal\n * to `target` You can perform the following operations on the string `source`:\n * 1. Capitalize zero or more of `source`'s lowercase letters.\n * 2. Delete all the remaining lowercase letters in `source`.\n *\n * Time Complexity: (O(|source|*|target|)) where `|source|` => length of string `source`\n *\n * @param {String} source - The string to be transformed.\n * @param {String} target - The string we want to transform `source` into.\n * @returns {Boolean} - Whether the transformation is possible.\n * @see https://www.hackerrank.com/challenges/abbr/problem - Related problem on HackerRank.\n */\nexport const isAbbreviation = (source, target) => {\n  const sourceLength = source.length\n  const targetLength = target.length\n\n  // Initialize a table to keep track of possible abbreviations\n  let canAbbreviate = Array.from({ length: sourceLength + 1 }, () =>\n    Array(targetLength + 1).fill(false)\n  )\n  // Empty strings are trivially abbreviatable\n  canAbbreviate[0][0] = true\n\n  for (let sourceIndex = 0; sourceIndex < sourceLength; sourceIndex++) {\n    for (let targetIndex = 0; targetIndex <= targetLength; targetIndex++) {\n      if (canAbbreviate[sourceIndex][targetIndex]) {\n        // If characters at the current position are equal, move to the next position in both strings.\n        if (\n          targetIndex < targetLength &&\n          source[sourceIndex].toUpperCase() === target[targetIndex]\n        ) {\n          canAbbreviate[sourceIndex + 1][targetIndex + 1] = true\n        }\n        // If the current character in `source` is lowercase, explore two possibilities:\n        // a) Capitalize it (which is akin to \"using\" it in `source` to match `target`), or\n        // b) Skip it (effectively deleting it from `source`).\n        if (source[sourceIndex] === source[sourceIndex].toLowerCase()) {\n          canAbbreviate[sourceIndex + 1][targetIndex] = true\n        }\n      }\n    }\n  }\n\n  return canAbbreviate[sourceLength][targetLength]\n}\n"
  },
  {
    "path": "Dynamic-Programming/CatalanNumbers.js",
    "content": "/*\n * Author: IcarusTheFly (https://github.com/IcarusTheFly)\n * Catalan Numbers explanation can be found in the following links:\n * Wikipedia: https://en.wikipedia.org/wiki/Catalan_number\n * Brilliant: https://brilliant.org/wiki/catalan-numbers\n */\n\n/**\n * @function catalanNumbers\n * @description Returns all catalan numbers from index 0 to n\n * @param {number} n\n * @returns {number[]} Array with the catalan numbers from 0 to n\n */\n\nexport const catalanNumbers = (n) => {\n  if (n === 0) {\n    return [1]\n  }\n  const catList = [1, 1]\n\n  for (let i = 2; i <= n; i++) {\n    let newNumber = 0\n    for (let j = 0; j < i; j++) {\n      newNumber += catList[j] * catList[i - j - 1]\n    }\n    catList.push(newNumber)\n  }\n\n  return catList\n}\n"
  },
  {
    "path": "Dynamic-Programming/ClimbingStairs.js",
    "content": "/**\n * @function ClimbStairs\n * @description You are climbing a stair case. It takes n steps to reach to the top.Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?\n * @param {Integer} n - The input integer\n * @return {Integer} distinct ways can you climb to the top.\n * @see [Climb_Stairs](https://www.geeksforgeeks.org/count-ways-reach-nth-stair/)\n */\n\nconst climbStairs = (n) => {\n  let prev = 0\n  let cur = 1\n  let temp\n\n  for (let i = 0; i < n; i++) {\n    temp = prev\n    prev = cur\n    cur += temp\n  }\n  return cur\n}\n\nexport { climbStairs }\n"
  },
  {
    "path": "Dynamic-Programming/CoinChange.js",
    "content": "/**\n * @params {Array} coins\n * @params {Number} amount\n */\nexport const change = (coins, amount) => {\n  // Create and initialize the storage\n  const combinations = new Array(amount + 1).fill(0)\n  combinations[0] = 1\n  // Determine the direction of smallest sub-problem\n  for (let i = 0; i < coins.length; i++) {\n    // Travel and fill the combinations array\n    for (let j = coins[i]; j < combinations.length; j++) {\n      combinations[j] += combinations[j - coins[i]]\n    }\n  }\n  return combinations[amount]\n}\n/**\n * @params {Array} coins\n * @params {Number} amount\n */\nexport const coinChangeMin = (coins, amount) => {\n  const map = { 0: 1 }\n  for (let i = 1; i <= amount; i++) {\n    let min = Infinity\n    for (const coin of coins) {\n      if (i < coin) continue\n      min = Math.min(min, 1 + map[i - coin])\n    }\n    map[i] = min\n  }\n  return map[amount] === Infinity ? -1 : map[amount] - 1\n}\n"
  },
  {
    "path": "Dynamic-Programming/EditDistance.js",
    "content": "/*\nWikipedia -> https://en.wikipedia.org/wiki/Edit_distance\n\nQ. -> Given two strings `word1` and `word2`. You can perform these operations on any of the string to make both strings similar.\n    - Insert\n    - Remove\n    - Replace\nFind the minimum operation cost required to make both same. Each operation cost is 1.\n\nAlgorithm details ->\ntime complexity - O(n*m)\nspace complexity - O(n*m)\n*/\n\nconst minimumEditDistance = (word1, word2) => {\n  const n = word1.length\n  const m = word2.length\n  const dp = new Array(m + 1).fill(0).map((item) => [])\n\n  /*\n    fill dp matrix with default values -\n        - first row is filled considering no elements in word2.\n        - first column filled considering no elements in word1.\n    */\n\n  for (let i = 0; i < n + 1; i++) {\n    dp[0][i] = i\n  }\n\n  for (let i = 0; i < m + 1; i++) {\n    dp[i][0] = i\n  }\n\n  /*\n        indexing is 1 based for dp matrix as we defined some known values at first row and first column/\n    */\n\n  for (let i = 1; i < m + 1; i++) {\n    for (let j = 1; j < n + 1; j++) {\n      const letter1 = word1[j - 1]\n      const letter2 = word2[i - 1]\n\n      if (letter1 === letter2) {\n        dp[i][j] = dp[i - 1][j - 1]\n      } else {\n        dp[i][j] = Math.min(dp[i - 1][j], dp[i - 1][j - 1], dp[i][j - 1]) + 1\n      }\n    }\n  }\n\n  return dp[m][n]\n}\n\nexport { minimumEditDistance }\n"
  },
  {
    "path": "Dynamic-Programming/FastFibonacciNumber.js",
    "content": "/**\n * @function fastFibonacci\n * @description fastFibonacci is same as fibonacci algorithm by calculating the sum of previous two fibonacci numbers but in O(log(n)).\n * @param {Integer} N - The input integer\n * @return {Integer} fibonacci of N.\n * @see [Fast_Fibonacci_Numbers](https://www.geeksforgeeks.org/fast-doubling-method-to-find-the-nth-fibonacci-number/)\n */\n\n// recursive function that returns (F(n), F(n-1))\nconst fib = (N) => {\n  if (N === 0) return [0, 1]\n  const [a, b] = fib(Math.trunc(N / 2))\n  const c = a * (b * 2 - a)\n  const d = a * a + b * b\n  return N % 2 ? [d, c + d] : [c, d]\n}\n\nconst fastFibonacci = (N) => {\n  if (!Number.isInteger(N)) {\n    throw new TypeError('Input should be integer')\n  }\n  return fib(N)[0]\n}\n\nexport { fastFibonacci }\n"
  },
  {
    "path": "Dynamic-Programming/FibonacciNumber.js",
    "content": "/**\n * @function fibonacci\n * @description Fibonacci is the sum of previous two fibonacci numbers.\n * @param {Integer} N - The input integer\n * @return {Integer} fibonacci of N.\n * @see [Fibonacci_Numbers](https://en.wikipedia.org/wiki/Fibonacci_number)\n */\nconst fibonacci = (N) => {\n  if (!Number.isInteger(N)) {\n    throw new TypeError('Input should be integer')\n  }\n\n  // memoize the last two numbers\n  let firstNumber = 0\n  let secondNumber = 1\n\n  for (let i = 1; i < N; i++) {\n    const sumOfNumbers = firstNumber + secondNumber\n    // update last two numbers\n    firstNumber = secondNumber\n    secondNumber = sumOfNumbers\n  }\n\n  return N ? secondNumber : firstNumber\n}\n\nexport { fibonacci }\n"
  },
  {
    "path": "Dynamic-Programming/FindMonthCalendar.js",
    "content": "/*\n *  This algorithm accepts a month in the format mm/yyyy.\n *  And prints out the month's calendar.\n *  It uses an epoch of 1/1/1900, Monday.\n */\nimport { isLeapYear } from '../Maths/LeapYear'\n\nclass Month {\n  constructor() {\n    this.Days = ['M', 'T', 'W', 'Th', 'F', 'S', 'Su']\n    this.BDays = ['M', 'Su', 'S', 'F', 'Th', 'W', 'T']\n    this.epoch = { month: 1, year: 1900 }\n    this.monthDays = [31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]\n    this.monthDaysLeap = [31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]\n  }\n\n  printCal(days, startDay, output = (value) => console.log(value)) {\n    output('M   T   W   Th  F   S   Su')\n    const dates = []\n    let i\n    for (i = 1; i <= days; i++) {\n      dates.push(i)\n    }\n    for (i = 0; i < this.Days.indexOf(startDay); i++) {\n      dates.unshift(' ')\n    }\n    while (true) {\n      let row = ''\n      for (i = 0; i < 7 && dates.length !== 0; i++) {\n        row += dates.shift()\n        while (row.length % 4 !== 0) {\n          row += ' '\n        }\n      }\n      output(row)\n      if (dates.length === 0) break\n    }\n  }\n\n  parseDate(date) {\n    const dateAr = []\n    let block = ''\n    let i\n    for (i = 0; i < date.length; i++) {\n      if (date[i] === '/') {\n        dateAr.push(parseInt(block))\n        block = ''\n        continue\n      }\n      block += date[i]\n    }\n    dateAr.push(parseInt(block))\n    if (dateAr.length !== 2) throw new Error('Improper string encoding')\n    const dateOb = { month: dateAr[0], year: dateAr[1] }\n    return dateOb\n  }\n\n  isGreater(startDate, endDate) {\n    if (startDate.year > endDate.year) {\n      return true\n    } else if (startDate.year < endDate.year) {\n      return false\n    } else if (startDate.month > endDate.month) {\n      return true\n    } else if (startDate.month < endDate.month) {\n      return false\n    }\n    return true\n  }\n\n  getDayDiff(startDate, endDate) {\n    if (this.isGreater(startDate, endDate) === null) {\n      return 0\n    } else if (this.isGreater(startDate, endDate) === true) {\n      const midDate = startDate\n      startDate = endDate\n      endDate = midDate\n    }\n    let diff = 0\n    while (startDate.year !== endDate.year) {\n      diff += isLeapYear(startDate.year) ? 366 : 365\n      startDate.year = startDate.year + 1\n    }\n    while (startDate.month !== endDate.month) {\n      if (startDate.month < endDate.month) {\n        if (isLeapYear(startDate.year))\n          diff += this.monthDaysLeap[startDate.month]\n        else diff += this.monthDays[startDate.month]\n        startDate.month = startDate.month + 1\n      } else {\n        if (isLeapYear(startDate.year))\n          diff -= this.monthDaysLeap[startDate.month - 1]\n        else diff -= this.monthDays[startDate.month - 1]\n        startDate.month = startDate.month - 1\n      }\n    }\n    return diff\n  }\n\n  generateMonthCal(date) {\n    const Month = this.parseDate(date)\n    let day = ''\n    let difference = this.getDayDiff(this.epoch, Month)\n    difference = difference % 7\n    let Month2 = this.parseDate(date)\n    day = this.isGreater(Month2, this.epoch)\n      ? this.Days[difference]\n      : this.BDays[difference]\n    Month2 = this.parseDate(date)\n    if (isLeapYear(Month2.year))\n      this.printCal(this.monthDaysLeap[Month2.month], day)\n    else this.printCal(this.monthDays[Month2.month], day)\n  }\n}\n\nexport { Month }\n\n// const x = new Month()\n// x.generateMonthCal('1/2021')\n"
  },
  {
    "path": "Dynamic-Programming/KadaneAlgo.js",
    "content": "/* Kadane's algorithm is one of the most efficient ways to\n * calculate the maximum contiguous subarray sum for a given array.\n * Below is the implementation of Kadane's algorithm along with\n * some sample test cases.\n * There might be a special case in this problem if al the elements\n * of the given array are negative. In such a case, the maximum negative\n * value present in the array is the answer.\n *\n * Reference article :- https://www.geeksforgeeks.org/largest-sum-contiguous-subarray/\n */\n\nexport function kadaneAlgo(array) {\n  let cumulativeSum = 0\n  let maxSum = Number.NEGATIVE_INFINITY // maxSum has the least possible value\n  for (let i = 0; i < array.length; i++) {\n    cumulativeSum = cumulativeSum + array[i]\n    if (maxSum < cumulativeSum) {\n      maxSum = cumulativeSum\n    } else if (cumulativeSum < 0) {\n      cumulativeSum = 0\n    }\n  }\n  return maxSum\n  // This function returns largest sum contiguous sum in a array\n}\n"
  },
  {
    "path": "Dynamic-Programming/LevenshteinDistance.js",
    "content": "/**\n * @function calculateLevenshteinDp\n * @description A Dynamic Programming based solution for calculation of the Levenshtein Distance.\n * @param {String} x - Word to be converted.\n * @param {String} y - Desired result after operations.\n * @return {Integer} The Levenshtein distance between x and y.\n * @see [Levenshtein_distance](https://en.wikipedia.org/wiki/Levenshtein_distance)\n */\n\nfunction minimum(a, b, c) {\n  if (a < b && a < c) {\n    return a\n  } else if (b < a && b < c) {\n    return b\n  } else {\n    return c\n  }\n}\n\nfunction costOfSubstitution(x, y) {\n  return x === y ? 0 : 1\n}\n\n// Levenshtein distance between x and y\nfunction calculateLevenshteinDp(x, y) {\n  const dp = new Array(x.length + 1)\n  for (let i = 0; i < x.length + 1; i++) {\n    dp[i] = new Array(y.length + 1)\n  }\n\n  for (let i = 0; i < x.length + 1; i++) {\n    for (let j = 0; j < y.length + 1; j++) {\n      if (i === 0) {\n        dp[i][j] = j\n      } else if (j === 0) {\n        dp[i][j] = i\n      } else {\n        dp[i][j] = minimum(\n          dp[i - 1][j - 1] +\n            costOfSubstitution(x.charAt(i - 1), y.charAt(j - 1)),\n          dp[i - 1][j] + 1,\n          dp[i][j - 1] + 1\n        )\n      }\n    }\n  }\n\n  return dp[x.length][y.length]\n}\n\nexport { calculateLevenshteinDp }\n"
  },
  {
    "path": "Dynamic-Programming/LongestCommonSubsequence.js",
    "content": "/*\nProblem:\nGiven two sequences, find the length of longest subsequence present in both of them.\nA subsequence is a sequence that appears in the same relative order, but not necessarily contiguous.\nFor example, “abc”, “abg”, “bdf”, “aeg”, ‘”acefg”, .. etc are subsequences of “abcdefg”\n\nOur Solution:\nWe use recursion with tabular memoization.\nTime complexity: O(M x N)\nSolving each subproblem has a cost of O(1). Again, there are MxN subproblems,\nand so we get a total time complexity of O(MxN).\nSpace complexity: O(M x N)\nWe need to store the answer for each of the MxN subproblems.\n\nImprovement:\nIt's possible to optimize space complexity to O(min(M, N)) or time to O((N + r)log(N))\nwhere r is the number of matches between the two sequences. Try to figure out how.\n\nReferences:\n[wikipedia](https://en.wikipedia.org/wiki/Longest_common_subsequence_problem)\n[leetcode](https://leetcode.com/problems/longest-common-subsequence/)\n*/\n\n/**\n * Finds length of the longest common subsequence among the two input string\n * @param {string} str1 Input string #1\n * @param {string} str2 Input string #2\n * @returns {number} Length of the longest common subsequence\n */\nfunction longestCommonSubsequence(str1, str2) {\n  const memo = new Array(str1.length + 1)\n    .fill(null)\n    .map(() => new Array(str2.length + 1).fill(null))\n\n  function recursive(end1, end2) {\n    if (end1 === -1 || end2 === -1) {\n      return 0\n    }\n\n    if (memo[end1][end2] !== null) {\n      return memo[end1][end2]\n    }\n\n    if (str1[end1] === str2[end2]) {\n      memo[end1][end2] = 1 + recursive(end1 - 1, end2 - 1)\n      return memo[end1][end2]\n    } else {\n      memo[end1][end2] = Math.max(\n        recursive(end1 - 1, end2),\n        recursive(end1, end2 - 1)\n      )\n      return memo[end1][end2]\n    }\n  }\n\n  return recursive(str1.length - 1, str2.length - 1)\n}\n\nexport { longestCommonSubsequence }\n"
  },
  {
    "path": "Dynamic-Programming/LongestIncreasingSubsequence.js",
    "content": "/**\n * A Dynamic Programming based solution for calculating Longest Increasing Subsequence\n * https://en.wikipedia.org/wiki/Longest_increasing_subsequence\n */\n\n// Return the length of the Longest Increasing Subsequence, given array x\nfunction longestIncreasingSubsequence(x) {\n  const length = x.length\n  if (length == 0) {\n    return 0\n  }\n  const dp = Array(length).fill(1)\n\n  let res = 1\n\n  for (let i = 0; i < length; i++) {\n    for (let j = 0; j < i; j++) {\n      if (x[i] > x[j]) {\n        dp[i] = Math.max(dp[i], 1 + dp[j])\n        if (dp[i] > res) {\n          res = dp[i]\n        }\n      }\n    }\n  }\n\n  return res\n}\n\nexport { longestIncreasingSubsequence }\n"
  },
  {
    "path": "Dynamic-Programming/LongestPalindromicSubsequence.js",
    "content": "/*\n  LeetCode -> https://leetcode.com/problems/longest-palindromic-subsequence/\n\n  Given a string s, find the longest palindromic subsequence's length in s.\n  You may assume that the maximum length of s is 1000.\n\n*/\n\nexport const longestPalindromeSubsequence = function (s) {\n  const n = s.length\n\n  const dp = new Array(n)\n    .fill(0)\n    .map((item) => new Array(n).fill(0).map((item) => 0))\n\n  // fill predefined for single character\n  for (let i = 0; i < n; i++) {\n    dp[i][i] = 1\n  }\n\n  for (let i = 1; i < n; i++) {\n    for (let j = 0; j < n - i; j++) {\n      const col = j + i\n      if (s[j] === s[col]) {\n        dp[j][col] = 2 + dp[j + 1][col - 1]\n      } else {\n        dp[j][col] = Math.max(dp[j][col - 1], dp[j + 1][col])\n      }\n    }\n  }\n\n  return dp[0][n - 1]\n}\n"
  },
  {
    "path": "Dynamic-Programming/LongestValidParentheses.js",
    "content": "/*\n  LeetCode -> https://leetcode.com/problems/longest-valid-parentheses/\n\n  Given a string containing just the characters '(' and ')',\n  find the length of the longest valid (well-formed) parentheses substring.\n*/\n\nexport const longestValidParentheses = (s) => {\n  const n = s.length\n  const stack = []\n\n  // storing results\n  const res = new Array(n).fill(-Infinity)\n\n  for (let i = 0; i < n; i++) {\n    const bracket = s[i]\n\n    if (bracket === ')' && s[stack[stack.length - 1]] === '(') {\n      res[i] = 1\n      res[stack[stack.length - 1]] = 1\n      stack.pop()\n    } else {\n      stack.push(i)\n    }\n  }\n\n  // summing all adjacent valid\n  for (let i = 1; i < n; i++) {\n    res[i] = Math.max(res[i], res[i] + res[i - 1])\n  }\n\n  // adding 0 if there are none so it will return 0 instead of -Infinity\n  res.push(0)\n  return Math.max(...res)\n}\n"
  },
  {
    "path": "Dynamic-Programming/MaxNonAdjacentSum.js",
    "content": "function maximumNonAdjacentSum(nums) {\n  /*\n   * Find the maximum non-adjacent sum of the integers in the nums input list\n   * :param nums: Array of Numbers\n   * :return: The maximum non-adjacent sum\n   */\n\n  if (nums.length < 0) return 0\n\n  let maxIncluding = nums[0]\n  let maxExcluding = 0\n\n  for (const num of nums.slice(1)) {\n    const temp = maxIncluding\n    maxIncluding = maxExcluding + num\n    maxExcluding = Math.max(temp, maxExcluding)\n  }\n\n  return Math.max(maxExcluding, maxIncluding)\n}\n\n// Example\n\n// maximumNonAdjacentSum([1, 2, 3]))\n// maximumNonAdjacentSum([1, 5, 3, 7, 2, 2, 6]))\n// maximumNonAdjacentSum([-1, -5, -3, -7, -2, -2, -6]))\n// maximumNonAdjacentSum([499, 500, -3, -7, -2, -2, -6]))\n\nexport { maximumNonAdjacentSum }\n"
  },
  {
    "path": "Dynamic-Programming/MaxProductOfThree.js",
    "content": "/**\n *  Given an array of numbers, return the maximum product\n *  of 3 numbers from the array\n *  https://wsvincent.com/javascript-three-sum-highest-product-of-three-numbers/\n * @param {number[]} arrayItems\n * @returns number\n */\nexport function maxProductOfThree(arrayItems) {\n  // if size is less than 3, no triplet exists\n  const n = arrayItems.length\n  if (n < 3) throw new Error('Triplet cannot exist with the given array')\n  let max1 = arrayItems[0]\n  let max2 = null\n  let max3 = null\n  let min1 = arrayItems[0]\n  let min2 = null\n  for (let i = 1; i < n; i++) {\n    if (arrayItems[i] > max1) {\n      max3 = max2\n      max2 = max1\n      max1 = arrayItems[i]\n    } else if (max2 === null || arrayItems[i] > max2) {\n      max3 = max2\n      max2 = arrayItems[i]\n    } else if (max3 === null || arrayItems[i] > max3) {\n      max3 = arrayItems[i]\n    }\n    if (arrayItems[i] < min1) {\n      min2 = min1\n      min1 = arrayItems[i]\n    } else if (min2 === null || arrayItems[i] < min2) {\n      min2 = arrayItems[i]\n    }\n  }\n  const prod1 = max1 * max2 * max3\n  const prod2 = max1 * min1 * min2\n  return Math.max(prod1, prod2)\n}\n"
  },
  {
    "path": "Dynamic-Programming/MinimumCostPath.js",
    "content": "// Problem Statement => https://www.youtube.com/watch?v=lBRtnuxg-gU\n\nconst minCostPath = (matrix) => {\n  /*\n        Find the min cost path from top-left to bottom-right in matrix\n        >>> minCostPath([[2, 1], [3, 1], [4, 2]])\n        >>> 6\n    */\n\n  const n = matrix.length\n  const m = matrix[0].length\n\n  // moves[i][j] => minimum number of moves to reach cell i, j\n  const moves = new Array(n)\n  for (let i = 0; i < moves.length; i++) moves[i] = new Array(m)\n\n  // base conditions\n  moves[0][0] = matrix[0][0] // to reach cell (0, 0) from (0, 0) is of no moves\n  for (let i = 1; i < m; i++) moves[0][i] = moves[0][i - 1] + matrix[0][i]\n  for (let i = 1; i < n; i++) moves[i][0] = moves[i - 1][0] + matrix[i][0]\n\n  for (let i = 1; i < n; i++) {\n    for (let j = 1; j < m; j++) {\n      moves[i][j] = Math.min(moves[i - 1][j], moves[i][j - 1]) + matrix[i][j]\n    }\n  }\n\n  return moves[n - 1][m - 1]\n}\n\nexport { minCostPath }\n\n// Example\n\n// minCostPath([\n//   [2, 1],\n//   [3, 1],\n//   [4, 2]\n// ])\n\n// minCostPath([\n//   [2, 1, 4],\n//   [2, 1, 3],\n//   [3, 2, 1]\n// ])\n"
  },
  {
    "path": "Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js",
    "content": "/*\nGiven an array of positive integers and a value sum,\ndetermine the total number of the subset with sum\nequal to the given sum.\n*/\n/*\n  Given solution is O(n*sum) Time complexity and O(sum) Space complexity\n*/\nfunction NumberOfSubsetSum(array, sum) {\n  if (sum < 0) {\n    throw new Error('The sum must be non-negative.')\n  }\n\n  if (!array.every((num) => num > 0)) {\n    throw new Error('All of the inputs of the array must be positive.')\n  }\n  const dp = [] // create an dp array where dp[i] denote number of subset with sum equal to i\n  for (let i = 1; i <= sum; i++) {\n    dp[i] = 0\n  }\n  dp[0] = 1 // since sum equal to 0 is always possible with no element in subset\n\n  for (let i = 0; i < array.length; i++) {\n    for (let j = sum; j >= array[i]; j--) {\n      if (j - array[i] >= 0) {\n        dp[j] += dp[j - array[i]]\n      }\n    }\n  }\n  return dp[sum]\n}\n\nexport { NumberOfSubsetSum }\n"
  },
  {
    "path": "Dynamic-Programming/RodCutting.js",
    "content": "/*\n * You are given a rod of 'n' length and an array of prices associated with all the lengths less than 'n'.\n * Find the maximum profit possible by cutting the rod and selling the pieces.\n */\n\nexport function rodCut(prices, n) {\n  const memo = new Array(n + 1)\n  memo[0] = 0\n\n  for (let i = 1; i <= n; i++) {\n    let maxVal = Number.MIN_VALUE\n    for (let j = 0; j < i; j++) {\n      maxVal = Math.max(maxVal, prices[j] + memo[i - j - 1])\n    }\n    memo[i] = maxVal\n  }\n\n  return memo[n]\n}\n"
  },
  {
    "path": "Dynamic-Programming/Shuf.js",
    "content": "/*\nGiven a data set of an unknown size,\nGet a random sample in a random order\nIt's used in data analytics, often as a way to get a small random sample from a data lake or warehouse, or from a large CSV file\n*/\nfunction shuf(datasetSource, sampleSize) {\n  const output = fillBaseSample(datasetSource, sampleSize)\n\n  return randomizeOutputFromDataset(datasetSource, output)\n}\n\n/**\n * Fills the output if possible, with the minimum number of values\n * @param {Iterable.<T>} datasetSource The iterable source of data\n * @param {number} sampleSize The size of the sample to extract from the dataset\n * @returns {Array.<T>} The random sample, as an array\n * @template T\n */\nfunction fillBaseSample(datasetSource, sampleSize) {\n  let filledIndexes = []\n  let output = new Array(sampleSize)\n\n  // Spread data out filling the array\n  while (true) {\n    const iterator = datasetSource.next()\n    if (iterator.done) break\n\n    let insertTo = Math.floor(Math.random() * output.length)\n    while (filledIndexes.includes(insertTo)) {\n      insertTo++\n      if (insertTo === output.length) {\n        insertTo = 0\n      }\n    }\n    output[insertTo] = {\n      value: iterator.value\n    }\n\n    filledIndexes = [...filledIndexes, insertTo]\n\n    if (filledIndexes.length === sampleSize) {\n      break\n    }\n  }\n\n  if (filledIndexes.length < output.length) {\n    // Not a large enough dataset to fill the sample - trim empty values\n    output = output.filter((_, i) => filledIndexes.includes(i))\n  }\n\n  return output.map((o) => o.value)\n}\n\n/**\n * Replaces values in the output randomly with new ones from the dataset\n * @param {Iterable.<T>} datasetSource The iterable source of data\n * @param {Array.<T>} output The output so far, filled with data\n * @returns {Array.<T>} The random sample, as an array\n * @template T\n */\nfunction randomizeOutputFromDataset(datasetSource, output) {\n  const newOutput = [...output]\n  let readSoFar = output.length\n\n  while (true) {\n    const iterator = datasetSource.next()\n    if (iterator.done) break\n    readSoFar++\n\n    const insertTo = Math.floor(Math.random() * readSoFar)\n    if (insertTo < newOutput.length) {\n      newOutput[insertTo] = iterator.value\n    }\n  }\n\n  return newOutput\n}\n\n// Example\n\n/**\n * Generates a random range of data, with values between 0 and 2^31 - 1\n * @param {number} length The number of data items to generate\n * @returns {Iterable<number>} Random iterable data\n */\nfunction* generateRandomData(length) {\n  const maxValue = Math.pow(2, 31) - 1\n  for (let i = 0; i < length; i++) {\n    yield Math.floor(Math.random() * maxValue)\n  }\n}\n\n// const source = generateRandomData(1000)\n// const result = shuf(source, 10)\n\nexport { shuf, generateRandomData }\n"
  },
  {
    "path": "Dynamic-Programming/SieveOfEratosthenes.js",
    "content": "/**\n * @function SieveOfEratosthenes\n * @description Calculates prime numbers till input number n\n * @param {Number} n - The input integer\n * @return {Number[]} List of Primes till n.\n * @see [Sieve_of_Eratosthenes](https://www.geeksforgeeks.org/sieve-of-eratosthenes/)\n */\nfunction sieveOfEratosthenes(n) {\n  if (n <= 1) return []\n  const primes = new Array(n + 1).fill(true) // set all as true initially\n  primes[0] = primes[1] = false // Handling case for 0 and 1\n  for (let i = 2; i * i <= n; i++) {\n    if (primes[i]) {\n      for (let j = i * i; j <= n; j += i) {\n        primes[j] = false\n      }\n    }\n  }\n\n  return primes.reduce((result, isPrime, index) => {\n    if (isPrime) {\n      result.push(index)\n    }\n    return result\n  }, [])\n}\n\n// Example\n\n// const n = 69 // number till where we wish to find primes\n// const primes = sieveOfEratosthenes(n)\n\nexport { sieveOfEratosthenes }\n"
  },
  {
    "path": "Dynamic-Programming/Sliding-Window/HouseRobber.js",
    "content": "/**\n * @function houseRobber\n * @description Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.\n * @param {number[]} nums\n * @return {number}\n * @see [Leetcode link](https://leetcode.com/problems/house-robber/)\n */\nexport const houseRobber = (nums) => {\n  const length = nums.length\n\n  if (length === 0) return 0\n  if (length === 1) return nums[0]\n  if (length === 2) return Math.max(nums[0], nums[1])\n\n  const dp = Array(length) // last element of this array always contains biggest loot possible\n  dp[0] = nums[0]\n  dp[1] = Math.max(nums[0], nums[1])\n\n  for (let i = 2; i < length; i++) {\n    dp[i] = Math.max(nums[i] + dp[i - 2], dp[i - 1])\n  }\n  return dp[length - 1]\n}\n"
  },
  {
    "path": "Dynamic-Programming/Sliding-Window/LongestSubstringWithoutRepeatingCharacters.js",
    "content": "/**\n *  @name The-Sliding-Window Algorithm is primarily used for the problems dealing with linear data structures like Arrays, Lists, Strings etc.\n *  These problems can easily be solved using Brute Force techniques which result in quadratic or exponential time complexity.\n *  Sliding window technique reduces the required time to linear O(n).\n *  @see [The-Sliding-Window](https://www.geeksforgeeks.org/window-sliding-technique/)\n */\n\n/**\n * @function LongestSubstringWithoutRepeatingCharacters\n * @description Get the length of the longest substring without repeating characters\n * @param {String} s - The input string\n */\nexport function LongestSubstringWithoutRepeatingCharacters(s) {\n  let maxLength = 0\n  let start = 0\n  let end = 0\n  const map = {}\n  while (end < s.length) {\n    if (map[s[end]] === undefined) {\n      map[s[end]] = 1\n      maxLength = Math.max(maxLength, end - start + 1)\n      end++\n    } else {\n      while (s[start] !== s[end]) {\n        delete map[s[start]]\n        start++\n      }\n      delete map[s[start]]\n      start++\n    }\n  }\n  return maxLength\n}\n\n// Example 1:\n// Input: s = \"abcabcbb\"\n// Output: 3\n// Explanation: The answer is \"abc\", with the length of 3.\n\n// Example 2:\n// Input: s = \"bbbbb\"\n// Output: 1\n// Explanation: The answer is \"b\", with the length of 1.\n\n// Example 3:\n// Input: s = \"pwwkew\"\n// Output: 3\n// Explanation: The answer is \"wke\", with the length of 3.\n// Notice that the answer must be a substring, \"pwke\" is a subsequence and not a substring.\n"
  },
  {
    "path": "Dynamic-Programming/Sliding-Window/MaxConsecutiveOnes.js",
    "content": "/**\n * @function maxConsecutiveOnes\n * @description Given a binary array nums, return the maximum number of consecutive 1's in the array.\n * @param {number[]} nums\n * @return {number}\n * @see [Leetcode link](https://leetcode.com/problems/max-consecutive-ones/)\n */\nexport const maxConsecutiveOnes = (nums) => {\n  if (!nums.length) return 0\n\n  let result = 0\n  let k = 0\n\n  for (\n    let slowPointer = 0, fastPointer = 0;\n    fastPointer < nums.length;\n    fastPointer++\n  ) {\n    if (nums[fastPointer] === 0) k--\n\n    while (k < 0) {\n      if (nums[slowPointer] === 0) {\n        k++\n      }\n      slowPointer++\n    }\n    result = Math.max(result, fastPointer - slowPointer + 1)\n  }\n  return result\n}\n"
  },
  {
    "path": "Dynamic-Programming/Sliding-Window/MaxConsecutiveOnesIII.js",
    "content": "/**\n * @function maxConsecutiveOnesIII\n * @description Given a binary array nums and an integer k, return the maximum number of consecutive 1's in the array if you can flip at most k 0's.\n * @param {number[]} nums\n * @param {number} k\n * @return {number}\n * @see [Leetcode link](https://leetcode.com/problems/max-consecutive-ones-iii/)\n */\nexport const maxConsecutiveOnesIII = (nums, k) => {\n  if (!nums.length) return 0\n\n  let result = 0\n\n  for (\n    let slowPointer = 0, fastPointer = 0;\n    fastPointer < nums.length;\n    fastPointer++\n  ) {\n    if (nums[fastPointer] === 0) {\n      k--\n    }\n\n    while (k < 0) {\n      if (slowPointer === 0) {\n        k++\n      }\n      slowPointer++\n    }\n    result = Math.max(result, fastPointer - slowPointer + 1)\n  }\n  return result\n}\n"
  },
  {
    "path": "Dynamic-Programming/Sliding-Window/PermutationinString.js",
    "content": "/**\n *  @name The-Sliding-Window Algorithm is primarily used for the problems dealing with linear data structures like Arrays, Lists, Strings etc.\n *  These problems can easily be solved using Brute Force techniques which result in quadratic or exponential time complexity.\n *  Sliding window technique reduces the required time to linear O(n).\n *  @see [The-Sliding-Window](https://www.geeksforgeeks.org/window-sliding-technique/)\n */\n/**\n * @function PermutationinString\n * @description Given two strings s1 and s2, return true if s2 contains a permutation of s1, or false otherwise.\n * @param {String} s1 - The input string\n * @param {String} s2 - The input string\n * @return {boolean} - Returns true if s2 contains a permutation of s1, or false otherwise.\n */\n\nexport function PermutationinString(s1, s2) {\n  if (s1.length > s2.length) return false\n  let start = 0\n  let end = s1.length - 1\n  const s1Set = SetHash()\n  const s2Set = SetHash()\n  for (let i = 0; i < s1.length; i++) {\n    s1Set[s1[i]]++\n    s2Set[s2[i]]++\n  }\n  if (equals(s1Set, s2Set)) return true\n  while (end < s2.length - 1) {\n    if (equals(s1Set, s2Set)) return true\n    end++\n    const c1 = s2[start]\n    const c2 = s2[end]\n    if (s2Set[c1] > 0) s2Set[c1]--\n    s2Set[c2]++\n    start++\n    if (equals(s1Set, s2Set)) return true\n  }\n  return false\n}\nfunction equals(a, b) {\n  return JSON.stringify(a) === JSON.stringify(b)\n}\n\nfunction SetHash() {\n  const set = new Set()\n  const alphabets = 'abcdefghijklmnopqrstuvwxyz'\n  for (let i = 0; i < alphabets.length; i++) {\n    set[alphabets[i]] = 0\n  }\n  return set\n}\n\n// Example 1:\n// Input: s1 = \"ab\", s2 = \"eidbaooo\"\n// Output: true\n// Explanation: s2 contains one permutation of s1 (\"ba\").\n\n// Example 2:\n// Input: s1 = \"ab\", s2 = \"eidboaoo\"\n// Output: false\n"
  },
  {
    "path": "Dynamic-Programming/Sliding-Window/test/HouseRobber.test.js",
    "content": "import { houseRobber } from '../HouseRobber'\n\ndescribe('houseRobber', () => {\n  it('expects to return 0 when argument is empty array', () => {\n    expect(houseRobber([])).toBe(0)\n  })\n\n  it('expects to return element at index 0 when argument is array of length one', () => {\n    expect(houseRobber([9])).toBe(9)\n  })\n\n  it('expects to return greater number when argument is an array of length two', () => {\n    expect(houseRobber([3, 6])).toBe(6)\n  })\n\n  it('expects to return the maximum loot possible', () => {\n    expect(houseRobber([1, 2, 3, 1])).toBe(4)\n    expect(houseRobber([2, 7, 9, 3, 1])).toBe(12)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/Sliding-Window/test/LongestSubstringWithoutRepeatingCharacters.test.js",
    "content": "import { LongestSubstringWithoutRepeatingCharacters } from '../LongestSubstringWithoutRepeatingCharacters.js'\n\ndescribe('LongestSubstringWithoutRepeatingCharacters', () => {\n  it('should return longest substring without repeating characters', () => {\n    expect(LongestSubstringWithoutRepeatingCharacters('abcabcbb')).toEqual(3)\n    expect(LongestSubstringWithoutRepeatingCharacters('bbbbb')).toEqual(1)\n    expect(LongestSubstringWithoutRepeatingCharacters('pwwkew')).toEqual(3)\n    expect(LongestSubstringWithoutRepeatingCharacters('a')).toEqual(1)\n    expect(LongestSubstringWithoutRepeatingCharacters('')).toEqual(0)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/Sliding-Window/test/MaxConsecutiveOnes.test.js",
    "content": "import { maxConsecutiveOnes } from '../MaxConsecutiveOnes.js'\n\ndescribe('maxConsecutiveOnes', () => {\n  it('expects to return 0 when argument is empty array', () => {\n    expect(maxConsecutiveOnes([])).toBe(0)\n  })\n\n  it('expects to return 3', () => {\n    expect(maxConsecutiveOnes([1, 1, 0, 1, 1, 1])).toBe(3)\n  })\n\n  it('expects to return 2', () => {\n    expect(maxConsecutiveOnes([1, 0, 1, 1, 0, 1])).toBe(2)\n  })\n\n  it('expects to return 5', () => {\n    expect(maxConsecutiveOnes([0, 1, 1, 1, 1, 1, 0, 0, 1, 0])).toBe(5)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/Sliding-Window/test/MaxConsecutiveOnesIII.test.js",
    "content": "import { maxConsecutiveOnesIII } from '../MaxConsecutiveOnesIII'\n\ndescribe('maxConsecutiveOnesIIIIII', () => {\n  it('expects to return 0 when argument is empty array', () => {\n    expect(maxConsecutiveOnesIII([], 3)).toBe(0)\n  })\n\n  it('expects to return 6', () => {\n    expect(maxConsecutiveOnesIII([1, 1, 0, 1, 1, 1], 1)).toBe(6)\n  })\n\n  it('expects to return 8', () => {\n    expect(maxConsecutiveOnesIII([1, 0, 1, 1, 1, 1, 0, 1], 2)).toBe(8)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/Sliding-Window/test/PermutationinString.test.js",
    "content": "import { PermutationinString } from '../PermutationinString.js'\n\ndescribe('PermutationinString', () => {\n  it(\"should  return true if one of s1's permutations is the substring of s2\", () => {\n    expect(PermutationinString('ab', 'eidbaooo')).toEqual(true)\n    expect(PermutationinString('abc', 'bcab')).toEqual(true)\n    expect(PermutationinString('ab', 'eidboaoo')).toEqual(false)\n    expect(PermutationinString('abc', '')).toEqual(false)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/SudokuSolver.js",
    "content": "const isValid = (board, row, col, k) => {\n  for (let i = 0; i < 9; i++) {\n    const m = 3 * Math.floor(row / 3) + Math.floor(i / 3)\n    const n = 3 * Math.floor(col / 3) + (i % 3)\n    if (board[row][i] === k || board[i][col] === k || board[m][n] === k) {\n      return false\n    }\n  }\n  return true\n}\n\nconst sudokuSolver = (data) => {\n  for (let i = 0; i < 9; i++) {\n    for (let j = 0; j < 9; j++) {\n      if (data[i][j] === '.') {\n        for (let k = 1; k <= 9; k++) {\n          if (isValid(data, i, j, `${k}`)) {\n            data[i][j] = `${k}`\n            if (sudokuSolver(data)) {\n              return true\n            } else {\n              data[i][j] = '.'\n            }\n          }\n        }\n        return false\n      }\n    }\n  }\n  return true\n}\n\n// testing\n\n// const board = [\n//   ['.', '9', '.', '.', '4', '2', '1', '3', '6'],\n//   ['.', '.', '.', '9', '6', '.', '4', '8', '5'],\n//   ['.', '.', '.', '5', '8', '1', '.', '.', '.'],\n//   ['.', '.', '4', '.', '.', '.', '.', '.', '.'],\n//   ['5', '1', '7', '2', '.', '.', '9', '.', '.'],\n//   ['6', '.', '2', '.', '.', '.', '3', '7', '.'],\n//   ['1', '.', '.', '8', '.', '4', '.', '2', '.'],\n//   ['7', '.', '6', '.', '.', '.', '8', '1', '.'],\n//   ['3', '.', '.', '.', '9', '.', '.', '.', '.']\n// ]\n// sudokuSolver(board) // -> board updated by reference\n\nexport { sudokuSolver }\n"
  },
  {
    "path": "Dynamic-Programming/TrappingRainWater.js",
    "content": "/**\n * @param {number[]} height\n * @return {number}\n */\n\n/* 42. Trapping Rain Water\nhttps://leetcode.com/problems/trapping-rain-water/\n\nHelpful animation of this prompt: https://youtu.be/HmBbcDiJapY?t=51\n\nGiven n non-negative integers representing an elevation map where\nthe width of each bar is 1, compute how much water it is able to trap\nafter raining.\n\nVIEW ELEVATION MAP ON LEETCODE\n\nExample:\n\nInput:            [0,1,0,2,1,0,1,3,2,1,2,1]\nOutput: 6\n\nPlan:\niterate through and find left maxes\niterate through and find right maxes\ncreate minheight and assign it to the min(leftmax, rightmax)\nif current height(element) < minheight\n  push minheight - height into water array\nelse\n  push 0 onto water array\n\nsum up water array and return\n\nleft maxes =      [0,0,1,1,2,2,2,2,3,3,3,3]\nright maxes =     [3,3,3,3,3,3,3,2,2,2,1,0]\nwater contained = [0,0,1,0,1,2,1,0,0,1,0,0] -> sum = 6\n*/\n\nexport const trap = (heights) => {\n  const maxes = new Array(heights.length).fill(0)\n\n  let leftMax = 0\n  for (let i = 0; i < heights.length; i++) {\n    const height = heights[i]\n    maxes[i] = leftMax\n    leftMax = Math.max(leftMax, height)\n  }\n\n  let rightMax = 0\n  for (let i = heights.length - 1; i >= 0; i -= 1) {\n    const height = heights[i]\n    const minHeight = Math.min(rightMax, maxes[i])\n\n    if (height < minHeight) {\n      maxes[i] = minHeight - height\n    } else {\n      maxes[i] = 0\n    }\n    rightMax = Math.max(rightMax, height)\n  }\n  return maxes.reduce((a, b) => a + b, 0)\n}\n"
  },
  {
    "path": "Dynamic-Programming/TribonacciNumber.js",
    "content": "/**\n * @function Tribonacci\n * @description Tribonacci is the sum of previous three tribonacci numbers.\n * @param {Integer} n - The input integer\n * @return {Integer} tribonacci of n.\n * @see [Tribonacci_Numbers](https://www.geeksforgeeks.org/tribonacci-numbers/)\n */\nconst tribonacci = (n) => {\n  // creating array to store previous tribonacci numbers\n  const dp = new Array(n + 1)\n  dp[0] = 0\n  dp[1] = 1\n  dp[2] = 1\n  for (let i = 3; i <= n; i++) {\n    dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]\n  }\n  return dp[n]\n}\n\nexport { tribonacci }\n"
  },
  {
    "path": "Dynamic-Programming/UniquePaths.js",
    "content": "/*\n *\n *  Unique Paths\n *\n *  There is a robot on an `m x n` grid.\n *  The robot is initially located at the top-left corner.\n *  The robot tries to move to the bottom-right corner.\n *  The robot can only move either down or right at any point in time.\n *\n *  Given the two integers `m` and `n`,\n *  return the number of possible unique paths that the robot can take to reach the bottom-right corner.\n *  More info: https://leetcode.com/problems/unique-paths/\n */\n\n/*\n * @param {number} m\n * @param {number} n\n * @return {number}\n */\n\nconst uniquePaths = (m, n) => {\n  // only one way to reach end\n  if (m === 1 || n === 1) return 1\n\n  // build a linear grid of size m\n  // base case, position 1 has only 1 move\n  const paths = new Array(m).fill(1)\n\n  for (let i = 1; i < n; i++) {\n    for (let j = 1; j < m; j++) {\n      // paths[j] in RHS represents the cell value stored above the current cell\n      // paths[j-1] in RHS represents the cell value stored to the left of the current cell\n      // paths [j] on the LHS represents the number of distinct pathways to the cell (i, j)\n      paths[j] = paths[j - 1] + paths[j]\n    }\n  }\n  return paths[m - 1]\n}\n\nexport { uniquePaths }\n"
  },
  {
    "path": "Dynamic-Programming/UniquePaths2.js",
    "content": "/*\n * Unique Paths 2\n *\n * There is a robot on an `m x n` grid.\n * The robot is initially located at the top-left corner\n * The robot tries to move to the bottom-right corner.\n * The robot can only move either down or right at any point in time.\n *\n * Given grid with obstacles\n * An obstacle and space are marked as 1 or 0 respectively in grid.\n * A path that the robot takes cannot include any square that is an obstacle.\n * Return the number of possible unique paths that the robot can take to reach the bottom-right corner.\n *\n * More info: https://leetcode.com/problems/unique-paths-ii/\n */\n\n/**\n * @description Return 'rows x columns' grid with cells filled by 'filler'\n * @param {Number} rows Number of rows in the grid\n * @param {Number} columns Number of columns in the grid\n * @param {String | Number | Boolean} filler The value to fill cells\n * @returns {Array [][]}\n */\nconst generateMatrix = (rows, columns, filler = 0) => {\n  const matrix = []\n  for (let i = 0; i < rows; i++) {\n    const submatrix = []\n    for (let k = 0; k < columns; k++) {\n      submatrix[k] = filler\n    }\n    matrix[i] = submatrix\n  }\n  return matrix\n}\n\n/**\n * @description Return number of unique paths\n * @param {Array [][]} obstacles Obstacles grid\n * @returns {Number}\n */\nconst uniquePaths2 = (obstacles) => {\n  if (!Array.isArray(obstacles)) {\n    throw new Error('Input data must be type of Array')\n  }\n  // Create grid for calculating number of unique ways\n  const rows = obstacles.length\n  const columns = obstacles[0].length\n  const grid = generateMatrix(rows, columns)\n  // Fill the outermost cell with 1 b/c it has\n  // the only way to reach neighbor\n  for (let i = 0; i < rows; i++) {\n    // If robot encounters an obstacle in these cells,\n    // he cannot continue moving in that direction\n    if (obstacles[i][0]) {\n      break\n    }\n    grid[i][0] = 1\n  }\n  for (let j = 0; j < columns; j++) {\n    if (obstacles[0][j]) {\n      break\n    }\n    grid[0][j] = 1\n  }\n  // Fill the rest of grid by dynamic programming\n  // using following recurrent formula:\n  // K[i][j] = K[i - 1][j] + K[i][j - 1]\n  for (let i = 1; i < rows; i++) {\n    for (let j = 1; j < columns; j++) {\n      grid[i][j] = obstacles[i][j] ? 0 : grid[i - 1][j] + grid[i][j - 1]\n    }\n  }\n  return grid[rows - 1][columns - 1]\n}\n\nexport { uniquePaths2 }\n"
  },
  {
    "path": "Dynamic-Programming/ZeroOneKnapsack.js",
    "content": "/**\n * A Dynamic Programming based solution for calculating Zero One Knapsack\n * https://en.wikipedia.org/wiki/Knapsack_problem\n *\n * Time and Space Complexity: O(n*cap)\n */\nconst zeroOneKnapsack = (arr, n, cap, cache) => {\n  // Base Case: No capacity or no items\n  if (cap === 0 || n === 0) {\n    cache[n][cap] = 0\n    return cache[n][cap]\n  }\n\n  // Lookup (value already calculated)\n  if (cache[n][cap] !== -1) {\n    return cache[n][cap]\n  }\n\n  // Profit when excluding the nth item\n  let notPick = zeroOneKnapsack(arr, n - 1, cap, cache)\n\n  // Profit when including the nth item\n  let pick = 0\n  if (arr[n - 1][0] <= cap) {\n    // If weight of the nth item is within the capacity\n    pick =\n      arr[n - 1][1] + zeroOneKnapsack(arr, n - 1, cap - arr[n - 1][0], cache)\n  }\n\n  cache[n][cap] = Math.max(pick, notPick) // maximize profit\n  return cache[n][cap]\n}\n\nconst example = () => {\n  /*\n  Problem Statement:\n  You are a thief carrying a single bag with limited capacity S. The museum you stole had N artifact that you could steal. Unfortunately you might not be able to steal all the artifact because of your limited bag capacity.\n  You have to cherry pick the artifact in order to maximize the total value of the artifacts you stole.\n\n  Link for the Problem: https://www.hackerrank.com/contests/srin-aadc03/challenges/classic-01-knapsack\n  */\n  let input = `1\n    4 5\n    1 8\n    2 4\n    3 0\n    2 5\n    2 3`\n\n  input = input.trim().split('\\n')\n  input.shift()\n  const length = input.length\n\n  const output = []\n\n  let i = 0\n  while (i < length) {\n    const cap = Number(input[i].trim().split(' ')[0])\n    const currlen = Number(input[i].trim().split(' ')[1])\n    let j = i + 1\n    const arr = []\n    while (j <= i + currlen) {\n      arr.push(input[j])\n      j++\n    }\n    const newArr = arr.map((e) => e.trim().split(' ').map(Number))\n    const cache = []\n    for (let i = 0; i <= currlen; i++) {\n      const temp = []\n      for (let j = 0; j <= cap; j++) {\n        temp.push(-1)\n      }\n      cache.push(temp)\n    }\n    const result = zeroOneKnapsack(newArr, currlen, cap, cache)\n    output.push(result)\n    i += currlen + 1\n  }\n\n  return output\n}\n\nexport { zeroOneKnapsack, example }\n"
  },
  {
    "path": "Dynamic-Programming/tests/Abbreviation.test.js",
    "content": "import { isAbbreviation } from '../Abbreviation.js'\n\nconst expectPositive = (word, abbr) =>\n  expect(isAbbreviation(word, abbr)).toBe(true)\nconst expectNegative = (word, abbr) =>\n  expect(isAbbreviation(word, abbr)).toBe(false)\n\ndescribe('Abbreviation - Positive Tests', () => {\n  test('it should correctly abbreviate or transform the source string to match the target string', () => {\n    expectPositive('', '')\n    expectPositive('a', '')\n    expectPositive('a', 'A')\n    expectPositive('abcDE', 'ABCDE')\n    expectPositive('ABcDE', 'ABCDE')\n    expectPositive('abcde', 'ABCDE')\n    expectPositive('abcde', 'ABC')\n    expectPositive('abcXYdefghijKLmnopqrs', 'XYKL')\n    expectPositive('abc123', 'ABC')\n    expectPositive('abc123', 'ABC123')\n    expectPositive('abc!@#def', 'ABC')\n  })\n})\n\ndescribe('Abbreviation - Negative Tests', () => {\n  test('it should fail to abbreviate or transform the source string when it is not possible to match the target string', () => {\n    expectNegative('', 'A')\n    expectNegative('a', 'ABC')\n    expectNegative('aBcXYdefghijKLmnOpqrs', 'XYKLOP')\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/CatalanNumbers.test.js",
    "content": "import { catalanNumbers } from '../CatalanNumbers'\n\ndescribe('Testing catalanNumbers function', () => {\n  test('should return the expected array for inputs from 0 to 20', () => {\n    const expectedOutput = [\n      1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900,\n      2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420\n    ]\n\n    for (let i = 0; i <= 20; i++) {\n      expect(catalanNumbers(i)).toStrictEqual(expectedOutput.slice(0, i + 1))\n    }\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/ClimbingStairs.test.js",
    "content": "import { climbStairs } from '../ClimbingStairs'\n\ndescribe('ClimbingStairs', () => {\n  it('climbStairs of 0', () => {\n    expect(climbStairs(0)).toBe(1)\n  })\n\n  it('climbStairs of 1', () => {\n    expect(climbStairs(1)).toBe(1)\n  })\n\n  it('climbStairs of 10', () => {\n    expect(climbStairs(10)).toBe(89)\n  })\n\n  it('climbStairs of 15', () => {\n    expect(climbStairs(15)).toBe(987)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/CoinChange.test.js",
    "content": "import { change, coinChangeMin } from '../CoinChange'\n\ntest('Base Case 1', () => {\n  const coins = [2, 3, 5]\n  const amount = 0\n  expect(change(coins, amount)).toBe(1)\n  expect(coinChangeMin(coins, amount)).toBe(0)\n})\ntest('Base Case 2', () => {\n  const coins = []\n  const amount = 100\n  expect(change(coins, amount)).toBe(0)\n  expect(coinChangeMin(coins, amount)).toBe(-1)\n})\ntest('Test Case 1', () => {\n  const coins = [2, 4, 5]\n  const amount = 12\n  expect(change(coins, amount)).toBe(5)\n  expect(coinChangeMin(coins, amount)).toBe(3)\n})\ntest('Test Case 2', () => {\n  const coins = [5, 2, 3, 7, 6, 1, 12, 11, 9, 15]\n  const amount = 45\n  expect(change(coins, amount)).toBe(12372)\n  expect(coinChangeMin(coins, amount)).toBe(3)\n})\ntest('Test Case 3', () => {\n  const coins = [2]\n  const amount = 3\n  expect(change(coins, amount)).toBe(0)\n  expect(coinChangeMin(coins, amount)).toBe(-1)\n})\ntest('Test Case 4', () => {\n  const coins = [3, 5, 7, 8, 9, 10, 11]\n  const amount = 500\n  expect(change(coins, amount)).toBe(35502874)\n  expect(coinChangeMin(coins, amount)).toBe(46)\n})\ntest('Test Case 5', () => {\n  const coins = [10]\n  const amount = 10\n  expect(change(coins, amount)).toBe(1)\n  expect(coinChangeMin(coins, amount)).toBe(1)\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/EditDistance.test.js",
    "content": "import { minimumEditDistance } from '../EditDistance'\n\ntest('minimumEditDistance(kitten, sitten) => 1', () => {\n  const str1 = 'kitten'\n  const str2 = 'sitten'\n  const res = minimumEditDistance(str1, str2)\n  expect(res).toEqual(1)\n})\n\ntest('minimumEditDistance(school, skull) => 4', () => {\n  const str1 = 'school'\n  const str2 = 'skull'\n  const res = minimumEditDistance(str1, str2)\n  expect(res).toEqual(4)\n})\n\ntest('minimumEditDistance(Algorithm, Algorithm) => 0', () => {\n  const str1 = 'Algorithm'\n  const str2 = 'Algorithm'\n  const res = minimumEditDistance(str1, str2)\n  expect(res).toEqual(0)\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/FastFibonacciNumber.test.js",
    "content": "import { fastFibonacci } from '../FastFibonacciNumber'\n\ndescribe('Testing FibonacciNumber', () => {\n  const errorCases = ['0', '12', true]\n\n  test.each(errorCases)('throws an error if %p is invalid', (input) => {\n    expect(() => {\n      fastFibonacci(input)\n    }).toThrow()\n  })\n\n  const testCases = [\n    [0, 0],\n    [1, 1],\n    [10, 55],\n    [25, 75025],\n    [40, 102334155]\n  ]\n\n  test.each(testCases)('if input is %i it returns %i', (input, expected) => {\n    expect(fastFibonacci(input)).toBe(expected)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/FibonacciNumber.test.js",
    "content": "import { fibonacci } from '../FibonacciNumber'\n\ndescribe('Testing FibonacciNumber', () => {\n  it('Testing for invalid type', () => {\n    expect(() => fibonacci('0')).toThrowError()\n    expect(() => fibonacci('12')).toThrowError()\n    expect(() => fibonacci(true)).toThrowError()\n  })\n\n  it('fibonacci of 0', () => {\n    expect(fibonacci(0)).toBe(0)\n  })\n\n  it('fibonacci of 1', () => {\n    expect(fibonacci(1)).toBe(1)\n  })\n\n  it('fibonacci of 10', () => {\n    expect(fibonacci(10)).toBe(55)\n  })\n\n  it('fibonacci of 25', () => {\n    expect(fibonacci(25)).toBe(75025)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/KadaneAlgo.test.js",
    "content": "import { kadaneAlgo } from '../KadaneAlgo'\ntest('it is being checked that 15 is the answer to the corresponding array input', () => {\n  expect(kadaneAlgo([1, 2, 3, 4, 5])).toBe(15)\n})\n\ntest('it is being checked that 5 is the answer to the corresponding array input', () => {\n  expect(kadaneAlgo([-1, -2, -3, -4, 5])).toBe(5)\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/LevenshteinDistance.test.js",
    "content": "import { calculateLevenshteinDp } from '../LevenshteinDistance'\n\ntest('Should return the distance counting additions and removals', () => {\n  const from = 'kitten'\n  const to = 'sitting'\n  expect(calculateLevenshteinDp(from, to)).toBe(3)\n})\n\ntest('Should return the distance based on replacements in the middle of the strings', () => {\n  const from = 'book'\n  const to = 'back'\n  expect(calculateLevenshteinDp(from, to)).toBe(2)\n})\n\ntest('Should return the distance for strings with different length', () => {\n  const from = 'sunday'\n  const to = 'saturday'\n  expect(calculateLevenshteinDp(from, to)).toBe(3)\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/LongestCommonSubsequence.test.js",
    "content": "import { longestCommonSubsequence } from '../LongestCommonSubsequence'\n\ndescribe('LongestCommonSubsequence', () => {\n  it('expects to return an empty string for empty inputs', () => {\n    expect(longestCommonSubsequence('', '')).toEqual(''.length)\n    expect(longestCommonSubsequence('aaa', '')).toEqual(''.length)\n    expect(longestCommonSubsequence('', 'bbb')).toEqual(''.length)\n  })\n\n  it('expects to return an empty string for inputs without a common subsequence', () => {\n    expect(longestCommonSubsequence('abc', 'deffgf')).toEqual(''.length)\n    expect(longestCommonSubsequence('de', 'ghm')).toEqual(''.length)\n    expect(longestCommonSubsequence('aupj', 'xyz')).toEqual(''.length)\n  })\n\n  it('expects to return the longest common subsequence, short inputs', () => {\n    expect(longestCommonSubsequence('abc', 'abc')).toEqual('abc'.length)\n    expect(longestCommonSubsequence('abc', 'abcd')).toEqual('abc'.length)\n    expect(longestCommonSubsequence('abc', 'ab')).toEqual('ab'.length)\n    expect(longestCommonSubsequence('abc', 'a')).toEqual('a'.length)\n    expect(longestCommonSubsequence('abc', 'b')).toEqual('b'.length)\n    expect(longestCommonSubsequence('abc', 'c')).toEqual('c'.length)\n    expect(longestCommonSubsequence('abd', 'abcd')).toEqual('abd'.length)\n    expect(longestCommonSubsequence('abd', 'ab')).toEqual('ab'.length)\n    expect(longestCommonSubsequence('abc', 'abd')).toEqual('ab'.length)\n  })\n\n  it('expects to return the longest common subsequence, medium-length inputs', () => {\n    expect(longestCommonSubsequence('bsbininm', 'jmjkbkjkv')).toEqual(\n      'b'.length\n    )\n    expect(longestCommonSubsequence('oxcpqrsvwf', 'shmtulqrypy')).toEqual(\n      'qr'.length\n    )\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/LongestIncreasingSubsequence.test.js",
    "content": "import { longestIncreasingSubsequence } from '../LongestIncreasingSubsequence'\n\ndescribe('Testing longestIncreasingSubsequence', () => {\n  it.each([\n    [[], 0],\n    [[1], 1],\n    [[2, 2], 1],\n    [[3, 3, 3], 1],\n    [[4, 4, 4, 4], 1],\n    [[1, 2], 2],\n    [[1, 2, 2, 2, 2], 2],\n    [[1, 0, 2], 2],\n    [[1, 10, 2, 30], 3],\n    [[5, 8, 3, 7, 9, 1], 3],\n    [[10, 9, 2, 5, 3, 7, 101, 18], 4],\n    [[10, 10, 9, 9, 2, 2, 5, 5, 3, 3, 7, 7, 101, 101, 18, 18], 4],\n    [[0, 1, 0, 3, 2, 3], 4],\n    [[1, 1, 2, 2, 2], 2],\n    [[1, 1, 2, 2, 2, 3, 3, 3, 3], 3],\n    [[0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15], 6]\n  ])('check with %j', (input, expected) => {\n    expect(longestIncreasingSubsequence(input)).toBe(expected)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/LongestPalindromicSubsequence.test.js",
    "content": "import { longestPalindromeSubsequence } from '../LongestPalindromicSubsequence'\n\ndescribe('LongestPalindromicSubsequence', () => {\n  it('expects to return 1 as longest palindromic subsequence', () => {\n    expect(longestPalindromeSubsequence('abcdefgh')).toBe(1)\n  })\n\n  it('expects to return 4 as longest palindromic subsequence', () => {\n    expect(longestPalindromeSubsequence('bbbab')).toBe(4)\n  })\n\n  it('expects to return 2 as longest palindromic subsequence', () => {\n    expect(longestPalindromeSubsequence('cbbd')).toBe(2)\n  })\n\n  it('expects to return 7 as longest palindromic subsequence', () => {\n    expect(longestPalindromeSubsequence('racexyzcxar')).toBe(7)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/LongestValidParentheses.test.js",
    "content": "import { longestValidParentheses } from '../LongestValidParentheses'\n\ndescribe('longestValidParentheses', () => {\n  it('expects to return 0 as longest valid parentheses substring', () => {\n    expect(longestValidParentheses('')).toBe(0)\n  })\n\n  it('expects to return 2 as longest valid parentheses substring', () => {\n    expect(longestValidParentheses('(()')).toBe(2)\n  })\n\n  it('expects to return 2 as longest valid parentheses substring', () => {\n    expect(longestValidParentheses(')()())')).toBe(4)\n  })\n\n  it('expects to return 2 as longest valid parentheses substring', () => {\n    expect(longestValidParentheses('(((')).toBe(0)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/MaxProductOfThree.test.js",
    "content": "import { maxProductOfThree } from '../MaxProductOfThree'\n\ndescribe('MaxProductOfThree', () => {\n  it('expects to throw error for array with only 2 numbers', () => {\n    expect(() => {\n      maxProductOfThree([1, 3])\n    }).toThrow('Triplet cannot exist with the given array')\n  })\n\n  it('expects to return 300 as the maximum product', () => {\n    expect(maxProductOfThree([10, 6, 5, 3, 1, -10])).toBe(300)\n  })\n\n  it('expects to return 300 as the maximum product', () => {\n    expect(maxProductOfThree([10, -6, 5, 3, 1, -10])).toBe(600)\n  })\n})\n\n// Tests using random arrays of size 3 to 5, with values rangin from -4 to 4\n// The output is compared to a slower function that calculates all possible products of 3 numbers in the array and returns the largest one\ndescribe('MaxProductOfThree, random arrays of size 3 to 5', () => {\n  // Slower function that operates in O(n^3), where n is the length of the input array.\n  // Calculates all possible products of 3 numbers in the array and returns the largest\n  function completeMaxThree(array) {\n    let maximumProduct = null\n    for (let i = 0; i < array.length - 2; i++) {\n      for (let j = i + 1; j < array.length - 1; j++) {\n        for (let k = j + 1; k < array.length; k++) {\n          const currentProduct = array[i] * array[j] * array[k]\n          if (maximumProduct === null || currentProduct > maximumProduct) {\n            maximumProduct = currentProduct\n          }\n        }\n      }\n    }\n    return maximumProduct\n  }\n\n  // Set up consts for the tests\n  const maxValue = 4\n  const minValue = -4\n  const maxLength = 5\n  const minLength = 3\n  const numberOfRandomTests = 5000\n\n  // Run each test\n  for (let i = 0; i < numberOfRandomTests; i++) {\n    const arr = []\n    // Randomize the length of the array in the current test\n    const length = Math.floor(\n      Math.random() * (maxLength - minLength) + minLength\n    )\n\n    // Fill the array with random values in the specified range\n    for (let j = 0; j < length + 1; j++) {\n      arr.push(Math.floor(Math.random() * (maxValue - minValue) + minValue))\n    }\n\n    // Calculate the actual max product, slow but completely\n    const expectedProduct = completeMaxThree(arr)\n\n    // Set up the expectation\n    it(\n      'Expect the array ' +\n        arr.toString() +\n        ' to return the maximum three product of ' +\n        expectedProduct,\n      () => {\n        // Calculate the max three product using the function being tested\n        const actualProduct = maxProductOfThree(arr)\n\n        // Was unable to use expect().toBe(), since it sometimes compared 0 to -0, and that would not pass\n        // At the same time, standardjs forbid me from checking for === -0 to convert to 0\n        expect(actualProduct === expectedProduct).toBeTruthy()\n      }\n    )\n  }\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/NumberOfSubsetEqualToGivenSum.test.js",
    "content": "import { NumberOfSubsetSum } from '../NumberOfSubsetEqualToGivenSum'\n\ndescribe('Testing NumberOfSubsetSum', () => {\n  it.each([\n    [[], 0, 1],\n    [[], 1, 0],\n    [[1], 2, 0],\n    [[1, 2, 3, 4, 5], 0, 1],\n    [[1, 1, 1, 1, 1], 5, 1],\n    [[1, 1, 1, 1, 1], 4, 5],\n    [[1, 2, 3, 3], 6, 3],\n    [[10, 20, 30, 1], 31, 2],\n    [[1, 1, 2, 2, 3, 1, 1], 4, 18]\n  ])('check with %j and %i', (arr, sum, expected) => {\n    expect(NumberOfSubsetSum(arr, sum)).toBe(expected)\n  })\n\n  it.each([\n    [[1, 2], -1],\n    [[0, 2], 2],\n    [[1, -1], 0]\n  ])('throws for %j and %i', (arr, sum) => {\n    expect(() => NumberOfSubsetSum(arr, sum)).toThrowError()\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/RodCutting.test.js",
    "content": "import { rodCut } from '../RodCutting'\n\ntest('Test Case 1', () => {\n  expect(rodCut([1, 5, 8, 9, 10, 17, 17, 20], 8)).toBe(22)\n})\n\ntest('Test Case 2', () => {\n  expect(rodCut([1, 5, 4, 2, 1, 11, 19, 12], 8)).toBe(20)\n})\n\ntest('Test Case 3', () => {\n  expect(rodCut([1, 2, 1], 3)).toBe(3)\n})\n\ntest('Test Case 4', () => {\n  expect(rodCut([5, 4, 3, 2, 1], 5)).toBe(25)\n})\n\ntest('Test Case 5', () => {\n  expect(rodCut([3, 5, 8, 8, 10, 16, 14, 19], 8)).toBe(24)\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/SieveOfEratosthenes.test.js",
    "content": "import { sieveOfEratosthenes } from '../SieveOfEratosthenes'\n\ndescribe('SieveOfEratosthenes', () => {\n  it('Primes till 0', () => {\n    expect(sieveOfEratosthenes(0)).toEqual([])\n  })\n\n  it('Primes till 1', () => {\n    expect(sieveOfEratosthenes(1)).toEqual([])\n  })\n\n  it('Primes till 10', () => {\n    expect(sieveOfEratosthenes(10)).toEqual([2, 3, 5, 7])\n  })\n\n  it('Primes till 23', () => {\n    expect(sieveOfEratosthenes(23)).toEqual([2, 3, 5, 7, 11, 13, 17, 19, 23])\n  })\n\n  it('Primes till 70', () => {\n    expect(sieveOfEratosthenes(70)).toEqual([\n      2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67\n    ])\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/TrappingRainWater.test.js",
    "content": "import { trap } from '../TrappingRainWater'\n\ndescribe('TrappingRainWater', () => {\n  it('expects 6 units of rain water are being trapped', () => {\n    expect(trap([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1])).toBe(6)\n  })\n\n  it('expects 9 units of rain water are being trapped', () => {\n    expect(trap([4, 2, 0, 3, 2, 5])).toBe(9)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/TribonacciNumber.test.js",
    "content": "import { tribonacci } from '../TribonacciNumber'\n\ndescribe('TribonacciNumber', () => {\n  it('tribonacci of 0', () => {\n    expect(tribonacci(0)).toBe(0)\n  })\n\n  it('tribonacci of 1', () => {\n    expect(tribonacci(1)).toBe(1)\n  })\n\n  it('tribonacci of 2', () => {\n    expect(tribonacci(2)).toBe(1)\n  })\n\n  it('tribonacci of 10', () => {\n    expect(tribonacci(10)).toBe(149)\n  })\n\n  it('tribonacci of 25', () => {\n    expect(tribonacci(25)).toBe(1389537)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/UniquePaths.test.js",
    "content": "import { uniquePaths } from '../UniquePaths'\n\ndescribe('Unique Paths', () => {\n  it('should return 28 when m is 3 and n is 7', () => {\n    expect(uniquePaths(3, 7)).toBe(28)\n  })\n\n  it('should return 48620 when m is 10 and n is 10', () => {\n    expect(uniquePaths(10, 10)).toBe(48620)\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/UniquePaths2.test.js",
    "content": "import { uniquePaths2 } from '../UniquePaths2'\n\ndescribe('Unique Paths2', () => {\n  // Should return number of ways, taken into account the obstacles\n  test('There are obstacles in the way', () => {\n    expect(\n      uniquePaths2([\n        [0, 0, 0],\n        [0, 1, 0],\n        [0, 0, 0]\n      ])\n    ).toEqual(2)\n    expect(\n      uniquePaths2([\n        [0, 0, 0],\n        [0, 1, 0],\n        [0, 0, 0],\n        [1, 0, 0]\n      ])\n    ).toEqual(3)\n  })\n  // Should return number of all possible ways to reach right-bottom corner\n  test('There are no obstacles in the way', () => {\n    expect(\n      uniquePaths2([\n        [0, 0, 0],\n        [0, 0, 0],\n        [0, 0, 0]\n      ])\n    ).toEqual(6)\n    expect(\n      uniquePaths2([\n        [0, 0, 0],\n        [0, 0, 0]\n      ])\n    ).toEqual(3)\n  })\n  // Should throw an exception b/c input data has wrong type\n  test('There are wrong type of input data', () => {\n    expect(() => uniquePaths2('wrong input')).toThrow()\n    expect(() => uniquePaths2(100)).toThrow()\n  })\n})\n"
  },
  {
    "path": "Dynamic-Programming/tests/ZeroOneKnapsack.test.js",
    "content": "import { zeroOneKnapsack } from '../ZeroOneKnapsack'\n\ndescribe('ZeroOneKnapsack', () => {\n  it('zeroOneKnapsack when capacity is 4 and 5 items', () => {\n    expect(\n      zeroOneKnapsack(\n        [\n          [1, 8],\n          [2, 4],\n          [3, 0],\n          [2, 5],\n          [2, 3]\n        ],\n        5,\n        4,\n        [\n          [-1, -1, -1, -1, -1],\n          [-1, -1, -1, -1, -1],\n          [-1, -1, -1, -1, -1],\n          [-1, -1, -1, -1, -1],\n          [-1, -1, -1, -1, -1],\n          [-1, -1, -1, -1, -1]\n        ]\n      )\n    ).toBe(13)\n  })\n\n  it('zeroOneKnapsack when capacity is 1 and 1 items', () => {\n    expect(\n      zeroOneKnapsack([[1, 80]], 1, 1, [\n        [-1, -1],\n        [-1, -1]\n      ])\n    ).toBe(80)\n  })\n\n  it('zeroOneKnapsack when capacity is 0 and 1 items', () => {\n    expect(zeroOneKnapsack([[1, 80]], 1, 0, [[-1], [-1]])).toBe(0)\n  })\n})\n"
  },
  {
    "path": "Geometry/Circle.js",
    "content": "/**\n * This class represents a circle and can calculate it's perimeter and area\n * https://en.wikipedia.org/wiki/Circle\n * @constructor\n * @param {number} radius - The radius of the circle.\n */\nexport default class Circle {\n  constructor(radius) {\n    this.radius = radius\n  }\n\n  perimeter = () => {\n    return this.radius * 2 * Math.PI\n  }\n\n  area = () => {\n    return Math.pow(this.radius, 2) * Math.PI\n  }\n}\n"
  },
  {
    "path": "Geometry/Cone.js",
    "content": "/**\n * This class represents a circular cone and can calculate its volume and surface area\n * https://en.wikipedia.org/wiki/Cone\n * @constructor\n * @param {number} baseRadius - The radius of the base of the cone.\n * @param {number} height - The height of the cone\n */\nexport default class Cone {\n  constructor(baseRadius, height) {\n    this.baseRadius = baseRadius\n    this.height = height\n  }\n\n  baseArea = () => {\n    return Math.pow(this.baseRadius, 2) * Math.PI\n  }\n\n  volume = () => {\n    return (this.baseArea() * this.height * 1) / 3\n  }\n\n  surfaceArea = () => {\n    return (\n      this.baseArea() +\n      Math.PI *\n        this.baseRadius *\n        Math.sqrt(Math.pow(this.baseRadius, 2) + Math.pow(this.height, 2))\n    )\n  }\n}\n"
  },
  {
    "path": "Geometry/ConvexHullGraham.js",
    "content": "/**\n * Author: Arnab Ray\n * ConvexHull using Graham Scan\n * Wikipedia: https://en.wikipedia.org/wiki/Graham_scan\n * Given a set of points in the plane. The Convex hull of the set is the smallest\n * convex polygon that contains all the points of it.\n */\n\nfunction compare(a, b) {\n  // Compare Function to Sort the points, a and b are points to compare\n  if (a.x < b.x) return -1\n  if (a.x === b.x && a.y < b.y) return -1\n  return 1\n}\nfunction orientation(a, b, c) {\n  // Check orientation of Line(a, b) and Line(b, c)\n  const alpha = (b.y - a.y) / (b.x - a.x)\n  const beta = (c.y - b.y) / (c.x - b.x)\n\n  // Clockwise\n  if (alpha > beta) return 1\n  // Anticlockwise\n  else if (beta > alpha) return -1\n  // Colinear\n  return 0\n}\n\nfunction convexHull(points) {\n  const pointsLen = points.length\n  if (pointsLen <= 2) {\n    throw new Error('Minimum of 3 points is required to form closed polygon!')\n  }\n\n  points.sort(compare)\n  const p1 = points[0]\n  const p2 = points[pointsLen - 1]\n\n  // Divide Hull in two halves\n  const upperPoints = []\n  const lowerPoints = []\n\n  upperPoints.push(p1)\n  lowerPoints.push(p1)\n\n  for (let i = 1; i < pointsLen; i++) {\n    if (i === pointsLen - 1 || orientation(p1, points[i], p2) !== -1) {\n      let upLen = upperPoints.length\n\n      while (\n        upLen >= 2 &&\n        orientation(\n          upperPoints[upLen - 2],\n          upperPoints[upLen - 1],\n          points[i]\n        ) === -1\n      ) {\n        upperPoints.pop()\n        upLen = upperPoints.length\n      }\n      upperPoints.push(points[i])\n    }\n    if (i === pointsLen - 1 || orientation(p1, points[i], p2) !== 1) {\n      let lowLen = lowerPoints.length\n      while (\n        lowLen >= 2 &&\n        orientation(\n          lowerPoints[lowLen - 2],\n          lowerPoints[lowLen - 1],\n          points[i]\n        ) === 1\n      ) {\n        lowerPoints.pop()\n        lowLen = lowerPoints.length\n      }\n      lowerPoints.push(points[i])\n    }\n  }\n  const hull = []\n  for (let i = 1; i < upperPoints.length - 1; i++) {\n    hull.push(upperPoints[i])\n  }\n  for (let i = lowerPoints.length - 1; i >= 0; i--) {\n    hull.push(lowerPoints[i])\n  }\n\n  return hull\n}\n\nexport { convexHull }\n\n// Example\n\n// const points = [\n//   { x: 0, y: 3 },\n//   { x: 1, y: 1 },\n//   { x: 2, y: 2 },\n//   { x: 4, y: 4 },\n//   { x: 0, y: 0 },\n//   { x: 1, y: 2 },\n//   { x: 3, y: 1 },\n//   { x: 3, y: 3 }]\n\n// convexHull(points)\n"
  },
  {
    "path": "Geometry/Pyramid.js",
    "content": "/**\n * This class represents a regular pyramid and can calculate its volume and surface area\n * https://en.wikipedia.org/wiki/Pyramid_(geometry)\n * @constructor\n * @param {number} bsl - The side length of the base of the pyramid.\n * @param {number} height - The height of the pyramid\n */\nexport default class Pyramid {\n  constructor(bsl, height) {\n    this.bsl = bsl\n    this.height = height\n  }\n\n  baseArea = () => {\n    return Math.pow(this.bsl, 2)\n  }\n\n  volume = () => {\n    return (this.baseArea() * this.height) / 3\n  }\n\n  surfaceArea = () => {\n    return (\n      this.baseArea() +\n      ((this.bsl * 4) / 2) *\n        Math.sqrt(Math.pow(this.bsl / 2, 2) + Math.pow(this.height, 2))\n    )\n  }\n}\n"
  },
  {
    "path": "Geometry/Sphere.js",
    "content": "/**\n * This class represents a sphere and can calculate its volume and surface area\n * @constructor\n * @param {number} radius - The radius of the sphere\n * @see https://en.wikipedia.org/wiki/Sphere\n */\nexport default class Sphere {\n  constructor(radius) {\n    this.radius = radius\n  }\n\n  volume = () => {\n    return (Math.pow(this.radius, 3) * Math.PI * 4) / 3\n  }\n\n  surfaceArea = () => {\n    return Math.pow(this.radius, 2) * Math.PI * 4\n  }\n}\n"
  },
  {
    "path": "Geometry/Test/Circle.test.js",
    "content": "import Circle from '../Circle'\n\nconst circle = new Circle(3)\n\ntest('The area of a circle with radius equal to 3', () => {\n  expect(parseFloat(circle.area().toFixed(2))).toEqual(28.27)\n})\n\ntest('The perimeter of a circle with radius equal to 3', () => {\n  expect(parseFloat(circle.perimeter().toFixed(2))).toEqual(18.85)\n})\n"
  },
  {
    "path": "Geometry/Test/Cone.test.js",
    "content": "import Cone from '../Cone'\n\nconst cone = new Cone(3, 5)\n\ntest('The Volume of a cone with base radius equal to 3 and height equal to 5', () => {\n  expect(parseFloat(cone.volume().toFixed(2))).toEqual(47.12)\n})\n\ntest('The Surface Area of a cone with base radius equal to 3 and height equal to 5', () => {\n  expect(parseFloat(cone.surfaceArea().toFixed(2))).toEqual(83.23)\n})\n"
  },
  {
    "path": "Geometry/Test/ConvexHullGraham.test.js",
    "content": "import { convexHull } from '../ConvexHullGraham'\n\ntest('The ConvexHull of the following points is [{x: 0, y: 3}, {x: 4, y: 4}, {x: 3, y: 1}, {x: 0, y: 0}]', () => {\n  const points = [\n    { x: 0, y: 3 },\n    { x: 1, y: 1 },\n    { x: 2, y: 2 },\n    { x: 4, y: 4 },\n    { x: 0, y: 0 },\n    { x: 1, y: 2 },\n    { x: 3, y: 1 },\n    { x: 3, y: 3 }\n  ]\n  const res = convexHull(points)\n  expect(res).toEqual([\n    { x: 0, y: 3 },\n    { x: 4, y: 4 },\n    { x: 3, y: 1 },\n    { x: 0, y: 0 }\n  ])\n})\n\ntest('The ConvexHull of the following points is [{x: 1, y: 4}, {x: 9, y: 6}, {x: 7, y: 0}, {x: 0, y: 0}]', () => {\n  const points = [\n    { x: 4, y: 3 },\n    { x: 1, y: 4 },\n    { x: 2, y: 4 },\n    { x: 0, y: 0 },\n    { x: 9, y: 6 },\n    { x: 1, y: 3 },\n    { x: 4, y: 1 },\n    { x: 7, y: 0 }\n  ]\n  const res = convexHull(points)\n  expect(res).toEqual([\n    { x: 1, y: 4 },\n    { x: 9, y: 6 },\n    { x: 7, y: 0 },\n    { x: 0, y: 0 }\n  ])\n})\n"
  },
  {
    "path": "Geometry/Test/Pyramid.test.js",
    "content": "import Pyramid from '../Pyramid'\n\nconst pyramid = new Pyramid(3, 5)\n\ntest('The Volume of a cone with base radius equal to 3 and height equal to 5', () => {\n  expect(parseFloat(pyramid.volume().toFixed(2))).toEqual(15)\n})\n\ntest('The Surface Area of a cone with base radius equal to 3 and height equal to 5', () => {\n  expect(parseFloat(pyramid.surfaceArea().toFixed(2))).toEqual(40.32)\n})\n"
  },
  {
    "path": "Geometry/Test/Sphere.test.js",
    "content": "import Sphere from '../Sphere'\n\nconst sphere = new Sphere(3)\n\ntest('The Volume of a sphere with base radius equal to 3 and height equal to 5', () => {\n  expect(parseFloat(sphere.volume().toFixed(2))).toEqual(113.1)\n})\n\ntest('The Surface Area of a sphere with base radius equal to 3 and height equal to 5', () => {\n  expect(parseFloat(sphere.surfaceArea().toFixed(2))).toEqual(113.1)\n})\n"
  },
  {
    "path": "Graphs/BellmanFord.js",
    "content": "/*\nThe Bellman–Ford algorithm is an algorithm that computes shortest paths\nfrom a single source vertex to all of the other vertices in a weighted digraph.\nIt also detects negative weight cycle.\n\nComplexity:\n    Worst-case performance O(VE)\n    Best-case performance O(E)\n    Worst-case space complexity O(V)\n\nReference:\n    https://en.wikipedia.org/wiki/Bellman–Ford_algorithm\n    https://cp-algorithms.com/graph/bellman_ford.html\n\n*/\n\n/**\n *\n * @param graph Graph in the format (u, v, w) where\n *  the edge is from vertex u to v. And weight\n *  of the edge is w.\n * @param V Number of vertices in graph\n * @param E Number of edges in graph\n * @param src Starting node\n * @param dest Destination node\n * @returns Shortest distance from source to destination\n */\nfunction BellmanFord(graph, V, E, src, dest) {\n  // Initialize distance of all vertices as infinite.\n  const dis = Array(V).fill(Infinity)\n  // initialize distance of source as 0\n  dis[src] = 0\n\n  // Relax all edges |V| - 1 times. A simple\n  // shortest path from src to any other\n  // vertex can have at-most |V| - 1 edges\n  for (let i = 0; i < V - 1; i++) {\n    for (let j = 0; j < E; j++) {\n      if (dis[graph[j][0]] + graph[j][2] < dis[graph[j][1]]) {\n        dis[graph[j][1]] = dis[graph[j][0]] + graph[j][2]\n      }\n    }\n  }\n  // check for negative-weight cycles.\n  for (let i = 0; i < E; i++) {\n    const x = graph[i][0]\n    const y = graph[i][1]\n    const weight = graph[i][2]\n    if (dis[x] !== Infinity && dis[x] + weight < dis[y]) {\n      return null\n    }\n  }\n  for (let i = 0; i < V; i++) {\n    if (i === dest) return dis[i]\n  }\n}\n\nexport { BellmanFord }\n"
  },
  {
    "path": "Graphs/BinaryLifting.js",
    "content": "/**\n * Author: Adrito Mukherjee\n * Binary Lifting implementation in Javascript\n * Binary Lifting is a technique that is used to find the kth ancestor of a node in a rooted tree with N nodes\n * The technique requires preprocessing the tree in O(N log N) using dynamic programming\n * The technique can answer Q queries about kth ancestor of any node in O(Q log N)\n * It is faster than the naive algorithm that answers Q queries with complexity O(Q K)\n * It can be used to find Lowest Common Ancestor of two nodes in O(log N)\n * Tutorial on Binary Lifting: https://codeforces.com/blog/entry/100826\n */\n\nexport class BinaryLifting {\n  constructor(root, tree) {\n    this.root = root\n    this.connections = new Map()\n    this.up = new Map() // up[node][i] stores the 2^i-th  parent of node\n    for (const [i, j] of tree) {\n      this.addEdge(i, j)\n    }\n    this.log = Math.ceil(Math.log2(this.connections.size))\n    this.dfs(root, root)\n  }\n\n  addNode(node) {\n    // Function to add a node to the tree (connection represented by set)\n    this.connections.set(node, new Set())\n  }\n\n  addEdge(node1, node2) {\n    // Function to add an edge (adds the node too if they are not present in the tree)\n    if (!this.connections.has(node1)) {\n      this.addNode(node1)\n    }\n    if (!this.connections.has(node2)) {\n      this.addNode(node2)\n    }\n    this.connections.get(node1).add(node2)\n    this.connections.get(node2).add(node1)\n  }\n\n  dfs(node, parent) {\n    // The dfs function calculates 2^i-th ancestor of all nodes for i ranging from 0 to this.log\n    // We make use of the fact the two consecutive jumps of length 2^(i-1) make the total jump length 2^i\n    this.up.set(node, new Map())\n    this.up.get(node).set(0, parent)\n    for (let i = 1; i < this.log; i++) {\n      this.up\n        .get(node)\n        .set(i, this.up.get(this.up.get(node).get(i - 1)).get(i - 1))\n    }\n    for (const child of this.connections.get(node)) {\n      if (child !== parent) this.dfs(child, node)\n    }\n  }\n\n  kthAncestor(node, k) {\n    // if value of k is more than or equal to the number of total nodes, we return the root of the graph\n    if (k >= this.connections.size) {\n      return this.root\n    }\n    // if i-th bit is set in the binary representation of k, we jump from a node to its 2^i-th ancestor\n    // so after checking all bits of k, we will have made jumps of total length k, in just log k steps\n    for (let i = 0; i < this.log; i++) {\n      if (k & (1 << i)) {\n        node = this.up.get(node).get(i)\n      }\n    }\n    return node\n  }\n}\n\nfunction binaryLifting(root, tree, queries) {\n  const graphObject = new BinaryLifting(root, tree)\n  const ancestors = []\n  for (const [node, k] of queries) {\n    const ancestor = graphObject.kthAncestor(node, k)\n    ancestors.push(ancestor)\n  }\n  return ancestors\n}\n\nexport default binaryLifting\n"
  },
  {
    "path": "Graphs/BreadthFirstSearch.js",
    "content": "import Queue from '../Data-Structures/Queue/Queue'\n\n/**\n * Breadth-first search is an algorithm for traversing a graph.\n *\n * It discovers all nodes reachable from the starting position by exploring all of the neighbor nodes at the present\n * depth prior to moving on to the nodes at the next depth level.\n *\n * (description adapted from https://en.wikipedia.org/wiki/Breadth-first_search)\n * @see https://www.koderdojo.com/blog/breadth-first-search-and-shortest-path-in-csharp-and-net-core\n */\nexport function breadthFirstSearch(graph, startingNode) {\n  // visited keeps track of all nodes visited\n  const visited = new Set()\n\n  // queue contains the nodes to be explored in the future\n  const queue = new Queue()\n  queue.enqueue(startingNode)\n\n  while (!queue.isEmpty()) {\n    // start with the queue's first node\n    const node = queue.dequeue()\n\n    if (!visited.has(node)) {\n      // mark the node as visited\n      visited.add(node)\n      const neighbors = graph[node]\n\n      // put all its neighbors into the queue\n      for (let i = 0; i < neighbors.length; i++) {\n        queue.enqueue(neighbors[i])\n      }\n    }\n  }\n\n  return visited\n}\n"
  },
  {
    "path": "Graphs/BreadthFirstShortestPath.js",
    "content": "import Queue from '../Data-Structures/Queue/Queue'\n/**\n * Breadth-first approach can be applied to determine the shortest path between two nodes in an equi-weighted graph.\n *\n * It searches the target node among all neighbors of the starting node, then the process is repeated on the level of\n * the neighbors of the neighbors and so on.\n *\n * @see https://en.wikipedia.org/wiki/Breadth-first_search\n * @see https://www.koderdojo.com/blog/breadth-first-search-and-shortest-path-in-csharp-and-net-core\n */\nexport function breadthFirstShortestPath(graph, startNode, targetNode) {\n  // check if startNode & targetNode are identical\n  if (startNode === targetNode) {\n    return [startNode]\n  }\n\n  // visited keeps track of all nodes visited\n  const visited = new Set()\n\n  // queue contains the paths to be explored in the future\n  const initialPath = [startNode]\n  const queue = new Queue()\n  queue.enqueue(initialPath)\n\n  while (!queue.isEmpty()) {\n    // start with the queue's first path\n    const path = queue.dequeue()\n    const node = path[path.length - 1]\n\n    // explore this node if it hasn't been visited yet\n    if (!visited.has(node)) {\n      // mark the node as visited\n      visited.add(node)\n\n      const neighbors = graph[node]\n\n      // create a new path in the queue for each neighbor\n      for (let i = 0; i < neighbors.length; i++) {\n        const newPath = path.concat([neighbors[i]])\n\n        // the first path to contain the target node is the shortest path\n        if (neighbors[i] === targetNode) {\n          return newPath\n        }\n\n        // queue the new path\n        queue.enqueue(newPath)\n      }\n    }\n  }\n\n  // the target node was not reachable\n  return []\n}\n"
  },
  {
    "path": "Graphs/ConnectedComponents.js",
    "content": "class GraphUnweightedUndirectedAdjacencyList {\n  // Unweighted Undirected Graph class\n  constructor() {\n    this.connections = {}\n  }\n\n  addNode(node) {\n    // Function to add a node to the graph (connection represented by set)\n    this.connections[node] = new Set()\n  }\n\n  addEdge(node1, node2) {\n    // Function to add an edge (adds the node too if they are not present in the graph)\n    if (!(node1 in this.connections)) {\n      this.addNode(node1)\n    }\n    if (!(node2 in this.connections)) {\n      this.addNode(node2)\n    }\n    this.connections[node1].add(node2)\n    this.connections[node2].add(node1)\n  }\n\n  DFSComponent(components, node, visited) {\n    // Helper function to populate the visited set with the nodes in each component\n\n    // adding the first visited node in the component to the array\n    components.push(node)\n    const stack = [node]\n    // populating the visited set using DFS (Iterative)\n    while (stack.length > 0) {\n      const curr = stack.pop()\n      visited.add(curr.toString())\n      for (const neighbour of this.connections[curr].keys()) {\n        if (!visited.has(neighbour.toString())) {\n          stack.push(neighbour)\n        }\n      }\n    }\n  }\n\n  connectedComponents() {\n    // Function to generate the Connected Components\n    // Result is an array containing 1 node from each component\n    const visited = new Set()\n    const components = []\n    for (const node of Object.keys(this.connections)) {\n      if (!visited.has(node.toString())) {\n        this.DFSComponent(components, node, visited)\n      }\n    }\n    return components\n  }\n}\n\nexport { GraphUnweightedUndirectedAdjacencyList }\n\n// Example\n\n// const graph = new GraphUnweightedUndirectedAdjacencyList()\n// graph.addEdge(1, 2) // Component 1\n// graph.addEdge(3, 4) // Component 2\n// graph.addEdge(3, 5) // Component 2\n// const components = graph.connectedComponents()\n"
  },
  {
    "path": "Graphs/Density.js",
    "content": "/*\nThe density of a network is a measure of how many edges exist proportional to\nhow many edges would exist in a complete network (where all possible edges).\nhttps://networkx.org/documentation/networkx-1.9/reference/generated/networkx.classes.function.density.html\n*/\nfunction density(numberOfNodes, numberOfEdges, isDirected = false) {\n  const multi = isDirected ? 1 : 2\n  return (multi * numberOfEdges) / (numberOfNodes * (numberOfNodes - 1))\n}\n\nexport { density }\n"
  },
  {
    "path": "Graphs/DepthFirstSearchIterative.js",
    "content": "class GraphUnweightedUndirected {\n  // Unweighted Undirected Graph class\n  constructor() {\n    this.connections = {}\n  }\n\n  addNode(node) {\n    // Function to add a node to the graph (connection represented by set)\n    this.connections[node] = new Set()\n  }\n\n  addEdge(node1, node2) {\n    // Function to add an edge (adds the node too if they are not present in the graph)\n    if (!(node1 in this.connections)) {\n      this.addNode(node1)\n    }\n    if (!(node2 in this.connections)) {\n      this.addNode(node2)\n    }\n    this.connections[node1].add(node2)\n    this.connections[node2].add(node1)\n  }\n\n  DFSIterative(node, value) {\n    // DFS Function to search if a node with the given value is present in the graph\n    const stack = [node]\n    const visited = new Set()\n    while (stack.length > 0) {\n      const currNode = stack.pop()\n      // if the current node contains the value being searched for, true is returned\n      if (currNode === value) {\n        return true\n      }\n      // adding the current node to the visited set\n      visited.add(currNode)\n      // adding neighbours in the stack\n      for (const neighbour of this.connections[currNode]) {\n        if (!visited.has(neighbour)) {\n          stack.push(neighbour)\n        }\n      }\n    }\n    return false\n  }\n}\n\nexport { GraphUnweightedUndirected }\n\n// Example\n\n// const graph = new GraphUnweightedUndirected()\n// graph.addEdge(1, 2)\n// graph.addEdge(2, 3)\n// graph.addEdge(2, 4)\n// graph.addEdge(3, 5)\n// graph.DFSIterative(5, 1)\n// graph.DFSIterative(5, 100)\n"
  },
  {
    "path": "Graphs/DepthFirstSearchRecursive.js",
    "content": "class GraphUnweightedUndirected {\n  // Unweighted Undirected Graph class\n  constructor() {\n    this.connections = {}\n  }\n\n  addNode(node) {\n    // Function to add a node to the graph (connection represented by set)\n    this.connections[node] = new Set()\n  }\n\n  addEdge(node1, node2) {\n    // Function to add an edge (adds the node too if they are not present in the graph)\n    if (!(node1 in this.connections)) {\n      this.addNode(node1)\n    }\n    if (!(node2 in this.connections)) {\n      this.addNode(node2)\n    }\n    this.connections[node1].add(node2)\n    this.connections[node2].add(node1)\n  }\n\n  DFSRecursive(node, value, visited = new Set()) {\n    // DFS Function to search if a node with the given value is present in the graph\n    // checking if the searching node has been found\n    if (node === value) {\n      return true\n    }\n    // adding the current node to the visited set\n    visited.add(node)\n    // calling the helper function recursively for all unvisited nodes\n    for (const neighbour of this.connections[node]) {\n      if (!visited.has(neighbour)) {\n        if (this.DFSRecursive(neighbour, value, visited)) {\n          return true\n        }\n      }\n    }\n    return false\n  }\n}\n\nexport { GraphUnweightedUndirected }\n\n// const graph = new GraphUnweightedUndirected()\n// graph.addEdge(1, 2)\n// graph.addEdge(2, 3)\n// graph.addEdge(2, 4)\n// graph.addEdge(3, 5)\n// graph.DFSRecursive(5, 1)\n// graph.DFSRecursive(5, 100)\n"
  },
  {
    "path": "Graphs/Dijkstra.js",
    "content": "/**\n * Author: Samarth Jain\n * Dijkstra's Algorithm implementation in JavaScript\n * Dijkstra's Algorithm calculates the minimum distance between two nodes.\n * It is used to find the shortest path.\n * It uses graph data structure.\n */\n\nfunction createGraph(V, E) {\n  // V - Number of vertices in graph\n  // E - Number of edges in graph (u, v, w)\n  const adjList = [] // Adjacency list\n  for (let i = 0; i < V; i++) {\n    adjList.push([])\n  }\n  for (let i = 0; i < E.length; i++) {\n    adjList[E[i][0]].push([E[i][1], E[i][2]])\n    adjList[E[i][1]].push([E[i][0], E[i][2]])\n  }\n  return adjList\n}\n\nfunction djikstra(graph, V, src) {\n  const vis = Array(V).fill(0)\n  const dist = []\n  for (let i = 0; i < V; i++) dist.push([10000, -1])\n  dist[src][0] = 0\n\n  for (let i = 0; i < V - 1; i++) {\n    let mn = -1\n    for (let j = 0; j < V; j++) {\n      if (vis[j] === 0) {\n        if (mn === -1 || dist[j][0] < dist[mn][0]) mn = j\n      }\n    }\n\n    vis[mn] = 1\n    for (let j = 0; j < graph[mn].length; j++) {\n      const edge = graph[mn][j]\n      if (vis[edge[0]] === 0 && dist[edge[0]][0] > dist[mn][0] + edge[1]) {\n        dist[edge[0]][0] = dist[mn][0] + edge[1]\n        dist[edge[0]][1] = mn\n      }\n    }\n  }\n\n  return dist\n}\n\nexport { createGraph, djikstra }\n\n// const V = 9\n// const E = [\n//   [0, 1, 4],\n//   [0, 7, 8],\n//   [1, 7, 11],\n//   [1, 2, 8],\n//   [7, 8, 7],\n//   [6, 7, 1],\n//   [2, 8, 2],\n//   [6, 8, 6],\n//   [5, 6, 2],\n//   [2, 5, 4],\n//   [2, 3, 7],\n//   [3, 5, 14],\n//   [3, 4, 9],\n//   [4, 5, 10]\n// ]\n\n// const graph = createGraph(V, E)\n// const distances = djikstra(graph, V, 0)\n\n/**\n * The first value in the array determines the minimum distance and the\n * second value represents the parent node from which the minimum distance has been calculated\n */\n"
  },
  {
    "path": "Graphs/DijkstraSmallestPath.js",
    "content": "// starting at s\nfunction solve(graph, s) {\n  const solutions = {}\n  solutions[s] = []\n  solutions[s].dist = 0\n\n  while (true) {\n    let p = null\n    let neighbor = null\n    let dist = Infinity\n\n    for (const n in solutions) {\n      if (!solutions[n]) {\n        continue\n      }\n      const ndist = solutions[n].dist\n      const adj = graph[n]\n\n      for (const a in adj) {\n        if (solutions[a]) {\n          continue\n        }\n\n        const d = adj[a] + ndist\n        if (d < dist) {\n          p = solutions[n]\n          neighbor = a\n          dist = d\n        }\n      }\n    }\n\n    // no more solutions\n    if (dist === Infinity) {\n      break\n    }\n\n    // extend parent's solution path\n    solutions[neighbor] = p.concat(neighbor)\n    // extend parent's cost\n    solutions[neighbor].dist = dist\n  }\n\n  return solutions\n}\n\nexport { solve }\n"
  },
  {
    "path": "Graphs/FloydWarshall.js",
    "content": "/*\n  Source:\n    https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm\n\n  Complexity:\n    O(|V|^3) where V is the set of vertices\n*/\n\nconst FloydWarshall = (dist) => {\n  // Input:- dist: 2D Array where dist[i][j] = edge weight b/w i and j\n  // Output:- dist: 2D Array where dist[i][j] = shortest dist b/w i and j\n  const n = dist.length\n  for (let k = 0; k < n; k++) {\n    for (let i = 0; i < n; i++) {\n      for (let j = 0; j < n; j++) {\n        if (dist[i][j] > dist[i][k] + dist[k][j]) {\n          // dist from i to j via k is lesser than the current distance\n          dist[i][j] = dist[i][k] + dist[k][j]\n        }\n      }\n    }\n  }\n  return dist\n}\n\nexport { FloydWarshall }\n\n// For the following graph (edge weights are shown in brackets)\n//  4       1       dist[1][2] = dist[2][1] = 1\n//   \\  (2)/ \\      dist[1][3] = dist[3][1] = 2\n//    \\   /   \\(1)  dist[1][4] = dist[4][1] = Infinity\n//  (1)\\ /     \\    dist[3][4] = dist[4][3] = 1\n//      3       2   dist[2][4] = dist[4][2] = Infinity\n//                  dist[2][3] = dist[3][2] = Infinity\n// Output should be:\n// [ [0, 1, 2, 3],\n//   [1, 0, 3, 4],\n//   [2, 3, 0, 1],\n//   [3, 4, 1, 0] ]\n\n// FloydWarshall(\n//     [[0, 1, 2, Infinity],\n//       [1, 0, Infinity, Infinity],\n//       [2, Infinity, 0, 1],\n//       [Infinity, Infinity, 1, 0]\n//     ]\n//   )\n"
  },
  {
    "path": "Graphs/Kosaraju.js",
    "content": "/**\n * Author: Adrito Mukherjee\n * Kosaraju's Algorithm implementation in Javascript\n * Kosaraju's Algorithm finds all the connected components in a Directed Acyclic Graph (DAG)\n * It uses Stack data structure to store the Topological Sorted Order of vertices and also Graph data structure\n *\n * Wikipedia: https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm\n *\n */\n\nclass Kosaraju {\n  constructor(graph) {\n    this.connections = {}\n    this.reverseConnections = {}\n    this.stronglyConnectedComponents = []\n    for (const [i, j] of graph) {\n      this.addEdge(i, j)\n    }\n    this.topoSort()\n    return this.kosaraju()\n  }\n\n  addNode(node) {\n    // Function to add a node to the graph (connection represented by set)\n    this.connections[node] = new Set()\n    this.reverseConnections[node] = new Set()\n    this.topoSorted = []\n  }\n\n  addEdge(node1, node2) {\n    // Function to add an edge (adds the node too if they are not present in the graph)\n    if (!(node1 in this.connections) || !(node1 in this.reverseConnections)) {\n      this.addNode(node1)\n    }\n    if (!(node2 in this.connections) || !(node2 in this.reverseConnections)) {\n      this.addNode(node2)\n    }\n    this.connections[node1].add(node2)\n    this.reverseConnections[node2].add(node1)\n  }\n\n  dfsTopoSort(node, visited) {\n    visited.add(node)\n    for (const child of this.connections[node]) {\n      if (!visited.has(child)) this.dfsTopoSort(child, visited)\n    }\n    this.topoSorted.push(node)\n  }\n\n  topoSort() {\n    // Function to perform topological sorting\n    const visited = new Set()\n    const nodes = Object.keys(this.connections).map((key) => Number(key))\n    for (const node of nodes) {\n      if (!visited.has(node)) this.dfsTopoSort(node, visited)\n    }\n  }\n\n  dfsKosaraju(node, visited) {\n    visited.add(node)\n    this.stronglyConnectedComponents[\n      this.stronglyConnectedComponents.length - 1\n    ].push(node)\n    for (const child of this.reverseConnections[node]) {\n      if (!visited.has(child)) this.dfsKosaraju(child, visited)\n    }\n  }\n\n  kosaraju() {\n    // Function to perform Kosaraju Algorithm\n    const visited = new Set()\n    while (this.topoSorted.length > 0) {\n      const node = this.topoSorted.pop()\n      if (!visited.has(node)) {\n        this.stronglyConnectedComponents.push([])\n        this.dfsKosaraju(node, visited)\n      }\n    }\n    return this.stronglyConnectedComponents\n  }\n}\n\nfunction kosaraju(graph) {\n  const stronglyConnectedComponents = new Kosaraju(graph)\n  return stronglyConnectedComponents\n}\n\nexport { kosaraju }\n\n// kosaraju([\n//   [1, 2],\n//   [2, 3],\n//   [3, 1],\n//   [2, 4],\n//   [4, 5],\n//   [5, 6],\n//   [6, 4],\n// ])\n\n// [ [ 1, 3, 2 ], [ 4, 6, 5 ] ]\n"
  },
  {
    "path": "Graphs/KruskalMST.js",
    "content": "class DisjointSetTreeNode {\n  // Disjoint Set Node to store the parent and rank\n  constructor(key) {\n    this.key = key\n    this.parent = this\n    this.rank = 0\n  }\n}\n\nclass DisjointSetTree {\n  // Disjoint Set DataStructure\n  constructor() {\n    // map to from node name to the node object\n    this.map = {}\n  }\n\n  makeSet(x) {\n    // Function to create a new set with x as its member\n    this.map[x] = new DisjointSetTreeNode(x)\n  }\n\n  findSet(x) {\n    // Function to find the set x belongs to (with path-compression)\n    if (this.map[x] !== this.map[x].parent) {\n      this.map[x].parent = this.findSet(this.map[x].parent.key)\n    }\n    return this.map[x].parent\n  }\n\n  union(x, y) {\n    // Function to merge 2 disjoint sets\n    this.link(this.findSet(x), this.findSet(y))\n  }\n\n  link(x, y) {\n    // Helper function for union operation\n    if (x.rank > y.rank) {\n      y.parent = x\n    } else {\n      x.parent = y\n      if (x.rank === y.rank) {\n        y.rank += 1\n      }\n    }\n  }\n}\n\nclass GraphWeightedUndirectedAdjacencyList {\n  // Weighted Undirected Graph class\n  constructor() {\n    this.connections = {}\n    this.nodes = 0\n  }\n\n  addNode(node) {\n    // Function to add a node to the graph (connection represented by set)\n    this.connections[node] = {}\n    this.nodes += 1\n  }\n\n  addEdge(node1, node2, weight) {\n    // Function to add an edge (adds the node too if they are not present in the graph)\n    if (!(node1 in this.connections)) {\n      this.addNode(node1)\n    }\n    if (!(node2 in this.connections)) {\n      this.addNode(node2)\n    }\n    this.connections[node1][node2] = weight\n    this.connections[node2][node1] = weight\n  }\n\n  KruskalMST() {\n    // Kruskal's Algorithm to generate a Minimum Spanning Tree (MST) of a graph\n    // Details: https://en.wikipedia.org/wiki/Kruskal%27s_algorithm\n    // getting the edges in ascending order of weights\n    const edges = []\n    const seen = new Set()\n    for (const start of Object.keys(this.connections)) {\n      for (const end of Object.keys(this.connections[start])) {\n        if (!seen.has(`${start} ${end}`)) {\n          seen.add(`${end} ${start}`)\n          edges.push([start, end, this.connections[start][end]])\n        }\n      }\n    }\n    edges.sort((a, b) => a[2] - b[2])\n    // creating the disjoint set\n    const disjointSet = new DisjointSetTree()\n    Object.keys(this.connections).forEach((node) => disjointSet.makeSet(node))\n    // MST generation\n    const graph = new GraphWeightedUndirectedAdjacencyList()\n    let numEdges = 0\n    let index = 0\n    while (numEdges < this.nodes - 1) {\n      const [u, v, w] = edges[index]\n      index += 1\n      if (disjointSet.findSet(u) !== disjointSet.findSet(v)) {\n        numEdges += 1\n        graph.addEdge(u, v, w)\n        disjointSet.union(u, v)\n      }\n    }\n    return graph\n  }\n}\n\nexport { GraphWeightedUndirectedAdjacencyList }\n\n// const graph = new GraphWeightedUndirectedAdjacencyList()\n// graph.addEdge(1, 2, 1)\n// graph.addEdge(2, 3, 2)\n// graph.addEdge(3, 4, 1)\n// graph.addEdge(3, 5, 100) // Removed in MST\n// graph.addEdge(4, 5, 5)\n// graph.KruskalMST()\n"
  },
  {
    "path": "Graphs/LCABinaryLifting.js",
    "content": "/**\n * Author: Adrito Mukherjee\n * Finding Lowest Common Ancestor By Binary Lifting implementation in JavaScript\n * The technique requires preprocessing the tree in O(N log N) using dynamic programming)\n * It can be used to find Lowest Common Ancestor of two nodes in O(log N)\n * Tutorial on Lowest Common Ancestor: https://www.geeksforgeeks.org/lca-in-a-tree-using-binary-lifting-technique\n */\n\nimport { BinaryLifting } from './BinaryLifting'\n\nclass LCABinaryLifting extends BinaryLifting {\n  constructor(root, tree) {\n    super(root, tree)\n    this.depth = new Map() // depth[node] stores the depth of node from root\n    this.depth.set(root, 1)\n    this.dfsDepth(root, root)\n  }\n\n  dfsDepth(node, parent) {\n    // DFS to find depth of every node in the tree\n    for (const child of this.connections.get(node)) {\n      if (child !== parent) {\n        this.depth.set(child, this.depth.get(node) + 1)\n        this.dfsDepth(child, node)\n      }\n    }\n  }\n\n  getLCA(node1, node2) {\n    // We make sure that node1 is the deeper node among node1 and node2\n    if (this.depth.get(node1) < this.depth.get(node2)) {\n      ;[node1, node2] = [node2, node1]\n    }\n    // We check if node1 is the ancestor of node2, and if so, then return node1\n    const k = this.depth.get(node1) - this.depth.get(node2)\n    node1 = this.kthAncestor(node1, k)\n    if (node1 === node2) {\n      return node1\n    }\n\n    for (let i = this.log - 1; i >= 0; i--) {\n      if (this.up.get(node1).get(i) !== this.up.get(node2).get(i)) {\n        node1 = this.up.get(node1).get(i)\n        node2 = this.up.get(node2).get(i)\n      }\n    }\n    return this.up.get(node1).get(0)\n  }\n}\n\nfunction lcaBinaryLifting(root, tree, queries) {\n  const graphObject = new LCABinaryLifting(root, tree)\n  const lowestCommonAncestors = []\n  for (const [node1, node2] of queries) {\n    const lca = graphObject.getLCA(node1, node2)\n    lowestCommonAncestors.push(lca)\n  }\n  return lowestCommonAncestors\n}\n\nexport default lcaBinaryLifting\n"
  },
  {
    "path": "Graphs/NodeNeighbors.js",
    "content": "// https://en.wikipedia.org/wiki/Neighbourhood_(graph_theory)\n\nclass Graph {\n  // Generic graph: the algorithm works regardless of direction or weight\n  constructor() {\n    this.edges = []\n  }\n\n  addEdge(node1, node2) {\n    // Adding edges to the graph\n    this.edges.push({\n      node1,\n      node2\n    })\n  }\n\n  nodeNeighbors(node) {\n    // Returns an array with all of the node neighbors\n    const neighbors = new Set()\n    for (const edge of this.edges) {\n      // Checks if they have an edge between them and if the neighbor is not\n      // already in the neighbors array\n      if (edge.node1 === node && !neighbors.has(edge.node2)) {\n        neighbors.add(edge.node2)\n      } else if (edge.node2 === node && !neighbors.has(edge.node1)) {\n        neighbors.add(edge.node1)\n      }\n    }\n    return neighbors\n  }\n}\n\nexport { Graph }\n\n// const graph = new Graph()\n// graph.addEdge(1, 2)\n// graph.addEdge(2, 3)\n// graph.addEdge(3, 5)\n// graph.addEdge(1, 5)\n// graph.nodeNeighbors(1)\n"
  },
  {
    "path": "Graphs/NumberOfIslands.js",
    "content": "/* Number of Islands\nhttps://dev.to/rattanakchea/amazons-interview-question-count-island-21h6\nGiven a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.\n\na two dimensional grid map\neach element is going to represent a piece of land\n1 is land,\n0 is water\noutput a number which is the number of islands\n\nExample 1:\n  Input:\n  11110\n  11010\n  11000\n  00000\n\n  Output: 1\n\nExample 2:\n  Input:\n  11000\n  11000\n  00100\n  00011\n\n  Output: 3\n\nI: two dimensional array\nO: a single integer; total number of islands\n\nPseudocode:\n  OUTER FUNCTION\n    set count to 0\n\n    INNER FUNCTION - flood (col, row)\n      if the tile is water\n        return\n      make tile water(flood tile)\n      invoke flood on the neighbor coordinates\n\n    iterate over the matrix (col, row)\n      if the current element is a 1\n        increment count\n        invoke flood (coordinates for col and row)\n\n    Return the count\n*/\n\nconst islands = (matrixGrid) => {\n  const matrix = matrixGrid\n  let counter = 0\n\n  const flood = (row, col) => {\n    if (row < 0 || col < 0) return // Off the map above or left\n    if (row >= matrix.length || col >= matrix[row].length) return // Off the map below or right\n\n    const tile = matrix[row][col]\n    if (tile !== '1') return\n\n    matrix[row][col] = '0'\n\n    flood(row + 1, col) // Down\n    flood(row - 1, col) // Up\n    flood(row, col + 1) // Right\n    flood(row, col - 1) // Left\n  }\n\n  for (let row = 0; row < matrix.length; row += 1) {\n    for (let col = 0; col < matrix[row].length; col += 1) {\n      const current = matrix[row][col]\n      if (current === '1') {\n        flood(row, col)\n        counter += 1\n      }\n    }\n  }\n  return counter\n}\n\nexport { islands }\n"
  },
  {
    "path": "Graphs/PrimMST.js",
    "content": "import { KeyPriorityQueue } from '../Data-Structures/Heap/KeyPriorityQueue'\nclass GraphWeightedUndirectedAdjacencyList {\n  // Weighted Undirected Graph class\n  constructor() {\n    this.connections = {}\n  }\n\n  addNode(node) {\n    // Function to add a node to the graph (connection represented by set)\n    this.connections[node] = {}\n  }\n\n  addEdge(node1, node2, weight) {\n    // Function to add an edge (adds the node too if they are not present in the graph)\n    if (!(node1 in this.connections)) {\n      this.addNode(node1)\n    }\n    if (!(node2 in this.connections)) {\n      this.addNode(node2)\n    }\n    this.connections[node1][node2] = weight\n    this.connections[node2][node1] = weight\n  }\n\n  PrimMST(start) {\n    // Prim's Algorithm to generate a Minimum Spanning Tree (MST) of a graph\n    // Details: https://en.wikipedia.org/wiki/Prim%27s_algorithm\n    const distance = {}\n    const parent = {}\n    const priorityQueue = new KeyPriorityQueue()\n    // Initialization\n    for (const node in this.connections) {\n      distance[node] = node === start.toString() ? 0 : Infinity\n      parent[node] = null\n      priorityQueue.push(node, distance[node])\n    }\n    // Updating 'distance' object\n    while (!priorityQueue.isEmpty()) {\n      const node = priorityQueue.pop()\n      Object.keys(this.connections[node]).forEach((neighbour) => {\n        if (\n          priorityQueue.contains(neighbour) &&\n          distance[node] + this.connections[node][neighbour] <\n            distance[neighbour]\n        ) {\n          distance[neighbour] =\n            distance[node] + this.connections[node][neighbour]\n          parent[neighbour] = node\n          priorityQueue.update(neighbour, distance[neighbour])\n        }\n      })\n    }\n\n    // MST Generation from the 'parent' object\n    const graph = new GraphWeightedUndirectedAdjacencyList()\n    Object.keys(parent).forEach((node) => {\n      if (node && parent[node]) {\n        graph.addEdge(node, parent[node], this.connections[node][parent[node]])\n      }\n    })\n    return graph\n  }\n}\n\nexport { GraphWeightedUndirectedAdjacencyList }\n"
  },
  {
    "path": "Graphs/test/BellmanFord.test.js",
    "content": "import { BellmanFord } from '../BellmanFord.js'\n\ntest('Test Case 1', () => {\n  const V = 5\n  const E = 8\n  const destination = 3\n  const graph = [\n    [0, 1, -1],\n    [0, 2, 4],\n    [1, 2, 3],\n    [1, 3, 2],\n    [1, 4, 2],\n    [3, 2, 5],\n    [3, 1, 1],\n    [4, 3, -3]\n  ]\n  const dist = BellmanFord(graph, V, E, 0, destination)\n  expect(dist).toBe(-2)\n})\ntest('Test Case 2', () => {\n  const V = 6\n  const E = 9\n  const destination = 4\n  const graph = [\n    [0, 1, 3],\n    [0, 3, 6],\n    [0, 5, -1],\n    [1, 2, -3],\n    [1, 4, -2],\n    [5, 2, 5],\n    [2, 3, 1],\n    [4, 3, 5],\n    [5, 4, 2]\n  ]\n  const dist = BellmanFord(graph, V, E, 0, destination)\n  expect(dist).toBe(1)\n})\ntest('Test Case 3', () => {\n  const V = 4\n  const E = 5\n  const destination = 1\n  const graph = [\n    [0, 3, -1],\n    [0, 2, 4],\n    [3, 2, 2],\n    [3, 1, 5],\n    [2, 1, -1]\n  ]\n  const dist = BellmanFord(graph, V, E, 0, destination)\n  expect(dist).toBe(0)\n})\n"
  },
  {
    "path": "Graphs/test/BinaryLifting.test.js",
    "content": "import binaryLifting from '../BinaryLifting'\n\n// The graph for Test Case 1 looks like this:\n//\n//         0\n//        /|\\\n//       / | \\\n//      1  3  5\n//     / \\     \\\n//    2   4     6\n//         \\\n//          7\n//         / \\\n//        11  8\n//             \\\n//              9\n//               \\\n//                10\n\ntest('Test case 1', () => {\n  const root = 0\n  const graph = [\n    [0, 1],\n    [0, 3],\n    [0, 5],\n    [5, 6],\n    [1, 2],\n    [1, 4],\n    [4, 7],\n    [7, 11],\n    [7, 8],\n    [8, 9],\n    [9, 10]\n  ]\n  const queries = [\n    [2, 1],\n    [6, 1],\n    [7, 2],\n    [8, 2],\n    [10, 2],\n    [10, 3],\n    [10, 5],\n    [11, 3]\n  ]\n  const kthAncestors = binaryLifting(root, graph, queries)\n  expect(kthAncestors).toEqual([1, 5, 1, 4, 8, 7, 1, 1])\n})\n\n// The graph for Test Case 2 looks like this:\n//\n//         0\n//        / \\\n//       1   2\n//      / \\   \\\n//     3   4   5\n//    /       / \\\n//   6       7   8\n\ntest('Test case 2', () => {\n  const root = 0\n  const graph = [\n    [0, 1],\n    [0, 2],\n    [1, 3],\n    [1, 4],\n    [2, 5],\n    [3, 6],\n    [5, 7],\n    [5, 8]\n  ]\n  const queries = [\n    [2, 1],\n    [3, 1],\n    [3, 2],\n    [6, 2],\n    [7, 3],\n    [8, 2],\n    [8, 3]\n  ]\n  const kthAncestors = binaryLifting(root, graph, queries)\n  expect(kthAncestors).toEqual([0, 1, 0, 1, 0, 2, 0])\n})\n"
  },
  {
    "path": "Graphs/test/BreadthFirstSearch.test.js",
    "content": "import { breadthFirstSearch } from '../BreadthFirstSearch'\n\ndescribe('BreadthFirstSearch', () => {\n  const graph = {\n    A: ['B', 'D'],\n    B: ['E'],\n    C: ['D'],\n    D: ['A'],\n    E: ['D'],\n    F: ['G'],\n    G: []\n  }\n  /*\n        A <-> B\n        ʌ     |\n        |     |\n        v     v\n  C --> D <-- E\n\n  F --> G\n  */\n\n  it('should return the visited nodes', () => {\n    expect(Array.from(breadthFirstSearch(graph, 'C'))).toEqual([\n      'C',\n      'D',\n      'A',\n      'B',\n      'E'\n    ])\n    expect(Array.from(breadthFirstSearch(graph, 'A'))).toEqual([\n      'A',\n      'B',\n      'D',\n      'E'\n    ])\n    expect(Array.from(breadthFirstSearch(graph, 'F'))).toEqual(['F', 'G'])\n  })\n})\n"
  },
  {
    "path": "Graphs/test/BreadthFirstShortestPath.test.js",
    "content": "import { breadthFirstShortestPath } from '../BreadthFirstShortestPath'\n\ndescribe('BreadthFirstShortestPath', () => {\n  const graph = {\n    A: ['B', 'D'],\n    B: ['E'],\n    C: ['D'],\n    D: ['A'],\n    E: ['D'],\n    F: ['G'],\n    G: []\n  }\n  /*\n        A <-> B\n        ʌ     |\n        |     |\n        v     v\n  C --> D <-- E\n\n  F --> G\n  */\n\n  it('should return the visited nodes', () => {\n    expect(breadthFirstShortestPath(graph, 'C', 'E')).toEqual([\n      'C',\n      'D',\n      'A',\n      'B',\n      'E'\n    ])\n    expect(breadthFirstShortestPath(graph, 'E', 'B')).toEqual([\n      'E',\n      'D',\n      'A',\n      'B'\n    ])\n    expect(breadthFirstShortestPath(graph, 'F', 'G')).toEqual(['F', 'G'])\n    expect(breadthFirstShortestPath(graph, 'A', 'G')).toEqual([])\n  })\n})\n"
  },
  {
    "path": "Graphs/test/Kosaraju.test.js",
    "content": "import { kosaraju } from '../Kosaraju.js'\n\ntest('Test Case 1', () => {\n  const graph = [\n    [1, 2],\n    [2, 3],\n    [3, 1],\n    [2, 4],\n    [4, 5],\n    [5, 6],\n    [6, 4]\n  ]\n  const stronglyConnectedComponents = kosaraju(graph)\n  expect(stronglyConnectedComponents).toStrictEqual([\n    [1, 3, 2],\n    [4, 6, 5]\n  ])\n})\n\ntest('Test Case 2', () => {\n  const graph = [\n    [1, 2],\n    [2, 3],\n    [3, 1],\n    [2, 4],\n    [4, 5]\n  ]\n  const stronglyConnectedComponents = kosaraju(graph)\n  expect(stronglyConnectedComponents).toStrictEqual([[1, 3, 2], [4], [5]])\n})\n"
  },
  {
    "path": "Graphs/test/LCABinaryLifting.test.js",
    "content": "import lcaBinaryLifting from '../LCABinaryLifting'\n\n// The graph for Test Case 1 looks like this:\n//\n//         0\n//        /|\\\n//       / | \\\n//      1  3  5\n//     / \\     \\\n//    2   4     6\n//         \\\n//          7\n//         / \\\n//        11  8\n//             \\\n//              9\n//               \\\n//                10\n\ntest('Test case 1', () => {\n  const root = 0\n  const graph = [\n    [0, 1],\n    [0, 3],\n    [0, 5],\n    [5, 6],\n    [1, 2],\n    [1, 4],\n    [4, 7],\n    [7, 11],\n    [7, 8],\n    [8, 9],\n    [9, 10]\n  ]\n  const queries = [\n    [1, 3],\n    [6, 5],\n    [3, 6],\n    [7, 10],\n    [8, 10],\n    [11, 2],\n    [11, 10]\n  ]\n  const lowestCommonAncestors = lcaBinaryLifting(root, graph, queries)\n  expect(lowestCommonAncestors).toEqual([0, 5, 0, 7, 8, 1, 7])\n})\n\n// The graph for Test Case 2 looks like this:\n//\n//         0\n//        / \\\n//       1   2\n//      / \\   \\\n//     3   4   5\n//    /       / \\\n//   6       7   8\n\ntest('Test case 2', () => {\n  const root = 0\n  const graph = [\n    [0, 1],\n    [0, 2],\n    [1, 3],\n    [1, 4],\n    [2, 5],\n    [3, 6],\n    [5, 7],\n    [5, 8]\n  ]\n  const queries = [\n    [1, 2],\n    [3, 4],\n    [5, 4],\n    [6, 7],\n    [6, 8],\n    [7, 8]\n  ]\n  const lowestCommonAncestors = lcaBinaryLifting(root, graph, queries)\n  expect(lowestCommonAncestors).toEqual([0, 1, 0, 0, 0, 5])\n})\n"
  },
  {
    "path": "Graphs/test/NumberOfIslands.test.js",
    "content": "import { islands } from '../NumberOfIslands'\n\ndescribe('Number of Islands', () => {\n  test('Graph with three islands', () => {\n    const graph = [\n      ['1', '1', '0', '0', '0'],\n      ['1', '1', '0', '0', '0'],\n      ['0', '0', '1', '0', '0'],\n      ['0', '0', '0', '1', '1']\n    ]\n    expect(islands(graph)).toBe(3)\n  })\n\n  test('Graph with only one island', () => {\n    const graph = [\n      ['1', '1'],\n      ['1', '1'],\n      ['0', '0'],\n      ['0', '0']\n    ]\n    expect(islands(graph)).toBe(1)\n  })\n\n  test('No islands', () => {\n    const graph = [\n      ['0', '0'],\n      ['0', '0']\n    ]\n    expect(islands(graph)).toBe(0)\n  })\n})\n"
  },
  {
    "path": "Graphs/test/PrimMST.test.js",
    "content": "import { GraphWeightedUndirectedAdjacencyList } from '../PrimMST.js'\n\ntest('Test Case PrimMST 1', () => {\n  // create graph to compute MST on\n  const graph = new GraphWeightedUndirectedAdjacencyList()\n  graph.addEdge(1, 2, 1)\n  graph.addEdge(2, 3, 2)\n  graph.addEdge(3, 4, 1)\n  graph.addEdge(3, 5, 100) // Removed in MST\n  graph.addEdge(4, 5, 5)\n  // create expected graph\n  const expectedGraph = new GraphWeightedUndirectedAdjacencyList()\n  expectedGraph.addEdge(1, 2, 1)\n  expectedGraph.addEdge(2, 3, 2)\n  expectedGraph.addEdge(3, 4, 1)\n  expectedGraph.addEdge(4, 5, 5)\n  // result from MST\n  const res = graph.PrimMST(1)\n  expect(res).toEqual(expectedGraph)\n})\n"
  },
  {
    "path": "Hashes/MD5.js",
    "content": "// Module that replicates the MD5 Cryptographic Hash\n// function in Javascript.\n\n// main variables\nconst S = [\n  7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5,\n  9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11,\n  16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15,\n  21\n]\n\nconst K = [\n  0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,\n  0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,\n  0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340,\n  0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,\n  0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,\n  0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,\n  0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,\n  0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,\n  0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,\n  0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,\n  0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391\n]\n\n/**\n * Separates an array into equal sized chunks\n *\n * @param {Array|string} array - array or string to separate into chunks\n * @param {number} size - number of elements wanted in each chunk\n * @return {Array} - array of original array split into chunks\n *\n * @example\n *      chunkify(\"this is a test\", 2)\n */\nfunction chunkify(array, size) {\n  const chunks = []\n  for (let i = 0; i < array.length; i += size) {\n    chunks.push(array.slice(i, i + size))\n  }\n  return chunks\n}\n\n/**\n * Rotates the bits to the left\n *\n * @param {number} bits - 32 bit number\n * @param {number} turns - number of rotations to make\n * @return {number} - number after bits rotation\n *\n * @example\n *      rotateLeft(0b1011, 3); // 0b1011000\n */\nfunction rotateLeft(bits, turns) {\n  return (bits << turns) | (bits >>> (32 - turns))\n}\n\n/**\n * Converts Uint8Array to Uint32Array\n *\n * @param {Uint8Array} u8Array Uint8Array to convert\n * @returns {Uint32Array} - Required Uint32Array\n */\nfunction u8ToU32(u8Array) {\n  const uint32Array = new Uint32Array(u8Array.length / 4)\n\n  for (let i = 0; i < u8Array.length; i += 4) {\n    uint32Array[i / 4] =\n      (u8Array[i] |\n        (u8Array[i + 1] << 8) |\n        (u8Array[i + 2] << 16) |\n        (u8Array[i + 3] << 24)) >>>\n      0\n  }\n\n  return uint32Array\n}\n\n/**\n * Converts Uint32Array to Uint8Array\n *\n * @param {Uint32Array} u32Array Uint32Array to convert\n * @returns {Uint8Array} - Required Uint8Array\n */\nfunction u32ToU8(u32Array) {\n  const uint8Array = new Uint8Array(u32Array.length * 4)\n\n  for (let i = 0; i < u32Array.length; i++) {\n    uint8Array[i * 4] = u32Array[i] & 0xff\n    uint8Array[i * 4 + 1] = (u32Array[i] >> 8) & 0xff\n    uint8Array[i * 4 + 2] = (u32Array[i] >> 16) & 0xff\n    uint8Array[i * 4 + 3] = (u32Array[i] >> 24) & 0xff\n  }\n\n  return uint8Array\n}\n\n/**\n * Adds padding to the end of the given array\n *\n * @param {Uint8Array} u8Array Array to pad\n * @param {number} size Resulting size of the array\n */\nfunction padEnd(u8Array, size) {\n  const result = new Uint8Array(size)\n  result.set(u8Array)\n  result.fill(0, u8Array.length)\n\n  return result\n}\n\n/**\n * Pre-processes message to feed the algorithm loop\n *\n * @param {Uint8Array} message - message to pre-process\n * @return {Uint32Array} - processed message\n */\nfunction preProcess(message) {\n  // Extend message by adding '0'\n  //\n  // message.length + 1 is for adding '1' bit\n  // 56 - (length % 64) is for padding with '0's\n  // 8 is for appending 64 bit message length\n  let m = padEnd(\n    message,\n    message.length + 1 + (56 - ((message.length + 1) % 64)) + 8\n  )\n\n  // Add '1' bit at the end of the message\n  m[message.length] = 1 << 7\n\n  // convert message to 32 bit uint array\n  m = u8ToU32(m)\n\n  // Append the length of the message to the end\n  // (ml / 0x100000000) | 0 is equivalent to (ml >> 32) & 0xffffffff) in other languages\n  let ml = message.length * 8\n  m[m.length - 2] = ml & 0xffffffff\n  m[m.length - 1] = (ml / 0x100000000) | 0\n\n  return m\n}\n\n/**\n * Hashes message using MD5 Cryptographic Hash Function\n *\n * @see\n * For more info: https://en.wikipedia.org/wiki/MD5\n *\n * @param {Uint8Array} message - message to hash\n * @return {Uint8Array} - message digest (hash value)\n */\nfunction MD5(message) {\n  // Initialize variables:\n  let [a0, b0, c0, d0] = [\n    0x67452301 >>> 0,\n    0xefcdab89 >>> 0,\n    0x98badcfe >>> 0,\n    0x10325476 >>> 0\n  ]\n\n  // pre-process message and split into 512 bit chunks\n  const words = Array.from(preProcess(message))\n  const chunks = chunkify(words, 16)\n\n  chunks.forEach(function (chunk, _) {\n    // initialize variables for this chunk\n    let [A, B, C, D] = [a0, b0, c0, d0]\n\n    for (let i = 0; i < 64; i++) {\n      let [F, g] = [0, 0]\n\n      if (i <= 15) {\n        F = (B & C) | (~B & D)\n        g = i\n      } else if (i <= 31) {\n        F = (D & B) | (~D & C)\n        g = (5 * i + 1) % 16\n      } else if (i <= 47) {\n        F = B ^ C ^ D\n        g = (3 * i + 5) % 16\n      } else {\n        F = C ^ (B | ~D)\n        g = (7 * i) % 16\n      }\n\n      F = (F + A + K[i] + chunk[g]) >>> 0\n      A = D\n      D = C\n      C = B\n      B = ((B + rotateLeft(F, S[i])) & 0xffffffff) >>> 0\n    }\n\n    // add values for this chunk to main hash variables (unsigned)\n    a0 = (a0 + A) >>> 0\n    b0 = (b0 + B) >>> 0\n    c0 = (c0 + C) >>> 0\n    d0 = (d0 + D) >>> 0\n  })\n\n  return u32ToU8([a0, b0, c0, d0])\n}\n\n// export MD5 function\nexport { MD5 }\n"
  },
  {
    "path": "Hashes/SHA1.js",
    "content": "//= ===============================================================\n// SHA1.js\n//\n// Module that replicates the SHA-1 Cryptographic Hash\n// function in Javascript.\n//= ===============================================================\n\n// main variables\nconst CHAR_SIZE = 8\n\n/**\n * Adds padding to binary/hex string representation\n *\n * @param {string} str - string representation (binary/hex)\n * @param {int} bits - total number of bits wanted\n * @return {string} - string representation padding with empty (0) bits\n *\n * @example\n *      pad(\"10011\", 8); // \"00010011\"\n */\nfunction pad(str, bits) {\n  let res = str\n  while (res.length % bits !== 0) {\n    res = '0' + res\n  }\n  return res\n}\n\n/**\n * Separates string into chunks of the same size\n *\n * @param {string} str - string to separate into chunks\n * @param {int} size - number of characters wanted in each chunk\n * @return {array} - array of original string split into chunks\n *\n * @example\n *      chunkify(\"this is a test\", 2)\n */\nfunction chunkify(str, size) {\n  const chunks = []\n  for (let i = 0; i < str.length; i += size) {\n    chunks.push(str.slice(i, i + size))\n  }\n  return chunks\n}\n\n/**\n * Rotates string representation of bits to the left\n *\n * @param {string} bits - string representation of bits\n * @param {int} turns - number of rotations to make\n * @return {string} - string representation of bits after rotation\n *\n * @example\n *      rotateLeft(\"1011\", 3); // \"1101\"\n */\nfunction rotateLeft(bits, turns) {\n  return bits.substr(turns) + bits.substr(0, turns)\n}\n\n/**\n * Pre-processes message to feed the algorithm loop\n *\n * @param {string} message - message to pre-process\n * @return {string} - processed message\n */\nfunction preProcess(message) {\n  // convert message to binary representation padded to\n  // 8 bits, and add 1\n  let m =\n    message\n      .split('')\n      .map((e) => e.charCodeAt(0))\n      .map((e) => e.toString(2))\n      .map((e) => pad(e, 8))\n      .join('') + '1'\n\n  // extend message by adding empty bits (0)\n  while (m.length % 512 !== 448) {\n    m += '0'\n  }\n\n  // length of message in binary, padded, and extended\n  // to a 64 bit representation\n  let ml = (message.length * CHAR_SIZE).toString(2)\n  ml = pad(ml, 8)\n  ml = '0'.repeat(64 - ml.length) + ml\n\n  return m + ml\n}\n\n/**\n * Hashes message using SHA-1 Cryptographic Hash Function\n *\n * @param {string} message - message to hash\n * @return {string} - message digest (hash value)\n */\nfunction SHA1(message) {\n  // main variables\n  let H0 = 0x67452301\n  let H1 = 0xefcdab89\n  let H2 = 0x98badcfe\n  let H3 = 0x10325476\n  let H4 = 0xc3d2e1f0\n\n  // pre-process message and split into 512 bit chunks\n  const bits = preProcess(message)\n  const chunks = chunkify(bits, 512)\n\n  chunks.forEach(function (chunk, i) {\n    // break each chunk into 16 32-bit words\n    const words = chunkify(chunk, 32)\n\n    // extend 16 32-bit words to 80 32-bit words\n    for (let i = 16; i < 80; i++) {\n      const val = [words[i - 3], words[i - 8], words[i - 14], words[i - 16]]\n        .map((e) => parseInt(e, 2))\n        .reduce((acc, curr) => curr ^ acc, 0)\n      const bin = (val >>> 0).toString(2)\n      const paddedBin = pad(bin, 32)\n      const word = rotateLeft(paddedBin, 1)\n      words.push(word)\n    }\n\n    // initialize variables for this chunk\n    let [a, b, c, d, e] = [H0, H1, H2, H3, H4]\n\n    for (let i = 0; i < 80; i++) {\n      let f, k\n      if (i < 20) {\n        f = (b & c) | (~b & d)\n        k = 0x5a827999\n      } else if (i < 40) {\n        f = b ^ c ^ d\n        k = 0x6ed9eba1\n      } else if (i < 60) {\n        f = (b & c) | (b & d) | (c & d)\n        k = 0x8f1bbcdc\n      } else {\n        f = b ^ c ^ d\n        k = 0xca62c1d6\n      }\n      // make sure f is unsigned\n      f >>>= 0\n\n      const aRot = rotateLeft(pad(a.toString(2), 32), 5)\n      const aInt = parseInt(aRot, 2) >>> 0\n      const wordInt = parseInt(words[i], 2) >>> 0\n      const t = aInt + f + e + k + wordInt\n      e = d >>> 0\n      d = c >>> 0\n      const bRot = rotateLeft(pad(b.toString(2), 32), 30)\n      c = parseInt(bRot, 2) >>> 0\n      b = a >>> 0\n      a = t >>> 0\n    }\n\n    // add values for this chunk to main hash variables (unsigned)\n    H0 = (H0 + a) >>> 0\n    H1 = (H1 + b) >>> 0\n    H2 = (H2 + c) >>> 0\n    H3 = (H3 + d) >>> 0\n    H4 = (H4 + e) >>> 0\n  })\n\n  // combine hash values of main hash variables and return\n  const HH = [H0, H1, H2, H3, H4]\n    .map((e) => e.toString(16))\n    .map((e) => pad(e, 8))\n    .join('')\n\n  return HH\n}\n\n// export SHA1 function\nexport { SHA1 }\n"
  },
  {
    "path": "Hashes/SHA256.js",
    "content": "//= ===============================================================\n// SHA256.js\n//\n// Module that replicates the SHA-256 Cryptographic Hash\n// function in Javascript.\n//= ===============================================================\n\n// main variables\nconst CHAR_SIZE = 8\n\nconst K = [\n  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,\n  0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\n  0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,\n  0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,\n  0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\n  0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,\n  0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,\n  0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\n  0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\n]\n\n/**\n * Adds padding to binary/hex string representation\n *\n * @param {string} str - string representation (binary/hex)\n * @param {int} bits - total number of bits wanted\n * @return {string} - string representation padding with empty (0) bits\n *\n * @example\n *      pad(\"10011\", 8); // \"00010011\"\n */\nfunction pad(str, bits) {\n  let res = str\n  while (res.length % bits !== 0) {\n    res = '0' + res\n  }\n  return res\n}\n\n/**\n * Separates string into chunks of the same size\n *\n * @param {string} str - string to separate into chunks\n * @param {int} size - number of characters wanted in each chunk\n * @return {array} - array of original string split into chunks\n *\n * @example\n *      chunkify(\"this is a test\", 2)\n */\nfunction chunkify(str, size) {\n  const chunks = []\n  for (let i = 0; i < str.length; i += size) {\n    chunks.push(str.slice(i, i + size))\n  }\n  return chunks\n}\n\n/**\n * Rotates string representation of bits to the right\n *\n * @param {string} bits - string representation of bits\n * @param {int} turns - number of rotations to make\n * @return {string} - string representation of bits after rotation\n *\n * @example\n *      rotateRight(\"1011\", 3); // \"1101\"\n */\nfunction rotateRight(bits, turns) {\n  return bits.substr(bits.length - turns) + bits.substr(0, bits.length - turns)\n}\n\n/**\n * Pre-processes message to feed the algorithm loop\n *\n * @param {string} message - message to pre-process\n * @return {string} - processed message\n */\nfunction preProcess(message) {\n  // convert message to binary representation padded to\n  // 8 bits, and add 1\n  let m =\n    message\n      .split('')\n      .map((e) => e.charCodeAt(0))\n      .map((e) => e.toString(2))\n      .map((e) => pad(e, 8))\n      .join('') + '1'\n\n  // extend message by adding empty bits (0)\n  while (m.length % 512 !== 448) {\n    m += '0'\n  }\n\n  // length of message in binary, padded, and extended\n  // to a 64 bit representation\n  let ml = (message.length * CHAR_SIZE).toString(2)\n  ml = pad(ml, 8)\n  ml = '0'.repeat(64 - ml.length) + ml\n\n  return m + ml\n}\n\n/**\n * Hashes message using SHA-256 Cryptographic Hash Function\n *\n * @param {string} message - message to hash\n * @return {string} - message digest (hash value)\n */\nfunction SHA256(message) {\n  // initial hash variables\n  let H0 = 0x6a09e667\n  let H1 = 0xbb67ae85\n  let H2 = 0x3c6ef372\n  let H3 = 0xa54ff53a\n  let H4 = 0x510e527f\n  let H5 = 0x9b05688c\n  let H6 = 0x1f83d9ab\n  let H7 = 0x5be0cd19\n\n  // pre-process message and split into 512 bit chunks\n  const bits = preProcess(message)\n  const chunks = chunkify(bits, 512)\n\n  chunks.forEach(function (chunk, i) {\n    // break each chunk into 16 32-bit words\n    const words = chunkify(chunk, 32)\n\n    // extend 16 32-bit words to 80 32-bit words\n    for (let i = 16; i < 64; i++) {\n      const W1 = words[i - 15]\n      const W2 = words[i - 2]\n      const R1 = rotateRight(W1, 7)\n      const R2 = rotateRight(W1, 18)\n      const R3 = rotateRight(W2, 17)\n      const R4 = rotateRight(W2, 19)\n      const S0 = parseInt(R1, 2) ^ parseInt(R2, 2) ^ (parseInt(W1, 2) >>> 3)\n      const S1 = parseInt(R3, 2) ^ parseInt(R4, 2) ^ (parseInt(W2, 2) >>> 10)\n      const val =\n        parseInt(words[i - 16], 2) + S0 + parseInt(words[i - 7], 2) + S1\n      words[i] = pad((val >>> 0).toString(2), 32)\n    }\n\n    // initialize variables for this chunk\n    let [a, b, c, d, e, f, g, h] = [H0, H1, H2, H3, H4, H5, H6, H7]\n\n    for (let i = 0; i < 64; i++) {\n      const S1 =\n        [6, 11, 25]\n          .map((turns) => rotateRight(pad(e.toString(2), 32), turns))\n          .map((bitstring) => parseInt(bitstring, 2))\n          .reduce((acc, curr) => acc ^ curr, 0) >>> 0\n      const CH = ((e & f) ^ (~e & g)) >>> 0\n      const temp1 = (h + S1 + CH + K[i] + parseInt(words[i], 2)) >>> 0\n      const S0 =\n        [2, 13, 22]\n          .map((turns) => rotateRight(pad(a.toString(2), 32), turns))\n          .map((bitstring) => parseInt(bitstring, 2))\n          .reduce((acc, curr) => acc ^ curr, 0) >>> 0\n      const maj = ((a & b) ^ (a & c) ^ (b & c)) >>> 0\n      const temp2 = (S0 + maj) >>> 0\n\n      h = g\n      g = f\n      f = e\n      e = (d + temp1) >>> 0\n      d = c\n      c = b\n      b = a\n      a = (temp1 + temp2) >>> 0\n    }\n\n    // add values for this chunk to main hash variables (unsigned)\n    H0 = (H0 + a) >>> 0\n    H1 = (H1 + b) >>> 0\n    H2 = (H2 + c) >>> 0\n    H3 = (H3 + d) >>> 0\n    H4 = (H4 + e) >>> 0\n    H5 = (H5 + f) >>> 0\n    H6 = (H6 + g) >>> 0\n    H7 = (H7 + h) >>> 0\n  })\n\n  // combine hash values of main hash variables and return\n  const HH = [H0, H1, H2, H3, H4, H5, H6, H7]\n    .map((e) => e.toString(16))\n    .map((e) => pad(e, 8))\n    .join('')\n\n  return HH\n}\n\n// export SHA256 function\nexport { SHA256 }\n"
  },
  {
    "path": "Hashes/tests/MD5.test.js",
    "content": "import { MD5 } from '../MD5'\n\n/**\n * Returns the MD5 hash of the given message as a hexadecimal string\n *\n * @param {Uint8Array} message - message to hash\n * @return {string} - hash as a hexadecimal string\n */\nfunction hexMD5(message) {\n  return Array.from(MD5(message), (byte) =>\n    byte.toString(16).padStart(2, '0')\n  ).join('')\n}\n\ndescribe('Testing MD5 function', () => {\n  it('should return the correct hash for \"The quick brown fox jumps over the lazy dog\"', () => {\n    const input = new TextEncoder().encode(\n      'The quick brown fox jumps over the lazy dog'\n    )\n    const hash = hexMD5(input)\n\n    expect(hash).toBe('9e107d9d372bb6826bd81d3542a419d6')\n  })\n\n  it('should return the correct hash for \"JavaScript!\"', () => {\n    const input = new TextEncoder().encode('JavaScript!')\n    const hash = hexMD5(input)\n\n    expect(hash).toBe('209eddd6b61af0643907a8e069a08fb8')\n  })\n\n  it('should correctly hash an empty string', () => {\n    const input = new TextEncoder().encode('')\n    const hash = hexMD5(input)\n\n    expect(hash).toBe('d41d8cd98f00b204e9800998ecf8427e')\n  })\n})\n"
  },
  {
    "path": "Hashes/tests/SHA1.test.js",
    "content": "import { describe, test } from 'vitest'\nimport { SHA1 } from '../SHA1'\n\ndescribe('Testing SHA1 function', () => {\n  it.each([\n    ['', 'da39a3ee5e6b4b0d3255bfef95601890afd80709'],\n    [\n      'The quick brown fox jumps over the lazy dog',\n      '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'\n    ],\n    [\n      'The quick brown fox jumps over the lazy cog',\n      'de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3'\n    ],\n    ['a', '86f7e437faa5a7fce15d1ddcb9eaeaea377667b8'],\n    ['Today is 29.01.2024!', 'ae829b60d11fb5ab527d5db2501e06da3402718d'],\n    ['Have a nice day.', 'ed51dd3909281c25db5e1d8b1ce6fc701fda20ab'],\n    [\n      '12345678901234567890123456789012345678901234567890123456789012345678901234567890',\n      '50abf5706a150990a08b2c5ea40fa0e585554732'\n    ]\n  ])('check with %j', (input, expected) => {\n    expect(SHA1(input)).toBe(expected)\n  })\n})\n"
  },
  {
    "path": "Hashes/tests/SHA256.test.js",
    "content": "import { describe, test } from 'vitest'\nimport { SHA256 } from '../SHA256'\n\ndescribe('Testing SHA256 function', () => {\n  it.each([\n    ['', 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'],\n    [\n      'The quick brown fox jumps over the lazy dog',\n      'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592'\n    ],\n    [\n      'The quick brown fox jumps over the lazy cog',\n      'e4c4d8f3bf76b692de791a173e05321150f7a345b46484fe427f6acc7ecc81be'\n    ],\n    [\n      'This was added by vil02 on 01.02.2024. Have a nice day!',\n      '476025d91db754ab6ac0c124367afd7c108d041b2f497006a214d5035769ed5d'\n    ],\n    [\n      '012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789',\n      '14582b3f153941891dca966b036a5b1de65fa3b7a2540095a31614da1de0feaf'\n    ],\n    ['a', 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb']\n  ])('check with %j', (input, expected) => {\n    expect(SHA256(input)).toBe(expected)\n  })\n})\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    {one line to give the program's name and a brief idea of what it does.}\n    Copyright (C) {year}  {name of author}\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    {project}  Copyright (C) {year}  {fullname}\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "Maths/Abs.js",
    "content": "/**\n * @function abs\n * @description This script will find the absolute value of a number.\n * @param {number} num - The input integer\n * @return {number} - Absolute number of num.\n * @see https://en.wikipedia.org/wiki/Absolute_value\n * @example abs(-10) = 10\n * @example abs(50) = 50\n * @example abs(0) = 0\n */\n\nconst abs = (num) => {\n  const validNumber = +num // converted to number, also can use - Number(num)\n\n  if (Number.isNaN(validNumber) || typeof num === 'object') {\n    throw new TypeError('Argument is NaN - Not a Number')\n  }\n\n  return validNumber < 0 ? -validNumber : validNumber // if number is less than zero means negative, then it converted to positive. i.e., n = -2 = -(-2) = 2\n}\n\nexport { abs }\n"
  },
  {
    "path": "Maths/AliquotSum.js",
    "content": "/*\n  A program to calculate the Aliquot Sum of a number.\n  The aliquot sum of a number n, is the sum of all the proper divisors of n apart from n itself\n  For example, for the number 6\n  The divisors are 1, 2, 3 (we don't consider 6), so its aliquot sum is 1 + 2 + 3 = 6\n  1 is the only number whose aliquot sum is 0 (since its only divisor is 1 and aliquot sum of a number couldn't have itself)\n  For all prime numbers, the aliquot sum is 1, since their only divisor apart from themselves is 1\n  Article on Aliquot Sum: https://en.wikipedia.org/wiki/Aliquot_sum\n */\n\n/**\n * @param {Number} input The number whose aliquot sum you want to calculate\n */\nfunction aliquotSum(input) {\n  // input can't be negative\n  if (input < 0) throw new TypeError('Input cannot be Negative')\n\n  // input can't be a decimal\n  if (Math.floor(input) !== input)\n    throw new TypeError('Input cannot be a Decimal')\n\n  // Dealing with 1, which isn't a prime\n  if (input === 1) return 0\n\n  let sum = 0\n  for (let i = 1; i <= input / 2; i++) {\n    if (input % i === 0) sum += i\n  }\n\n  return sum\n}\n\nexport { aliquotSum }\n"
  },
  {
    "path": "Maths/Area.js",
    "content": "/*\n  Calculate the area of various shapes\n*/\n\n/**\n * @function surfaceAreaCube\n * @description Calculate the Surface Area of a Cube.\n * @param {Integer} side - Integer\n * @return {Integer} - 6 * side ** 2\n * @see [surfaceAreaCube](https://en.wikipedia.org/wiki/Area#Surface_area)\n * @example surfaceAreaCube(1) = 6\n */\nconst surfaceAreaCube = (side) => {\n  validateNumericParam(side, 'side')\n  return 6 * side ** 2\n}\n\n/**\n * @function surfaceAreaSphere\n * @description Calculate the Surface Area of a Sphere.\n * @param {Integer} radius - Integer\n * @return {Integer} - 4 * pi * r^2\n * @see [surfaceAreaSphere](https://en.wikipedia.org/wiki/Sphere)\n * @example surfaceAreaSphere(5) = 314.1592653589793\n */\nconst surfaceAreaSphere = (radius) => {\n  validateNumericParam(radius, 'radius')\n  return 4.0 * Math.PI * radius ** 2.0\n}\n\n/**\n * @function areaRectangle\n * @description Calculate the area of a rectangle.\n * @param {Integer} length - Integer\n * @param {Integer} width - Integer\n * @return {Integer} - width * length\n * @see [areaRectangle](https://en.wikipedia.org/wiki/Area#Quadrilateral_area)\n * @example areaRectangle(4) = 16\n */\nconst areaRectangle = (length, width) => {\n  validateNumericParam(length, 'Length')\n  validateNumericParam(width, 'Width')\n  return width * length\n}\n\n/**\n * @function areaSquare\n * @description Calculate the area of a square.\n * @param {Integer} side - Integer\n * @return {Integer} - side ** 2.\n * @see [areaSquare](https://en.wikipedia.org/wiki/Square)\n * @example areaSquare(4) = 16\n */\nconst areaSquare = (side) => {\n  validateNumericParam(side, 'square side')\n  return side ** 2\n}\n\n/**\n * @function areaTriangle\n * @description Calculate the area of a triangle.\n * @param {Integer} base - Integer\n * @param {Integer} height - Integer\n * @return {Integer} - base * height / 2.\n * @see [areaTriangle](https://en.wikipedia.org/wiki/Area#Triangle_area)\n * @example areaTriangle(1.66, 3.44) = 2.8552\n */\nconst areaTriangle = (base, height) => {\n  validateNumericParam(base, 'Base')\n  validateNumericParam(height, 'Height')\n  return (base * height) / 2.0\n}\n\n/**\n * @function areaTriangleWithAllThreeSides\n * @description Calculate the area of a triangle with the all three sides given.\n * @param {Integer} side1 - Integer\n * @param {Integer} side2 - Integer\n * @param {Integer} side3 - Integer\n * @return {Integer} - area of triangle.\n * @see [areaTriangleWithAllThreeSides](https://en.wikipedia.org/wiki/Heron%27s_formula)\n * @example areaTriangleWithAllThreeSides(5, 6, 7) = 14.7\n */\nconst areaTriangleWithAllThreeSides = (side1, side2, side3) => {\n  validateNumericParam(side1, 'side1')\n  validateNumericParam(side2, 'side2')\n  validateNumericParam(side3, 'side3')\n  if (\n    side1 + side2 <= side3 ||\n    side1 + side3 <= side2 ||\n    side2 + side3 <= side1\n  ) {\n    throw new TypeError('Invalid Triangle sides.')\n  }\n  // Finding Semi perimeter of the triangle using formula\n  const semi = (side1 + side2 + side3) / 2\n\n  // Calculating the area of the triangle\n  const area = Math.sqrt(\n    semi * (semi - side1) * (semi - side2) * (semi - side3)\n  )\n  return Number(area.toFixed(2))\n}\n\n/**\n * @function areaParallelogram\n * @description Calculate the area of a parallelogram.\n * @param {Integer} base - Integer\n * @param {Integer} height - Integer\n * @return {Integer} - base * height\n * @see [areaParallelogram](https://en.wikipedia.org/wiki/Area#Dissection,_parallelograms,_and_triangles)\n * @example areaParallelogram(5, 6) = 24\n */\nconst areaParallelogram = (base, height) => {\n  validateNumericParam(base, 'Base')\n  validateNumericParam(height, 'Height')\n  return base * height\n}\n\n/**\n * @function areaTrapezium\n * @description Calculate the area of a trapezium.\n * @param {Integer} base1 - Integer\n * @param {Integer} base2 - Integer\n * @param {Integer} height - Integer\n * @return {Integer} - (1 / 2) * (base1 + base2) * height\n * @see [areaTrapezium](https://en.wikipedia.org/wiki/Trapezoid)\n * @example areaTrapezium(5, 12, 10) = 85\n */\nconst areaTrapezium = (base1, base2, height) => {\n  validateNumericParam(base1, 'Base One')\n  validateNumericParam(base2, 'Base Two')\n  validateNumericParam(height, 'Height')\n  return (1 / 2) * (base1 + base2) * height\n}\n\n/**\n * @function areaCircle\n * @description Calculate the area of a circle.\n * @param {Integer} radius - Integer\n * @return {Integer} - Math.PI * radius ** 2\n * @see [areaCircle](https://en.wikipedia.org/wiki/Area_of_a_circle)\n * @example areaCircle(5, 12, 10) = 85\n */\nconst areaCircle = (radius) => {\n  validateNumericParam(radius, 'Radius')\n  return Math.PI * radius ** 2\n}\n\n/**\n * @function areaRhombus\n * @description Calculate the area of a rhombus.\n * @param {Integer} diagonal1 - Integer\n * @param {Integer} diagonal2 - Integer\n * @return {Integer} - (1 / 2) * diagonal1 * diagonal2\n * @see [areaRhombus](https://en.wikipedia.org/wiki/Rhombus)\n * @example areaRhombus(12, 10) = 60\n */\nconst areaRhombus = (diagonal1, diagonal2) => {\n  validateNumericParam(diagonal1, 'diagonal one')\n  validateNumericParam(diagonal2, 'diagonal two')\n  return (1 / 2) * diagonal1 * diagonal2\n}\n\nconst validateNumericParam = (param, paramName = 'param') => {\n  if (typeof param !== 'number') {\n    throw new TypeError('The ' + paramName + ' should be type Number')\n  } else if (param < 0) {\n    throw new Error('The ' + paramName + ' only accepts non-negative values')\n  }\n}\n\nexport {\n  surfaceAreaCube,\n  surfaceAreaSphere,\n  areaRectangle,\n  areaSquare,\n  areaTriangle,\n  areaParallelogram,\n  areaTrapezium,\n  areaCircle,\n  areaRhombus,\n  areaTriangleWithAllThreeSides\n}\n"
  },
  {
    "path": "Maths/ArithmeticGeometricMean.js",
    "content": "/**\n * @function agm\n * @description This finds the Arithmetic-Geometric Mean between any 2 numbers.\n * @param {Number} a - 1st number, also used to store Arithmetic Mean.\n * @param {Number} g - 2nd number, also used to store Geometric Mean.\n * @return {Number} - AGM of both numbers.\n * @see [AGM](https://en.wikipedia.org/wiki/Arithmetic%E2%80%93geometric_mean)\n */\n\nexport const agm = (a, g) => {\n  if (a === Infinity && g === 0) return NaN\n  if (Object.is(a, -0) && !Object.is(g, -0)) return 0\n  if (a === g) return a // avoid rounding errors, and increase efficiency\n  let x // temp var\n  do {\n    ;[a, g, x] = [(a + g) / 2, Math.sqrt(a * g), a]\n  } while (a !== x && !isNaN(a))\n  /*\n  `x !== a` ensures the return value has full precision,\n  and prevents infinite loops caused by rounding differences between `div` and `sqrt` (no need for \"epsilon\").\n  If we were to compare `a` with `g`, some input combinations (not all) can cause an infinite loop,\n  because the rounding mode never changes at runtime.\n  Precision is not the same as accuracy, but they're related.\n  This function isn't always 100% accurate (round-errors), but at least is more than 95% accurate.\n  `!isNaN(x)` prevents infinite loops caused by invalid inputs like: negatives, NaNs and Infinities.\n  */\n  return a\n}\n"
  },
  {
    "path": "Maths/ArmstrongNumber.js",
    "content": "/**\n * Author: dephraiim\n * License: GPL-3.0 or later\n *\n * An Armstrong number is equal to the sum of its own digits each raised to the power of the number of digits.\n * For example, 370 is an Armstrong number because 3*3*3 + 7*7*7 + 0*0*0 = 370.\n * An Armstrong number is often called Narcissistic number.\n *\n */\n\nconst armstrongNumber = (num) => {\n  if (typeof num !== 'number' || num < 0) return false\n  const numStr = num.toString()\n  const sum = [...numStr].reduce(\n    (acc, digit) => acc + parseInt(digit) ** numStr.length,\n    0\n  )\n  return sum === num\n}\n\nexport { armstrongNumber }\n"
  },
  {
    "path": "Maths/AutomorphicNumber.js",
    "content": "/**\n * @function isAutomorphic\n * @author [SilverDragonOfR] (https://github.com/SilverDragonOfR)\n *\n * @see [Automorphic] (https://en.wikipedia.org/wiki/Automorphic_number)\n * @description This script will check whether a number is Automorphic or not\n * @description A number n is said to be a Automorphic number if the square of n ends in the same digits as n itself.\n *\n * @param {Integer} n - the n for nth Catalan Number\n * @return {Integer} - the nth Catalan Number\n * @complexity Time: O(log10(n)) , Space: O(1)\n *\n * @convention We define Automorphic only for whole number integers. For negetive integer we return False. For float or String we show error.\n * @examples 0, 1, 5, 6, 25, 76, 376, 625, 9376 are some Automorphic numbers\n */\n\n// n is the number to be checked\nexport const isAutomorphic = (n) => {\n  if (typeof n !== 'number') {\n    throw new Error('Type of n must be number')\n  }\n  if (!Number.isInteger(n)) {\n    throw new Error('n cannot be a floating point number')\n  }\n  if (n < 0) {\n    return false\n  }\n\n  // now n is a whole number integer >= 0\n  let n_sq = n * n\n  while (n > 0) {\n    if (n % 10 !== n_sq % 10) {\n      return false\n    }\n    n = Math.floor(n / 10)\n    n_sq = Math.floor(n_sq / 10)\n  }\n\n  return true\n}\n"
  },
  {
    "path": "Maths/AverageMean.js",
    "content": "/**\n * @function mean\n * @description This script will find the mean value of a array of numbers.\n * @param {number[]} numbers - Array of integer\n * @return {number} - mean of numbers.\n * @throws {TypeError} If the input is not an array or contains non-number elements.\n * @throws {Error} If the input array is empty.\n * @see [Mean](https://en.wikipedia.org/wiki/Mean)\n * @example mean([1, 2, 4, 5]) = 3\n * @example mean([10, 40, 100, 20]) = 42.5\n */\nconst mean = (numbers) => {\n  if (!Array.isArray(numbers)) {\n    throw new TypeError('Invalid Input')\n  } else if (numbers.length === 0) {\n    throw new Error('Array is empty')\n  }\n\n  let total = 0\n  numbers.forEach((num) => {\n    if (typeof num !== 'number') {\n      throw new TypeError('Invalid Input')\n    }\n    total += num\n  })\n\n  return total / numbers.length\n}\n\nexport { mean }\n"
  },
  {
    "path": "Maths/AverageMedian.js",
    "content": "/*\n * Median: https://en.wikipedia.org/wiki/Median\n *\n * function averageMedian\n * to find the median value of an array of numbers\n * the numbers in an array will be sorted in ascending order by the function sortNumbers\n * if the length of the array is even number, the median value will be the average of the two middle numbers\n * else if the length of the array is odd number, the median value will be the middle number in the array\n */\n\nconst averageMedian = (sourceArrayOfNumbers) => {\n  const numbers = [...sourceArrayOfNumbers].sort(sortNumbers)\n  const numLength = numbers.length\n\n  return numLength % 2 === 0\n    ? (numbers[numLength / 2 - 1] + numbers[numLength / 2]) / 2\n    : numbers[Math.floor(numLength / 2)]\n}\n\nconst sortNumbers = (num1, num2) => num1 - num2\n\nexport { averageMedian }\n"
  },
  {
    "path": "Maths/BinaryConvert.js",
    "content": "/**\n * @function BinaryConvert\n * @description Convert the decimal to binary.\n * @param {Integer} num - The input integer\n * @return {Integer} - Binary of num.\n * @see [BinaryConvert](https://www.programiz.com/javascript/examples/decimal-binary)\n * @example BinaryConvert(12) = 1100\n * @example BinaryConvert(12 + 2) = 1110\n */\n\nconst BinaryConvert = (num) => {\n  let power = 1\n  let binary = 0\n\n  while (num) {\n    const rem = num % 2\n    num = Math.floor(num / 2)\n    binary = rem * power + binary\n    power *= 10\n  }\n\n  return binary\n}\n\nexport { BinaryConvert }\n"
  },
  {
    "path": "Maths/BinaryExponentiationIterative.js",
    "content": "// To calculate x^n i.e., exponent(x, n) in O(log n) time in iterative way\n// n is an integer and n >= 0\n\n// Explanation: https://en.wikipedia.org/wiki/Exponentiation_by_squaring\n\n// Examples:\n// 2^3 = 8\n// 5^0 = 1\n\n// Uses the fact that\n// exponent(x, n)\n//          = exponent(x*x, floor(n/2))   ; if n is odd\n//          = x*exponent(x*x, floor(n/2)) ; if n is even\nconst exponent = (x, n) => {\n  let answer = 1\n  while (n > 0) {\n    if (n % 2 !== 0) answer *= x\n    n = Math.floor(n / 2)\n    if (n > 0) x *= x\n  }\n  return answer\n}\n\nexport { exponent }\n"
  },
  {
    "path": "Maths/BinaryExponentiationRecursive.js",
    "content": "/*\n  Modified from:\n    https://github.com/TheAlgorithms/Python/blob/master/maths/binary_exponentiation.py\n\n  Explanation:\n    https://en.wikipedia.org/wiki/Exponentiation_by_squaring\n*/\n\nexport const binaryExponentiation = (a, n) => {\n  // input: a: int, n: int\n  // returns: a^n: int\n  if (n === 0) {\n    return 1\n  } else if (n % 2 === 1) {\n    return binaryExponentiation(a, n - 1) * a\n  } else {\n    const b = binaryExponentiation(a, n / 2)\n    return b * b\n  }\n}\n"
  },
  {
    "path": "Maths/BinomialCoefficient.js",
    "content": "/*\n * Author: Akshay Dubey (https://github.com/itsAkshayDubey)\n * Binomial Coefficient: https://en.wikipedia.org/wiki/Binomial_coefficient\n * function to find binomial coefficient of numbers n and k.\n * return binomial coefficient of n,k\n */\n\n/**\n * @function findBinomialCoefficient\n * @description -> this function returns binomial coefficient\n * of two numbers n & k given by n!/((n-k)!k!)\n * @param {number} n\n * @param {number} k\n * @returns {number}\n */\n\nimport { calcFactorial } from './Factorial'\n\nexport const findBinomialCoefficient = (n, k) => {\n  if (typeof n !== 'number' || typeof k !== 'number') {\n    throw Error('Type of arguments must be number.')\n  }\n  if (n < 0 || k < 0) {\n    throw Error('Arguments must be greater than zero.')\n  }\n  let product = 1\n  for (let i = n; i > k; i--) {\n    product *= i\n  }\n  return product / calcFactorial(n - k)\n}\n"
  },
  {
    "path": "Maths/BisectionMethod.js",
    "content": "/**\n *\n * @file\n * @brief Find real roots of a function in a specified interval [a, b], where f(a)*f(b) < 0\n *\n * @details Given a function f(x) and an interval [a, b], where f(a) * f(b) < 0, find an approximation of the root\n * by calculating the middle m = (a + b) / 2, checking f(m) * f(a) and f(m) * f(b) and then by choosing the\n * negative product that means Bolzano's theorem is applied,, define the new interval with these points. Repeat until\n * we get the precision we want [Wikipedia](https://en.wikipedia.org/wiki/Bisection_method)\n *\n * @author [ggkogkou](https://github.com/ggkogkou)\n *\n */\n\nconst findRoot = (a, b, func, numberOfIterations) => {\n  // Check if a given  real value belongs to the function's domain\n  const belongsToDomain = (x, f) => {\n    const res = f(x)\n    return !Number.isNaN(res)\n  }\n  if (!belongsToDomain(a, func) || !belongsToDomain(b, func))\n    throw Error(\"Given interval is not a valid subset of function's domain\")\n\n  // Bolzano theorem\n  const hasRoot = (a, b, func) => {\n    return func(a) * func(b) <= 0\n  }\n  if (hasRoot(a, b, func) === false) {\n    throw Error(\n      'Product f(a)*f(b) has to be negative so that Bolzano theorem is applied'\n    )\n  }\n\n  // Declare m\n  const m = (a + b) / 2\n\n  // Recursion terminal condition\n  if (numberOfIterations === 0) {\n    return m\n  }\n\n  // Find the products of f(m) and f(a), f(b)\n  const fm = func(m)\n  const prod1 = fm * func(a)\n  const prod2 = fm * func(b)\n\n  // Depending on the sign of the products above, decide which position will m fill (a's or b's)\n  if (prod2 <= 0) return findRoot(m, b, func, --numberOfIterations)\n\n  return findRoot(a, m, func, --numberOfIterations)\n}\n\nexport { findRoot }\n"
  },
  {
    "path": "Maths/CheckKishnamurthyNumber.js",
    "content": "/*\n    Problem statement and Explanation : https://www.geeksforgeeks.org/check-if-a-number-is-a-krishnamurthy-number-or-not-2/\n\n    krishnamurthy number is a number the sum of the all factorial of the all dights is equal to the number itself.\n    145 => 1! + 4! + 5! = 1  + 24 + 120 = 145\n*/\n\n// factorial utility method.\nconst factorial = (n) => {\n  let fact = 1\n  while (n !== 0) {\n    fact = fact * n\n    n--\n  }\n  return fact\n}\n\n/**\n * krishnamurthy number is a number the sum of the factorial of the all dights is equal to the number itself.\n * @param {Number} number a number for checking is krishnamurthy number or not.\n * @returns return correspond boolean value, if the number is krishnamurthy number return `true` else return `false`.\n * @example 145 => 1! + 4! + 5! = 1  + 24 + 120 = 145\n */\nconst CheckKishnamurthyNumber = (number) => {\n  // firstly, check that input is a number or not.\n  if (typeof number !== 'number') {\n    throw new TypeError('Argument is not a number.')\n  }\n  if (number === 0) {\n    return false\n  }\n  // create a variable to store the sum of all digits factorial.\n  let sumOfAllDigitFactorial = 0\n  // convert the number to string for convenience.\n  let newNumber = number\n  // Extract number digits using the remainder method.\n  while (newNumber > 0) {\n    const lastDigit = newNumber % 10\n    // calculate each digit factorial.\n    sumOfAllDigitFactorial += factorial(lastDigit)\n    newNumber = Math.floor(newNumber / 10)\n  }\n  // if the sumOfAllDigitFactorial is equal to the given number it means the number is a Krishnamurthy number.\n  return sumOfAllDigitFactorial === number\n}\n\nexport { CheckKishnamurthyNumber }\n"
  },
  {
    "path": "Maths/CircularArc.js",
    "content": "import { degreeToRadian } from './DegreeToRadian.js'\n\n/**\n * @function circularArcLength\n * @description calculate the length of a circular arc\n * @param {Integer} radius\n * @param {Integer} degrees\n * @returns {Integer} radius * angle_in_radians\n * @see https://en.wikipedia.org/wiki/Circular_arc\n * @example circularArcLength(3, 45) = 2.356194490192345\n */\nfunction circularArcLength(radius, degrees) {\n  return radius * degreeToRadian(degrees)\n}\n/**\n * @function circularArcArea\n * @description calculate the area of the sector formed by an arc\n * @param {Integer} radius\n * @param {Integer} degrees\n * @returns {Integer} 0.5 * r * r * angle_in_radians\n * @see https://en.wikipedia.org/wiki/Circular_arc\n * @example circularArcArea(3,45) = 3.5342917352885173\n */\nfunction circularArcArea(radius, degrees) {\n  return (Math.pow(radius, 2) * degreeToRadian(degrees)) / 2\n}\n\nexport { circularArcLength, circularArcArea }\n"
  },
  {
    "path": "Maths/CoPrimeCheck.js",
    "content": "/*\n    Problem statement and Explanation : https://en.wikipedia.org/wiki/Coprime_integers\n\n    In number theory, two integers a and b are coprime, relatively prime or\n    mutually prime if the only positive integer that is a divisor of both\n    of them is Consequently, any prime number that divides one of a\n    or b does not divide the other. This is equivalent to their greatest\n    common divisor (gcd) being. One says also a is prime to b or a\n    is coprime with b.\n*/\n\nimport { GetEuclidGCD } from './GetEuclidGCD'\n\n// CoPrimeCheck function return the boolean in respect of the given number is co-prime or not.\n/**\n * CoPrimeCheck function return the boolean in respect of the given number is co-prime or not.\n * @param {Number} firstNumber first number for checking is prime or not.\n * @param {Number} secondNumber second number for checking is prime or not.\n * @returns return correspond boolean value, if both number are co-prime return `true`, else return `false`.\n */\nconst CoPrimeCheck = (firstNumber, secondNumber) => {\n  /*\n    This is the most efficient algorithm for checking co-primes\n    if the GCD of both the numbers is 1 that means they are co-primes.\n    */\n  return GetEuclidGCD(firstNumber, secondNumber) === 1\n}\n\nexport { CoPrimeCheck }\n"
  },
  {
    "path": "Maths/CollatzSequence.js",
    "content": "/**\n * @function collatz\n * @description Applies the Collatz Sequence on a specified number.\n * The Collatz Sequence states that every natural number will always fall in a 1, 2, 4 loop when iterated under the following function:\n * If the number is even, divide by 2, and if its odd, multiply it by 3 and add 1.\n *\n * @parama {Integer} n The number to apply the Collatz Sequence to.\n *\n * @return An array of steps and the final result..\n *\n * @see [Collatz Conjecture](https://en.wikipedia.org/wiki/Collatz_conjecture)\n *\n * @example collatz(1) = { result: 1, steps: [] }\n * @example collatz(5) = { result: 1, steps: [16, 8, 4, 2, 1] }\n */\nexport function collatz(n) {\n  const steps = []\n\n  while (n !== 1) {\n    if (n % 2 === 0) {\n      n = n / 2\n    } else {\n      n = 3 * n + 1\n    }\n\n    steps.push(n)\n  }\n\n  return { result: n, steps }\n}\n"
  },
  {
    "path": "Maths/Coordinate.js",
    "content": "/*\n Calculate the mathematical properties involving coordinates\n Calculate the Distance Between 2 Points on a 2 Dimensional Plane\n Example: coorDistance(2,2,14,11) will return 15\n Wikipedia reference: https://en.wikipedia.org/wiki/Geographical_distance#Flat-surface_formulae\n*/\nconst euclideanDistance = (longitude1, latitude1, longitude2, latitude2) => {\n  const width = longitude2 - longitude1\n  const height = latitude2 - latitude1\n  return Math.sqrt(width * width + height * height)\n}\n\nconst manhattanDistance = (longitude1, latitude1, longitude2, latitude2) => {\n  const width = Math.abs(longitude2 - longitude1)\n  const height = Math.abs(latitude2 - latitude1)\n  return width + height\n}\n\nexport { euclideanDistance, manhattanDistance }\n"
  },
  {
    "path": "Maths/CountNumbersDivisible.js",
    "content": "/**\n * Count the numbers divisible by ‘M’ in a given range\n *\n * @see {@link https://www.tutorialspoint.com/count-the-numbers-divisible-by-m-in-a-given-range-in-cplusplus}\n *\n * We have 3 numbers A, B, M as inputs, A and B defines the numbers range [A, B]\n * Count the total number of divisibles in that range by number M\n *\n * @author Chetan07j\n */\n\n/**\n * Function to find total divisibles in given range\n *\n * @param {number} num1\n * @param {number} num2\n * @param {number} divider\n *\n * @returns {number} count of total number of divisibles\n */\nconst countNumbersDivisible = (num1, num2, divider) => {\n  if (\n    typeof num1 !== 'number' ||\n    typeof num2 !== 'number' ||\n    typeof divider !== 'number'\n  ) {\n    throw new Error('Invalid input, please pass only numbers')\n  }\n\n  // Valid number range is num1 < num2, otherwise throw error\n  if (num1 > num2) {\n    throw new Error(\n      'Invalid number range, please provide numbers such that num1 < num2'\n    )\n  }\n\n  // if divider is out of range then return 0\n  // as in such case no divisible exists\n  if (divider > num2) {\n    return 0\n  }\n\n  // Find the number of multiples of divider for num1 and num2\n  // integer division part\n  const num1Multiplier = num1 / divider\n  const num2Multiplier = num2 / divider\n\n  // The count of numbers divisibles by divider between num1 and num2\n  let divisibleCount = num2Multiplier - num1Multiplier\n\n  // If num1 is divisible by divider then, edge case for num1 is ignored\n  // which results in 1 less count\n  // to fix that we add +1 in this case\n  if (num1 % divider === 0) {\n    divisibleCount++\n  }\n\n  // As it includes integer division meaning floating values\n  // to get exact count Math.round() is added\n  return Math.round(divisibleCount)\n}\n\nexport { countNumbersDivisible }\n"
  },
  {
    "path": "Maths/DecimalExpansion.js",
    "content": "/**\n * @author Eric Lavault <https://github.com/lvlte>\n *\n * Represents the decimal (or binary, octal, any base from 2 to 10) expansion\n * of a/b using euclidean division.\n *\n * Because this function is recursive, it may throw an error when reaching the\n * maximum call stack size.\n *\n * Returns an array containing : [\n *  0: integer part of the division\n *  1: array of decimals (if any, or an empty array)\n *  2: indexOf 1st cycle digit in decimals array if a/b is periodic, or undef.\n * ]\n *\n * @see https://mathworld.wolfram.com/DecimalExpansion.html\n *\n * @param {number} a\n * @param {number} b\n * @param {number} [base=10]\n * @returns {array}\n */\nexport function decExp(a, b, base = 10, exp = [], d = {}, dlen = 0) {\n  if (base < 2 || base > 10) {\n    throw new RangeError('Unsupported base. Must be in range [2, 10]')\n  }\n\n  if (a === 0) {\n    return [0, [], undefined]\n  }\n\n  if (a === b && dlen === 0) {\n    return [1, [], undefined]\n  }\n\n  // d contains the dividends used so far and the corresponding index of its\n  // euclidean division by b in the expansion array.\n  d[a] = dlen++\n\n  if (a < b) {\n    exp.push(0)\n    return decExp(a * base, b, base, exp, d, dlen)\n  }\n\n  // Euclid's division lemma : a = bq + r\n  const r = a % b\n  const q = (a - r) / b\n\n  // Decimal expansion (1st element is the integer part)\n  exp.push(+q.toString(base))\n\n  if (r === 0) {\n    // got a regular number (division terminates)\n    return [exp[0], exp.slice(1), undefined]\n  }\n\n  // For the next iteration\n  a = r * base\n\n  // Check if `a` has already been used as a dividend, in which case it means\n  // the expansion is periodic.\n  if (a in d) {\n    return [exp[0], exp.slice(1), d[a] - 1]\n  }\n\n  return decExp(a, b, base, exp, d, dlen)\n}\n"
  },
  {
    "path": "Maths/DecimalIsolate.js",
    "content": "/*\n * function isolates the decimal part of a number.\n * Take the number and subtract it from the floored number.\n * Return the result.\n */\n\nexport const decimalIsolate = (number) => {\n  const answer = parseFloat((number + '').replace(/^[-\\d]+./, '.'))\n  return isNaN(answer) === true ? 0 : answer\n}\n"
  },
  {
    "path": "Maths/DegreeToRadian.js",
    "content": "/*\n * Radian : https://en.wikipedia.org/wiki/Radian\n * Degree : https://en.wikipedia.org/wiki/Degree_(angle)\n *\n * Angle in Radian = ( Angle in Degree ) x ( pi / 180 )\n *\n * Example :\n * Question : Convert 90 degree to radian\n * So, Angle in Degree = 90\n *\n * Solution :\n * Angle in Radian = ( 90 ) x ( pi / 180 ) = pi / 2\n *\n * So, 90 degree is equal to pi / 2 radian\n */\n\n/**\n * @param {number} degree\n * @return {number}\n */\nexport const degreeToRadian = (degree) => {\n  return degree * (Math.PI / 180)\n}\n"
  },
  {
    "path": "Maths/Determinant.js",
    "content": "/**\n * Given a square matrix, find its determinant using Laplace Expansion.\n * Time Complexity : O(n!)\n *\n * For more info: https://en.wikipedia.org/wiki/Determinant\n *\n * @param {number[[]]} matrix - Two dimensional array of integers.\n * @returns {number} - An integer equal to the determinant.\n *\n * @example\n * const squareMatrix = [\n *                          [2,3,4,6],\n *                          [5,8,9,0],\n *                          [7,4,3,9],\n *                          [4,0,2,1]\n *                      ];\n *\n * const result = determinant(squareMatrix);\n * // The function should return 858 as the resultant determinant.\n */\n\nconst subMatrix = (matrix, i, j) => {\n  let matrixSize = matrix[0].length\n  if (matrixSize === 1) {\n    return matrix[0][0]\n  }\n  let subMatrix = []\n  for (let x = 0; x < matrixSize; x++) {\n    if (x === i) {\n      continue\n    }\n    subMatrix.push([])\n    for (let y = 0; y < matrixSize; y++) {\n      if (y === j) {\n        continue\n      }\n      subMatrix[subMatrix.length - 1].push(matrix[x][y])\n    }\n  }\n  return subMatrix\n}\n\nconst isMatrixSquare = (matrix) => {\n  let numRows = matrix.length\n  for (let i = 0; i < numRows; i++) {\n    if (numRows !== matrix[i].length) {\n      return false\n    }\n  }\n  return true\n}\n\nconst determinant = (matrix) => {\n  if (\n    !Array.isArray(matrix) ||\n    matrix.length === 0 ||\n    !Array.isArray(matrix[0])\n  ) {\n    throw new Error('Input is not a valid 2D matrix.')\n  }\n  if (!isMatrixSquare(matrix)) {\n    throw new Error('Square matrix is required.')\n  }\n  let numCols = matrix[0].length\n  if (numCols === 1) {\n    return matrix[0][0]\n  }\n  let result = 0\n  let setIndex = 0\n  for (let i = 0; i < numCols; i++) {\n    result +=\n      Math.pow(-1, i) *\n      matrix[setIndex][i] *\n      determinant(subMatrix(matrix, setIndex, i))\n  }\n  return result\n}\nexport { determinant }\n"
  },
  {
    "path": "Maths/EuclideanDistance.js",
    "content": "/**\n * @see [Wikipedia](https://en.wikipedia.org/wiki/Euclidean_distance)\n * Calculate the Euclidean distance between two vectors.\n * @param {number[]} vector1 - The first vector.\n * @param {number[]} vector2 - The second vector.\n * @returns {number} The Euclidean distance between the two vectors.\n */\n\nconst EuclideanDistance = (vector1, vector2) => {\n  let sumOfSquares = 0\n\n  for (let i = 0; i < vector1.length; i++) {\n    sumOfSquares += Math.pow(vector1[i] - vector2[i], 2)\n  }\n\n  return Math.sqrt(sumOfSquares)\n}\n\nexport { EuclideanDistance }\n"
  },
  {
    "path": "Maths/EulerMethod.js",
    "content": "/**\n * In mathematics and computational science, the Euler method (also called forward Euler method) is a first-order\n * numerical procedure for solving ordinary differential equations (ODEs) with a given initial value. It is the most\n * basic explicit method for numerical integration of ordinary differential equations. The method proceeds in a series\n * of steps. At each step the y-value is calculated by evaluating the differential equation at the previous step,\n * multiplying the result with the step-size and adding it to the last y-value: y_n+1 = y_n + stepSize * f(x_n, y_n).\n *\n * (description adapted from https://en.wikipedia.org/wiki/Euler_method)\n * @see https://www.geeksforgeeks.org/euler-method-solving-differential-equation/\n */\nexport function eulerStep(xCurrent, stepSize, yCurrent, differentialEquation) {\n  // calculates the next y-value based on the current value of x, y and the stepSize\n  return yCurrent + stepSize * differentialEquation(xCurrent, yCurrent)\n}\n\nexport function eulerFull(\n  xStart,\n  xEnd,\n  stepSize,\n  yStart,\n  differentialEquation\n) {\n  // loops through all the steps until xEnd is reached, adds a point for each step and then returns all the points\n  const points = [{ x: xStart, y: yStart }]\n  let yCurrent = yStart\n  let xCurrent = xStart\n\n  while (xCurrent < xEnd) {\n    // Euler method for next step\n    yCurrent = eulerStep(xCurrent, stepSize, yCurrent, differentialEquation)\n    xCurrent += stepSize\n    points.push({ x: xCurrent, y: yCurrent })\n  }\n\n  return points\n}\n"
  },
  {
    "path": "Maths/EulersTotient.js",
    "content": "/*\n  Source:\n    https://en.wikipedia.org/wiki/Euler%27s_totient_function\n\n  EulersTotient(n) = n * product(1 - 1/p for all prime p dividing n)\n\n  Complexity:\n    O(sqrt(n))\n*/\n\nexport const EulersTotient = (n) => {\n  // input: n: int\n  // output: phi(n): count of numbers b/w 1 and n that are coprime to n\n  let res = n\n  for (let i = 2; i * i <= n; i++) {\n    if (n % i === 0) {\n      while (n % i === 0) {\n        n = Math.floor(n / i)\n      }\n      // i is a prime dividing n, multiply res by 1 - 1/i\n      // res = res * (1 - 1/i) = res - (res / i)\n      res = res - Math.floor(res / i)\n    }\n  }\n  if (n > 1) {\n    res = res - Math.floor(res / n)\n  }\n  return res\n}\n"
  },
  {
    "path": "Maths/EulersTotientFunction.js",
    "content": "/*\n    author sandyboypraper\n\n    Here is the EulerTotientFunction.\n    it is also represented by phi\n\n    so EulersTotientFunction(n) (or phi(n)) is the count of numbers in {1,2,3,....,n} that are relatively\n    prime to n, i.e., the numbers whose GCD (Greatest Common Divisor) with n is 1.\n*/\n\nconst gcdOfTwoNumbers = (x, y) => {\n  // x is smaller than y\n  // let gcd of x and y is gcdXY\n  // so it divides x and y completely\n  // so gcdXY should also divide y%x (y = gcdXY*a and x = gcdXY*b and y%x = y - x*k so y%x = gcdXY(a - b*k))\n  // and gcd(x,y) is equal to gcd(y%x, x)\n  return x === 0 ? y : gcdOfTwoNumbers(y % x, x)\n}\n\nconst eulersTotientFunction = (n) => {\n  let countOfRelativelyPrimeNumbers = 1\n  for (let iterator = 2; iterator <= n; iterator++) {\n    if (gcdOfTwoNumbers(iterator, n) === 1) countOfRelativelyPrimeNumbers++\n  }\n  return countOfRelativelyPrimeNumbers\n}\n\nexport { eulersTotientFunction }\n"
  },
  {
    "path": "Maths/ExponentialFunction.js",
    "content": "/**\n * @function exponentialFunction\n * @description Calculates the n+1 th order Taylor series approximation of exponential function e^x given n\n * @param {Integer} power\n * @param {Integer} order - 1\n * @returns exponentialFunction(2,20) = 7.3890560989301735\n * @url https://en.wikipedia.org/wiki/Exponential_function\n */\nfunction exponentialFunction(power, n) {\n  let output = 0\n  let fac = 1\n  if (isNaN(power) || isNaN(n) || n < 0) {\n    throw new TypeError('Invalid Input')\n  }\n  if (n === 0) {\n    return 1\n  }\n  for (let i = 0; i < n; i++) {\n    output += power ** i / fac\n    fac *= i + 1\n  }\n  return output\n}\n\nexport { exponentialFunction }\n"
  },
  {
    "path": "Maths/ExtendedEuclideanGCD.js",
    "content": "/**\n * Problem statement and explanation: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm\n *\n * This algorithm plays an important role for modular arithmetic, and by extension for cryptography algorithms\n *\n * Basic explanation:\n * The Extended Euclidean algorithm is a modification of the standard Euclidean GCD algorithm.\n * It allows to calculate coefficients x and y for the equation:\n *          ax + by = gcd(a,b)\n *\n * This is called Bézout's identity and the coefficients are called Bézout coefficients\n *\n * The algorithm uses the Euclidean method of getting remainder:\n * r_i+1 = r_i-1 - qi*ri\n * and applies it to series s and t (with same quotient q at each stage)\n * When r_n reaches 0, the value r_n-1 gives the gcd, and s_n-1 and t_n-1 give the coefficients\n *\n * This implementation uses an iterative approach to calculate the values\n */\n\n/**\n *\n * @param {Number} arg1 first argument\n * @param {Number} arg2 second argument\n * @returns Array with GCD and first and second Bézout coefficients\n */\nconst extendedEuclideanGCD = (arg1, arg2) => {\n  if (typeof arg1 !== 'number' || typeof arg2 !== 'number')\n    throw new TypeError('Not a Number')\n  if (arg1 < 1 || arg2 < 1) throw new TypeError('Must be positive numbers')\n\n  // Make the order of coefficients correct, as the algorithm assumes r0 > r1\n  if (arg1 < arg2) {\n    const res = extendedEuclideanGCD(arg2, arg1)\n    const temp = res[1]\n    res[1] = res[2]\n    res[2] = temp\n    return res\n  }\n\n  // At this point arg1 > arg2\n\n  // Remainder values\n  let r0 = arg1\n  let r1 = arg2\n\n  // Coefficient1 values\n  let s0 = 1\n  let s1 = 0\n\n  // Coefficient 2 values\n  let t0 = 0\n  let t1 = 1\n\n  while (r1 !== 0) {\n    const q = Math.floor(r0 / r1)\n\n    const r2 = r0 - r1 * q\n    const s2 = s0 - s1 * q\n    const t2 = t0 - t1 * q\n\n    r0 = r1\n    r1 = r2\n    s0 = s1\n    s1 = s2\n    t0 = t1\n    t1 = t2\n  }\n  return [r0, s0, t0]\n}\n\nexport { extendedEuclideanGCD }\n"
  },
  {
    "path": "Maths/Factorial.js",
    "content": "/*\n    author: PatOnTheBack\n    license: GPL-3.0 or later\n\n    Modified from:\n        https://github.com/TheAlgorithms/Python/blob/master/maths/factorial_python.py\n\n    This script will find the factorial of a number provided by the user.\n\n    More about factorials:\n        https://en.wikipedia.org/wiki/factorial\n*/\n\n'use strict'\n\nconst calcRange = (num) => {\n  return [...Array(num).keys()].map((i) => i + 1)\n}\n\nconst calcFactorial = (num) => {\n  if (num === 0) {\n    return 1\n  }\n  if (num < 0) {\n    throw Error('Sorry, factorial does not exist for negative numbers.')\n  }\n  if (!num) {\n    throw Error(\n      'Sorry, factorial does not exist for null or undefined numbers.'\n    )\n  }\n  if (num > 0) {\n    const range = calcRange(num)\n    const factorial = range.reduce((a, c) => a * c, 1)\n    return factorial\n  }\n}\n\nexport { calcFactorial }\n"
  },
  {
    "path": "Maths/Factors.js",
    "content": "/**\n * Author: dephraiim\n * License: GPL-3.0 or later\n *\n * More on Factors:\n *      https://www.mathsisfun.com/definitions/factor.html\n *\n */\n\nconst factorsOfANumber = (number = 0) => {\n  return Array.from(Array(number + 1).keys()).filter(\n    (num) => number % num === 0\n  )\n}\n\nexport { factorsOfANumber }\n"
  },
  {
    "path": "Maths/FareyApproximation.js",
    "content": "/*\n * Reference: https://en.wikipedia.org/wiki/Farey_sequence\n * Inspiration: https://www.youtube.com/watch?v=7LKy3lrkTRA\n *\n * Farey Approximation algorithm is an algorithm to\n * approximate a reduced fraction value for a certain\n * decimal number x where 0 < x < 1.\n *\n * The algorithm works by keeping two fractional upper and\n * lower bounds which start at 0 / 1 and 1 / 1. These values\n * are then used to find the \"mediate\" which is a value between\n * the two fractions.\n *\n * For any two fractions a / b and c / d,\n * mediate = a + c / b + d\n *\n * Then it is checked if the decimal is greater than or less\n * than the mediate and then the lower or the upper value is\n * set to be the mediate respectively.\n *\n * This is repeated for n times and then the mediate is\n * returned.\n *\n * This is explained in a greater detail in the \"Inspiration\"\n * link.\n */\n\nfunction fareyApproximation(decimal, repeat = 20) {\n  let a = 0\n  let b = 1\n  let c = 1\n  let d = 1\n  let numerator\n  let denominator\n\n  for (let i = 0; i < repeat; i++) {\n    numerator = a + c\n    denominator = b + d\n\n    if (decimal > numerator / denominator) {\n      ;[a, b] = [numerator, denominator]\n    } else {\n      ;[c, d] = [numerator, denominator]\n    }\n  }\n\n  return { numerator, denominator }\n}\n\nexport { fareyApproximation }\n"
  },
  {
    "path": "Maths/FermatPrimalityTest.js",
    "content": "/*\n * The Fermat primality test is a probabilistic test to determine whether a number\n * is a probable prime.\n *\n * It relies on Fermat's Little Theorem, which states that if p is prime and a\n * is not divisible by p, then\n *\n *     a^(p - 1) % p = 1\n *\n * However, there are certain numbers (so called Fermat Liars) that screw things up;\n * if a is one of these liars the equation will hold even though p is composite.\n *\n * But not everything is lost! It's been proven that at least half of all integers\n * aren't Fermat Liars (these ones called Fermat Witnesses). Thus, if we keep\n * testing the primality with random integers, we can achieve higher reliability.\n *\n * The interesting about all of this is that since half of all integers are\n * Fermat Witnesses, the precision gets really high really fast! Suppose that we\n *  make the test 50 times: the chance of getting only Fermat Liars in all runs is\n *\n *     1 / 2^50 = 8.8 * 10^-16 (a pretty small number)\n *\n * For comparison, the probability of a cosmic ray causing an error to your\n * infallible program is around 1.4 * 10^-15. An order of magnitude below!\n *\n * But because nothing is perfect, there's a major flaw to this algorithm, and\n * the cause are the so called Carmichael Numbers. These are composite numbers n\n * that hold the equality from Fermat's Little Theorem for every a < n (excluding\n * is factors). In other words, if we are trying to determine if a Carmichael Number\n * is prime or not, the chances of getting a wrong answer are pretty high! Because\n * of that, the Fermat Primality Test is not used is serious applications. :(\n *\n * You can find more about the Fermat primality test and its flaws here:\n * https://en.wikipedia.org/wiki/Fermat_primality_test\n *\n * And about Carmichael Numbers here:\n * https://primes.utm.edu/glossary/xpage/CarmichaelNumber.html\n */\n\n/**\n * Faster exponentiation that capitalize on the fact that we are only interested\n * in the modulus of the exponentiation.\n *\n * Find out more about it here: https://en.wikipedia.org/wiki/Modular_exponentiation\n *\n * @param {number} base\n * @param {number} exponent\n * @param {number} modulus\n */\nconst modularExponentiation = (base, exponent, modulus) => {\n  if (modulus === 1) return 0 // after all, any x % 1 = 0\n\n  let result = 1\n  base %= modulus // make sure that base < modulus\n\n  while (exponent > 0) {\n    // if exponent is odd, multiply the result by the base\n    if (exponent % 2 === 1) {\n      result = (result * base) % modulus\n      exponent--\n    } else {\n      exponent = exponent / 2 // exponent is even for sure\n      base = (base * base) % modulus\n    }\n  }\n\n  return result\n}\n\n/**\n * Test if a given number n is prime or not.\n *\n * @param {number} n The number to check for primality\n * @param {number} numberOfIterations The number of times to apply Fermat's Little Theorem\n * @returns True if prime, false otherwise\n */\nconst fermatPrimeCheck = (n, numberOfIterations = 50) => {\n  // first check for edge cases\n  if (n <= 1 || n === 4) return false\n  if (n <= 3) return true // 2 and 3 are included here\n\n  for (let i = 0; i < numberOfIterations; i++) {\n    // pick a random number a, with 2 <= a < n - 2\n    const randomNumber = Math.floor(Math.random() * (n - 2) + 2)\n\n    // if a^(n - 1) % n is different than 1, n is composite\n    if (modularExponentiation(randomNumber, n - 1, n) !== 1) {\n      return false\n    }\n  }\n\n  // if we arrived here without finding a Fermat Witness, this is almost guaranteed\n  // to be a prime number (or a Carmichael number, if you are unlucky)\n  return true\n}\n\nexport { modularExponentiation, fermatPrimeCheck }\n"
  },
  {
    "path": "Maths/Fibonacci.js",
    "content": "// https://en.wikipedia.org/wiki/Generalizations_of_Fibonacci_numbers#Extension_to_negative_integers\nconst FibonacciIterative = (num) => {\n  const isNeg = num < 0\n  if (isNeg) num *= -1\n  const sequence = [0]\n\n  if (num >= 1) sequence.push(1)\n  if (num >= 2) sequence.push(isNeg ? -1 : 1)\n\n  for (let i = 2; i < num; i++) {\n    sequence.push(\n      isNeg ? sequence[i - 1] - sequence[i] : sequence[i] + sequence[i - 1]\n    )\n  }\n\n  return sequence\n}\n\nconst FibonacciGenerator = function* (neg) {\n  let a = 0\n  let b = 1\n  yield a\n  while (true) {\n    yield b\n    ;[a, b] = neg ? [b, a - b] : [b, a + b]\n  }\n}\n\nconst list = []\nconst FibonacciRecursive = (num) => {\n  const isNeg = num < 0\n  if (isNeg) num *= -1\n  return (() => {\n    switch (list.length) {\n      case 0:\n        list.push(0)\n        return FibonacciRecursive(num)\n      case 1:\n        list.push(1)\n        return FibonacciRecursive(num)\n      case num + 1:\n        return list\n      default:\n        list.push(list.at(-1) + list.at(-2))\n        return FibonacciRecursive(num)\n    }\n  })().map((fib, i) => fib * (isNeg ? (-1) ** (i + 1) : 1))\n}\n\nconst dict = new Map()\nconst FibonacciRecursiveDP = (stairs) => {\n  const isNeg = stairs < 0\n  if (isNeg) stairs *= -1\n\n  if (stairs <= 1) return stairs\n\n  // Memoize stair count\n  if (dict.has(stairs))\n    return (isNeg ? (-1) ** (stairs + 1) : 1) * dict.get(stairs)\n\n  const res =\n    FibonacciRecursiveDP(stairs - 1) + FibonacciRecursiveDP(stairs - 2)\n\n  dict.set(stairs, res)\n\n  return (isNeg ? (-1) ** (stairs + 1) : 1) * res\n}\n\n// Algorithms\n// Calculates Fibonacci(n) such that Fibonacci(n) = Fibonacci(n - 1) + Fibonacci(n - 2)\n// Fibonacci(0) = Fibonacci(1) = 1\n// Uses a bottom up dynamic programming approach\n// Solve each sub-problem once, using results of previous sub-problems\n// which are n-1 and n-2 for Fibonacci numbers\n// Although this algorithm is linear in space and time as a function\n// of the input value n, it is exponential in the size of n as\n// a function of the number of input bits\n// @Satzyakiz\n\nconst FibonacciDpWithoutRecursion = (num) => {\n  const isNeg = num < 0\n  if (isNeg) num *= -1\n  const table = [0]\n  table.push(1)\n  table.push(isNeg ? -1 : 1)\n  for (let i = 2; i < num; ++i) {\n    table.push(isNeg ? table[i - 1] - table[i] : table[i] + table[i - 1])\n  }\n  return table\n}\n\n// Using Matrix exponentiation to find n-th fibonacci in O(log n) time\n\nconst copyMatrix = (A) => {\n  return A.map((row) => row.map((cell) => cell))\n}\n\nconst Identity = (size) => {\n  const isBigInt = typeof size === 'bigint'\n  const ZERO = isBigInt ? 0n : 0\n  const ONE = isBigInt ? 1n : 1\n  size = Number(size)\n  const I = Array(size)\n    .fill(null)\n    .map(() => Array(size).fill())\n  return I.map((row, rowIdx) =>\n    row.map((_col, colIdx) => {\n      return rowIdx === colIdx ? ONE : ZERO\n    })\n  )\n}\n\n// A of size (l x m) and B of size (m x n)\n// product C will be of size (l x n).\n// both matrices must have same-type numeric values\n// either both BigInt or both Number\nconst matrixMultiply = (A, B) => {\n  A = copyMatrix(A)\n  B = copyMatrix(B)\n  const isBigInt = typeof A[0][0] === 'bigint'\n  const l = A.length\n  const m = B.length\n  const n = B[0].length // Assuming non-empty matrices\n  const C = Array(l)\n    .fill(null)\n    .map(() => Array(n).fill())\n  for (let i = 0; i < l; i++) {\n    for (let j = 0; j < n; j++) {\n      C[i][j] = isBigInt ? 0n : 0\n      for (let k = 0; k < m; k++) {\n        C[i][j] += A[i][k] * B[k][j]\n      }\n    }\n  }\n  return C\n}\n\n/**\n * Computes A raised to the power n i.e. pow(A, n) where A is a square matrix\n * @param {*} A the square matrix\n * @param {*} n the exponent\n */\n// A is a square matrix\nconst matrixExpo = (A, n) => {\n  A = copyMatrix(A)\n  const isBigInt = typeof n === 'bigint'\n  const ZERO = isBigInt ? 0n : 0\n  const TWO = isBigInt ? 2n : 2\n\n  // Just like Binary exponentiation mentioned in ./BinaryExponentiationIterative.js\n  let result = Identity((isBigInt ? BigInt : Number)(A.length)) // Identity matrix\n  while (n > ZERO) {\n    if (n % TWO !== ZERO) result = matrixMultiply(result, A)\n    n /= TWO\n    if (!isBigInt) n = Math.floor(n)\n    if (n > ZERO) A = matrixMultiply(A, A)\n  }\n  return result\n}\n\nconst FibonacciMatrixExpo = (num) => {\n  const isBigInt = typeof num === 'bigint'\n  const ZERO = isBigInt ? 0n : 0\n  const ONE = isBigInt ? 1n : 1\n  // F(0) = 0, F(1) = 1\n  // F(n) = F(n-1) + F(n-2)\n  // Consider below matrix multiplication:\n\n  // | F(n) |   |1  1|   |F(n-1)|\n  // |      | = |    | * |      |\n  // |F(n-1)|   |1  0|   |F(n-2)|\n\n  // Let's rewrite it as F(n, n-1) = A * F(n-1, n-2)\n  // or                  F(n, n-1) = A * A * F(n-2, n-3)\n  // or                  F(n, n-1) = pow(A, n-1) * F(1, 0)\n\n  if (num === ZERO) return num\n\n  const isNeg = num < 0\n  if (isNeg) num *= -ONE\n\n  const A = [\n    [ONE, ONE],\n    [ONE, ZERO]\n  ]\n\n  const poweredA = matrixExpo(A, num - ONE) // A raised to the power n-1\n  let F = [[ONE], [ZERO]]\n  F = matrixMultiply(poweredA, F)\n  return F[0][0] * (isNeg ? (-ONE) ** (num + ONE) : ONE)\n}\n\n/*\n  Resource : https://math.hmc.edu/funfacts/fibonacci-number-formula/\n*/\n\nconst sqrt5 = Math.sqrt(5)\nconst phi = (1 + sqrt5) / 2\nconst psi = (1 - sqrt5) / 2\n\nconst FibonacciUsingFormula = (n) => Math.round((phi ** n - psi ** n) / sqrt5)\n\nexport { FibonacciDpWithoutRecursion }\nexport { FibonacciIterative }\nexport { FibonacciGenerator }\nexport { FibonacciRecursive }\nexport { FibonacciRecursiveDP }\nexport { FibonacciMatrixExpo }\nexport { FibonacciUsingFormula }\n"
  },
  {
    "path": "Maths/FigurateNumber.js",
    "content": "/**\n Problem Statement and Explanation :\n Triangular  => https://en.wikipedia.org/wiki/Triangular_number\n Tetrahedral => https://en.wikipedia.org/wiki/Tetrahedral_number\n Pentatope   => https://en.wikipedia.org/wiki/Pentatope_number\n\n Example:\n Triangular  => (0, 1, 3, 6, 10, 15, 21, 28, 36, 45)\n Tetrahedral => (1, 4, 10, 20, 35, 56, 84, 120, 165,)\n Pentatope   => (1, 5, 15, 35, 70, 126, 210, 330, 495)\n */\n\n/**\n *\n * @param {*} number\n * @returns\n */\nconst isTriangular = (number) => {\n  for (let i = 0; i <= number; i++) {\n    if ((i * (i + 1)) / 2 === number) {\n      return true\n    } else if ((i * (i + 1)) / 2 > number) {\n      return false\n    }\n  }\n  return false\n}\n\n/**\n *\n * @param {*} number\n * @returns\n */\nconst isTetrahedral = (number) => {\n  for (let i = 1; i <= number; i++) {\n    if ((i * (i + 1) * (i + 2)) / 6 === number) {\n      return true\n    } else if ((i * (i + 1) * (i + 2)) / 6 > number) {\n      return false\n    }\n  }\n  return false\n}\n/**\n *\n * @param {*} number\n * @returns\n */\nconst isPentatope = (number) => {\n  for (let i = 1; i <= number; i++) {\n    if ((i * (i + 1) * (i + 2) * (i + 3)) / 24 === number) {\n      return true\n    } else if ((i * (i + 1) * (i + 2) * (i + 3)) / 24 > number) {\n      return false\n    }\n  }\n  return false\n}\n\n/**\n *\n * @param {*} number\n * @returns\n */\nconst checkAll = (number) => {\n  return {\n    isTriangular: isTriangular(number),\n    isTetrahedral: isTetrahedral(number),\n    isPentatope: isPentatope(number)\n  }\n}\nexport { isTriangular }\nexport { isTetrahedral }\nexport { isPentatope }\nexport { checkAll }\n"
  },
  {
    "path": "Maths/FindHcf.js",
    "content": "/*\n    author: redfly1\n    More about HCF:\n        https://en.wikipedia.org/wiki/Greatest_common_divisor\n */\n\nconst findHCF = (x, y) => {\n  // If the input numbers are less than 1 return an error message.\n  if (x < 1 || y < 1) {\n    return 'Please enter values greater than zero.'\n  }\n\n  // If the input numbers are not integers return an error message.\n  if (x !== Math.round(x) || y !== Math.round(y)) {\n    return 'Please enter whole numbers.'\n  }\n\n  // Now apply Euclid's algorithm to the two numbers.\n  while (Math.max(x, y) % Math.min(x, y) !== 0) {\n    if (x > y) {\n      x %= y\n    } else {\n      y %= x\n    }\n  }\n\n  // When the while loop finishes the minimum of x and y is the HCF.\n  return Math.min(x, y)\n}\n\nexport { findHCF }\n"
  },
  {
    "path": "Maths/FindLcm.js",
    "content": "/*\n    author: PatOnTheBack\n    license: GPL-3.0 or later\n\n    Modified from:\n        https://github.com/TheAlgorithms/Python/blob/master/maths/findLcm.py\n\n    More about LCM:\n        https://en.wikipedia.org/wiki/Least_common_multiple\n*/\n\n'use strict'\n\nimport { findHCF } from './FindHcf'\n\n// Find the LCM of two numbers.\nconst findLcm = (num1, num2) => {\n  // If the input numbers are less than 1 return an error message.\n  if (num1 < 1 || num2 < 1) {\n    throw Error('Numbers must be positive.')\n  }\n\n  // If the input numbers are not integers return an error message.\n  if (num1 !== Math.round(num1) || num2 !== Math.round(num2)) {\n    throw Error('Numbers must be whole.')\n  }\n\n  // Get the larger number between the two\n  const maxNum = Math.max(num1, num2)\n  let lcm = maxNum\n\n  while (true) {\n    if (lcm % num1 === 0 && lcm % num2 === 0) return lcm\n    lcm += maxNum\n  }\n}\n\n// Typically, but not always, more efficient\nconst findLcmWithHcf = (num1, num2) => {\n  // If the input numbers are less than 1 return an error message.\n  if (num1 < 1 || num2 < 1) {\n    throw Error('Numbers must be positive.')\n  }\n\n  // If the input numbers are not integers return an error message.\n  if (num1 !== Math.round(num1) || num2 !== Math.round(num2)) {\n    throw Error('Numbers must be whole.')\n  }\n\n  return (num1 * num2) / findHCF(num1, num2)\n}\n\nexport { findLcm, findLcmWithHcf }\n"
  },
  {
    "path": "Maths/FindMaxRecursion.js",
    "content": "/**\n * @function findMaxRecursion\n * @description This algorithm will find the maximum value of a array of numbers.\n *\n * @param {Integer[]} arr Array of numbers\n * @param {Integer} left Index of the first element\n * @param {Integer} right Index of the last element\n *\n * @return {Integer} Maximum value of the array\n *\n * @see [Maximum value](https://en.wikipedia.org/wiki/Maximum_value)\n *\n * @example findMaxRecursion([1, 2, 4, 5]) = 5\n * @example findMaxRecursion([10, 40, 100, 20]) = 100\n * @example findMaxRecursion([-1, -2, -4, -5]) = -1\n */\nfunction findMaxRecursion(arr, left, right) {\n  const len = arr.length\n\n  if (len === 0 || !arr) {\n    return undefined\n  }\n\n  if (left >= len || left < -len || right >= len || right < -len) {\n    throw new Error('Index out of range')\n  }\n\n  if (left === right) {\n    return arr[left]\n  }\n\n  // n >> m is equivalent to floor(n / pow(2, m)), floor(n / 2) in this case, which is the mid index\n  const mid = (left + right) >> 1\n\n  const leftMax = findMaxRecursion(arr, left, mid)\n  const rightMax = findMaxRecursion(arr, mid + 1, right)\n\n  // Return the maximum\n  return Math.max(leftMax, rightMax)\n}\n\nexport { findMaxRecursion }\n"
  },
  {
    "path": "Maths/FindMin.js",
    "content": "/**\n * @function FindMin\n * @description Function to find the minimum number given in an array of integers.\n * @param {Integer[]} nums - Array of Integers\n * @return {Integer} - The minimum number of the array.\n */\n\nconst findMin = (...nums) => {\n  if (nums.length === 0) {\n    throw new TypeError('Array is empty')\n  }\n\n  let min = nums[0]\n  for (let i = 1; i < nums.length; i++) {\n    if (nums[i] < min) {\n      min = nums[i]\n    }\n  }\n\n  return min\n}\n\nexport { findMin }\n"
  },
  {
    "path": "Maths/FindMinIterator.js",
    "content": "/**\n * @function FindMinIterator\n * @description Function to find the minimum number given in an array.\n */\n\nconst FindMinIterator = (_iterable, _selector = undefined) => {\n  let min\n\n  const iterator = _iterable[Symbol.iterator]()\n  if (!_selector) {\n    let current = iterator.next()\n    if (current.done) {\n      return undefined\n    }\n    min = current.value\n\n    current = iterator.next()\n    while (!current.done) {\n      const x = current.value\n      if (x < min) {\n        min = x\n      }\n      current = iterator.next()\n    }\n  } else {\n    let current = iterator.next()\n    if (current.done) {\n      return undefined\n    }\n    min = _selector(current.value)\n\n    current = iterator.next()\n    while (!current.done) {\n      const x = _selector(current.value)\n      if (x < min) {\n        min = x\n      }\n      current = iterator.next()\n    }\n  }\n  return min\n}\n\nexport { FindMinIterator }\n"
  },
  {
    "path": "Maths/FriendlyNumbers.js",
    "content": "/*\n  'In number theory, friendly numbers are two or more natural numbers with a common abundancy index, the\n  ratio between the sum of divisors of a number and the number itself.'\n  Source: https://en.wikipedia.org/wiki/Friendly_number\n  See also: https://mathworld.wolfram.com/FriendlyNumber.html#:~:text=The%20numbers%20known%20to%20be,numbers%20have%20a%20positive%20density.\n*/\n\nexport const FriendlyNumbers = (firstNumber, secondNumber) => {\n  // input: two integers\n  // output: true if the two integers are friendly numbers, false if they are not friendly numbers\n\n  // First, check that the parameters are valid\n  if (\n    !Number.isInteger(firstNumber) ||\n    !Number.isInteger(secondNumber) ||\n    firstNumber === 0 ||\n    secondNumber === 0 ||\n    firstNumber === secondNumber\n  ) {\n    throw new Error('The two parameters must be distinct, non-null integers')\n  }\n\n  return abundancyIndex(firstNumber) === abundancyIndex(secondNumber)\n}\n\nfunction abundancyIndex(number) {\n  return sumDivisors(number) / number\n}\n\nfunction sumDivisors(number) {\n  let runningSumDivisors = number\n  for (let i = 0; i < number / 2; i++) {\n    if (Number.isInteger(number / i)) {\n      runningSumDivisors += i\n    }\n  }\n  return runningSumDivisors\n}\n"
  },
  {
    "path": "Maths/GetEuclidGCD.js",
    "content": "function CheckInput(a, b) {\n  if (typeof a !== 'number' || typeof b !== 'number') {\n    throw new TypeError('Arguments must be numbers')\n  }\n}\n\n/**\n * GetEuclidGCD Euclidean algorithm to determine the GCD of two numbers\n * @param {Number} a integer (may be negative)\n * @param {Number} b integer (may be negative)\n * @returns {Number} Greatest Common Divisor gcd(a, b)\n */\nexport function GetEuclidGCD(a, b) {\n  CheckInput(a, b)\n  a = Math.abs(a)\n  b = Math.abs(b)\n  while (b !== 0) {\n    const rem = a % b\n    a = b\n    b = rem\n  }\n  return a\n}\n\n/**\n * Recursive version of GetEuclidGCD\n * @param {Number} a integer (may be negative)\n * @param {Number} b integer (may be negative)\n * @returns {Number} Greatest Common Divisor gcd(a, b)\n */\nexport function GetEuclidGCDRecursive(a, b) {\n  CheckInput(a, b)\n  a = Math.abs(a)\n  b = Math.abs(b)\n  if (b == 0) {\n    return a\n  }\n  return GetEuclidGCDRecursive(b, a % b)\n}\n"
  },
  {
    "path": "Maths/GridGet.js",
    "content": "/*\n    author: TangibleDream\n    license: GPL-3.0 or later\n\n    These methods will find x or y given the element and columns for a 2 dimensional array.\n\n    If your array is a perfect square, you can find columns by getting the square\n    root of the length of the array.\n\n    Let's say for instance you had an array of 10 by 10 or 100, elements and you wanted to\n    find the shortest distance between element 3, and element 49. In this case coding out\n    a function to return the distance without finding x and y for both elements I found to\n    be painful. If you first find x and y, where 3 becomes 4,1 and 49 becomes 10,5, you can\n    find distance by first subtracting x from x and y from y this returns 6,4 or -6,-4.\n    Next apply absolute value to assure the results are positive,\n    last choose the maximum value of the set, or 6.\n\n    +--+--+--+--+--+--+--+--+--+--+\n    |  |  |  | 3|  |  |  |  |  |  |\n    +--+--+--+--+--+--+--+--+--+--+\n    |  |  |  |  |  |  |  |  |  |  |\n    +--+--+--+--+--+--+--+--+--+--+\n    |  |  |  |  |  |  |  |  |  |  |\n    +--+--+--+--+--+--+--+--+--+--+\n    |  |  |  |  |  |  |  |  |  |49|\n    +--+--+--+--+--+--+--+--+--+--+\n    |  |  |  |  |  |  |  |  |  |  |\n\n    +--+--+--+--+--+--+--+--+--+--+\n    |  |  |  | 3|  |  |  |  |  |  |\n    +--+--+--+--+--+--+--+--+--+--+\n    |  |  |  |  | 1|  |  |  |  |  |\n    +--+--+--+--+--+--+--+--+--+--+\n    |  |  |  |  |  | 2|  |  |  |  |\n    +--+--+--+--+--+--+--+--+--+--+\n    |  |  |  |  |  |  | 3| 4| 5|6!|\n    +--+--+--+--+--+--+--+--+--+--+\n    |  |  |  |  |  |  |  |  |  |  |\n\n*/\n\nconst gridGetX = (columns, index) => {\n  while (index + 1 > columns) {\n    index = index - columns\n  }\n  return index + 1\n}\n\nconst gridGetY = (columns, index) => {\n  return Math.floor(index / columns) + 1\n}\n\nexport { gridGetX, gridGetY }\n"
  },
  {
    "path": "Maths/HexagonalNumber.js",
    "content": "/*\n * Author: Akshay Dubey (https://github.com/itsAkshayDubey)\n * Hexagonal Number: https://en.wikipedia.org/wiki/Hexagonal_number\n * The nth hexagonal number hn is the number of distinct dots in a pattern of dots\n * consisting of the outlines of regular hexagons with sides up to n dots, when the\n * hexagons are overlaid so that they share one vertex.\n */\n\n/**\n * @function hexagonalNumber\n * @description -> returns nth hexagonal number\n * @param {Integer} number\n * @returns {Integer} nth hexagonal number\n */\n\nexport const hexagonalNumber = (number) => {\n  if (number <= 0) {\n    throw new Error('Number must be greater than zero.')\n  }\n  return number * (2 * number - 1)\n}\n"
  },
  {
    "path": "Maths/IntToBase.js",
    "content": "/**\n * @function intToBase\n * @description Convert a number from decimal system to another (till decimal)\n * @param {Number} number Number to be converted\n * @param {Number} base Base of new number system\n * @returns {String} Converted Number\n * @see [HornerMethod](https://en.wikipedia.org/wiki/Horner%27s_method)\n * @example\n * const num1 = 125 // Needs to be converted to the binary number system\n * gornerScheme(num, 2); // ===> 1111101\n * @example\n * const num2 = 125 // Needs to be converted to the octal number system\n * gornerScheme(num, 8); // ===> 175\n */\nconst intToBase = (number, base) => {\n  if (typeof number !== 'number' || typeof base !== 'number') {\n    throw new Error('Input data must be numbers')\n  }\n  // Zero in any number system is zero\n  if (number === 0) {\n    return '0'\n  }\n  let absoluteValue = Math.abs(number)\n  let convertedNumber = ''\n  while (absoluteValue > 0) {\n    // Every iteration last digit is taken away\n    // and added to the previous one\n    const lastDigit = absoluteValue % base\n    convertedNumber = lastDigit + convertedNumber\n    absoluteValue = Math.trunc(absoluteValue / base)\n  }\n  // Result is whether negative or positive,\n  // depending on the original value\n  if (number < 0) {\n    convertedNumber = '-' + convertedNumber\n  }\n  return convertedNumber\n}\n\nexport { intToBase }\n"
  },
  {
    "path": "Maths/IsDivisible.js",
    "content": "// Checks if a number is divisible by another number.\n\nexport const isDivisible = (num1, num2) => {\n  if (!Number.isFinite(num1) || !Number.isFinite(num2)) {\n    throw new TypeError('Expected a valid real number')\n  }\n  if (num2 === 0) {\n    return false\n  }\n  return num1 % num2 === 0\n}\n\n// isDivisible(10, 5) // returns true\n// isDivisible(123498175, 5) // returns true\n// isDivisible(99, 5) // returns false\n"
  },
  {
    "path": "Maths/IsEven.js",
    "content": "/*\n * Even Number: https://simple.wikipedia.org/wiki/Even_number\n *\n * function to check if number is even\n * return true if number is even\n * else false\n */\n\n/**\n * @function isEven\n * @description - Checking if number is even using divisibility by 2\n *\n * If number is divisible by 2 i.e remainder = 0, then it is even\n * therefore, the function will return true\n *\n * If number is not divisible by 2 i.e remainder != 0, then it is not even i.e odd\n * therefore, the function will return false\n * @param {number} number\n * @return {boolean}\n */\nexport const isEven = (number) => number % 2 === 0\n\n/**\n * @function isEvenBitwise\n * @description - Checking if number is even using bitwise operator\n * Bitwise AND (&) compares the bits of the 32\n * bit binary representations of the number and\n * returns a number after comparing each bit:\n *\n * 0 & 0 -> 0\n * 0 & 1 -> 0\n * 1 & 0 -> 0\n * 1 & 1 -> 1\n *\n * For odd numbers, the last binary bit will be 1\n * and for even numbers, the last binary bit will\n * be 0.\n *\n * As the number is compared with one, all the\n * other bits except the last will become 0. The\n * last bit will be 0 for even numbers and 1 for\n * odd numbers, which is checked with the use\n * of the equality operator.\n * @param {number} number\n * @returns {boolean}\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_AND\n */\nexport const isEvenBitwise = (number) => (number & 1) === 0\n"
  },
  {
    "path": "Maths/IsOdd.js",
    "content": "/*\n * Odd Number: https://simple.wikipedia.org/wiki/Odd_number\n * function to check if number is odd.\n * return true if number is odd.\n * else false\n */\n\n/**\n * @function isOdd\n * @description -> Checking if number is odd using not divisibility by 2\n * If number is not divisible by 2 i.e remainder = 1, then it is odd\n * therefore, the function will return true\n *\n * If number is divisible by 2 i.e remainder != 1, then it is even\n * therefore, the function will return false\n * @param {number} number\n * @returns {boolean}\n */\nconst isOdd = (number) => Boolean(number % 2) // 1 -> true, 0 -> false\n/**\n * @function isOddBitwise\n * @description -> Checking if number is even using bitwise operator\n * Bitwise AND (&) compares the bits of the 32\n * bit binary representations of the number and\n * returns a number after comparing each bit:\n *\n * 0 & 0 -> 0\n * 0 & 1 -> 0\n * 1 & 0 -> 0\n * 1 & 1 -> 1\n *\n * For every odd numbers, the last binary bit will be 1\n * and for even numbers, the last binary bit will be 0.\n *\n * As the number is compared with one, all the\n * other bits except the last will become 0. The\n * last bit will be 0 for even numbers and 1 for\n * odd numbers.\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_AND\n * @param {number} number\n * @returns {boolean}\n */\nconst isOddBitwise = (number) => Boolean(number & 1) // 1 -> true, 0 -> false\n\nexport { isOdd, isOddBitwise }\n"
  },
  {
    "path": "Maths/IsPronic.js",
    "content": "/*\n * Author: Akshay Dubey (https://github.com/itsAkshayDubey)\n * Pronic Number: https://en.wikipedia.org/wiki/Pronic_number\n * function to check if number is pronic.\n * return true if number is pronic.\n * else false\n */\n\n/**\n * @function isPronic\n * @description -> Checking if number is pronic using product of two consecutive numbers\n * If number is a product of two consecutive numbers, then it is pronic\n * therefore, the function will return true\n *\n * If number is not a product of two consecutive numbers, then it is not pronic\n * therefore, the function will return false\n * @param {number} number\n * @returns {boolean}\n */\n\nexport const isPronic = (number) => {\n  if (number === 0) {\n    return true\n  }\n  const sqrt = Math.sqrt(number)\n  return sqrt % 1 !== 0 && Math.ceil(sqrt) * Math.floor(sqrt) === number\n}\n"
  },
  {
    "path": "Maths/IsSquareFree.js",
    "content": "/*\n * Author: Akshay Dubey (https://github.com/itsAkshayDubey)\n * Square free integer: https://en.wikipedia.org/wiki/Square-free_integer\n * function to check if an integer has repeated prime factors.\n * return false if the number as repeated prime factors.\n * else true\n */\n\n/**\n * @function isSquareFree\n * @description -> Checking if number is square free using prime factorization\n * @param {number} number\n * @returns {boolean} true if the number has unique prime factors, otherwise false\n */\n\nimport { PrimeFactors } from './PrimeFactors.js'\nexport const isSquareFree = (number) => {\n  const primeFactorsArray = PrimeFactors(number)\n  if (number <= 0) {\n    throw new Error('Number must be greater than zero.')\n  }\n  return primeFactorsArray.length === new Set(primeFactorsArray).size\n}\n"
  },
  {
    "path": "Maths/JugglerSequence.js",
    "content": "/*\n * Juggler Sequence: https://en.wikipedia.org/wiki/Juggler_sequence\n * function jugglerSequence\n * Juggler Sequence is a series of integer number in which the first term starts with a positive integer number n\n * and the remaining terms are generated from the immediate previous term using the recurrence relation\n * Produce Juggler Sequence using number n as the first term of the sequence and store in an array\n * Reference: https://www.geeksforgeeks.org/juggler-sequence/\n * jugglerSequence(3) // returns [3, 5, 11, 36, 6, 2, 1 ]\n * jugglerSequence(9) // returns [9, 27, 140, 11, 36, 6, 2, 1]\n * jugglerSequence(15) // returns [15, 58, 7, 18, 4, 2, 1]\n */\n\nfunction jugglerSequence(n) {\n  const sequence = []\n  sequence.push(n)\n  // Calculate terms until last term is not 1\n  while (n !== 1) {\n    n = Math.floor(n ** ((n % 2) + 0.5))\n    sequence.push(n)\n  }\n  return sequence\n}\n\nexport { jugglerSequence }\n"
  },
  {
    "path": "Maths/LeapYear.js",
    "content": "/**\n * isLeapYear :: Number -> Boolean\n *\n * Check if a year is a leap year or not. A leap year is a year which has 366 days.\n * For the extra +1 day the February month contains 29 days instead of 28 days.\n *\n * The logic behind the leap year is-\n * 1. If the year is divisible by 400 then it is a leap year.\n * 2. If it is not divisible by 400 but divisible by 100 then it is not a leap year.\n * 3. If the year is not divisible by both 400 and 100 but divisible by 4 then a leap year.\n * 4. Other cases except the describing ones are not a leap year.\n *\n * @param {number} year\n * @returns {boolean} true if this is a leap year, false otherwise.\n */\nexport const isLeapYear = (year) => {\n  return year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0)\n}\n"
  },
  {
    "path": "Maths/LinearSieve.js",
    "content": "const LinearSieve = (n) => {\n  /*\n   * Calculates prime numbers till a number n\n   * Time Complexity: O(n)\n   * Explanation: https://cp-algorithms.com/algebra/prime-sieve-linear.html\n   * :param n: Number up to which to calculate primes\n   * :return: A list containing only primes\n   */\n  const isnPrime = new Array(n + 1)\n  isnPrime[0] = isnPrime[1] = true\n  const primes = []\n  for (let i = 2; i <= n; i++) {\n    if (!isnPrime[i]) primes.push(i)\n    for (const p of primes) {\n      const k = i * p\n      if (k > n) break\n      isnPrime[k] = true\n      if (i % p === 0) break\n    }\n  }\n  return primes\n}\n\nexport { LinearSieve }\n"
  },
  {
    "path": "Maths/LiouvilleFunction.js",
    "content": "/*\n * Author: Akshay Dubey (https://github.com/itsAkshayDubey)\n * Liouville Function: https://en.wikipedia.org/wiki/Liouville_function\n * For any positive integer n, define λ(n) as the sum of the primitive nth roots of unity.\n * It has values in {−1, 1} depending on the factorization of n into prime factors:\n *   λ(n) = +1 if n positive integer with an even number of prime factors.\n *   λ(n) = −1 if n positive integer with an odd number of prime factors.\n */\n\n/**\n * @function liouvilleFunction\n * @description -> This method returns λ(n) of given number n\n * returns 1 when number has even number of prime factors\n * returns -1 when number has odd number of prime factors\n * @param {Integer} number\n * @returns {Integer} 1|-1\n */\n\nimport { PrimeFactors } from './PrimeFactors.js'\nexport const liouvilleFunction = (number) => {\n  if (number <= 0) {\n    throw new Error('Number must be greater than zero.')\n  }\n  return PrimeFactors(number).length % 2 === 0 ? 1 : -1\n}\n"
  },
  {
    "path": "Maths/LucasSeries.js",
    "content": "/*\n  Program to get the Nth Lucas Number\n  Article on Lucas Number: https://en.wikipedia.org/wiki/Lucas_number\n  Examples:\n    > loopLucas(1)\n    1\n    > loopLucas(20)\n    15127\n    > loopLucas(100)\n    792070839848372100000\n*/\n\n/**\n * @param {Number} index The position of the number you want to get from the Lucas Series\n */\nfunction lucas(index) {\n  // index can't be negative\n  if (index < 0) throw new TypeError('Index cannot be Negative')\n\n  // index can't be a decimal\n  if (Math.floor(index) !== index)\n    throw new TypeError('Index cannot be a Decimal')\n\n  let a = 2\n  let b = 1\n  for (let i = 0; i < index; i++) {\n    const temp = a + b\n    a = b\n    b = temp\n  }\n  return a\n}\n\nexport { lucas }\n"
  },
  {
    "path": "Maths/Mandelbrot.js",
    "content": "/**\n * Method to generate the image of the Mandelbrot set.\n *\n * Two types of coordinates are used: image-coordinates that refer to the pixels and figure-coordinates that refer to\n * the complex numbers inside and outside the Mandelbrot set. The figure-coordinates in the arguments of this method\n * determine which section of the Mandelbrot set is viewed. The main area of the Mandelbrot set is roughly between\n * \"-1.5 < x < 0.5\" and \"-1 < y < 1\" in the figure-coordinates.\n *\n * The Mandelbrot set is the set of complex numbers \"c\" for which the series \"z_(n+1) = z_n * z_n + c\" does not diverge,\n * i.e. remains bounded. Thus, a complex number \"c\" is a member of the Mandelbrot set if, when starting with \"z_0 = 0\"\n * and applying the iteration repeatedly, the absolute value of \"z_n\" remains bounded for all \"n > 0\". Complex numbers\n * can be written as \"a + b*i\": \"a\" is the real component, usually drawn on the x-axis, and \"b*i\" is the imaginary\n * component, usually drawn on the y-axis. Most visualizations of the Mandelbrot set use a color-coding to indicate\n * after how many steps in the series the numbers outside the set cross the divergence threshold. Images of the\n * Mandelbrot set exhibit an elaborate and infinitely complicated boundary that reveals progressively ever-finer\n * recursive detail at increasing magnifications, making the boundary of the Mandelbrot set a fractal curve.\n *\n * (description adapted from https://en.wikipedia.org/wiki/Mandelbrot_set)\n * @see https://en.wikipedia.org/wiki/Plotting_algorithms_for_the_Mandelbrot_set\n *\n * @param {number} imageWidth The width of the rendered image.\n * @param {number} imageHeight The height of the rendered image.\n * @param {number} figureCenterX The x-coordinate of the center of the figure.\n * @param {number} figureCenterY The y-coordinate of the center of the figure.\n * @param {number} figureWidth The width of the figure.\n * @param {number} maxStep Maximum number of steps to check for divergent behavior.\n * @param {boolean} useDistanceColorCoding Render in color or black and white.\n * @return {object} The RGB-data of the rendered Mandelbrot set.\n */\nexport function getRGBData(\n  imageWidth = 800,\n  imageHeight = 600,\n  figureCenterX = -0.6,\n  figureCenterY = 0,\n  figureWidth = 3.2,\n  maxStep = 50,\n  useDistanceColorCoding = true\n) {\n  if (imageWidth <= 0) {\n    throw new Error('imageWidth should be greater than zero')\n  }\n\n  if (imageHeight <= 0) {\n    throw new Error('imageHeight should be greater than zero')\n  }\n\n  if (maxStep <= 0) {\n    throw new Error('maxStep should be greater than zero')\n  }\n\n  const rgbData = []\n  const figureHeight = (figureWidth / imageWidth) * imageHeight\n\n  // loop through the image-coordinates\n  for (let imageX = 0; imageX < imageWidth; imageX++) {\n    rgbData[imageX] = []\n    for (let imageY = 0; imageY < imageHeight; imageY++) {\n      // determine the figure-coordinates based on the image-coordinates\n      const figureX = figureCenterX + (imageX / imageWidth - 0.5) * figureWidth\n      const figureY =\n        figureCenterY + (imageY / imageHeight - 0.5) * figureHeight\n\n      const distance = getDistance(figureX, figureY, maxStep)\n\n      // color the corresponding pixel based on the selected coloring-function\n      rgbData[imageX][imageY] = useDistanceColorCoding\n        ? colorCodedColorMap(distance)\n        : blackAndWhiteColorMap(distance)\n    }\n  }\n\n  return rgbData\n}\n\n/**\n * Black and white color-coding that ignores the relative distance.\n *\n * The Mandelbrot set is black, everything else is white.\n *\n * @param {number} distance Distance until divergence threshold\n * @return {object} The RGB-value corresponding to the distance.\n */\nfunction blackAndWhiteColorMap(distance) {\n  return distance >= 1 ? [0, 0, 0] : [255, 255, 255]\n}\n\n/**\n * Color-coding taking the relative distance into account.\n *\n * The Mandelbrot set is black.\n *\n * @param {number} distance Distance until divergence threshold\n * @return {object} The RGB-value corresponding to the distance.\n */\nfunction colorCodedColorMap(distance) {\n  if (distance >= 1) {\n    return [0, 0, 0]\n  } else {\n    // simplified transformation of HSV to RGB\n    // distance determines hue\n    const hue = 360 * distance\n    const saturation = 1\n    const val = 255\n    const hi = Math.floor(hue / 60) % 6\n    const f = hue / 60 - Math.floor(hue / 60)\n\n    const v = val\n    const p = 0\n    const q = Math.floor(val * (1 - f * saturation))\n    const t = Math.floor(val * (1 - (1 - f) * saturation))\n\n    switch (hi) {\n      case 0:\n        return [v, t, p]\n      case 1:\n        return [q, v, p]\n      case 2:\n        return [p, v, t]\n      case 3:\n        return [p, q, v]\n      case 4:\n        return [t, p, v]\n      default:\n        return [v, p, q]\n    }\n  }\n}\n\n/**\n * Return the relative distance (ratio of steps taken to maxStep) after which the complex number\n * constituted by this x-y-pair diverges.\n *\n * Members of the Mandelbrot set do not diverge so their distance is 1.\n *\n * @param {number} figureX The x-coordinate within the figure.\n * @param {number} figureY The y-coordinate within the figure.\n * @param {number} maxStep Maximum number of steps to check for divergent behavior.\n * @return {number} The relative distance as the ratio of steps taken to maxStep.\n */\nfunction getDistance(figureX, figureY, maxStep) {\n  let a = figureX\n  let b = figureY\n  let currentStep = 0\n  for (let step = 0; step < maxStep; step++) {\n    currentStep = step\n    const aNew = a * a - b * b + figureX\n    b = 2 * a * b + figureY\n    a = aNew\n\n    // divergence happens for all complex number with an absolute value\n    // greater than 4 (= divergence threshold)\n    if (a * a + b * b > 4) {\n      break\n    }\n  }\n  return currentStep / (maxStep - 1)\n}\n"
  },
  {
    "path": "Maths/MatrixExponentiationRecursive.js",
    "content": "/*\n  Source:\n    https://en.wikipedia.org/wiki/Exponentiation_by_squaring\n\n  Complexity:\n    O(d^3 log n)\n    where: d is the dimension of the square matrix\n           n is the power the matrix is raised to\n*/\n\nconst Identity = (n) => {\n  // Input: n: int\n  // Output: res: Identity matrix of size n x n\n  // Complexity: O(n^2)\n  const res = []\n  for (let i = 0; i < n; i++) {\n    res[i] = []\n    for (let j = 0; j < n; j++) {\n      res[i][j] = i === j ? 1 : 0\n    }\n  }\n  return res\n}\n\nconst MatMult = (matrixA, matrixB) => {\n  // Input: matrixA: 2D Array of Numbers of size n x n\n  //        matrixB: 2D Array of Numbers of size n x n\n  // Output: matrixA x matrixB: 2D Array of Numbers of size n x n\n  // Complexity: O(n^3)\n  const n = matrixA.length\n  const matrixC = []\n  for (let i = 0; i < n; i++) {\n    matrixC[i] = []\n    for (let j = 0; j < n; j++) {\n      matrixC[i][j] = 0\n    }\n  }\n  for (let i = 0; i < n; i++) {\n    for (let j = 0; j < n; j++) {\n      for (let k = 0; k < n; k++) {\n        matrixC[i][j] += matrixA[i][k] * matrixB[k][j]\n      }\n    }\n  }\n  return matrixC\n}\n\nexport const MatrixExponentiationRecursive = (mat, m) => {\n  // Input: mat: 2D Array of Numbers of size n x n\n  // Output: mat^n: 2D Array of Numbers of size n x n\n  // Complexity: O(n^3 log m)\n  if (m === 0) {\n    // return identity matrix of size n x n\n    return Identity(mat.length)\n  } else if (m % 2 === 1) {\n    // tmp = mat ^ m-1\n    const tmp = MatrixExponentiationRecursive(mat, m - 1)\n    /// return tmp * mat = (mat ^ m-1) * mat = mat ^ m\n    return MatMult(tmp, mat)\n  } else {\n    // tmp = mat ^ m/2\n    const tmp = MatrixExponentiationRecursive(mat, m >> 1)\n    // return tmp * tmp = (mat ^ m/2) ^ 2 = mat ^ m\n    return MatMult(tmp, tmp)\n  }\n}\n\n// const mat = [[1, 0, 2], [2, 1, 0], [0, 2, 1]]\n\n// // mat ^ 0 = [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ]\n// MatrixExponentiationRecursive(mat, 0)\n\n// // mat ^ 1 = [ [ 1, 0, 2 ], [ 2, 1, 0 ], [ 0, 2, 1 ] ]\n// MatrixExponentiationRecursive(mat, 1)\n\n// // mat ^ 2 = [ [ 1, 4, 4 ], [ 4, 1, 4 ], [ 4, 4, 1 ] ]\n// MatrixExponentiationRecursive(mat, 2)\n\n// // mat ^ 5 = [ [ 1, 4, 4 ], [ 4, 1, 4 ], [ 4, 4, 1 ] ]\n// MatrixExponentiationRecursive(mat, 5)\n"
  },
  {
    "path": "Maths/MatrixMultiplication.js",
    "content": "// Wikipedia URL for General Matrix Multiplication Concepts: https://en.wikipedia.org/wiki/Matrix_multiplication\n\n// This algorithm has multiple functions that ultimately check if the inputs are actually matrices and if two Matrices (that can be different sizes) can be multiplied together.\n// matrices that are of the same size [2x2]x[2x2], and the second is the multiplication of two matrices that are not the same size [2x3]x[3x2].\n\n// MatrixCheck tests to see if all of the rows of the matrix inputted have similar size columns\nconst matrixCheck = (matrix) => {\n  let columnNumb\n  for (let index = 0; index < matrix.length; index++) {\n    if (index === 0) {\n      columnNumb = matrix[index].length\n    } else if (matrix[index].length !== columnNumb) {\n      // The columns in this array are not equal\n    } else {\n      return columnNumb\n    }\n  }\n}\n\n// tests to see if the matrices have a like side, i.e., the row length on the first matrix matches the column length on the second matrix, or vice versa.\nconst twoMatricesCheck = (first, second) => {\n  const [firstRowLength, secondRowLength, firstColLength, secondColLength] = [\n    first.length,\n    second.length,\n    matrixCheck(first),\n    matrixCheck(second)\n  ]\n\n  // These matrices do not have a common side\n  return (\n    firstRowLength === secondColLength && secondRowLength === firstColLength\n  )\n}\n\n// returns an empty array that has the same number of rows as the left matrix being multiplied.\n// Uses Array.prototype.map() to loop over the first (or left) matrix and returns an empty array on each iteration.\nconst initiateEmptyArray = (first, second) => {\n  if (twoMatricesCheck(first, second)) {\n    const emptyArray = first.map(() => {\n      return ['']\n    })\n    return emptyArray\n  } else {\n    return false\n  }\n}\n\n// Finally, `matrixMult` uses `Array.prototype.push()`, multiple layers of nested `for` loops, the addition assignment `+=` operator and multiplication operator `*` to perform the dot product between two matrices of differing sizes.\n// Dot product, takes the row of the first matrix and multiplies it by the column of the second matrix, the `twoMatricesCheck` tested to see if they were the same size already.\n// The dot product for each iteration is then saved to its respective index into `multMatrix`.\nexport const matrixMult = (firstArray, secondArray) => {\n  const multMatrix = initiateEmptyArray(firstArray, secondArray)\n  for (let rm = 0; rm < firstArray.length; rm++) {\n    const rowMult = []\n    for (let col = 0; col < firstArray[0].length; col++) {\n      rowMult.push(firstArray[rm][col])\n    }\n    for (let cm = 0; cm < firstArray.length; cm++) {\n      const colMult = []\n      for (let row = 0; row < secondArray.length; row++) {\n        colMult.push(secondArray[row][cm])\n      }\n      let newNumb = 0\n      for (let index = 0; index < rowMult.length; index++) {\n        newNumb += rowMult[index] * colMult[index]\n      }\n      multMatrix[rm][cm] = newNumb\n    }\n  }\n  return multMatrix\n}\n\n// const firstMatrix = [\n//   [1, 2],\n//   [3, 4]\n// ]\n\n// const secondMatrix = [\n//   [5, 6],\n//   [7, 8]\n// ]\n\n// matrixMult(firstMatrix, secondMatrix) // [ [ 19, 22 ], [ 43, 50 ] ]\n\n// const thirdMatrix = [\n//   [-1, 4, 1],\n//   [7, -6, 2]\n// ]\n// const fourthMatrix = [\n//   [2, -2],\n//   [5, 3],\n//   [3, 2]\n// ]\n\n// matrixMult(thirdMatrix, fourthMatrix) // [ [ 21, 16 ], [ -10, -28 ] ]\n"
  },
  {
    "path": "Maths/MeanAbsoluteDeviation.js",
    "content": "import { mean } from './AverageMean.js'\n/**\n *@function meanAbsoluteDeviation\n *@description Calculates the mean absolute deviation of list of numbers\n * @param {Integer} data\n * @returns meanAbsoluteDeviation([2,34,5,0,-2]) = 10.480\n * @url https://en.wikipedia.org/wiki/Average_absolute_deviation\n */\nfunction meanAbsoluteDeviation(data) {\n  if (!Array.isArray(data)) {\n    throw new TypeError('Invalid Input')\n  }\n  let absoluteSum = 0\n  const meanValue = mean(data)\n  for (const dataPoint of data) {\n    absoluteSum += Math.abs(dataPoint - meanValue)\n  }\n  return absoluteSum / data.length\n}\n\nexport { meanAbsoluteDeviation }\n"
  },
  {
    "path": "Maths/MeanSquareError.js",
    "content": "// Wikipedia: https://en.wikipedia.org/wiki/Mean_squared_error\n\nconst meanSquaredError = (predicted, expected) => {\n  if (!Array.isArray(predicted) || !Array.isArray(expected)) {\n    throw new TypeError('Argument must be an Array')\n  }\n\n  if (predicted.length !== expected.length) {\n    throw new TypeError('The two lists must be of equal length')\n  }\n\n  let err = 0\n\n  for (let i = 0; i < expected.length; i++) {\n    err += (expected[i] - predicted[i]) ** 2\n  }\n\n  return err / expected.length\n}\n\nexport { meanSquaredError }\n"
  },
  {
    "path": "Maths/MidpointIntegration.js",
    "content": "/**\n *\n * @title Midpoint rule for definite integral evaluation\n * @author [ggkogkou](https://github.com/ggkogkou)\n * @brief Calculate definite integrals with midpoint method\n *\n * @details The idea is to split the interval in a number N of intervals and use as interpolation points the xi\n * for which it applies that xi = x0 + i*h, where h is a step defined as h = (b-a)/N where a and b are the\n * first and last points of the interval of the integration [a, b].\n *\n * We create a table of the xi and their corresponding f(xi) values and we evaluate the integral by the formula:\n * I = h * {f(x0+h/2) + f(x1+h/2) + ... + f(xN-1+h/2)}\n *\n * N must be > 0 and a<b. By increasing N, we also increase precision\n *\n * [More info link](https://tutorial.math.lamar.edu/classes/calcii/approximatingdefintegrals.aspx)\n *\n */\n\nfunction integralEvaluation(N, a, b, func) {\n  // Check if all restrictions are satisfied for the given N, a, b\n  if (!Number.isInteger(N) || Number.isNaN(a) || Number.isNaN(b)) {\n    throw new TypeError('Expected integer N and finite a, b')\n  }\n  if (N <= 0) {\n    throw Error('N has to be >= 2')\n  } // check if N > 0\n  if (a > b) {\n    throw Error('a must be less or equal than b')\n  } // Check if a < b\n  if (a === b) return 0 // If a === b integral is zero\n\n  // Calculate the step h\n  const h = (b - a) / N\n\n  // Find interpolation points\n  let xi = a // initialize xi = x0\n  const pointsArray = []\n\n  // Find the sum {f(x0+h/2) + f(x1+h/2) + ... + f(xN-1+h/2)}\n  let temp\n  for (let i = 0; i < N; i++) {\n    temp = func(xi + h / 2)\n    pointsArray.push(temp)\n    xi += h\n  }\n\n  // Calculate the integral\n  let result = h\n  temp = pointsArray.reduce((acc, currValue) => acc + currValue, 0)\n\n  result *= temp\n\n  if (Number.isNaN(result)) {\n    throw Error(\n      'Result is NaN. The input interval does not belong to the functions domain'\n    )\n  }\n\n  return result\n}\n\nexport { integralEvaluation }\n"
  },
  {
    "path": "Maths/MobiusFunction.js",
    "content": "/*\n * Author: Akshay Dubey (https://github.com/itsAkshayDubey)\n * Mobius Function: https://en.wikipedia.org/wiki/M%C3%B6bius_function\n * For any positive integer n, define μ(n) as the sum of the primitive nth roots of unity.\n * It has values in {−1, 0, 1} depending on the factorization of n into prime factors:\n *   μ(n) = +1 if n is a square-free positive integer with an even number of prime factors.\n *   μ(n) = −1 if n is a square-free positive integer with an odd number of prime factors.\n *   μ(n) = 0 if n has a squared prime factor.\n */\n\n/**\n * @function mobiusFunction\n * @description -> This method returns μ(n) of given number n\n * returns 1 when number is less than or equals 1\n * or number has even number of prime factors\n * returns 0 when number has repeated prime factor\n * returns -1 when number has odd number of prime factors\n * @param {Integer} number\n * @returns {Integer}\n */\n\nimport { PrimeFactors } from './PrimeFactors.js'\nexport const mobiusFunction = (number) => {\n  const primeFactorsArray = PrimeFactors(number)\n  if (number <= 0) {\n    throw new Error('Number must be greater than zero.')\n  }\n  return primeFactorsArray.length !== new Set(primeFactorsArray).size\n    ? 0\n    : primeFactorsArray.length % 2 === 0\n    ? 1\n    : -1\n}\n"
  },
  {
    "path": "Maths/ModularArithmetic.js",
    "content": "import { extendedEuclideanGCD } from './ExtendedEuclideanGCD'\n\n/**\n * https://brilliant.org/wiki/modular-arithmetic/\n * @param {Number} arg1 first argument\n * @param {Number} arg2 second argument\n * @returns {Number}\n */\n\nexport class ModRing {\n  constructor(MOD) {\n    this.MOD = MOD\n  }\n\n  isInputValid = (arg1, arg2) => {\n    if (!this.MOD) {\n      throw new Error('Modulus must be initialized in the object constructor')\n    }\n    if (typeof arg1 !== 'number' || typeof arg2 !== 'number') {\n      throw new TypeError('Input must be Numbers')\n    }\n  }\n  /**\n   * Modulus is Distributive property,\n   * As a result, we separate it into numbers in order to keep it within MOD's range\n   */\n\n  add = (arg1, arg2) => {\n    this.isInputValid(arg1, arg2)\n    return ((arg1 % this.MOD) + (arg2 % this.MOD)) % this.MOD\n  }\n\n  subtract = (arg1, arg2) => {\n    this.isInputValid(arg1, arg2)\n    // An extra MOD is added to check negative results\n    return ((arg1 % this.MOD) - (arg2 % this.MOD) + this.MOD) % this.MOD\n  }\n\n  multiply = (arg1, arg2) => {\n    this.isInputValid(arg1, arg2)\n    return ((arg1 % this.MOD) * (arg2 % this.MOD)) % this.MOD\n  }\n\n  /**\n   *\n   * It is not Possible to find Division directly like the above methods,\n   * So we have to use the Extended Euclidean Theorem for finding Multiplicative Inverse\n   * https://github.com/TheAlgorithms/JavaScript/blob/master/Maths/ExtendedEuclideanGCD.js\n   */\n\n  divide = (arg1, arg2) => {\n    // 1st Index contains the required result\n    // The theorem may have return Negative value, we need to add MOD to make it Positive\n    return (extendedEuclideanGCD(arg1, arg2)[1] + this.MOD) % this.MOD\n  }\n}\n"
  },
  {
    "path": "Maths/ModularBinaryExponentiationRecursive.js",
    "content": "/*\n  Modified from:\n    https://github.com/TheAlgorithms/Python/blob/master/maths/binary_exp_mod.py\n\n  Explanation:\n    https://en.wikipedia.org/wiki/Exponentiation_by_squaring\n*/\n\nconst modularBinaryExponentiation = (a, n, m) => {\n  // input: a: int, n: int, m: int\n  // returns: (a^n) % m: int\n  if (n === 0) {\n    return 1\n  } else if (n % 2 === 1) {\n    return (modularBinaryExponentiation(a, n - 1, m) * a) % m\n  } else {\n    const b = modularBinaryExponentiation(a, n / 2, m)\n    return (b * b) % m\n  }\n}\n\nexport { modularBinaryExponentiation }\n"
  },
  {
    "path": "Maths/NumberOfDigits.js",
    "content": "/**\n *\n * Author: dephraiim\n * License: GPL-3.0 or later\n *\n * Returns the number of digits of a given integer\n *\n */\n\nconst numberOfDigit = (n) => Math.abs(n).toString().length\n\n/**\n * Returns the number of digits of a given integer.\n *\n * @param {number} n - The integer for which to count digits.\n * @returns {number} The number of digits in the integer.\n * @see https://math.stackexchange.com/questions/2145480/how-does-the-logarithm-returns-the-number-of-digits-of-a-number\n * @author dev-madhurendra\n */\nconst numberOfDigitsUsingLog = (n) =>\n  n === 0 ? 1 : Math.floor(Math.log10(Math.abs(n))) + 1\n\nexport { numberOfDigit, numberOfDigitsUsingLog }\n"
  },
  {
    "path": "Maths/Palindrome.js",
    "content": "/**\n * A palindrome is any string that can be reversed and still be the same.\n * An example of one is 'radar', since it is spelled the same even after\n * being reversed. One method to check if a\n *\n * Here's how this works recursively:\n *\n * Palindrome('radar')\n * true && Palindrome('ada')\n * true && true && Palindrome('d')\n * true && true && true && true\n *\n * @flow\n * @complexity: O(n)\n */\n\nconst PalindromeRecursive = (string) => {\n  // Base case\n  if (string.length < 2) return true\n\n  // Check outermost keys\n  if (string[0] !== string[string.length - 1]) {\n    return false\n  }\n\n  return PalindromeRecursive(string.slice(1, string.length - 1))\n}\n\nconst PalindromeIterative = (string) => {\n  const _string = string\n    .toLowerCase()\n    .replace(/ /g, '')\n    .replace(/,/g, '')\n    .replace(/'.'/g, '')\n    .replace(/:/g, '')\n    .split('')\n\n  // A word of only 1 character is already a palindrome, so we skip to check it\n  while (_string.length > 1) {\n    if (_string.shift() !== _string.pop()) {\n      return false\n    }\n  }\n\n  return true\n}\n\n/**\n *\n * Checks if a string is a palindrome.\n * @author dev-madhurendra\n * @param {string} str - The string to check.\n * @returns {boolean} True if the string is a palindrome, false otherwise.\n *\n * @example\n * const isPalindrome = checkPalindrome('racecar'); // Returns true\n * const isNotPalindrome = checkPalindrome('hello');  // Returns false\n */\nconst checkPalindrome = (str) =>\n  str.replace(/\\s/g, '') === str.replace(/\\s/g, '').split('').reverse().join('')\n\nexport { PalindromeIterative, PalindromeRecursive, checkPalindrome }\n"
  },
  {
    "path": "Maths/ParityOutlier.js",
    "content": "/**\n * @author mrmagic2020\n * @description The function will find the parity outlier from an array of integers.\n * @see https://en.wikipedia.org/wiki/Parity_(mathematics)\n * @param {number[]} integers - An array of integers.\n * @returns {number} - The parity outlier.\n * @example parityOutlier([1, 3, 5, 8, 9]) = 8\n */\nconst parityOutlier = (integers) => {\n  let oddsCount = 0 // define counter for odd number(s)\n  let evensCount = 0 // define counter for even number(s)\n  let odd, even\n\n  for (const e of integers) {\n    if (!Number.isInteger(e)) {\n      // detect non-integer elements\n      return null\n    }\n    if (e % 2 === 0) {\n      // an even number\n      even = e\n      evensCount++\n    } else {\n      // an odd number\n      odd = e\n      oddsCount++\n    }\n  }\n\n  if (oddsCount === 0 || evensCount === 0) return null // array has only odd/even number(s)\n  if (oddsCount > 1 && evensCount > 1) return null // array has more than one even and odd number\n\n  return oddsCount === 1 ? odd : even\n}\n\nexport { parityOutlier }\n"
  },
  {
    "path": "Maths/PascalTriangle.js",
    "content": "const addRow = (triangle) => {\n  const previous = triangle[triangle.length - 1]\n  const newRow = [1]\n  for (let i = 0; i < previous.length - 1; i++) {\n    const current = previous[i]\n    const next = previous[i + 1]\n    newRow.push(current + next)\n  }\n  newRow.push(1)\n  return triangle.push(newRow)\n}\n\nconst generate = (numRows) => {\n  const triangle = [[1], [1, 1]]\n\n  if (numRows === 0) {\n    return []\n  } else if (numRows === 1) {\n    return [[1]]\n  } else {\n    for (let i = 2; i < numRows; i++) {\n      addRow(triangle)\n    }\n  }\n  return triangle\n}\n\nexport { generate }\n"
  },
  {
    "path": "Maths/PerfectCube.js",
    "content": "/**\n * Author: dephraiim\n * License: GPL-3.0 or later\n *\n * This uses `round` instead of `floor` or `trunc`, to guard against potential `cbrt` accuracy errors\n */\n\nconst perfectCube = (num) =>\n  Number.isFinite(num) && Math.round(Math.cbrt(num)) ** 3 === num\n\nexport { perfectCube }\n"
  },
  {
    "path": "Maths/PerfectNumber.js",
    "content": "/**\n * Author: dephraiim\n * License: GPL-3.0 or later\n *\n * == Perfect Number ==\n * In number theory, a perfect number is a positive integer that is equal to the sum of\n * its positive divisors(factors), excluding the number itself.\n * For example: 6 ==> divisors[1, 2, 3, 6]\n *      Excluding 6, the sum(divisors) is 1 + 2 + 3 = 6\n *      So, 6 is a Perfect Number\n * Other examples of Perfect Numbers: 28, 486, ...\n *\n * More on Perfect Number:\n *      https://en.wikipedia.org/wiki/Perfect_number\n *\n */\n\nconst factorsExcludingNumber = (n) => {\n  return [...Array(n).keys()].filter((num) => n % num === 0)\n}\n\nconst perfectNumber = (n) => {\n  const factorSum = factorsExcludingNumber(n).reduce((num, initialValue) => {\n    return num + initialValue\n  }, 0)\n\n  return factorSum === n\n}\n\nexport { perfectNumber }\n"
  },
  {
    "path": "Maths/PerfectSquare.js",
    "content": "/**\n * Author: dephraiim\n * License: GPL-3.0 or later\n *\n * This uses `round` instead of `floor` or `trunc`, to guard against potential `sqrt` accuracy errors\n */\n\nconst perfectSquare = (num) =>\n  Number.isFinite(num) && Math.round(Math.sqrt(num)) ** 2 === num\n\nexport { perfectSquare }\n"
  },
  {
    "path": "Maths/PermutationAndCombination.js",
    "content": "/**\n * @details Calculates the number of permutations and combinations.\n * @external_link (Permutation And Combinations)[https://www.geeksforgeeks.org/permutation-and-combination/]\n */\n\n/**\n * @brief Calculates the factorial of the given number.\n * @param num: integer\n * @details Factorial of n = n * (n - 1) * (n - 2) * ... * 1\n * @returns integer: Factorial of the number.\n            NaN: if negative number is provided.\n */\nconst factorial = (n) => {\n  if (n >= 0) {\n    if (n === 0) {\n      return 1\n    } else {\n      return n * factorial(n - 1)\n    }\n  } else {\n    return NaN\n  }\n}\n\n/**\n * @brief Calculates the number of Permutations from the given data.\n * @param\n * n: integer -> number of items.\n * r: integer -> number of times n is taken.\n * @returns integer: The number of permutations.\n            NaN: if negative number is provided.\n */\nconst permutation = (n, r) => {\n  return factorial(n) / factorial(n - r)\n}\n\n/**\n * @brief Calculates the number of Combinations from the given data.\n * @param\n * n -> number of items.\n * r -> number of times n is taken.\n * @returns integer: The number of combinations.\n            NaN: if negative number is provided.\n */\nconst combination = (n, r) => {\n  return factorial(n) / (factorial(r) * factorial(n - r))\n}\n\n// Exports the functions to be used in other files.\nexport { factorial, permutation, combination }\n"
  },
  {
    "path": "Maths/PiApproximationMonteCarlo.js",
    "content": "// Wikipedia: https://en.wikipedia.org/wiki/Monte_Carlo_method\n// Video Explanation: https://www.youtube.com/watch?v=ELetCV_wX_c\n\nconst piEstimation = (iterations = 100000) => {\n  let circleCounter = 0\n\n  for (let i = 0; i < iterations; i++) {\n    // generating random points and checking if it lies within a circle of radius 1\n    const x = Math.random()\n    const y = Math.random()\n    const radius = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))\n\n    if (radius < 1) circleCounter += 1\n  }\n\n  // formula for pi = (ratio of number inside circle and total iteration) x 4\n  const pi = (circleCounter / iterations) * 4\n  return pi\n}\n\nexport { piEstimation }\n"
  },
  {
    "path": "Maths/Polynomial.js",
    "content": "/**\n * Polynomials are algebraic expressions consisting of two or more algebraic terms.\n * Terms of a polynomial are:\n * 1. Coefficients e.g. 5, 4 in 5x^0, 4x^3 respectively\n * 2. Variables e.g. y in 3y^2\n * 3. Exponents e.g. 5 in y^5\n *\n * Class Polynomial constructs the polynomial using Array as an argument.\n * The members of array are coefficients and their indexes as exponents.\n */\nclass Polynomial {\n  constructor(array) {\n    this.coefficientArray = array // array of coefficients\n    this.polynomial = '' // in terms of x e.g., (2x) + (1)\n    this.construct()\n  }\n\n  /**\n   * Function to construct the polynomial in terms of x using the coefficientArray\n   */\n  construct() {\n    this.polynomial = this.coefficientArray\n      .map((coefficient, exponent) => {\n        if (coefficient === 0) {\n          return '0'\n        }\n        if (exponent === 0) {\n          return `(${coefficient})`\n        } else if (exponent === 1) {\n          return `(${coefficient}x)`\n        } else {\n          return `(${coefficient}x^${exponent})`\n        }\n      })\n      .filter((x) => x !== '0')\n      .reverse()\n      .join(' + ')\n  }\n\n  /**\n   * Function to display polynomial in terms of x\n   * @returns {String} of polynomial representation in terms of x\n   */\n  display() {\n    return this.polynomial\n  }\n\n  /**\n   * Function to calculate the value of the polynomial by substituting variable x\n   * @param {Number} value\n   */\n  evaluate(value) {\n    return this.coefficientArray.reduce((result, coefficient, exponent) => {\n      return result + coefficient * Math.pow(value, exponent)\n    }, 0)\n  }\n}\n\nexport { Polynomial }\n"
  },
  {
    "path": "Maths/Pow.js",
    "content": "/**\n * @function powLinear\n * @description - The powLinear function is a power function with Linear O(n) complexity\n * @param {number} base\n * @param {number} exponent\n * @returns {number}\n * @example - powLinear(2, 2) => 4 --> 2 * 2\n * @example - powLinear(3, 3) => 27 --> 3 * 3 * 3\n */\nconst powLinear = (base, exponent) => {\n  if (exponent < 0) {\n    base = 1 / base\n    exponent = -exponent\n  }\n\n  let result = 1\n\n  while (exponent--) {\n    // Break the execution while the exponent will 0\n    result *= base\n  }\n\n  return result\n}\n\n/**\n * @function powFaster\n * @description - The powFaster function is a power function with O(logN) complexity\n * @param {number} base\n * @param {number} exponent\n * @returns {number}\n * @example - powFaster(2, 2) => 4 --> 2 * 2\n * @example - powFaster(3, 3) => 27 --> 3 * 3 * 3\n */\nconst powFaster = (base, exponent) => {\n  if (exponent < 2) {\n    // explanation below - 1\n    return base && ([1, base][exponent] || powFaster(1 / base, -exponent))\n  }\n\n  if (exponent & 1) {\n    // if the existing exponent is odd\n    return base * powFaster(base * base, exponent >> 1) // explanation below - 2\n  }\n\n  return powFaster(base * base, exponent / 2)\n}\n\n/**\n * 1 - Magic of short circuit evaluation (&&, ||)\n * if the base is 0 then it returns 0 cause 0 is falsy\n * if the base is not 0 then it's must be truthy. after that, it will be executed the right portion of the && (AND) operator\n * Now it checks the exponent by the help array index, is it 0 or 1.\n * if the exponent is not 0 or 1 it's definitely less than 0, and a negative number is not a valid index number so it returns \"undefined\"\n * if the expression is undefined mean -> falsy, the || (OR) operator evaluates the right portion that is a recursive function.\n */\n\n/**\n * 2 - Play with right shift bitwise operator (>>)\n * right shift with any odd numbers it returns the floor number instead of float.\n * E.g. if the number is 5, after right shifting with 1 it's will give us 2, not 2.5\n * cause the right shift formula is --> x >> y = |x| / 2^y\n */\n\nexport { powLinear, powFaster }\n"
  },
  {
    "path": "Maths/PowLogarithmic.js",
    "content": "import { isEven } from './IsEven'\n\n/**\n * This algorithm is divide the n by 2 every time and pass this to recursive call to find the result of smaller result.\n * why? Because\n *      x^n => [if n is even] x^(n / 2) *  x^(n / 2)     (example : 7^4 => 7^2 * 7^2)\n *             [if n is odd]  x^(n / 2) *  x^(n / 2) * x (example : 7^5 => 7^2 * 7^2 * 7)\n * and repeat the above step until we reach to the base case.\n *\n * @function PowLogarithmic\n * @description Given two integers x and n, return x^n in logarithmic complexity.\n * @param {Integer} x - The input integer\n * @param {Integer} n - The input integer\n * @return {Integer} - Returns x^n.\n * @see [Pow-Logarithmic](https://www.geeksforgeeks.org/write-a-c-program-to-calculate-powxn/)\n */\nconst powLogarithmic = (x, n) => {\n  if (n === 0) return 1\n  const result = powLogarithmic(x, Math.floor(n / 2))\n  if (isEven(n)) {\n    return result * result\n  }\n  return result * result * x\n}\n\nexport { powLogarithmic }\n"
  },
  {
    "path": "Maths/PrimeCheck.js",
    "content": "/*\n  Modified from:\n    https://github.com/TheAlgorithms/Python/blob/master/maths/prime_check.py\n\n  Complexity:\n    O(sqrt(n))\n*/\n\nconst PrimeCheck = (n) => {\n  // input: n: int\n  // output: boolean\n  if (n === 1) return false\n  if (n === 0) return false\n  if (n === 2) return true\n  if (n % 2 === 0) return false\n\n  for (let i = 3; i * i <= n; i += 2) {\n    if (n % i === 0) {\n      return false\n    }\n  }\n  return true\n}\n\nexport { PrimeCheck }\n"
  },
  {
    "path": "Maths/PrimeFactors.js",
    "content": "/*\n  Modified from:\n    https://github.com/TheAlgorithms/Python/blob/master/maths/prime_factors.py\n*/\n\nexport const PrimeFactors = (n) => {\n  // input: n: int\n  // output: primeFactors: Array of all prime factors of n\n  const primeFactors = []\n  for (let i = 2; i * i <= n; i++) {\n    while (n % i === 0) {\n      primeFactors.push(i)\n      n = Math.floor(n / i)\n    }\n  }\n  if (n > 1) {\n    primeFactors.push(n)\n  }\n  return primeFactors\n}\n"
  },
  {
    "path": "Maths/QuadraticRoots.js",
    "content": "/**\n * @see https://www.cuemath.com/algebra/roots-of-quadratic-equation/\n * @author Dibya Debayan Dash\n * Calculates the roots of a quadratic equation of the form ax^2 + bx + c = 0.\n *\n * @param {number} a - Coefficient of x^2.\n * @param {number} b - Coefficient of x.\n * @param {number} c - Constant term.\n * @returns {number[]} - An array containing the roots if they are real,\n *                      or an empty array indicating no real roots.\n *\n * @example\n * // Find the roots of the quadratic equation: 2x^2 - 4x + 2 = 0\n * const roots = quadraticRoots(2, -4, 2);\n * // Expected output: [1]\n */\nconst quadraticRoots = (a, b, c) => {\n  // Calculate the discriminant\n  const discriminant = b * b - 4 * a * c\n\n  // Check if roots are real\n  if (discriminant < 0) {\n    return []\n  } else if (discriminant === 0) {\n    // One real root\n    return [-b / (2 * a)]\n  } else {\n    // Two real roots\n    const sqrtDiscriminant = Math.sqrt(discriminant)\n    return [\n      (-b + sqrtDiscriminant) / (2 * a),\n      (-b - sqrtDiscriminant) / (2 * a)\n    ]\n  }\n}\n\nexport { quadraticRoots }\n"
  },
  {
    "path": "Maths/RadianToDegree.js",
    "content": "/*\n * Radian : https://en.wikipedia.org/wiki/Radian\n * Degree : https://en.wikipedia.org/wiki/Degree_(angle)\n *\n * Angle in Degree = ( Angle in Radian ) x ( 180 / pi )\n *\n * Example :\n * Question : Convert pi / 2 degree to radian\n * So, Angle in Radian = pi / 2\n *\n * Solution :\n * Angle in Degree = ( pi / 2 ) x ( 180 / pi ) = 90\n *\n * So, pi / 2 radian is equal to 90 degree\n */\n\n/**\n * @param {number} radian\n * @return {number}\n */\nexport const radianToDegree = (radian) => {\n  return radian * (180 / Math.PI)\n}\n"
  },
  {
    "path": "Maths/ReverseNumber.js",
    "content": "/*\n    Problem statement and Explanation : https://medium.com/@ManBearPigCode/how-to-reverse-a-number-mathematically-97c556626ec6\n*/\n\n/**\n * ReverseNumber return the reversed value of the given number.\n * @param {Number} n any digit number.\n * @returns `Number` n reverse in reverse.\n */\nconst ReverseNumber = (number) => {\n  // firstly, check that input is a number or not.\n  if (typeof number !== 'number') {\n    throw new TypeError('Argument is not a number.')\n  }\n  // A variable for storing the reversed number.\n  let reverseNumber = 0\n  // Iterate the process until getting the number is 0.\n  while (number > 0) {\n    // get the last digit of the number\n    const lastDigit = number % 10\n    // add to the last digit to in reverseNumber\n    reverseNumber = reverseNumber * 10 + lastDigit\n    // reduce the actual number.\n    number = Math.floor(number / 10)\n  }\n  return reverseNumber\n}\n\nexport { ReverseNumber }\n"
  },
  {
    "path": "Maths/ReversePolishNotation.js",
    "content": "// Wikipedia: https://en.wikipedia.org/wiki/Reverse_Polish_notation\n\nconst calcRPN = (expression) => {\n  const operators = {\n    '+': (a, b) => a + b,\n    '-': (a, b) => a - b,\n    '*': (a, b) => a * b,\n    '/': (a, b) => b / a\n  }\n\n  const tokens = expression.split(' ')\n\n  const stack = []\n\n  tokens.forEach((token) => {\n    const operator = operators[token]\n\n    if (typeof operator === 'function') {\n      const a = stack.pop()\n      const b = stack.pop()\n\n      const result = operator(a, b)\n\n      stack.push(result)\n    } else {\n      stack.push(parseFloat(token))\n    }\n  })\n\n  return stack.pop()\n}\n\nexport { calcRPN }\n"
  },
  {
    "path": "Maths/RowEchelon.js",
    "content": "/**\n * Given a two dimensional matrix, find its row echelon form.\n *\n * For more info: https://en.wikipedia.org/wiki/Row_echelon_form\n *\n * @param {number[[]]} matrix - Two dimensional array of rational numbers.\n * @returns {number[[]]} - Two dimensional array of rational numbers (row echelon form).\n *\n * @example\n * const matrix = [\n *                          [2,3,4,5,7],\n *                          [9,8,4,0,9],\n *                          [5,7,4,3,9],\n *                          [3,4,0,2,1]\n *                ]\n *\n * const result = rowEchelon(matrix)\n *\n * // The function returns the corresponding row echelon form:\n * // result:\n * //             [\n * //                       [1,  1.5,  2,        2.5,      3.5],\n * //                       [0,  1,    2.54545,  4.09091,  4.09091],\n * //                       [0,  0,    1,        1.57692,  1.36539],\n * //                       [0,  0,    0,        1,        -0.25]\n * //             ]\n */\n\n// Set a tolerance value for floating-point comparisons\nconst tolerance = 0.000001\n\n// Check if all the rows have same length of elements\nconst isMatrixValid = (matrix) => {\n  let numRows = matrix.length\n  let numCols = matrix[0].length\n  for (let i = 0; i < numRows; i++) {\n    if (numCols !== matrix[i].length) {\n      return false\n    }\n  }\n\n  // Check for input other than a 2D matrix\n  if (\n    !Array.isArray(matrix) ||\n    matrix.length === 0 ||\n    !Array.isArray(matrix[0])\n  ) {\n    return false\n  }\n  return true\n}\n\nconst checkNonZero = (currentRow, currentCol, matrix) => {\n  let numRows = matrix.length\n  for (let i = currentRow; i < numRows; i++) {\n    // Checks if the current element is not very near to zero.\n    if (!isTolerant(0, matrix[i][currentCol], tolerance)) {\n      return true\n    }\n  }\n  return false\n}\n\nconst swapRows = (currentRow, withRow, matrix) => {\n  let numCols = matrix[0].length\n  let tempValue = 0\n  for (let j = 0; j < numCols; j++) {\n    tempValue = matrix[currentRow][j]\n    matrix[currentRow][j] = matrix[withRow][j]\n    matrix[withRow][j] = tempValue\n  }\n}\n\n// Select a pivot element in the current column to facilitate row operations.\n// Pivot element is the first non-zero element found from the current row\n// down to the last row.\nconst selectPivot = (currentRow, currentCol, matrix) => {\n  let numRows = matrix.length\n  for (let i = currentRow; i < numRows; i++) {\n    if (matrix[i][currentCol] !== 0) {\n      swapRows(currentRow, i, matrix)\n      return\n    }\n  }\n}\n\n// Multiply each element of the given row with a factor.\nconst scalarMultiplication = (currentRow, factor, matrix) => {\n  let numCols = matrix[0].length\n  for (let j = 0; j < numCols; j++) {\n    matrix[currentRow][j] *= factor\n  }\n}\n\n// Subtract one row from another row\nconst subtractRow = (currentRow, fromRow, matrix) => {\n  let numCols = matrix[0].length\n  for (let j = 0; j < numCols; j++) {\n    matrix[fromRow][j] -= matrix[currentRow][j]\n  }\n}\n\n// Check if two numbers are equal within a given tolerance\nconst isTolerant = (a, b, tolerance) => {\n  const absoluteDifference = Math.abs(a - b)\n  return absoluteDifference <= tolerance\n}\n\nconst rowEchelon = (matrix) => {\n  // Check if the input matrix is valid; if not, throw an error.\n  if (!isMatrixValid(matrix)) {\n    throw new Error('Input is not a valid 2D matrix.')\n  }\n\n  let numRows = matrix.length\n  let numCols = matrix[0].length\n  let result = matrix\n\n  // Iterate through the rows (i) and columns (j) of the matrix.\n  for (let i = 0, j = 0; i < numRows && j < numCols; ) {\n    // If the current column has all zero elements below the current row,\n    // move to the next column.\n    if (!checkNonZero(i, j, result)) {\n      j++\n      continue\n    }\n\n    // Select a pivot element and normalize the current row.\n    selectPivot(i, j, result)\n    let factor = 1 / result[i][j]\n    scalarMultiplication(i, factor, result)\n\n    // Make elements below the pivot element zero by performing\n    // row operations on subsequent rows.\n    for (let x = i + 1; x < numRows; x++) {\n      factor = result[x][j]\n      if (isTolerant(0, factor, tolerance)) {\n        continue\n      }\n      scalarMultiplication(i, factor, result)\n      subtractRow(i, x, result)\n      factor = 1 / factor\n      scalarMultiplication(i, factor, result)\n    }\n    i++\n  }\n  return result\n}\n\nexport { rowEchelon }\n"
  },
  {
    "path": "Maths/ShorsAlgorithm.js",
    "content": "/**\n * @function ShorsAlgorithm\n * @description Classical implementation of Shor's Algorithm.\n * @param {Integer} num - Find a non-trivial factor of this number.\n * @returns {Integer} - A non-trivial factor of num.\n * @see https://en.wikipedia.org/wiki/Shor%27s_algorithm\n * @see https://www.youtube.com/watch?v=lvTqbM5Dq4Q\n *\n * Shor's algorithm is a quantum algorithm for integer factorization. This\n * function implements a version of the algorithm which is computable using\n * a classical computer, but is not as efficient as the quantum algorithm.\n *\n * The algorithm basically consists of guessing a number g which may share\n * factors with our target number N, and then use Euclid's GCD algorithm to\n * find the common factor.\n *\n * The algorithm starts with a random guess for g, and then improves the\n * guess by using the fact that for two coprimes A and B, A^p = mB + 1.\n * For our purposes, this means that g^p = mN + 1. This mathematical\n * identity can be rearranged into (g^(p/2) + 1)(g^(p/2) - 1) = mN.\n * Provided that p/2 is an integer, and neither g^(p/2) + 1 nor g^(p/2) - 1\n * are a multiple of N, either g^(p/2) + 1 or g^(p/2) - 1 must share a\n * factor with N, which can then be found using Euclid's GCD algorithm.\n */\nfunction ShorsAlgorithm(num) {\n  const N = BigInt(num)\n\n  while (true) {\n    // generate random g such that 1 < g < N\n    const g = BigInt(Math.floor(Math.random() * (num - 1)) + 2)\n\n    // check if g shares a factor with N\n    // if it does, find and return the factor\n    let K = gcd(g, N)\n    if (K !== 1) return K\n\n    // find p such that g^p = mN + 1\n    const p = findP(g, N)\n\n    // p needs to be even for it's half to be an integer\n    if (p % 2n === 1n) continue\n\n    const base = g ** (p / 2n) // g^(p/2)\n    const upper = base + 1n // g^(p/2) + 1\n    const lower = base - 1n // g^(p/2) - 1\n\n    // upper and lower can't be a multiple of N\n    if (upper % N === 0n || lower % N === 0n) continue\n\n    // either upper or lower must share a factor with N\n    K = gcd(upper, N)\n    if (K !== 1) return K // upper shares a factor\n    return gcd(lower, N) // otherwise lower shares a factor\n  }\n}\n\n/**\n * @function findP\n * @description Finds a value p such that A^p = mB + 1.\n * @param {BigInt} A\n * @param {BigInt} B\n * @returns The value p.\n */\nfunction findP(A, B) {\n  let p = 1n\n  while (!isValidP(A, B, p)) p++\n  return p\n}\n\n/**\n * @function isValidP\n * @description Checks if A, B, and p fulfill A^p = mB + 1.\n * @param {BigInt} A\n * @param {BigInt} B\n * @param {BigInt} p\n * @returns Whether A, B, and p fulfill A^p = mB + 1.\n */\nfunction isValidP(A, B, p) {\n  // A^p = mB + 1 => A^p - 1 = 0 (mod B)\n  return (A ** p - 1n) % B === 0n\n}\n\n/**\n * @function gcd\n * @description Euclid's GCD algorithm.\n * @param {BigInt} A\n * @param {BigInt} B\n * @returns Greatest Common Divisor between A and B.\n */\nfunction gcd(A, B) {\n  while (B !== 0n) {\n    ;[A, B] = [B, A % B]\n  }\n\n  return Number(A)\n}\n\nexport { ShorsAlgorithm }\n"
  },
  {
    "path": "Maths/SieveOfEratosthenes.js",
    "content": "/**\n * @function sieveOfEratosthenes\n * @description Function to get all the prime numbers below a given number using sieve of eratosthenes algorithm\n * @param {Number} max The limit below which all the primes are required to be\n * @returns {Number[]} An array of all the prime numbers below max\n * @see [Sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes)\n * @example\n * sieveOfEratosthenes(1) // ====> []\n * @example\n * sieveOfEratosthenes(20) // ====> [2, 3, 5, 7, 11, 13, 17, 19]\n *\n */\nfunction sieveOfEratosthenes(max) {\n  const sieve = []\n  const primes = []\n\n  for (let i = 2; i <= max; ++i) {\n    if (!sieve[i]) {\n      // If i has not been marked then it is prime\n      primes.push(i)\n      for (let j = i << 1; j <= max; j += i) {\n        // Mark all multiples of i as non-prime\n        sieve[j] = true\n      }\n    }\n  }\n  return primes\n}\n\nexport { sieveOfEratosthenes }\n"
  },
  {
    "path": "Maths/Signum.js",
    "content": "/*\n  A program to demonstrate the implementation of the signum function,\n  also known as the sign function, in JavaScript.\n\n  The signum function is an odd mathematical function, which returns the\n  sign of the provided real number.\n  It can return 3 values: 1 for values greater than zero, 0 for zero itself,\n  and -1 for values less than zero\n\n  Wikipedia: https://en.wikipedia.org/wiki/Sign_function\n*/\n\n/**\n * @param {Number} input\n * @returns {-1 | 0 | 1 | NaN} sign of input (and NaN if the input is not a number)\n */\nfunction signum(input) {\n  if (input === 0) return 0\n  if (input > 0) return 1\n  if (input < 0) return -1\n\n  return NaN\n}\n\nexport { signum }\n"
  },
  {
    "path": "Maths/SimpsonIntegration.js",
    "content": "/*\n *\n * @file\n * @title Composite Simpson's rule for definite integral evaluation\n * @author: [ggkogkou](https://github.com/ggkogkou)\n * @brief Calculate definite integrals using composite Simpson's numerical method\n *\n * @details The idea is to split the interval in an EVEN number N of intervals and use as interpolation points the xi\n * for which it applies that xi = x0 + i*h, where h is a step defined as h = (b-a)/N where a and b are the\n * first and last points of the interval of the integration [a, b].\n *\n * We create a table of the xi and their corresponding f(xi) values and we evaluate the integral by the formula:\n * I = h/3 * {f(x0) + 4*f(x1) + 2*f(x2) + ... + 2*f(xN-2) + 4*f(xN-1) + f(xN)}\n *\n * That means that the first and last indexed i f(xi) are multiplied by 1,\n * the odd indexed f(xi) by 4 and the even by 2.\n *\n * N must be even number and a<b. By increasing N, we also increase precision\n *\n * More info: [Wikipedia link](https://en.wikipedia.org/wiki/Simpson%27s_rule#Composite_Simpson's_rule)\n *\n */\n\nfunction integralEvaluation(N, a, b, func) {\n  // Check if N is an even integer\n  let isNEven = true\n  if (N % 2 !== 0) isNEven = false\n\n  if (!Number.isInteger(N) || Number.isNaN(a) || Number.isNaN(b)) {\n    throw new TypeError('Expected integer N and finite a, b')\n  }\n  if (!isNEven) {\n    throw Error('N is not an even number')\n  }\n  if (N <= 0) {\n    throw Error('N has to be >= 2')\n  }\n\n  // Check if a < b\n  if (a > b) {\n    throw Error('a must be less or equal than b')\n  }\n  if (a === b) return 0\n\n  // Calculate the step h\n  const h = (b - a) / N\n\n  // Find interpolation points\n  let xi = a // initialize xi = x0\n  const pointsArray = []\n\n  // Find the sum {f(x0) + 4*f(x1) + 2*f(x2) + ... + 2*f(xN-2) + 4*f(xN-1) + f(xN)}\n  let temp\n  for (let i = 0; i < N + 1; i++) {\n    if (i === 0 || i === N) temp = func(xi)\n    else if (i % 2 === 0) temp = 2 * func(xi)\n    else temp = 4 * func(xi)\n\n    pointsArray.push(temp)\n    xi += h\n  }\n\n  // Calculate the integral\n  let result = h / 3\n  temp = pointsArray.reduce((acc, currValue) => acc + currValue, 0)\n\n  result *= temp\n\n  if (Number.isNaN(result)) {\n    throw Error(\n      \"Result is NaN. The input interval doesn't belong to the functions domain\"\n    )\n  }\n\n  return result\n}\n\nexport { integralEvaluation }\n"
  },
  {
    "path": "Maths/Softmax.js",
    "content": "// Wikipedia: https://en.wikipedia.org/wiki/Softmax_function\n\nconst Softmax = (inputs) => {\n  const eulerExpOfAllInputs = inputs.map((input) => Math.exp(input))\n  const sumOfEulerExpOfAllInputs = eulerExpOfAllInputs.reduce((a, b) => a + b)\n\n  return inputs.map((input) => {\n    const eulerExpInputs = Math.exp(input)\n    return eulerExpInputs / sumOfEulerExpOfAllInputs\n  })\n}\n\nexport { Softmax }\n"
  },
  {
    "path": "Maths/SquareRoot.js",
    "content": "/*\n * Author: Rak Laptudirm\n *\n * https://en.wikipedia.org/wiki/Newton%27s_method\n *\n * Finding the square root of a number using Newton's method.\n */\n\nfunction sqrt(num, precision = 4) {\n  if (!Number.isFinite(num)) {\n    throw new TypeError(`Expected a number, received ${typeof num}`)\n  }\n  if (!Number.isFinite(precision)) {\n    throw new TypeError(`Expected a number, received ${typeof precision}`)\n  }\n  let sqrt = 1\n  for (let i = 0; i < precision; i++) {\n    sqrt -= (sqrt * sqrt - num) / (2 * sqrt)\n  }\n  return sqrt\n}\n\nexport { sqrt }\n"
  },
  {
    "path": "Maths/SquareRootLogarithmic.js",
    "content": "/**\n * @function squareRootLogarithmic\n * @description\n * Return the square root of 'num' rounded down\n * to the nearest integer.\n * More info: https://leetcode.com/problems/sqrtx/\n * @param {Number} num Number whose square of root is to be found\n * @returns {Number} Square root\n * @see [BinarySearch](https://en.wikipedia.org/wiki/Binary_search_algorithm)\n * @example\n * const num1 = 4\n * logarithmicSquareRoot(num1) // ====> 2\n * @example\n * const num2 = 8\n * logarithmicSquareRoot(num1) // ====> 2\n *\n */\nconst squareRootLogarithmic = (num) => {\n  if (typeof num !== 'number') {\n    throw new Error('Input data must be numbers')\n  }\n  let answer = 0\n  let sqrt = 0\n  let edge = num\n\n  while (sqrt <= edge) {\n    const mid = Math.trunc((sqrt + edge) / 2)\n    if (mid * mid === num) {\n      return mid\n    } else if (mid * mid < num) {\n      sqrt = mid + 1\n      answer = mid\n    } else {\n      edge = mid - 1\n    }\n  }\n\n  return answer\n}\n\nexport { squareRootLogarithmic }\n"
  },
  {
    "path": "Maths/SumOfDigits.js",
    "content": "/*\n  Gets the sum of the digits of the numbers inputted\n  sumOfDigits(10) will return 1 + 0 = 1\n  sumOfDigits(255) will return 2 + 5 + 5 = 12\n  Wikipedia: https://en.wikipedia.org/wiki/Digit_sum\n*/\n\n/*\n  The given input is converted to a string, split into an array of characters.\n  This array is reduced to a number using the method <Array>.reduce\n*/\nfunction sumOfDigitsUsingString(number) {\n  if (number < 0) number = -number\n\n  return +number\n    .toString()\n    .split('')\n    .reduce((a, b) => +a + +b)\n}\n\n/*\n  The input is divided by 10 in each iteration, till the input is equal to 0\n  The sum of all the digits is returned (The res variable acts as a collector, taking the remainders on each iteration)\n*/\nfunction sumOfDigitsUsingLoop(number) {\n  if (number < 0) number = -number\n  let res = 0\n\n  while (number > 0) {\n    res += number % 10\n    number = Math.floor(number / 10)\n  }\n\n  return res\n}\n\n/*\n  We use the fact that the sum of the digits of a one digit number is itself, and check whether the number is less than 10. If so, then we return the number. Else, we take the number divided by 10 and floored, and recursively call the function, while adding it with the number mod 10\n*/\nfunction sumOfDigitsUsingRecursion(number) {\n  if (number < 0) number = -number\n\n  if (number < 10) return number\n\n  return (number % 10) + sumOfDigitsUsingRecursion(Math.floor(number / 10))\n}\n\nexport {\n  sumOfDigitsUsingRecursion,\n  sumOfDigitsUsingLoop,\n  sumOfDigitsUsingString\n}\n"
  },
  {
    "path": "Maths/SumOfGeometricProgression.js",
    "content": "/*\n  Returns the sum of a geometric progression\n  Article on Geometric Progression: https://en.wikipedia.org/wiki/Geometric_series\n  Examples:\n  > sumOfGeometricProgression(2, 0.5, 6)\n  3.9375\n  > sumOfGeometricProgression(0.5, 10, 3)\n  55.5\n  > sumOfGeometricProgression(0.5, 10, Infinity)\n  Error: The geometric progression is diverging, and its sum cannot be calculated\n*/\n\n/**\n *\n * @param {Number} firstTerm The first term of the geometric progression\n * @param {Number} commonRatio The common ratio of the geometric progression\n * @param {Number} numOfTerms The number of terms in the progression\n */\nfunction sumOfGeometricProgression(firstTerm, commonRatio, numOfTerms) {\n  if (!Number.isFinite(numOfTerms)) {\n    /*\n      If the number of Terms is Infinity, the common ratio needs to be less than 1 to be a convergent geometric progression\n      Article on Convergent Series: https://en.wikipedia.org/wiki/Convergent_series\n    */\n    if (Math.abs(commonRatio) < 1) return firstTerm / (1 - commonRatio)\n    throw new Error(\n      'The geometric progression is diverging, and its sum cannot be calculated'\n    )\n  }\n\n  if (commonRatio === 1) return firstTerm * numOfTerms\n\n  return (\n    (firstTerm * (Math.pow(commonRatio, numOfTerms) - 1)) / (commonRatio - 1)\n  )\n}\n\nexport { sumOfGeometricProgression }\n"
  },
  {
    "path": "Maths/TwoSum.js",
    "content": "/**\n * Given an array of integers, find two numbers that add up to a specific target.\n *\n * @param {number[]} nums - The array of integers.\n * @param {number} target - The target sum.\n * @returns {number[]} - An array containing the indices of the two numbers.\n *\n * @example\n * const nums = [2, 7, 11, 15];\n * const target = 9;\n * const result = twoSum(nums, target);\n * // The function should return [0, 1] because nums[0] + nums[1] = 2 + 7 = 9.\n */\n\nconst TwoSum = (nums, target) => {\n  const numIndicesMap = new Map()\n  for (let i = 0; i < nums.length; i++) {\n    const complement = target - nums[i]\n    if (numIndicesMap.has(complement)) return [numIndicesMap.get(complement), i]\n    numIndicesMap.set(nums[i], i)\n  }\n  return []\n}\nexport { TwoSum }\n"
  },
  {
    "path": "Maths/Volume.js",
    "content": "/*\nCalculate the volume of the shapes\n\nVolume for Cuboid\nVolume for Cube\nVolume for Cone\nVolume for Pyramid\nVolume for Cylinder\nVolume for Triangular Prism\nVolume for Pentagonal Prism\nVolume for Sphere\nVolume for Hemisphere\n*/\n\n/*\n  Calculate the volume for a Cuboid\n  Reference: https://www.cuemath.com/measurement/volume-of-cuboid/\n  return width * length * height\n*/\nconst volCuboid = (width, length, height) => {\n  isNumber(width, 'Width')\n  isNumber(length, 'Length')\n  isNumber(height, 'Height')\n  return width * length * height\n}\n\n/*\n  Calculate the volume for a Cube\n  Reference: https://www.cuemath.com/measurement/volume-of-cube/\n  return length * length * length\n*/\nconst volCube = (length) => {\n  isNumber(length, 'Length')\n  return length ** 3\n}\n\n/*\n  Calculate the volume for a Cone\n  Reference: https://www.cuemath.com/measurement/volume-of-cone/\n  return PI * radius^2 * height/3\n*/\nconst volCone = (radius, height) => {\n  isNumber(radius, 'Radius')\n  isNumber(height, 'Height')\n  return (Math.PI * radius ** 2 * height) / 3.0\n}\n\n/*\n  Calculate the volume for a Pyramid\n  Reference: https://www.cuemath.com/measurement/volume-of-pyramid/\n  return (baseLength * baseWidth * height) / 3\n*/\nconst volPyramid = (baseLength, baseWidth, height) => {\n  isNumber(baseLength, 'BaseLength')\n  isNumber(baseWidth, 'BaseWidth')\n  isNumber(height, 'Height')\n  return (baseLength * baseWidth * height) / 3.0\n}\n\n/*\n  Calculate the volume for a Cylinder\n  Reference: https://www.cuemath.com/measurement/volume-of-cylinder/\n  return PI * radius^2 * height\n*/\nconst volCylinder = (radius, height) => {\n  isNumber(radius, 'Radius')\n  isNumber(height, 'Height')\n  return Math.PI * radius ** 2 * height\n}\n\n/*\n  Calculate the volume for a Triangular Prism\n  Reference: http://lrd.kangan.edu.au/numbers/content/03_volume/04_page.htm\n  return 1 / 2 * baseLengthTriangle * heightTriangle * height\n*/\nconst volTriangularPrism = (baseLengthTriangle, heightTriangle, height) => {\n  isNumber(baseLengthTriangle, 'BaseLengthTriangle')\n  isNumber(heightTriangle, 'HeightTriangle')\n  isNumber(height, 'Height')\n  return (1 / 2) * baseLengthTriangle * heightTriangle * height\n}\n\n/*\n  Calculate the volume for a Pentagonal Prism\n  Reference: https://www.cuemath.com/measurement/volume-of-pentagonal-prism/\n  return 5/2 * pentagonalLength * pentagonalBaseLength * height\n*/\nconst volPentagonalPrism = (pentagonalLength, pentagonalBaseLength, height) => {\n  isNumber(pentagonalLength, 'PentagonalLength')\n  isNumber(pentagonalBaseLength, 'PentagonalBaseLength')\n  isNumber(height, 'Height')\n  return (5 / 2) * pentagonalLength * pentagonalBaseLength * height\n}\n\n/*\n  Calculate the volume for a Sphere\n  Reference: https://www.cuemath.com/measurement/volume-of-sphere/\n  return 4/3 * PI * radius^3\n*/\nconst volSphere = (radius) => {\n  isNumber(radius, 'Radius')\n  return (4 / 3) * Math.PI * radius ** 3\n}\n\n/*\n  Calculate the volume for a Hemisphere\n  Reference: https://www.cuemath.com/measurement/volume-of-hemisphere/\n  return (2 * PI * radius^3)/3\n*/\nconst volHemisphere = (radius) => {\n  isNumber(radius, 'Radius')\n  return (2.0 * Math.PI * radius ** 3) / 3.0\n}\n\nconst isNumber = (number, noName = 'number') => {\n  if (typeof number !== 'number') {\n    throw new TypeError('The ' + noName + ' should be Number type')\n  } else if (number < 0 || !Number.isFinite(number)) {\n    throw new Error('The ' + noName + ' only accepts positive values')\n  }\n}\n\nexport {\n  volCuboid,\n  volCube,\n  volCone,\n  volPyramid,\n  volCylinder,\n  volTriangularPrism,\n  volPentagonalPrism,\n  volSphere,\n  volHemisphere\n}\n"
  },
  {
    "path": "Maths/WhileLoopFactorial.js",
    "content": "/*\n    author: Theepag, optimised by merelymyself\n */\nexport const factorialize = (num) => {\n  // Step 1. Handles cases where num is 0 or 1, by returning 1.\n  let result = 1\n  // Step 2. WHILE loop\n  while (num > 1) {\n    result *= num // or result = result * num;\n    num-- // decrement 1 at each iteration\n  }\n  // Step 3. Return the factorial\n  return result\n}\n"
  },
  {
    "path": "Maths/ZellersCongruenceAlgorithm.js",
    "content": "// Zeller's Congruence Algorithm finds the day of the week from the Gregorian Date. Wikipedia: https://en.wikipedia.org/wiki/Zeller%27s_congruence\nexport const zellersCongruenceAlgorithm = (day, month, year) => {\n  if (\n    typeof day !== 'number' ||\n    typeof month !== 'number' ||\n    typeof year !== 'number'\n  ) {\n    throw new TypeError('Arguments are not all numbers.')\n  }\n  const q = day\n  let m = month\n  let y = year\n  if (month < 3) {\n    m += 12\n    y -= 1\n  }\n  day =\n    (q +\n      Math.floor((26 * (m + 1)) / 10) +\n      (y % 100) +\n      Math.floor((y % 100) / 4) +\n      Math.floor(Math.floor(y / 100) / 4) +\n      5 * Math.floor(y / 100)) %\n    7\n  const days = [\n    'Saturday',\n    'Sunday',\n    'Monday',\n    'Tuesday',\n    'Wednesday',\n    'Thursday',\n    'Friday'\n  ]\n  return days[day]\n}\n"
  },
  {
    "path": "Maths/isPalindromeIntegerNumber.js",
    "content": "/**\n * @function isPalindromeIntegerNumber\n * @param { Number } x\n * @returns {boolean} - input integer is palindrome or not\n *\n * time complexity : O(log_10(N))\n * space complexity : O(1)\n */\nexport function isPalindromeIntegerNumber(x) {\n  if (typeof x !== 'number') {\n    throw new TypeError('Input must be a integer number')\n  }\n  // check x is integer\n  if (!Number.isInteger(x)) {\n    return false\n  }\n\n  // if it has '-' it cannot be palindrome\n  if (x < 0) return false\n\n  // make x reverse\n  let reversed = 0\n  let num = x\n\n  while (num > 0) {\n    const lastDigit = num % 10\n    reversed = reversed * 10 + lastDigit\n    num = Math.floor(num / 10)\n  }\n\n  // compare origin x and reversed are same\n  return x === reversed\n}\n"
  },
  {
    "path": "Maths/test/Abs.test.js",
    "content": "import { abs } from '../Abs'\n\ndescribe('Testing abs function', () => {\n  it('Testing for invalid types', () => {\n    expect(() => abs('234a')).toThrow()\n    expect(() => abs({})).toThrow()\n    expect(() => abs([12, -32, -60])).toThrow()\n    expect(() => abs([])).toThrow() // coerces to 0\n  })\n\n  it('Testing for number of string type', () => {\n    expect(abs('-345')).toBe(345)\n    expect(abs('-345.455645')).toBe(345.455645)\n  })\n\n  it('Testing for a boolean type', () => {\n    expect(abs(true)).toBe(1)\n    expect(abs(false)).toBe(0)\n  })\n\n  it('should return an absolute value of a negative number', () => {\n    const absOfNegativeNumber = abs(-34)\n    expect(absOfNegativeNumber).toBe(34)\n  })\n\n  it('should return an absolute value of a positive number', () => {\n    const absOfPositiveNumber = abs(50)\n    expect(absOfPositiveNumber).toBe(50)\n  })\n\n  it('should return an absolute value of a zero number', () => {\n    const absOfPositiveNumber = abs(0)\n    expect(absOfPositiveNumber).toBe(0)\n  })\n\n  it('should return an absolute value of any floating number', () => {\n    const absOfPositiveNumber = abs(-20.2034)\n    expect(absOfPositiveNumber).toBe(20.2034)\n  })\n})\n"
  },
  {
    "path": "Maths/test/AliquotSum.test.js",
    "content": "import { aliquotSum } from '../AliquotSum'\n\ndescribe('Aliquot Sum of a Number', () => {\n  it('Aliquot Sum of 6', () => {\n    expect(aliquotSum(6)).toBe(6)\n  })\n\n  it('Aliquot Sum of 1', () => {\n    expect(aliquotSum(1)).toBe(0)\n  })\n\n  it('Aliquot Sum of 28', () => {\n    expect(aliquotSum(28)).toBe(28)\n  })\n})\n"
  },
  {
    "path": "Maths/test/Area.test.js",
    "content": "import * as area from '../Area'\n\ndescribe('Testing surfaceAreaCube calculations', () => {\n  it('with natural number', () => {\n    const surfaceAreaOfOne = area.surfaceAreaCube(1.2)\n    const surfaceAreaOfThree = area.surfaceAreaCube(3)\n    expect(surfaceAreaOfOne).toBe(8.64)\n    expect(surfaceAreaOfThree).toBe(54)\n  })\n  it('with negative argument, expect throw', () => {\n    expect(() => area.surfaceAreaCube(-1)).toThrow()\n  })\n  it('with non-numeric argument, expect throw', () => {\n    expect(() => area.surfaceAreaCube('199')).toThrow()\n  })\n})\n\ndescribe('Testing surfaceAreaSphere calculations', () => {\n  it('with correct value', () => {\n    const calculateArea = area.surfaceAreaSphere(5)\n    const expected = 314.1592653589793\n    expect(calculateArea).toBe(expected)\n  })\n  it('with negative value, expect throw', () => {\n    expect(() => area.surfaceAreaSphere(-1)).toThrow()\n  })\n})\n\ndescribe('Testing areaRectangle calculations', () => {\n  it('with correct args', () => {\n    const areaRectangle = area.areaRectangle(2.5, 2)\n    expect(areaRectangle).toBe(5.0)\n  })\n  it('with incorrect args, expect throw', () => {\n    expect(() => area.areaRectangle(-1, 20)).toThrow()\n    expect(() => area.areaRectangle('1', 0)).toThrow()\n    expect(() => area.areaRectangle(23, -1)).toThrow()\n    expect(() => area.areaRectangle(23, 'zero')).toThrow()\n  })\n})\n\ndescribe('Testing areaSquare calculations', () => {\n  it('with correct args', () => {\n    const areaSquare = area.areaSquare(2.5)\n    expect(areaSquare).toBe(6.25)\n  })\n  it('with incorrect side length, expect throw', () => {\n    expect(() => area.areaSquare(-1)).toThrow()\n    expect(() => area.areaSquare('zero')).toThrow()\n  })\n})\n\ndescribe('Testing areaTriangle calculations', () => {\n  it('with correct args', () => {\n    const areaTriangle = area.areaTriangle(1.66, 3.44)\n    expect(areaTriangle).toBe(2.8552)\n  })\n  it('with incorrect base and height, expect throw', () => {\n    expect(() => area.areaTriangle(-1, 1)).toThrow()\n    expect(() => area.areaTriangle(9, 'zero')).toThrow()\n  })\n})\n\ndescribe('Testing areaTriangleWithAllThreeSides calculations', () => {\n  it('with correct args', () => {\n    const areaTriangle = area.areaTriangleWithAllThreeSides(5, 6, 7)\n    expect(areaTriangle).toBe(14.7)\n  })\n  it('with incorrect sides, expect throw', () => {\n    expect(() => area.areaTriangleWithAllThreeSides(-1, 1, 10)).toThrow()\n    expect(() => area.areaTriangleWithAllThreeSides(9, 'zero', 2)).toThrow()\n    expect(() => area.areaTriangleWithAllThreeSides(1, 10, 12)).toThrow()\n  })\n})\n\ndescribe('Testing areaParallelogram calculations', () => {\n  it('with correct args', () => {\n    const areaParallelogram = area.areaParallelogram(1.66, 3.44)\n    expect(areaParallelogram).toBe(5.7104)\n  })\n  it('with incorrect base and height, expect throw', () => {\n    expect(() => area.areaParallelogram(-1, 1)).toThrow()\n    expect(() => area.areaParallelogram(9, 'zero')).toThrow()\n  })\n})\n\ndescribe('Testing areaTrapezium calculations', () => {\n  it('with correct args', () => {\n    const areaTrapezium = area.areaTrapezium(1.66, 2.41, 4.1)\n    expect(areaTrapezium).toBe(8.3435)\n  })\n  it('with incorrect bases and height, expect throw', () => {\n    expect(() => area.areaTrapezium(-1, 1, 0)).toThrow()\n    expect(() => area.areaTrapezium(9, 'zero', 2)).toThrow()\n    expect(() => area.areaTrapezium(9, 1, 'seven')).toThrow()\n  })\n})\n\ndescribe('Testing areaCircle calculations', () => {\n  it('with correct args', () => {\n    const areaCircle = area.areaCircle(3.456)\n    expect(areaCircle).toBe(37.52298159254666)\n  })\n  it('with incorrect diagonal, expect throw', () => {\n    expect(() => area.areaCircle(-1)).toThrow()\n    expect(() => area.areaCircle('zero')).toThrow()\n  })\n})\n\ndescribe('Testing areaRhombus calculations', () => {\n  it('with correct args', () => {\n    const areaRhombus = area.areaRhombus(2.5, 2.0)\n    expect(areaRhombus).toBe(2.5)\n  })\n  it('with incorrect diagonals, expect throw', () => {\n    expect(() => area.areaRhombus(7, -1)).toThrow()\n    expect(() => area.areaRhombus('zero', 2)).toThrow()\n  })\n})\n"
  },
  {
    "path": "Maths/test/ArithmeticGeometricMean.test.js",
    "content": "import { agm } from '../ArithmeticGeometricMean.js'\n\ndescribe('Tests for AGM', () => {\n  it('should be a function', () => {\n    expect(typeof agm).toEqual('function')\n  })\n\n  it('number of parameters should be 2', () => {\n    expect(agm.length).toEqual(2)\n  })\n\n  const m = 0x100 // scale for rand\n\n  it('should return NaN if any or all params has a negative argument', () => {\n    // I multiplied by minus one, because the sign inversion is more clearly visible\n    expect(agm(-1 * Math.random() * m, Math.random() * m)).toBe(NaN)\n    expect(agm(Math.random() * m, -1 * Math.random() * m)).toBe(NaN)\n    expect(agm(-1 * Math.random() * m, -1 * Math.random() * m)).toBe(NaN)\n  })\n\n  it('should return Infinity if any arg is Infinity and the other is not 0', () => {\n    expect(agm(Math.random() * m + 1, Infinity)).toEqual(Infinity)\n    expect(agm(Infinity, Math.random() * m + 1)).toEqual(Infinity)\n    expect(agm(Infinity, Infinity)).toEqual(Infinity)\n  })\n\n  it('should return NaN if some arg is Infinity and the other is 0', () => {\n    expect(agm(0, Infinity)).toBe(NaN)\n    expect(agm(Infinity, 0)).toBe(NaN)\n  })\n\n  it('should return +0 if any or all args are +0 or -0, and return -0 if all are -0', () => {\n    expect(agm(Math.random() * m, 0)).toBe(0)\n    expect(agm(0, Math.random() * m)).toBe(0)\n    expect(agm(Math.random() * m, -0)).toBe(0)\n    expect(agm(-0, Math.random() * m)).toBe(0)\n    expect(agm(0, -0)).toBe(0)\n    expect(agm(-0, 0)).toBe(0)\n    expect(agm(-0, -0)).toBe(-0)\n  })\n\n  it('should return NaN if any or all args are NaN', () => {\n    expect(agm(Math.random() * m, NaN)).toBe(NaN)\n    expect(agm(NaN, Math.random() * m)).toBe(NaN)\n    expect(agm(NaN, NaN)).toBe(NaN)\n  })\n\n  it('should return an accurate approximation of the AGM between 2 valid input args', () => {\n    // all the constants are provided by WolframAlpha\n    expect(agm(1, 2)).toBeCloseTo(1.4567910310469068)\n    expect(agm(2, 256)).toBeCloseTo(64.45940719438667)\n    expect(agm(55555, 34)).toBeCloseTo(9933.4047239552)\n    // test \"unsafe\" numbers\n    expect(agm(2 ** 48, 3 ** 27)).toBeCloseTo(88506556379265.7)\n  })\n})\n"
  },
  {
    "path": "Maths/test/ArmstrongNumber.test.js",
    "content": "import { armstrongNumber } from '../ArmstrongNumber'\n\ndescribe('ArmstrongNumber', () => {\n  it('should return true for an armstrong number', () => {\n    expect(armstrongNumber(371)).toBeTruthy()\n  })\n\n  it('should return false for a non-armstrong number', () => {\n    expect(armstrongNumber(300)).toBeFalsy()\n  })\n  it('should return false for negative values', () => {\n    expect(armstrongNumber(-2)).toBeFalsy()\n  })\n})\n"
  },
  {
    "path": "Maths/test/AutomorphicNumber.test.js",
    "content": "import { isAutomorphic } from '../AutomorphicNumber'\n\ndescribe('AutomorphicNumber', () => {\n  it('should throw Error when n is String', () => {\n    expect(() => isAutomorphic('qwerty')).toThrow()\n  })\n  it('should throw Error when n is floating point', () => {\n    expect(() => isAutomorphic(13.6)).toThrow()\n  })\n\n  test.each([\n    { n: -3, expected: false },\n    { n: -25, expected: false }\n  ])('should return false when n is negetive', ({ n, expected }) => {\n    expect(isAutomorphic(n)).toBe(false)\n  })\n\n  test.each([\n    { n: 7, expected: false },\n    { n: 83, expected: false },\n    { n: 0, expected: true },\n    { n: 1, expected: true },\n    { n: 376, expected: true },\n    { n: 90625, expected: true }\n  ])('should return $expected when n is $n', ({ n, expected }) => {\n    expect(isAutomorphic(n)).toBe(expected)\n  })\n})\n"
  },
  {
    "path": "Maths/test/AverageMean.test.js",
    "content": "import { mean } from '../AverageMean'\n\ndescribe('Tests for average mean', () => {\n  it('should be a function', () => {\n    expect(typeof mean).toEqual('function')\n  })\n\n  it('should throw error for invalid input', () => {\n    expect(() => mean(123)).toThrow()\n  })\n\n  it('should return the mean of an array of numbers', () => {\n    const meanFunction = mean([1, 2, 4, 5])\n    expect(meanFunction).toBe(3)\n  })\n\n  it('should return the mean of an array of numbers', () => {\n    const meanFunction = mean([10, 40, 100, 20])\n    expect(meanFunction).toBe(42.5)\n  })\n\n  it('should return the number itself for a single-element array', () => {\n    const result = mean([5])\n    expect(result).toBe(5)\n  })\n\n  it('should throw error for empty array', () => {\n    expect(() => mean([])).toThrow()\n  })\n\n  it('should throw error for an array containing null', () => {\n    expect(() => mean([1, 2, null])).toThrow()\n  })\n\n  it('should throw error for an array containing booleans', () => {\n    expect(() => mean([1, 2, true])).toThrow()\n  })\n\n  it('should throw error for an array containing strings', () => {\n    expect(() => mean([1, 2, 'asd'])).toThrow()\n  })\n\n  it('should return the mean of an array with negative numbers', () => {\n    const result = mean([-1, -2, -3, -4])\n    expect(result).toBe(-2.5)\n  })\n\n  it('should return the mean of an array with floating-point numbers', () => {\n    const result = mean([1.5, 2.5, 3.5])\n    expect(result).toBe(2.5)\n  })\n\n  it('should return 0 for an array with zeros', () => {\n    const result = mean([0, 0, 0])\n    expect(result).toBe(0)\n  })\n\n  it('should handle very large numbers correctly', () => {\n    const result = mean([1000000000, 2000000000, 3000000000])\n    expect(result).toBe(2000000000)\n  })\n\n  it('should return correct mean for an array with integers and floating-point numbers', () => {\n    const result = mean([1, 2.5, 3])\n    expect(result).toBeCloseTo(2.1667, 4)\n  })\n})\n"
  },
  {
    "path": "Maths/test/AverageMedian.test.js",
    "content": "import { averageMedian } from '../AverageMedian'\n\ntest('should return the median of an array of numbers:', () => {\n  const medianValue = averageMedian([1, 2, 6, 4, 5])\n  expect(medianValue).toBe(4)\n})\n\ntest('should return the median of an array of numbers:', () => {\n  const medianValue = averageMedian([8, 9, 1, 2, 5, 10, 11])\n  expect(medianValue).toBe(8)\n})\n\ntest('should return the median of an array of numbers:', () => {\n  const medianValue = averageMedian([15, 18, 3, 9, 13, 5])\n  expect(medianValue).toBe(11)\n})\n\ntest('should return the median of an array of numbers:', () => {\n  const medianValue = averageMedian([1, 2, 3, 4, 6, 8])\n  expect(medianValue).toBe(3.5)\n})\n"
  },
  {
    "path": "Maths/test/BInaryConvert.test.js",
    "content": "import { BinaryConvert } from '../BinaryConvert'\n\ndescribe('BinaryConvert', () => {\n  it('should return the correct value', () => {\n    expect(BinaryConvert(4)).toBe(100)\n  })\n  it('should return the correct value', () => {\n    expect(BinaryConvert(12)).toBe(1100)\n  })\n  it('should return the correct value of the sum from two number', () => {\n    expect(BinaryConvert(12 + 2)).toBe(1110)\n  })\n  it('should return the correct value of the subtract from two number', () => {\n    expect(BinaryConvert(245 - 56)).toBe(10111101)\n  })\n  it('should return the correct value', () => {\n    expect(BinaryConvert(254)).toBe(11111110)\n  })\n  it('should return the correct value', () => {\n    expect(BinaryConvert(63483)).toBe(1111011111111011)\n  })\n})\n"
  },
  {
    "path": "Maths/test/BinaryExponentiationIterative.test.js",
    "content": "import { exponent } from '../BinaryExponentiationIterative'\n\ndescribe('exponent', () => {\n  it('should return 1 when power is 0', () => {\n    expect(exponent(5, 0)).toBe(1)\n  })\n\n  it('should return 0 when base is 0', () => {\n    expect(exponent(0, 7)).toBe(0)\n  })\n\n  it('should return the value of a base raised to a power', () => {\n    expect(exponent(3, 5)).toBe(243)\n  })\n})\n"
  },
  {
    "path": "Maths/test/BinaryExponentiationRecursive.test.js",
    "content": "import { binaryExponentiation } from '../BinaryExponentiationRecursive'\n\ndescribe('BinaryExponentiationRecursive', () => {\n  it('should calculate 2 to the power of 10 correctly', () => {\n    expect(binaryExponentiation(2, 10)).toBe(1024)\n  })\n\n  it('should calculate 3 to the power of 9 correctly', () => {\n    expect(binaryExponentiation(3, 9)).toBe(19683)\n  })\n})\n"
  },
  {
    "path": "Maths/test/BinomialCoefficient.test.js",
    "content": "import { findBinomialCoefficient } from '../BinomialCoefficient.js'\n\ndescribe('Testing findBinomialCoefficient function', () => {\n  it('should return 56', () => {\n    const binomialCoefficient = findBinomialCoefficient(8, 3)\n    expect(binomialCoefficient).toBe(56)\n  })\n\n  it('should return 10', () => {\n    const binomialCoefficient = findBinomialCoefficient(5, 2)\n    expect(binomialCoefficient).toBe(10)\n  })\n\n  it('should throw error when supplied arguments other than number', () => {\n    expect(() => {\n      findBinomialCoefficient('eight', 'three')\n    }).toThrow(Error)\n  })\n\n  it('should throw error when n is less than zero', () => {\n    expect(() => {\n      findBinomialCoefficient(-1, 3)\n    }).toThrow(Error)\n  })\n\n  it('should throw error when k is less than zero', () => {\n    expect(() => {\n      findBinomialCoefficient(1, -3)\n    }).toThrow(Error)\n  })\n\n  it('should throw error when n and k are less than zero', () => {\n    expect(() => {\n      findBinomialCoefficient(-1, -3)\n    }).toThrow(Error)\n  })\n})\n"
  },
  {
    "path": "Maths/test/BisectionMethod.test.js",
    "content": "import { findRoot } from '../BisectionMethod'\n\ntest('Equation f(x) = x^2 - 3*x + 2 = 0, has root x = 1 in [a, b] = [0, 1.5]', () => {\n  const root = findRoot(0, 1.5, (x) => x ** 2 - 3 * x + 2, 8)\n  expect(root).toBe(0.9990234375)\n})\n\ntest('Equation f(x) = ln(x) + sqrt(x) + π*x^2 = 0, has root x = 0.36247037 in [a, b] = [0, 10]', () => {\n  const root = findRoot(\n    0,\n    10,\n    (x) => {\n      return Math.log(x) + Math.sqrt(x) + Math.PI * Math.pow(x, 2)\n    },\n    32\n  )\n  expect(Number(Number(root).toPrecision(8))).toBe(0.36247037)\n})\n\ntest('Equation f(x) = sqrt(x) + e^(2*x) - 8*x = 0, has root x = 0.93945851 in [a, b] = [0.5, 100]', () => {\n  const root = findRoot(\n    0.5,\n    100,\n    (x) => {\n      return Math.exp(2 * x) + Math.sqrt(x) - 8 * x\n    },\n    32\n  )\n  expect(Number(Number(root).toPrecision(8))).toBe(0.93945851)\n})\n\ntest('Equation f(x) = x^3 = 0, has root x = 0.0 in [a, b] = [-1.0, 1.0]', () => {\n  const root = findRoot(-1.0, 1.0, (x) => x ** 3, 32)\n  expect(root).toBeCloseTo(0.0, 5)\n})\n\ntest('Throws an error when function does not change sign', () => {\n  expect(() => findRoot(-1.0, 1.0, (x) => x ** 2, 10)).toThrowError()\n})\n"
  },
  {
    "path": "Maths/test/CheckKishnamurthyNumber.test.js",
    "content": "import { CheckKishnamurthyNumber } from '../CheckKishnamurthyNumber'\n\ndescribe('CheckKishnamurthyNumber', () => {\n  it.each([1, 2, 145, 40585])('returns true for %i', (num) => {\n    expect(CheckKishnamurthyNumber(num)).toBe(true)\n  })\n\n  it.each([0, 3, 4, 5, 100, 146, 1019823, -1])(\n    'returns false for %i',\n    (num) => {\n      expect(CheckKishnamurthyNumber(num)).toBe(false)\n    }\n  )\n\n  it('should throw when input is not a number', () => {\n    expect(() => CheckKishnamurthyNumber('2')).toThrowError()\n  })\n})\n"
  },
  {
    "path": "Maths/test/CircularArc.test.js",
    "content": "import { circularArcLength, circularArcArea } from '../CircularArc'\n\ndescribe('circularArcLength', () => {\n  it('with natural number', () => {\n    const arcLengthOfOneThirty = circularArcLength(1, 30)\n    const arcLengthOfThreeSixty = circularArcLength(3, 60)\n    expect(arcLengthOfOneThirty).toBe(0.5235987755982988)\n    expect(arcLengthOfThreeSixty).toBe(3.141592653589793)\n  })\n})\n\ndescribe('circularArcArea', () => {\n  it('with natural number', () => {\n    const arcAreaOfOneThirty = circularArcArea(1, 30)\n    const arcAreaOfThreeSixty = circularArcArea(3, 60)\n    expect(arcAreaOfOneThirty).toBe(0.2617993877991494)\n    expect(arcAreaOfThreeSixty).toBe(4.71238898038469)\n  })\n})\n"
  },
  {
    "path": "Maths/test/CoPrimeCheck.test.js",
    "content": "import { CoPrimeCheck } from '../CoPrimeCheck'\n\ndescribe('CoPrimeCheck', () => {\n  it.each([\n    [1, 1],\n    [1, 2],\n    [1, 3],\n    [1, 7],\n    [20, 21],\n    [5, 7],\n    [-5, -7],\n    [1, 0],\n    [-1, 0]\n  ])('returns true for %j and %i', (inputA, inputB) => {\n    expect(CoPrimeCheck(inputA, inputB)).toBe(true)\n    expect(CoPrimeCheck(inputB, inputA)).toBe(true)\n  })\n\n  it.each([\n    [5, 15],\n    [13 * 17 * 19, 17 * 23 * 29],\n    [2, 0],\n    [0, 0]\n  ])('returns false for %j and %i', (inputA, inputB) => {\n    expect(CoPrimeCheck(inputA, inputB)).toBe(false)\n    expect(CoPrimeCheck(inputB, inputA)).toBe(false)\n  })\n\n  it('should throw when any of the inputs is not a number', () => {\n    expect(() => CoPrimeCheck('1', 2)).toThrowError()\n    expect(() => CoPrimeCheck(1, '2')).toThrowError()\n  })\n})\n"
  },
  {
    "path": "Maths/test/CollatzSequence.test.js",
    "content": "import { collatz } from '../CollatzSequence'\n\ndescribe('The Collatz Sequence', () => {\n  it('Should be 1', () => {\n    expect(collatz(1)).toStrictEqual({ result: 1, steps: [] })\n    expect(collatz(5)).toStrictEqual({ result: 1, steps: [16, 8, 4, 2, 1] })\n  })\n})\n"
  },
  {
    "path": "Maths/test/Coordinate.test.js",
    "content": "import * as coordinate from '../Coordinate'\n\ndescribe('Testing euclideanDistance calculations', () => {\n  it('Should give a numeric output (distance between 2 points) with 4 numeric arguments', () => {\n    const euclideanDistance = coordinate.euclideanDistance(2, 2, -10, -7)\n    expect(euclideanDistance).toBe(15)\n  })\n  it('Should not give any output given non-numeric argument', () => {\n    const euclideanDistance = coordinate.euclideanDistance(\n      'ABC',\n      '123',\n      '',\n      '###'\n    )\n    expect(euclideanDistance).toBeNaN()\n  })\n  it('Should not give any output given any number of numeric arguments less than 4', () => {\n    const euclideanDistance3arg = coordinate.euclideanDistance(2, 2, -10)\n    const euclideanDistance2arg = coordinate.euclideanDistance(2, 2)\n    const euclideanDistance1arg = coordinate.euclideanDistance(2)\n    const euclideanDistance0arg = coordinate.euclideanDistance()\n    expect(euclideanDistance3arg).toBeNaN()\n    expect(euclideanDistance2arg).toBeNaN()\n    expect(euclideanDistance1arg).toBeNaN()\n    expect(euclideanDistance0arg).toBeNaN()\n  })\n})\n\ndescribe('Testing manhattanDistance calculations', () => {\n  it('Should give a numeric output (distance between 2 points) with 4 numeric arguments', () => {\n    const manhattanDistance = coordinate.manhattanDistance(2, 2, -10, -7)\n    expect(manhattanDistance).toBe(21)\n  })\n  it('Should not give any output given non-numeric argument', () => {\n    const manhattanDistance = coordinate.manhattanDistance(\n      'ABC',\n      '123',\n      '',\n      '###'\n    )\n    expect(manhattanDistance).toBeNaN()\n  })\n  it('Should not give any output given any number of numeric arguments less than 4', () => {\n    const manhattanDistance3arg = coordinate.manhattanDistance(2, 2, -10)\n    const manhattanDistance2arg = coordinate.manhattanDistance(2, 2)\n    const manhattanDistance1arg = coordinate.manhattanDistance(2)\n    const manhattanDistance0arg = coordinate.manhattanDistance()\n    expect(manhattanDistance3arg).toBeNaN()\n    expect(manhattanDistance2arg).toBeNaN()\n    expect(manhattanDistance1arg).toBeNaN()\n    expect(manhattanDistance0arg).toBeNaN()\n  })\n})\n"
  },
  {
    "path": "Maths/test/CountNumbersDivisible.test.js",
    "content": "import { countNumbersDivisible } from '../CountNumbersDivisible'\n\ndescribe('Count the numbers divisible', () => {\n  test.each([\n    [1, 20, 6, 3],\n    [6, 15, 3, 4],\n    [25, 100, 30, 3],\n    [25, 70, 10, 5],\n    [1, 23, 30, 0]\n  ])(\n    'Total number(s) divisible between %i to %i by %i is/are %i',\n    (n1, n2, m, expected) => {\n      expect(countNumbersDivisible(n1, n2, m)).toBe(expected)\n    }\n  )\n\n  test.each([\n    ['test', 23, 10, 'Invalid input, please pass only numbers'],\n    [\n      44,\n      30,\n      10,\n      'Invalid number range, please provide numbers such that num1 < num2'\n    ]\n  ])(\n    'Should throw an error for input %i, %i, %i, %i',\n    (n1, n2, m, expected) => {\n      expect(() => countNumbersDivisible(n1, n2, m)).toThrowError(expected)\n    }\n  )\n})\n"
  },
  {
    "path": "Maths/test/DecimalExpansion.test.js",
    "content": "import { decExp } from '../DecimalExpansion'\n\n/**\n * Decimal\n */\n\ndescribe('Finite Decimal Expansion', () => {\n  it('1/2 = 0.5', () => {\n    const [integer, decimals, cycleIndex] = decExp(1, 2)\n    expect(integer).toBe(0)\n    expect(decimals).toEqual([5])\n    expect(cycleIndex).toBeUndefined()\n  })\n\n  it('1/5 = 0.2', () => {\n    const [integer, decimals, cycleIndex] = decExp(1, 5)\n    expect(integer).toBe(0)\n    expect(decimals).toEqual([2])\n    expect(cycleIndex).toBeUndefined()\n  })\n\n  it('1/8 = 0.125', () => {\n    const [integer, decimals, cycleIndex] = decExp(1, 8)\n    expect(integer).toBe(0)\n    expect(decimals).toEqual([1, 2, 5])\n    expect(cycleIndex).toBeUndefined()\n  })\n\n  it('255/40 = 6.375', () => {\n    const [integer, decimals, cycleIndex] = decExp(255, 40)\n    expect(integer).toBe(6)\n    expect(decimals).toEqual([3, 7, 5])\n    expect(cycleIndex).toBeUndefined()\n  })\n})\n\ndescribe('Repeating Decimal Expansion', () => {\n  it('1/3 = 0.(3)', () => {\n    expect(decExp(1, 3)).toStrictEqual([0, [3], 0])\n  })\n\n  it('1/6 = 0.1(6)', () => {\n    expect(decExp(1, 6)).toStrictEqual([0, [1, 6], 1])\n  })\n\n  it('1/7 = 0.(142857)', () => {\n    expect(decExp(1, 7)).toStrictEqual([0, [1, 4, 2, 8, 5, 7], 0])\n  })\n})\n\n/**\n * Binary\n */\n\ndescribe('Finite Binary Expansion', () => {\n  it('1/2 = 0.1₂', () => {\n    const [integer, decimals, cycleIndex] = decExp(1, 2, 2)\n    expect(integer).toBe(0)\n    expect(decimals).toEqual([1])\n    expect(cycleIndex).toBeUndefined()\n  })\n\n  it('1/8 = 0.001₂', () => {\n    const [integer, decimals, cycleIndex] = decExp(1, 8, 2)\n    expect(integer).toBe(0)\n    expect(decimals).toEqual([0, 0, 1])\n    expect(cycleIndex).toBeUndefined()\n  })\n\n  it('255/40 = 110.011₂', () => {\n    const [integer, decimals, cycleIndex] = decExp(255, 40, 2)\n    expect(integer).toBe(110)\n    expect(decimals).toEqual([0, 1, 1])\n    expect(cycleIndex).toBeUndefined()\n  })\n})\n\ndescribe('Repeating Binary Expansion', () => {\n  it('1/3 = 0.(01)₂', () => {\n    expect(decExp(1, 3, 2)).toStrictEqual([0, [0, 1], 0])\n  })\n\n  it('1/5 = 0.(0011)₂', () => {\n    expect(decExp(1, 5, 2)).toStrictEqual([0, [0, 0, 1, 1], 0])\n  })\n\n  it('1/6 = 0.0(01)₂', () => {\n    expect(decExp(1, 6, 2)).toStrictEqual([0, [0, 0, 1], 1])\n  })\n\n  it('1/7 = 0.(001)₂', () => {\n    expect(decExp(1, 7, 2)).toStrictEqual([0, [0, 0, 1], 0])\n  })\n})\n\n/**\n * Octal\n */\n\ndescribe('Finite Octal Expansion', () => {\n  it('1/2 = 0.4₈', () => {\n    const [integer, decimals, cycleIndex] = decExp(1, 2, 8)\n    expect(integer).toBe(0)\n    expect(decimals).toEqual([4])\n    expect(cycleIndex).toBeUndefined()\n  })\n\n  it('1/8 = 0.1₈', () => {\n    const [integer, decimals, cycleIndex] = decExp(1, 8, 8)\n    expect(integer).toBe(0)\n    expect(decimals).toEqual([1])\n    expect(cycleIndex).toBeUndefined()\n  })\n\n  it('255/40 = 6.3₈', () => {\n    const [integer, decimals, cycleIndex] = decExp(255, 40, 8)\n    expect(integer).toBe(6)\n    expect(decimals).toEqual([3])\n    expect(cycleIndex).toBeUndefined()\n  })\n})\n\ndescribe('Repeating Octal Expansion', () => {\n  it('1/3 = 0.(25)₈', () => {\n    expect(decExp(1, 3, 8)).toStrictEqual([0, [2, 5], 0])\n  })\n\n  it('1/5 = 0.(1463)₈', () => {\n    expect(decExp(1, 5, 8)).toStrictEqual([0, [1, 4, 6, 3], 0])\n  })\n\n  it('1/6 = 0.1(25)₈', () => {\n    expect(decExp(1, 6, 8)).toStrictEqual([0, [1, 2, 5], 1])\n  })\n\n  it('1/7 = 0.(1)₈', () => {\n    expect(decExp(1, 7, 8)).toStrictEqual([0, [1], 0])\n  })\n})\n\n/**\n * Integers\n */\n\ndescribe('Integers', () => {\n  it('1/1 = 1', () => {\n    const [integer, decimals, cycleIndex] = decExp(1, 1)\n    expect(integer).toBe(1)\n    expect(decimals).toStrictEqual([])\n    expect(cycleIndex).toBeUndefined()\n  })\n\n  it('5/5 = 1', () => {\n    const [integer, decimals, cycleIndex] = decExp(5, 5)\n    expect(integer).toBe(1)\n    expect(decimals).toStrictEqual([])\n    expect(cycleIndex).toBeUndefined()\n  })\n\n  it('2/1 = 2', () => {\n    const [integer, decimals, cycleIndex] = decExp(2, 1)\n    expect(integer).toBe(2)\n    expect(decimals).toStrictEqual([])\n    expect(cycleIndex).toBeUndefined()\n  })\n\n  it('9/3 = 3', () => {\n    const [integer, decimals, cycleIndex] = decExp(9, 3)\n    expect(integer).toBe(3)\n    expect(decimals).toStrictEqual([])\n    expect(cycleIndex).toBeUndefined()\n  })\n})\n\n/**\n * Unsupported base\n */\n\ndescribe('Throws on unsupported base', () => {\n  it('negative base', () => {\n    expect(() => decExp(1, 1, -2)).toThrow(RangeError)\n  })\n  it('base 0', () => {\n    expect(() => decExp(1, 1, 0)).toThrow(RangeError)\n  })\n  it('base 1', () => {\n    expect(() => decExp(1, 1, 1)).toThrow(RangeError)\n  })\n  it('base 11', () => {\n    expect(() => decExp(1, 1, 11)).toThrow(RangeError)\n  })\n})\n"
  },
  {
    "path": "Maths/test/DegreeToRadian.test.js",
    "content": "import { degreeToRadian } from '../DegreeToRadian'\n\ntest('should convert degree to radian:', () => {\n  const radianEqual = degreeToRadian(0)\n  expect(radianEqual).toBe(0)\n})\n\ntest('should convert degree to radian:', () => {\n  const radianEqual = degreeToRadian(45)\n  expect(radianEqual).toBe(Math.PI / 4)\n})\n\ntest('should convert degree to radian:', () => {\n  const radianEqual = degreeToRadian(90)\n  expect(radianEqual).toBe(Math.PI / 2)\n})\n\ntest('should convert degree to radian:', () => {\n  const radianEqual = degreeToRadian(180)\n  expect(radianEqual).toBe(Math.PI)\n})\n"
  },
  {
    "path": "Maths/test/Determinant.test.js",
    "content": "import { expect } from 'vitest'\nimport { determinant } from '../Determinant'\ndescribe('Determinant', () => {\n  test.each([\n    [\n      [\n        [8, 1, 6],\n        [1, 2, 3],\n        [4, 7, 5]\n      ],\n      -87\n    ],\n    [\n      [\n        [2, 1, 0, 2],\n        [1, 2, 4, 3],\n        [0, 4, 7, 5],\n        [4, 7, 9, 8]\n      ],\n      25\n    ],\n    [\n      [\n        [5, 9],\n        [3, 7]\n      ],\n      8\n    ],\n    [\n      [\n        [7, 5, 1, 4, 3],\n        [6, 8, 7, 9, 6],\n        [9, 8, 0, 4, 7],\n        [0, 3, 4, 7, 9],\n        [3, 6, 2, 8, 8]\n      ],\n      2476\n    ],\n    [[[23]], 23]\n  ])(\n    'Should return the determinant of the square matrix.',\n    (matrix, expected) => {\n      expect(determinant(matrix)).toEqual(expected)\n    }\n  )\n\n  test.each([\n    [\n      [\n        [1, 6],\n        [1, 2, 3],\n        [4, 7, 5]\n      ],\n      'Square matrix is required.'\n    ],\n    [[1, 3, 2, [5, 8, 6], 3], 'Input is not a valid 2D matrix.']\n  ])('Should return the error message.', (matrix, expected) => {\n    expect(() => determinant(matrix)).toThrowError(expected)\n  })\n})\n"
  },
  {
    "path": "Maths/test/EuclideanDistance.test.js",
    "content": "import { EuclideanDistance } from '../EuclideanDistance.js'\n\ndescribe('EuclideanDistance', () => {\n  it('should calculate the distance correctly for 2D vectors', () => {\n    expect(EuclideanDistance([0, 0], [2, 2])).toBeCloseTo(\n      2.8284271247461903,\n      10\n    )\n  })\n\n  it('should calculate the distance correctly for 3D vectors', () => {\n    expect(EuclideanDistance([0, 0, 0], [2, 2, 2])).toBeCloseTo(\n      3.4641016151377544,\n      10\n    )\n  })\n\n  it('should calculate the distance correctly for 4D vectors', () => {\n    expect(EuclideanDistance([1, 2, 3, 4], [5, 6, 7, 8])).toBeCloseTo(8.0, 10)\n  })\n\n  it('should calculate the distance correctly for different 2D vectors', () => {\n    expect(EuclideanDistance([1, 2], [4, 6])).toBeCloseTo(5.0, 10)\n  })\n})\n"
  },
  {
    "path": "Maths/test/EulerMethod.manual-test.js",
    "content": "import { eulerFull } from '../EulerMethod'\n\nfunction plotLine(label, points, width, height) {\n  // utility function to plot the results\n\n  // container needed to control the size of the canvas\n  const container = document.createElement('div')\n  container.style.width = width + 'px'\n  container.style.height = height + 'px'\n  document.body.append(container)\n\n  // the canvas for plotting\n  const canvas = document.createElement('canvas')\n  container.append(canvas)\n\n  // Chart-class from chartjs\n  const chart = new Chart(canvas, {\n    type: 'scatter',\n    data: {\n      datasets: [\n        {\n          label,\n          data: points,\n          showLine: true,\n          fill: false,\n          tension: 0,\n          borderColor: 'black'\n        }\n      ]\n    },\n    options: {\n      maintainAspectRatio: false,\n      responsive: true\n    }\n  })\n}\n\nfunction exampleEquation1(x, y) {\n  return x\n}\n\n// example from https://en.wikipedia.org/wiki/Euler_method\nfunction exampleEquation2(x, y) {\n  return y\n}\n\n// example from https://www.geeksforgeeks.org/euler-method-solving-differential-equation/\nfunction exampleEquation3(x, y) {\n  return x + y + x * y\n}\n\n// plot the results if the script is executed in a browser with a window-object\nif (typeof window !== 'undefined') {\n  const points1 = eulerFull(0, 4, 0.1, 0, exampleEquation1)\n  const points2 = eulerFull(0, 4, 0.1, 1, exampleEquation2)\n  const points3 = eulerFull(0, 0.1, 0.025, 1, exampleEquation3)\n\n  const script = document.createElement('script')\n\n  // using chartjs\n  script.src = 'https://www.chartjs.org/dist/2.9.4/Chart.min.js'\n  script.onload = function () {\n    plotLine('example 1: dy/dx = x', points1, 600, 400)\n    plotLine('example 2: dy/dx = y', points2, 600, 400)\n    plotLine('example 3: dy/dx = x + y + x * y', points3, 600, 400)\n  }\n  document.body.append(script)\n}\n"
  },
  {
    "path": "Maths/test/EulerMethod.test.js",
    "content": "import { eulerFull, eulerStep } from '../EulerMethod'\n\ndescribe('eulerStep', () => {\n  it('should calculate the next y value correctly', () => {\n    expect(\n      eulerStep(0, 0.1, 0, function (x, y) {\n        return x\n      })\n    ).toBe(0)\n    expect(\n      eulerStep(2, 1, 1, function (x, y) {\n        return x * x\n      })\n    ).toBe(5)\n  })\n})\n\ndescribe('eulerFull', () => {\n  it('should return all the points found', () => {\n    expect(\n      eulerFull(0, 3, 1, 0, function (x, y) {\n        return x\n      })\n    ).toEqual([\n      { x: 0, y: 0 },\n      { x: 1, y: 0 },\n      { x: 2, y: 1 },\n      { x: 3, y: 3 }\n    ])\n\n    expect(\n      eulerFull(3, 4, 0.5, 1, function (x, y) {\n        return x * x\n      })\n    ).toEqual([\n      { x: 3, y: 1 },\n      { x: 3.5, y: 5.5 },\n      { x: 4, y: 11.625 }\n    ])\n  })\n})\n"
  },
  {
    "path": "Maths/test/EulersTotient.test.js",
    "content": "import { EulersTotient } from '../EulersTotient'\n\ndescribe('EulersTotient', () => {\n  it('should return 6 as 1, 2, 4, 5, 7, and 8 are coprime to 9', () => {\n    expect(EulersTotient(9)).toBe(6)\n  })\n\n  it('should return 4 as 1, 3, 7, and 9 are coprime to 10', () => {\n    expect(EulersTotient(10)).toBe(4)\n  })\n})\n"
  },
  {
    "path": "Maths/test/EulersTotientFunction.test.js",
    "content": "import { eulersTotientFunction } from '../EulersTotientFunction'\n\ndescribe('eulersTotientFunction', () => {\n  it('is a function', () => {\n    expect(typeof eulersTotientFunction).toEqual('function')\n  })\n  it('should return the phi of a given number', () => {\n    const phiOfNumber = eulersTotientFunction(10)\n    expect(phiOfNumber).toBe(4)\n  })\n})\n"
  },
  {
    "path": "Maths/test/ExponentialFunction.test.js",
    "content": "import { exponentialFunction } from '../ExponentialFunction'\n\ndescribe('Tests for exponential function', () => {\n  it('should be a function', () => {\n    expect(typeof exponentialFunction).toEqual('function')\n  })\n\n  it('should throw error for invalid input', () => {\n    expect(() => exponentialFunction(2, -34)).toThrow()\n  })\n\n  it('should return the exponential function of power of 5 and order of 21', () => {\n    const ex = exponentialFunction(5, 20)\n    expect(ex).toBe(148.4131078683383)\n  })\n})\n"
  },
  {
    "path": "Maths/test/ExtendedEuclideanGCD.test.js",
    "content": "import { extendedEuclideanGCD } from '../ExtendedEuclideanGCD'\n\ndescribe('extendedEuclideanGCD', () => {\n  it('should return valid values in order for positive arguments', () => {\n    expect(extendedEuclideanGCD(240, 46)).toMatchObject([2, -9, 47])\n    expect(extendedEuclideanGCD(46, 240)).toMatchObject([2, 47, -9])\n  })\n  it('should give error on non-positive arguments', () => {\n    expect(() => extendedEuclideanGCD(0, 240)).toThrowError(\n      new TypeError('Must be positive numbers')\n    )\n    expect(() => extendedEuclideanGCD(46, -240)).toThrowError(\n      new TypeError('Must be positive numbers')\n    )\n  })\n  it('should give error on non-numeric arguments', () => {\n    expect(() => extendedEuclideanGCD('240', 46)).toThrowError(\n      new TypeError('Not a Number')\n    )\n    expect(() => extendedEuclideanGCD([240, 46])).toThrowError(\n      new TypeError('Not a Number')\n    )\n  })\n})\n"
  },
  {
    "path": "Maths/test/Factorial.test.js",
    "content": "import { calcFactorial } from '../Factorial'\n\ndescribe('calcFactorial', () => {\n  it('should return a statement for value \"0\"', () => {\n    expect(calcFactorial(0)).toBe(1)\n  })\n\n  it('should throw error for \"null\" and \"undefined\"', () => {\n    expect(() => {\n      calcFactorial(null)\n    }).toThrow(Error)\n    expect(() => {\n      calcFactorial(undefined)\n    }).toThrow(Error)\n  })\n\n  it('should throw error for negative numbers', () => {\n    expect(() => {\n      calcFactorial(-1)\n    }).toThrow(Error)\n  })\n\n  it('should return the factorial of a positive number', () => {\n    const positiveFactorial = calcFactorial(3)\n    expect(positiveFactorial).toBe(6)\n  })\n})\n"
  },
  {
    "path": "Maths/test/Factors.test.js",
    "content": "import { factorsOfANumber } from '../Factors'\n\ndescribe('Factors', () => {\n  factorsOfANumber(50).forEach((num) => {\n    it(`${num} is a factor of 50`, () => {\n      const isFactor = 50 % num === 0\n      expect(isFactor).toBeTruthy()\n    })\n  })\n})\n"
  },
  {
    "path": "Maths/test/FareyApproximation.test.js",
    "content": "import { fareyApproximation } from '../FareyApproximation'\n\ndescribe('fareyApproximation', () => {\n  it('Return Farey Approximation of 0.7538385', () => {\n    const approx = fareyApproximation(0.7538385)\n    expect(approx).toStrictEqual({ numerator: 52, denominator: 69 })\n  })\n\n  it('Return Farey Approximation of 0.23584936', () => {\n    const approx = fareyApproximation(0.23584936)\n    expect(approx).toStrictEqual({ numerator: 196, denominator: 831 })\n  })\n})\n"
  },
  {
    "path": "Maths/test/FermatPrimalityTest.test.js",
    "content": "import { fermatPrimeCheck, modularExponentiation } from '../FermatPrimalityTest'\n\ndescribe('modularExponentiation', () => {\n  it('should give the correct output for all exponentiations', () => {\n    expect(modularExponentiation(38, 220, 221)).toBe(1)\n    expect(modularExponentiation(24, 220, 221)).toBe(81)\n  })\n})\n\ndescribe('fermatPrimeCheck', () => {\n  it('should give the correct output for prime and composite numbers', () => {\n    expect(fermatPrimeCheck(2, 35)).toBe(true)\n    expect(fermatPrimeCheck(10, 30)).toBe(false)\n    expect(fermatPrimeCheck(94286167)).toBe(true)\n    expect(fermatPrimeCheck(83165867)).toBe(true)\n    expect(fermatPrimeCheck(13268774)).toBe(false)\n    expect(fermatPrimeCheck(13233852)).toBe(false)\n  })\n})\n"
  },
  {
    "path": "Maths/test/Fibonacci.test.js",
    "content": "import {\n  FibonacciDpWithoutRecursion,\n  FibonacciRecursiveDP,\n  FibonacciIterative,\n  FibonacciGenerator,\n  FibonacciRecursive,\n  FibonacciMatrixExpo,\n  FibonacciUsingFormula\n} from '../Fibonacci'\n\ndescribe('Fibonacci', () => {\n  it('should return an array of numbers for FibonacciIterative', () => {\n    expect(FibonacciIterative(6)).toEqual(\n      expect.arrayContaining([0, 1, 1, 2, 3, 5, 8])\n    )\n    expect(FibonacciIterative(-6)).toEqual(\n      expect.arrayContaining([0, 1, -1, 2, -3, 5, -8])\n    )\n  })\n\n  it('should return number for FibonacciGenerator', () => {\n    const positive = FibonacciGenerator()\n    expect(positive.next().value).toBe(0)\n    expect(positive.next().value).toBe(1)\n    expect(positive.next().value).toBe(1)\n    expect(positive.next().value).toBe(2)\n    expect(positive.next().value).toBe(3)\n    expect(positive.next().value).toBe(5)\n    expect(positive.next().value).toBe(8)\n\n    const negative = FibonacciGenerator(true)\n    expect(negative.next().value).toBe(0)\n    expect(negative.next().value).toBe(1)\n    expect(negative.next().value).toBe(-1)\n    expect(negative.next().value).toBe(2)\n    expect(negative.next().value).toBe(-3)\n    expect(negative.next().value).toBe(5)\n    expect(negative.next().value).toBe(-8)\n  })\n\n  it('should return an array of numbers for FibonacciRecursive', () => {\n    expect(FibonacciRecursive(6)).toEqual(\n      expect.arrayContaining([0, 1, 1, 2, 3, 5, 8])\n    )\n    expect(FibonacciRecursive(-6)).toEqual(\n      expect.arrayContaining([-0, 1, -1, 2, -3, 5, -8])\n    )\n  })\n\n  it('should return number for FibonacciRecursiveDP', () => {\n    expect(FibonacciRecursiveDP(6)).toBe(8)\n    expect(FibonacciRecursiveDP(-6)).toBe(-8)\n  })\n\n  it('should return an array of numbers for FibonacciDpWithoutRecursion', () => {\n    expect(FibonacciDpWithoutRecursion(6)).toEqual(\n      expect.arrayContaining([0, 1, 1, 2, 3, 5, 8])\n    )\n    expect(FibonacciDpWithoutRecursion(-6)).toEqual(\n      expect.arrayContaining([0, 1, -1, 2, -3, 5, -8])\n    )\n  })\n\n  it('should return number for FibonacciMatrixExpo', () => {\n    expect(FibonacciMatrixExpo(0)).toBe(0)\n    expect(FibonacciMatrixExpo(1)).toBe(1)\n    expect(FibonacciMatrixExpo(2)).toBe(1)\n    expect(FibonacciMatrixExpo(3)).toBe(2)\n    expect(FibonacciMatrixExpo(4)).toBe(3)\n    expect(FibonacciMatrixExpo(5)).toBe(5)\n    expect(FibonacciMatrixExpo(6)).toBe(8)\n\n    expect(FibonacciMatrixExpo(-0)).toBe(-0)\n    expect(FibonacciMatrixExpo(-1)).toBe(1)\n    expect(FibonacciMatrixExpo(-2)).toBe(-1)\n    expect(FibonacciMatrixExpo(-3)).toBe(2)\n    expect(FibonacciMatrixExpo(-4)).toBe(-3)\n    expect(FibonacciMatrixExpo(-5)).toBe(5)\n    expect(FibonacciMatrixExpo(-6)).toBe(-8)\n  })\n\n  it('should return bigint for FibonacciMatrixExpo', () => {\n    expect(FibonacciMatrixExpo(0n)).toBe(0n)\n    expect(FibonacciMatrixExpo(1n)).toBe(1n)\n    expect(FibonacciMatrixExpo(2n)).toBe(1n)\n    expect(FibonacciMatrixExpo(3n)).toBe(2n)\n    expect(FibonacciMatrixExpo(4n)).toBe(3n)\n    expect(FibonacciMatrixExpo(5n)).toBe(5n)\n    expect(FibonacciMatrixExpo(6n)).toBe(8n)\n\n    expect(FibonacciMatrixExpo(-0n)).toBe(0n)\n    expect(FibonacciMatrixExpo(-1n)).toBe(1n)\n    expect(FibonacciMatrixExpo(-2n)).toBe(-1n)\n    expect(FibonacciMatrixExpo(-3n)).toBe(2n)\n    expect(FibonacciMatrixExpo(-4n)).toBe(-3n)\n    expect(FibonacciMatrixExpo(-5n)).toBe(5n)\n    expect(FibonacciMatrixExpo(-6n)).toBe(-8n)\n  })\n  it.each([\n    [0, 0],\n    [1, 1],\n    [15, 610]\n  ])(\n    'should calculate the correct Fibonacci number for n = %i',\n    (n, expected) => {\n      expect(FibonacciUsingFormula(n)).toBe(expected)\n    }\n  )\n})\n"
  },
  {
    "path": "Maths/test/FigurateNumber.test.js",
    "content": "import {\n  isTriangular,\n  isTetrahedral,\n  isPentatope,\n  checkAll\n} from '../FigurateNumber'\n\ndescribe('FigurateNumber', () => {\n  it('Triangular : should return true', () => {\n    expect(isTriangular(1)).toEqual(true)\n  })\n  it('Triangular : should return true', () => {\n    expect(isTriangular(3)).toEqual(true)\n  })\n\n  it('Triangular : should return false', () => {\n    expect(isTriangular(5)).toEqual(false)\n  })\n\n  it('Triangular : should return true', () => {\n    expect(isTriangular(171)).toEqual(true)\n  })\n  /** End */\n\n  it('Tetrahedral : should return true', () => {\n    expect(isTetrahedral(1)).toEqual(true)\n  })\n  it('Tetrahedral : should return true', () => {\n    expect(isTetrahedral(4)).toEqual(true)\n  })\n\n  it('Tetrahedral : should return false', () => {\n    expect(isTetrahedral(3)).toEqual(false)\n  })\n\n  it('Tetrahedral : should return true', () => {\n    expect(isTetrahedral(165)).toEqual(true)\n  })\n\n  /** End */\n  it('Pentatope : should return true', () => {\n    expect(isPentatope(1)).toEqual(true)\n  })\n  it('Pentatope : should return true', () => {\n    expect(isPentatope(5)).toEqual(true)\n  })\n\n  it('Pentatope : should return false', () => {\n    expect(isPentatope(3)).toEqual(false)\n  })\n\n  it('Pentatope : should return true', () => {\n    expect(isPentatope(1001)).toEqual(true)\n  })\n  /** End */\n\n  it('Check All : should return all true', () => {\n    expect(checkAll(1)).toEqual({\n      isTriangular: true,\n      isTetrahedral: true,\n      isPentatope: true\n    })\n  })\n\n  it('Check All : should return all true,true,false', () => {\n    expect(checkAll(15)).toEqual({\n      isTriangular: true,\n      isTetrahedral: false,\n      isPentatope: true\n    })\n  })\n})\n"
  },
  {
    "path": "Maths/test/FindHcf.test.js",
    "content": "import { findHCF } from '../FindHcf'\n\ndescribe('findHCF', () => {\n  it('should throw a statement for values less than 1', () => {\n    expect(findHCF(0, 0)).toBe('Please enter values greater than zero.')\n  })\n\n  it('should throw a statement for one value less than 1', () => {\n    expect(findHCF(0, 1)).toBe('Please enter values greater than zero.')\n    expect(findHCF(1, 0)).toBe('Please enter values greater than zero.')\n  })\n\n  it('should return an error for values non-integer values', () => {\n    expect(findHCF(2.24, 4.35)).toBe('Please enter whole numbers.')\n  })\n\n  it('should return the HCF of two given integers', () => {\n    expect(findHCF(27, 36)).toBe(9)\n  })\n})\n"
  },
  {
    "path": "Maths/test/FindLcm.test.js",
    "content": "import { findLcm, findLcmWithHcf } from '../FindLcm'\n\ndescribe('findLcm', () => {\n  it('should throw a statement for values less than 1', () => {\n    expect(() => {\n      findLcm(0, 0)\n    }).toThrow(Error)\n  })\n\n  it('should throw a statement for one value less than 1', () => {\n    expect(() => {\n      findLcm(1, 0)\n    }).toThrow(Error)\n    expect(() => {\n      findLcm(0, 1)\n    }).toThrow(Error)\n  })\n\n  it('should return an error for values non-integer values', () => {\n    expect(() => {\n      findLcm(4.564, 7.39)\n    }).toThrow(Error)\n  })\n\n  it('should return the LCM of two given integers', () => {\n    expect(findLcm(27, 36)).toBe(108)\n  })\n})\n\ndescribe('findLcmWithHcf', () => {\n  it('should throw a statement for values less than 1', () => {\n    expect(() => {\n      findLcmWithHcf(0, 0)\n    }).toThrow(Error)\n  })\n\n  it('should throw a statement for one value less than 1', () => {\n    expect(() => {\n      findLcmWithHcf(1, 0)\n    }).toThrow(Error)\n    expect(() => {\n      findLcmWithHcf(0, 1)\n    }).toThrow(Error)\n  })\n\n  it('should return an error for values non-integer values', () => {\n    expect(() => {\n      findLcmWithHcf(4.564, 7.39)\n    }).toThrow(Error)\n  })\n\n  it('should return the LCM of two given integers', () => {\n    expect(findLcmWithHcf(27, 36)).toBe(108)\n  })\n})\n"
  },
  {
    "path": "Maths/test/FindMaxRecursion.test.js",
    "content": "import { findMaxRecursion } from '../FindMaxRecursion'\n\ndescribe('Test findMaxRecursion function', () => {\n  const positiveAndNegativeArray = [1, 2, 4, 5, -1, -2, -4, -5]\n  const positiveAndNegativeArray1 = [10, 40, 100, 20, -10, -40, -100, -20]\n\n  const positiveArray = [1, 2, 4, 5]\n  const positiveArray1 = [10, 40, 100, 20]\n\n  const negativeArray = [-1, -2, -4, -5]\n  const negativeArray1 = [-10, -40, -100, -20]\n\n  const zeroArray = [0, 0, 0, 0]\n  const emptyArray = []\n\n  it('Testing with positive arrays', () => {\n    expect(findMaxRecursion(positiveArray, 0, positiveArray.length - 1)).toBe(5)\n    expect(findMaxRecursion(positiveArray1, 0, positiveArray1.length - 1)).toBe(\n      100\n    )\n  })\n\n  it('Testing with negative arrays', () => {\n    expect(findMaxRecursion(negativeArray, 0, negativeArray.length - 1)).toBe(\n      -1\n    )\n    expect(findMaxRecursion(negativeArray1, 0, negativeArray1.length - 1)).toBe(\n      -10\n    )\n  })\n\n  it('Testing with positive and negative arrays', () => {\n    expect(\n      findMaxRecursion(\n        positiveAndNegativeArray,\n        0,\n        positiveAndNegativeArray.length - 1\n      )\n    ).toBe(5)\n    expect(\n      findMaxRecursion(\n        positiveAndNegativeArray1,\n        0,\n        positiveAndNegativeArray1.length - 1\n      )\n    ).toBe(100)\n  })\n\n  it('Testing with zero arrays', () => {\n    expect(findMaxRecursion(zeroArray, 0, zeroArray.length - 1)).toBe(0)\n  })\n\n  it('Testing with empty arrays', () => {\n    expect(findMaxRecursion(emptyArray, 0, emptyArray.length - 1)).toBe(\n      undefined\n    )\n  })\n})\n"
  },
  {
    "path": "Maths/test/FindMin.test.js",
    "content": "import { findMin } from '../FindMin'\n\ndescribe('FindMin', () => {\n  test('Should return the minimum number in the array', () => {\n    const min = findMin(2, 5, 1, 12, 43, 1, 9)\n    expect(min).toBe(1)\n  })\n\n  test('Should return the minimum number in the array', () => {\n    const min = findMin(21, 513, 6)\n    expect(min).toBe(6)\n  })\n\n  test('Should throw error', () => {\n    const min = () => findMin()\n    expect(min).toThrow('Array is empty')\n  })\n})\n"
  },
  {
    "path": "Maths/test/FindMinIterator.test.js",
    "content": "import { FindMinIterator } from '../FindMinIterator'\n\ndescribe('FindMinIterator', () => {\n  test('given empty array then min is undefined', () => {\n    expect(FindMinIterator([])).toBeUndefined()\n  })\n\n  test('given single value array then min is found', () => {\n    expect(FindMinIterator([1])).toBe(1)\n    expect(FindMinIterator([-1])).toBe(-1)\n    expect(FindMinIterator([0])).toBe(0)\n  })\n\n  test('given array then min is found', () => {\n    expect(FindMinIterator([1, 2])).toBe(1)\n    expect(FindMinIterator([-1, 10])).toBe(-1)\n    expect(FindMinIterator([0, 100])).toBe(0)\n    expect(FindMinIterator([100, 0])).toBe(0)\n    expect(\n      FindMinIterator([100, 50, 20, 0, -100, 0, 2, 30, 45, 99, 104, 23])\n    ).toBe(-100)\n  })\n\n  test('given empty generator then min is undefined', () => {\n    const src = function* () {}\n    expect(FindMinIterator(src())).toBeUndefined()\n  })\n\n  test('given generator then min is found', () => {\n    const src = function* () {\n      yield 1\n      yield -1\n      yield 0\n    }\n    expect(FindMinIterator(src())).toBe(-1)\n  })\n\n  test('given string generator then min string length is found', () => {\n    const src = function* () {\n      yield 'abc'\n      yield 'de'\n      yield 'qwerty'\n    }\n    expect(FindMinIterator(src(), (_x) => _x.length)).toBe(2)\n  })\n\n  test('given array of objects then min accessor is found', () => {\n    const array = [\n      { name: 'Item #1', price: 1.0 },\n      { name: 'Item #2', price: 0.0 },\n      { name: 'Item #3', price: -1.0 }\n    ]\n    expect(FindMinIterator(array, (_x) => _x.price)).toBe(-1)\n    expect(FindMinIterator(array, (_x) => _x.name)).toBe('Item #1')\n  })\n})\n"
  },
  {
    "path": "Maths/test/GetEuclidGCD.test.js",
    "content": "import { GetEuclidGCD, GetEuclidGCDRecursive } from '../GetEuclidGCD'\n\ndescribe.each([GetEuclidGCD, GetEuclidGCDRecursive])('%o', (gcdFunction) => {\n  it.each([\n    [5, 20, 5],\n    [109, 902, 1],\n    [290, 780, 10],\n    [104, 156, 52],\n    [0, 100, 100],\n    [-5, 50, 5],\n    [0, 0, 0],\n    [1, 1234567, 1]\n  ])('returns correct result for %i and %j', (inputA, inputB, expected) => {\n    expect(gcdFunction(inputA, inputB)).toBe(expected)\n    expect(gcdFunction(inputB, inputA)).toBe(expected)\n  })\n\n  it('should throw when any of the inputs is not a number', () => {\n    expect(() => gcdFunction('1', 2)).toThrowError()\n    expect(() => gcdFunction(1, '2')).toThrowError()\n  })\n})\n"
  },
  {
    "path": "Maths/test/GridGet.test.js",
    "content": "import { gridGetX, gridGetY } from '../GridGet'\n\ndescribe('GridGet', () => {\n  it('should have a value of x for the 27th element if the square array has 400 elements', () => {\n    expect(gridGetX(Math.sqrt(400), 27)).toEqual(8)\n  })\n  it('should have a value of x for the 11th element if the square array has 7 columns and 3 rows', () => {\n    expect(gridGetX(7, 11)).toEqual(5)\n  })\n  it('should have a value of y for the 27th element if the square array has 400 elements', () => {\n    expect(gridGetY(Math.sqrt(400), 27)).toEqual(2)\n  })\n  it('should have a value of y for the 11th element if the square array has 7 columns and 3 rows ', () => {\n    expect(gridGetX(7, 11)).toEqual(5)\n  })\n})\n"
  },
  {
    "path": "Maths/test/HexagonalNumber.test.js",
    "content": "import { hexagonalNumber } from '../HexagonalNumber'\n\nconst expectedValuesArray = [\n  1, 6, 15, 28, 45, 66, 91, 120, 153, 190, 231, 276, 325, 378, 435, 496, 561,\n  630, 703, 780, 861, 946\n]\n\ndescribe('Testing hexagonalNumber', () => {\n  for (let i = 1; i <= 22; i++) {\n    it(\n      'Testing for number = ' + i + ', should return ' + expectedValuesArray[i],\n      () => {\n        expect(hexagonalNumber(i)).toBe(expectedValuesArray[i - 1])\n      }\n    )\n  }\n\n  it('should throw error when supplied negative numbers', () => {\n    expect(() => {\n      hexagonalNumber(-1)\n    }).toThrow(Error)\n  })\n\n  it('should throw error when supplied zero', () => {\n    expect(() => {\n      hexagonalNumber(0)\n    }).toThrow(Error)\n  })\n})\n"
  },
  {
    "path": "Maths/test/IntToBase.test.js",
    "content": "import { intToBase } from '../IntToBase'\n\ndescribe('Int to Base', () => {\n  test('Conversion to the binary system', () => {\n    expect(intToBase(210, 2)).toEqual('11010010')\n    expect(intToBase(-210, 2)).toEqual('-11010010')\n  })\n  test('Conversion to the system with base 5', () => {\n    expect(intToBase(210, 5)).toEqual('1320')\n    expect(intToBase(-210, 5)).toEqual('-1320')\n  })\n  test('Conversion to the octal system', () => {\n    expect(intToBase(210, 8)).toEqual('322')\n    expect(intToBase(-210, 8)).toEqual('-322')\n  })\n  test('Output is 0', () => {\n    expect(intToBase(0, 8)).toEqual('0')\n    expect(intToBase(0, 8)).toEqual('0')\n  })\n  test('Throwing an exception', () => {\n    expect(() => intToBase('string', 2)).toThrow()\n    expect(() => intToBase(10, 'base')).toThrow()\n    expect(() => intToBase(true, false)).toThrow()\n  })\n})\n"
  },
  {
    "path": "Maths/test/IsDivisible.test.js",
    "content": "import { isDivisible } from '../IsDivisible'\n\ndescribe('isDivisible', () => {\n  const testCases = [\n    [0, 1, true],\n    [0, 2, true],\n    [1, 1, true],\n    [1, 2, false],\n    [2, 1, true],\n    [4, 4, true],\n    [16, 4, true],\n    [36978235, 5, true],\n    [36978235, 4, false],\n    [4.5, 1.5, true],\n    [4.5, 1.2, false],\n    [5, 0, false],\n    [5, -0, false]\n  ]\n\n  test.each(testCases)(\n    'if parameters are (%i, %i) it returns %p',\n    (dividend, divisor, expected) => {\n      expect(isDivisible(dividend, divisor)).toBe(expected)\n    }\n  )\n\n  const errorCases = [\n    [NaN, NaN],\n    [NaN, 1],\n    [1, NaN],\n    ['1', 1],\n    [1, '1'],\n    [1, true],\n    [false, 2]\n  ]\n\n  test.each(errorCases)(\n    'throws an error if parameters are (%p, %p)',\n    (dividend, divisor) => {\n      expect(() => {\n        isDivisible(dividend, divisor)\n      }).toThrow()\n    }\n  )\n})\n"
  },
  {
    "path": "Maths/test/IsEven.test.js",
    "content": "import { isEven, isEvenBitwise } from '../IsEven'\n\ndescribe('Testing isEven function', () => {\n  it('should return if the number is even or not', () => {\n    const isEvenNumber = isEven(4)\n    expect(isEvenNumber).toBe(true)\n  })\n\n  it('should return if the number is even or not', () => {\n    const isEvenNumber = isEven(7)\n    expect(isEvenNumber).toBe(false)\n  })\n})\n\ndescribe('Testing isEvenBitwise function', () => {\n  it('should return if the number is even or not', () => {\n    const isEvenNumber = isEvenBitwise(6)\n    expect(isEvenNumber).toBe(true)\n  })\n\n  it('should return if the number is even or not', () => {\n    const isEvenNumber = isEvenBitwise(3)\n    expect(isEvenNumber).toBe(false)\n  })\n})\n"
  },
  {
    "path": "Maths/test/IsOdd.test.js",
    "content": "import { isOdd, isOddBitwise } from '../IsOdd'\n\ndescribe('Testing the isOdd function', () => {\n  it('should return true, if the number is odd', () => {\n    const isOddNumber = isOdd(4)\n    expect(isOddNumber).toBe(false)\n  })\n\n  it('should return true, if the number is odd', () => {\n    const isOddNumber = isOdd(7)\n    expect(isOddNumber).toBe(true)\n  })\n})\n\ndescribe('Testing the isOddBitwise function', () => {\n  it('should return true, if the number is odd', () => {\n    const isOddNumber = isOddBitwise(6)\n    expect(isOddNumber).toBe(false)\n  })\n\n  it('should return true, if the number is odd', () => {\n    const isOddNumber = isOddBitwise(3)\n    expect(isOddNumber).toBe(true)\n  })\n})\n"
  },
  {
    "path": "Maths/test/IsPronic.test.js",
    "content": "import { isPronic } from '../IsPronic'\n\nconst pronicNumbers = [\n  0, 2, 6, 12, 20, 30, 42, 56, 72, 90, 110, 132, 156, 182, 210, 240, 272, 306,\n  342, 380, 420, 462, 506, 552, 600, 650, 702, 756, 812, 870, 930, 992, 1056,\n  1122, 1190, 1260, 1332, 1406, 1482, 1560, 1640, 1722, 1806, 1892, 1980, 2070,\n  2162, 2256, 2352, 2450, 2550\n]\n\ndescribe('Testing isPronic function', () => {\n  for (let i = 0; i <= 2500; i++) {\n    it('should return true', () => {\n      const isPronicNumber = isPronic(i)\n      expect(isPronicNumber).toBe(pronicNumbers.includes(i))\n    })\n  }\n})\n"
  },
  {
    "path": "Maths/test/IsSquareFree.test.js",
    "content": "import { isSquareFree } from '../IsSquareFree'\n\nconst squareFreeNumbers = [\n  1, 2, 3, 5, 6, 7, 10, 11, 13, 14, 15, 17, 19, 21, 22, 23, 26, 29, 30, 31, 33,\n  34, 35, 37, 38, 39, 41, 42, 43, 46, 47, 51, 53, 55, 57, 58, 59, 61, 62, 65,\n  66, 67, 69, 70, 71, 73, 74, 77, 78, 79, 82, 83, 85, 86, 87, 89, 91, 93, 94,\n  95, 97, 101, 102, 103, 105, 106, 107, 109, 110, 111, 113, 114, 115, 118, 119,\n  122, 123, 127, 129, 130, 131, 133, 134, 137, 138, 139, 141, 142, 143, 145,\n  146, 149, 151, 154, 155, 157, 158, 159, 161, 163, 165, 166, 167, 170, 173,\n  174, 177, 178, 179, 181, 182, 183, 185, 186, 187, 190, 191, 193, 194, 195,\n  197, 199, 201, 202, 203, 205, 206, 209, 210, 211, 213, 214, 215, 217, 218,\n  219, 221, 222, 223, 226, 227, 229, 230, 231, 233, 235, 237, 238, 239, 241,\n  246, 247, 249, 251, 253, 254, 255, 257, 258, 259, 262, 263, 265, 266, 267,\n  269, 271, 273, 274, 277, 278, 281, 282, 283, 285, 286, 287, 290, 291, 293,\n  295, 298, 299, 301, 302, 303, 305, 307, 309, 310, 311, 313, 314, 317, 318,\n  319, 321, 322, 323, 326, 327, 329, 330, 331, 334, 335, 337, 339, 341, 345,\n  346, 347, 349, 353, 354, 355, 357, 358, 359, 362, 365, 366, 367, 370, 371,\n  373, 374, 377, 379, 381, 382, 383, 385, 386, 389, 390, 391, 393, 394, 395,\n  397, 398, 399, 401, 402, 403, 406, 407, 409, 410, 411, 413, 415, 417, 418,\n  419, 421, 422, 426, 427, 429, 430, 431, 433, 434, 435, 437, 438, 439, 442,\n  443, 445, 446, 447, 449, 451, 453, 454, 455, 457, 458, 461, 462, 463, 465,\n  466, 467, 469, 470, 471, 473, 474, 478, 479, 481, 482, 483, 485, 487, 489,\n  491, 493, 494, 497, 498, 499, 501, 502, 503, 505, 506, 509, 510, 511, 514,\n  515, 517, 518, 519, 521, 523, 526, 527, 530, 533, 534, 535, 537, 538, 541,\n  542, 543, 545, 546, 547, 551, 553, 554, 555, 557, 559, 561, 562, 563, 565,\n  566, 569, 570, 571, 573, 574, 577, 579, 581, 582, 583, 586, 587, 589, 590,\n  591, 593, 595, 597, 598, 599, 601, 602, 606, 607, 609, 610, 611, 613, 614,\n  615, 617, 618, 619, 622, 623, 626, 627, 629, 631, 633, 634, 635, 638, 641,\n  642, 643, 645, 646, 647, 649, 651, 653, 654, 655, 658, 659, 661, 662, 663,\n  665, 667, 669, 670, 671, 673, 674, 677, 678, 679, 681, 682, 683, 685, 687,\n  689, 690, 691, 694, 695, 697, 698, 699, 701, 703, 705, 706, 707, 709, 710,\n  713, 714, 715, 717, 718, 719, 721, 723, 727, 730, 731, 733, 734, 737, 739,\n  741, 742, 743, 745, 746, 749, 751, 753, 754, 755, 757, 758, 759, 761, 762,\n  763, 766, 767, 769, 770, 771, 773, 777, 778, 779, 781, 782, 785, 786, 787,\n  789, 790, 791, 793, 794, 795, 797, 798, 799, 802, 803, 805, 806, 807, 809,\n  811, 813, 814, 815, 817, 818, 821, 822, 823, 826, 827, 829, 830, 831, 834,\n  835, 838, 839, 842, 843, 849, 851, 853, 854, 857, 858, 859, 861, 862, 863,\n  865, 866, 869, 870, 871, 874, 877, 878, 879, 881, 883, 885, 886, 887, 889,\n  890, 893, 894, 895, 897, 898, 899, 901, 902, 903, 905, 906, 907, 910, 911,\n  913, 914, 915, 917, 919, 921, 922, 923, 926, 929, 930, 933, 934, 935, 937,\n  938, 939, 941, 942, 943, 946, 947, 949, 951, 953, 955, 957, 958, 959, 962,\n  965, 966, 967, 969, 970, 971, 973, 974, 977, 978, 979, 982, 983, 985, 986,\n  987, 989, 991, 993, 994, 995, 997, 998, 1001, 1002, 1003, 1005, 1006, 1007,\n  1009, 1010, 1011, 1013, 1015, 1018, 1019, 1021, 1022, 1023, 1027, 1030, 1031,\n  1033, 1034, 1037, 1038, 1039, 1041, 1042, 1043, 1045, 1046, 1047, 1049, 1051,\n  1054, 1055, 1057, 1059, 1061, 1063, 1065, 1066, 1067, 1069, 1070, 1073, 1074,\n  1077, 1079, 1081, 1082, 1085, 1086, 1087, 1090, 1091, 1093, 1094, 1095, 1097,\n  1099, 1101, 1102, 1103, 1105, 1106, 1109, 1110, 1111, 1113, 1114, 1115, 1117,\n  1118, 1119, 1121, 1122, 1123, 1126, 1129, 1130, 1131, 1133, 1135, 1137, 1138,\n  1139, 1141, 1142, 1145, 1146, 1147, 1149, 1151, 1153, 1154, 1155, 1157, 1158,\n  1159, 1162, 1163, 1165, 1166, 1167, 1169, 1171, 1173, 1174, 1177, 1178, 1181,\n  1182, 1185, 1186, 1187, 1189, 1190, 1191, 1193, 1194, 1195, 1198, 1199, 1201,\n  1202, 1203, 1205, 1207, 1209, 1211, 1213, 1214, 1217, 1218, 1219, 1221, 1222,\n  1223, 1226, 1227, 1229, 1230, 1231, 1234, 1235, 1237, 1238, 1239, 1241, 1243,\n  1245, 1246, 1247, 1249, 1253, 1254, 1255, 1257, 1258, 1259, 1261, 1262, 1263,\n  1265, 1266, 1267, 1270, 1271, 1273, 1277, 1279, 1281, 1282, 1283, 1285, 1286,\n  1289, 1290, 1291, 1293, 1294, 1295, 1297, 1298, 1299, 1301, 1302, 1303, 1306,\n  1307, 1309, 1310, 1311, 1313, 1315, 1317, 1318, 1319, 1321, 1322, 1326, 1327,\n  1329, 1330, 1333, 1334, 1335, 1337, 1338, 1339, 1342, 1343, 1345, 1346, 1347,\n  1349, 1351, 1353, 1354, 1355, 1357, 1358, 1361, 1362, 1363, 1365, 1366, 1367,\n  1370, 1371, 1373, 1374, 1378, 1379, 1381, 1382, 1383, 1385, 1387, 1389, 1390,\n  1391, 1393, 1394, 1397, 1398, 1399, 1401, 1402, 1403, 1405, 1406, 1407, 1409,\n  1410, 1411, 1414, 1415, 1417, 1418, 1419, 1423, 1426, 1427, 1429, 1430, 1433,\n  1434, 1435, 1437, 1438, 1439, 1441, 1442, 1443, 1446, 1447, 1451, 1453, 1454,\n  1455, 1457, 1459, 1461, 1462, 1463, 1465, 1466, 1469, 1471, 1473, 1474, 1477,\n  1478, 1479, 1481, 1482, 1483, 1486, 1487, 1489, 1490, 1491, 1493, 1495, 1497,\n  1498, 1499, 1501, 1502, 1505, 1506, 1507, 1509, 1510, 1511, 1513, 1514, 1515,\n  1517, 1518, 1522, 1523, 1526, 1527, 1529, 1531, 1533, 1534, 1535, 1537, 1538,\n  1541, 1542, 1543, 1545, 1546, 1547, 1549, 1551, 1553, 1554, 1555, 1558, 1559,\n  1561, 1562, 1563, 1565, 1567, 1569, 1570, 1571, 1574, 1577, 1578, 1579, 1581,\n  1582, 1583, 1585, 1586, 1589, 1590, 1591, 1594, 1595, 1597, 1598, 1599, 1601,\n  1603, 1605, 1606, 1607, 1609, 1610, 1613, 1614, 1615, 1618, 1619, 1621, 1622,\n  1623, 1626, 1627, 1630, 1631, 1633, 1634, 1635, 1637, 1639, 1641, 1642, 1643,\n  1645, 1646, 1649, 1651, 1653, 1654, 1655, 1657, 1658, 1659, 1661, 1662, 1663,\n  1667, 1669, 1670, 1671, 1673, 1677, 1678, 1679, 1685, 1686, 1687, 1689, 1691,\n  1693, 1695, 1697, 1698, 1699, 1702, 1703, 1705, 1706, 1707, 1709, 1711, 1713,\n  1714, 1717, 1718, 1721, 1722, 1723, 1726, 1727, 1729, 1730, 1731, 1733, 1735,\n  1738, 1739, 1741, 1742, 1743, 1745, 1747, 1749, 1751, 1753, 1754, 1757, 1758,\n  1759, 1761, 1762, 1763, 1765, 1766, 1767, 1769, 1770, 1771, 1774, 1777, 1778,\n  1779, 1781, 1783, 1785, 1786, 1787, 1789, 1790, 1793, 1794, 1795, 1797, 1798,\n  1799, 1801, 1802, 1803, 1806, 1807, 1810, 1811, 1814, 1817, 1819, 1821, 1822,\n  1823, 1826, 1829, 1830, 1831, 1833, 1834, 1835, 1837, 1838, 1839, 1841, 1842,\n  1843, 1846, 1847, 1851, 1853, 1855, 1857, 1858, 1861, 1865, 1866, 1867, 1869,\n  1870, 1871, 1873, 1874, 1877, 1878, 1879, 1882, 1883, 1885, 1886, 1887, 1889,\n  1891, 1893, 1894, 1895, 1897, 1898, 1901, 1902, 1903, 1905, 1906, 1907, 1909,\n  1910, 1913, 1914, 1915, 1918, 1919, 1921, 1923, 1927, 1929, 1930, 1931, 1933,\n  1934, 1937, 1938, 1939, 1941, 1942, 1943, 1945, 1946, 1947, 1949, 1951, 1954,\n  1955, 1957, 1958, 1959, 1961, 1963, 1965, 1966, 1967, 1969, 1970, 1973, 1974,\n  1977, 1978, 1979, 1981, 1982, 1983, 1985, 1986, 1987, 1990, 1991, 1993, 1994,\n  1995, 1997, 1999, 2001, 2002, 2003, 2005, 2006, 2010, 2011, 2013, 2014, 2015,\n  2017, 2018, 2019, 2021, 2022, 2026, 2027, 2029, 2030, 2031, 2033, 2035, 2037,\n  2038, 2039, 2041, 2042, 2045, 2046, 2047, 2049, 2051, 2053, 2054, 2055, 2059,\n  2062, 2063, 2065, 2066, 2067, 2069, 2071, 2073, 2074, 2077, 2078, 2081, 2082,\n  2083, 2085, 2086, 2087, 2089, 2090, 2091, 2093, 2094, 2095, 2098, 2099, 2101,\n  2102, 2103, 2105, 2109, 2110, 2111, 2113, 2114, 2117, 2118, 2119, 2121, 2122,\n  2123, 2126, 2127, 2129, 2130, 2131, 2134, 2135, 2137, 2138, 2139, 2141, 2143,\n  2145, 2146, 2147, 2149, 2153, 2154, 2155, 2157, 2158, 2159, 2161, 2162, 2163,\n  2165, 2167, 2170, 2171, 2173, 2174, 2177, 2179, 2181, 2182, 2183, 2185, 2186,\n  2189, 2190, 2191, 2193, 2194, 2195, 2198, 2199, 2201, 2202, 2203, 2206, 2207,\n  2210, 2211, 2213, 2215, 2217, 2218, 2219, 2221, 2222, 2226, 2227, 2229, 2230,\n  2231, 2233, 2234, 2235, 2237, 2238, 2239, 2242, 2243, 2245, 2246, 2247, 2249,\n  2251, 2253, 2255, 2257, 2258, 2261, 2262, 2263, 2265, 2266, 2267, 2269, 2270,\n  2271, 2273, 2274, 2278, 2279, 2281, 2282, 2283, 2285, 2287, 2289, 2290, 2291,\n  2293, 2294, 2297, 2298, 2301, 2302, 2305, 2306, 2307, 2309, 2310, 2311, 2314,\n  2315, 2317, 2318, 2319, 2321, 2323, 2326, 2327, 2329, 2330, 2333, 2334, 2335,\n  2337, 2338, 2339, 2341, 2342, 2343, 2345, 2346, 2347, 2351, 2353, 2354, 2355,\n  2357, 2359, 2361, 2362, 2363, 2365, 2369, 2370, 2371, 2373, 2374, 2377, 2378,\n  2379, 2381, 2382, 2383, 2386, 2387, 2389, 2390, 2391, 2393, 2395, 2397, 2398,\n  2399, 2402, 2405, 2406, 2407, 2409, 2410, 2411, 2413, 2414, 2415, 2417, 2418,\n  2419, 2422, 2423, 2426, 2427, 2429, 2431, 2433, 2434, 2435, 2437, 2438, 2441,\n  2442, 2443, 2445, 2446, 2447, 2449, 2451, 2453, 2454, 2455, 2458, 2459, 2461,\n  2462, 2463, 2465, 2467, 2469, 2470, 2471, 2473, 2474, 2477, 2478, 2479, 2481,\n  2482, 2483, 2485, 2486, 2487, 2489, 2490, 2491, 2494, 2495, 2497, 2498\n]\n\ndescribe('Testing isSquareFree function', () => {\n  for (let i = 1; i <= 2500; i++) {\n    it('should return true or false', () => {\n      const isSquareFreeNumber = isSquareFree(i)\n      expect(isSquareFreeNumber).toBe(squareFreeNumbers.includes(i))\n    })\n  }\n\n  it('should throw error when supplied negative numbers', () => {\n    expect(() => {\n      isSquareFree(-1)\n    }).toThrow(Error)\n  })\n\n  it('should throw error when supplied zero', () => {\n    expect(() => {\n      isSquareFree(0)\n    }).toThrow(Error)\n  })\n})\n"
  },
  {
    "path": "Maths/test/JugglerSequence.test.js",
    "content": "import { jugglerSequence } from '../JugglerSequence'\n\ndescribe('Testing jugglerSequence function', () => {\n  it('should return [3, 5, 11, 36, 6, 2, 1 ] if the number is 3', () => {\n    expect(jugglerSequence(3)).toEqual(\n      expect.arrayContaining([3, 5, 11, 36, 6, 2, 1])\n    )\n  })\n\n  it('should return [9, 27, 140, 11, 36, 6, 2, 1] if the number is 9', () => {\n    expect(jugglerSequence(9)).toEqual(\n      expect.arrayContaining([9, 27, 140, 11, 36, 6, 2, 1])\n    )\n  })\n\n  it('should return [15, 58, 7, 18, 4, 2, 1] if the number is 15', () => {\n    expect(jugglerSequence(15)).toEqual(\n      expect.arrayContaining([15, 58, 7, 18, 4, 2, 1])\n    )\n  })\n})\n"
  },
  {
    "path": "Maths/test/LeapYear.test.js",
    "content": "import { isLeapYear } from '../LeapYear'\n\ndescribe('Leap Year', () => {\n  it('Should return true on the year 2000', () => {\n    expect(isLeapYear(2000)).toBe(true)\n  })\n  it('Should return false on the year 2001', () => {\n    expect(isLeapYear(2001)).toBe(false)\n  })\n  it('Should return false on the year 2002', () => {\n    expect(isLeapYear(2002)).toBe(false)\n  })\n  it('Should return false on the year 2003', () => {\n    expect(isLeapYear(2003)).toBe(false)\n  })\n  it('Should return false on the year 2004', () => {\n    expect(isLeapYear(2004)).toBe(true)\n  })\n  it('Should return false on the year 1900', () => {\n    expect(isLeapYear(1900)).toBe(false)\n  })\n})\n"
  },
  {
    "path": "Maths/test/LinearSieve.test.js",
    "content": "import { LinearSieve } from '../LinearSieve'\nimport { PrimeCheck } from '../PrimeCheck'\n\ndescribe('LinearSieve', () => {\n  it('should return primes below 100', () => {\n    expect(LinearSieve(100)).toEqual([\n      2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,\n      71, 73, 79, 83, 89, 97\n    ])\n  })\n\n  it('should return primes only', () => {\n    const n = 100000\n    const primes = LinearSieve(n)\n    for (const p of primes) {\n      expect(PrimeCheck(p)).toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "Maths/test/LiouvilleFunction.test.js",
    "content": "import { liouvilleFunction } from '../LiouvilleFunction'\n\nconst expectedValuesArray = [\n  1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1,\n  -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1,\n  -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1,\n  -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1,\n  -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1\n]\n\ndescribe('Testing liouville function', () => {\n  for (let i = 1; i <= 100; i++) {\n    it(\n      'Testing for number = ' + i + ', should return ' + expectedValuesArray[i],\n      () => {\n        expect(liouvilleFunction(i)).toBe(expectedValuesArray[i - 1])\n      }\n    )\n  }\n\n  it('should throw error when supplied negative numbers', () => {\n    expect(() => {\n      liouvilleFunction(-1)\n    }).toThrow(Error)\n  })\n\n  it('should throw error when supplied zero', () => {\n    expect(() => {\n      liouvilleFunction(0)\n    }).toThrow(Error)\n  })\n})\n"
  },
  {
    "path": "Maths/test/LucasSeries.test.js",
    "content": "import { lucas } from '../LucasSeries'\n\ndescribe('Nth Lucas Number', () => {\n  it('should return the 20th Lucas Number', () => {\n    expect(lucas(20)).toBe(15127)\n  })\n\n  it('should return the 20th Lucas Number', () => {\n    expect(lucas(0)).toBe(2)\n  })\n\n  it('should return the 20th Lucas Number', () => {\n    expect(lucas(100)).toBe(792070839848372100000)\n  })\n})\n"
  },
  {
    "path": "Maths/test/Mandelbrot.manual-test.js",
    "content": "import { getRGBData } from '../Mandelbrot'\n\n// plot the results if the script is executed in a browser with a window-object\nif (typeof window !== 'undefined') {\n  const rgbData = getRGBData()\n  const width = rgbData.length\n  const height = rgbData[0].length\n  const canvas = document.createElement('canvas')\n  canvas.width = width\n  canvas.height = height\n  const ctx = canvas.getContext('2d')\n  for (let x = 0; x < width; x++) {\n    for (let y = 0; y < height; y++) {\n      const rgb = rgbData[x][y]\n      ctx.fillStyle = 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')'\n      ctx.fillRect(x, y, 1, 1)\n    }\n  }\n  document.body.append(canvas)\n}\n"
  },
  {
    "path": "Maths/test/Mandelbrot.test.js",
    "content": "import { getRGBData } from '../Mandelbrot'\n\ndescribe('Mandelbrot', () => {\n  it('should produce black pixels inside the set', () => {\n    const blackAndWhite = getRGBData(800, 600, -0.6, 0, 3.2, 50, false)\n    expect(blackAndWhite[400][300]).toEqual([0, 0, 0]) // black\n\n    const colorCoded = getRGBData(800, 600, -0.6, 0, 3.2, 50, true)\n    expect(colorCoded[400][300]).toEqual([0, 0, 0]) // black\n  })\n\n  it('should produce white pixels outside of the set', () => {\n    const blackAndWhite = getRGBData(800, 600, -0.6, 0, 3.2, 50, false)\n    expect(blackAndWhite[0][0]).toEqual([255, 255, 255]) // black\n  })\n\n  it('should produce colored pixels distant to the set', () => {\n    const colorCoded = getRGBData(800, 600, -0.6, 0, 3.2, 50, true)\n    expect(colorCoded[0][0]).toEqual([255, 0, 0]) // red\n  })\n})\n"
  },
  {
    "path": "Maths/test/MeanAbsoluteDeviation.test.js",
    "content": "import { meanAbsoluteDeviation } from '../MeanAbsoluteDeviation.js'\n\ndescribe('tests for mean absolute deviation', () => {\n  it('should be a function', () => {\n    expect(typeof meanAbsoluteDeviation).toEqual('function')\n  })\n\n  it('should throw an invalid input error', () => {\n    expect(() => meanAbsoluteDeviation('fgh')).toThrow()\n  })\n\n  it('should return the mean absolute deviation of an array of numbers', () => {\n    const meanAbDev = meanAbsoluteDeviation([2, 34, 5, 0, -2])\n    expect(meanAbDev).toBe(10.479999999999999)\n  })\n})\n"
  },
  {
    "path": "Maths/test/MeanSquareError.test.js",
    "content": "import { meanSquaredError } from '../MeanSquareError'\n\ndescribe('meanSquareError', () => {\n  it('should throw an error on non-array arguments', () => {\n    expect(() => meanSquaredError(1, 4)).toThrow('Argument must be an Array')\n  })\n\n  it('should throw an error on non equal length ', () => {\n    const firstArr = [1, 2, 3, 4, 5]\n    const secondArr = [1, 2, 3]\n    expect(() => meanSquaredError(firstArr, secondArr)).toThrow(\n      'The two lists must be of equal length'\n    )\n  })\n\n  it('should return the mean square error of two equal length arrays', () => {\n    const firstArr = [1, 2, 3, 4, 5]\n    const secondArr = [1, 3, 5, 6, 7]\n    expect(meanSquaredError(firstArr, secondArr)).toBe(2.6)\n  })\n})\n"
  },
  {
    "path": "Maths/test/MidpointIntegration.test.js",
    "content": "import { integralEvaluation } from '../MidpointIntegration'\n\ntest('Should return the integral of f(x) = sqrt(x) in [1, 3] to be equal 2.797434', () => {\n  const result = integralEvaluation(10000, 1, 3, (x) => {\n    return Math.sqrt(x)\n  })\n  expect(Number(result.toPrecision(6))).toBe(2.79743)\n})\n\ntest('Should return the integral of f(x) = sqrt(x) + x^2 in [1, 3] to be equal 11.46410161', () => {\n  const result = integralEvaluation(10000, 1, 3, (x) => {\n    return Math.sqrt(x) + Math.pow(x, 2)\n  })\n  expect(Number(result.toPrecision(10))).toBe(11.46410161)\n})\n\ntest('Should return the integral of f(x) = log(x) + Pi*x^3 in [5, 12] to be equal 15809.9141543', () => {\n  const result = integralEvaluation(20000, 5, 12, (x) => {\n    return Math.log(x) + Math.PI * Math.pow(x, 3)\n  })\n  expect(Number(result.toPrecision(10))).toBe(15809.91415)\n})\n"
  },
  {
    "path": "Maths/test/MobiusFunction.test.js",
    "content": "import { mobiusFunction } from '../MobiusFunction'\n\nconst expectedValuesArray = [\n  1, -1, -1, 0, -1, 1, -1, 0, 0, 1, -1, 0, -1, 1, 1, 0, -1, 0, -1, 0, 1, 1, -1,\n  0, 0, 1, 0, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 0, -1, -1, -1, 0, 0, 1,\n  -1, 0, 0, 0, 1, 0, -1, 0, 1, 0, 1, 1, -1, 0, -1, 1, 0, 0, 1, -1, -1, 0, 1, -1,\n  -1, 0, -1, 1, 0, 0, 1, -1, -1, 0, 0, 1, -1, 0, 1, 1, 1, 0, -1, 0, 1, 0, 1, 1,\n  1, 0, -1, 0, 0, 0\n]\n\ndescribe('Testing mobius function', () => {\n  for (let i = 1; i <= 100; i++) {\n    it(\n      'Testing for number = ' + i + ', should return ' + expectedValuesArray[i],\n      () => {\n        expect(mobiusFunction(i)).toBe(expectedValuesArray[i - 1])\n      }\n    )\n  }\n\n  it('should throw error when supplied negative numbers', () => {\n    expect(() => {\n      mobiusFunction(-1)\n    }).toThrow(Error)\n  })\n\n  it('should throw error when supplied zero', () => {\n    expect(() => {\n      mobiusFunction(0)\n    }).toThrow(Error)\n  })\n})\n"
  },
  {
    "path": "Maths/test/ModularArithmetic.test.js",
    "content": "import { ModRing } from '../ModularArithmetic'\n\ndescribe('Modular Arithmetic', () => {\n  const MOD = 10000007\n  let ring\n  beforeEach(() => {\n    ring = new ModRing(MOD)\n  })\n\n  describe('add', () => {\n    it('Should return 9999993 for 10000000 and 10000000', () => {\n      expect(ring.add(10000000, 10000000)).toBe(9999993)\n    })\n    it('Should return 9999986 for 10000000 and 20000000', () => {\n      expect(ring.add(10000000, 20000000)).toBe(9999986)\n    })\n  })\n\n  describe('subtract', () => {\n    it('Should return 1000000 for 10000000 and 9000000', () => {\n      expect(ring.subtract(10000000, 9000000)).toBe(1000000)\n    })\n    it('Should return 7 for 10000000 and 20000000', () => {\n      expect(ring.subtract(10000000, 20000000)).toBe(7)\n    })\n  })\n\n  describe('multiply', () => {\n    it('Should return 1000000 for 100000 and 10000', () => {\n      expect(ring.multiply(100000, 10000)).toBe(9999307)\n    })\n    it('Should return 7 for 100000 and 10000100', () => {\n      expect(ring.multiply(10000000, 20000000)).toBe(98)\n    })\n  })\n\n  describe('divide', () => {\n    it('Should return 4 for 3 and 11', () => {\n      expect(ring.divide(3, 11)).toBe(4)\n    })\n    it('Should return 2 for 18 and 7', () => {\n      expect(ring.divide(18, 7)).toBe(2)\n    })\n  })\n})\n"
  },
  {
    "path": "Maths/test/ModularBinaryExponentiationRecursive.test.js",
    "content": "import { modularBinaryExponentiation } from '../ModularBinaryExponentiationRecursive'\n\ndescribe('modularBinaryExponentiation', () => {\n  it('should return the binary exponentiation', () => {\n    expect(modularBinaryExponentiation(2, 10, 17)).toBe(4)\n  })\n})\n"
  },
  {
    "path": "Maths/test/NumberOfDigits.test.js",
    "content": "import { numberOfDigit, numberOfDigitsUsingLog } from '../NumberOfDigits'\n\ndescribe('NumberOfDigits', () => {\n  it('should return the correct number of digits for an integer', () => {\n    expect(numberOfDigit(1234000)).toBe(7)\n  })\n\n  it('should return the correct number of digits for a negative number', () => {\n    expect(numberOfDigit(-2346243)).toBe(7)\n  })\n\n  it.each([\n    [0, 1],\n    [123423232, 9],\n    [-123423232, 9],\n    [9999, 4]\n  ])(\n    'should return the correct number of digits in an integer',\n    (value, expected) => {\n      expect(numberOfDigitsUsingLog(value)).toBe(expected)\n    }\n  )\n})\n"
  },
  {
    "path": "Maths/test/Palindrome.test.js",
    "content": "import {\n  PalindromeRecursive,\n  PalindromeIterative,\n  checkPalindrome\n} from '../Palindrome'\n\ndescribe('Palindrome', () => {\n  it('should return true for a palindrome for PalindromeRecursive', () => {\n    expect(PalindromeRecursive('mom')).toBeTruthy()\n  })\n  it('should return true  for a palindrome for PalindromeIterative', () => {\n    expect(PalindromeIterative('mom')).toBeTruthy()\n  })\n  it('should return false for a non-palindrome for PalindromeRecursive', () => {\n    expect(PalindromeRecursive('Algorithms')).toBeFalsy()\n  })\n  it('should return true  for a non-palindrome for PalindromeIterative', () => {\n    expect(PalindromeIterative('JavaScript')).toBeFalsy()\n  })\n\n  it.each([\n    ['radar', true],\n    ['hello', false],\n    ['r', true],\n    ['   racecar   ', true]\n  ])('should return value is palindrome or not', (value, expected) => {\n    expect(checkPalindrome(value)).toBe(expected)\n  })\n})\n"
  },
  {
    "path": "Maths/test/ParityOutlier.test.js",
    "content": "import { parityOutlier } from '../ParityOutlier'\n\ndescribe('Testing parityOutlier function', () => {\n  it('should return the odd number in an array of even numbers', () => {\n    expect(parityOutlier([1, 2, 16, -8848, 5126])).toBe(1)\n  })\n\n  it('should return the even number in an array of odd numbers', () => {\n    expect(parityOutlier([177, 5, 76, 1919])).toBe(76)\n  })\n\n  it('should, if the given array has only an odd and an even number, return the odd outlier', () => {\n    expect(parityOutlier([1, 2])).toBe(1)\n    expect(parityOutlier([4, 3])).toBe(3)\n  })\n\n  it('should return null if the given array is empty, contains only one integer, contains non-interger elements or does not have a parity outlier', () => {\n    expect(parityOutlier([])).toBe(null)\n    expect(parityOutlier([2])).toBe(null)\n    expect(parityOutlier([2, {}, 5, 'GitHub'])).toBe(null)\n    expect(parityOutlier([1, 3, 5, 7, 9])).toBe(null)\n    expect(parityOutlier([0, 2, 4, 6, 8])).toBe(null)\n    expect(parityOutlier([1, 3, 5, 7, 2, 4, 6, 8])).toBe(null)\n  })\n})\n"
  },
  {
    "path": "Maths/test/PascalTriangle.test.js",
    "content": "import { expect } from 'vitest'\nimport { generate } from '../PascalTriangle'\n\ndescribe('Pascals Triangle', () => {\n  it.each([\n    [0, []],\n    [1, [[1]]],\n    [2, [[1], [1, 1]]],\n    [3, [[1], [1, 1], [1, 2, 1]]],\n    [4, [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]]],\n    [5, [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]], [1, 4, 6, 4, 1]]\n  ])('check with %j', (input, expected) => {\n    const pascalsTriangle = generate(input)\n    expect(pascalsTriangle.length).toEqual(input)\n    pascalsTriangle.forEach((arr, index) => {\n      expect(arr.length).toEqual(index + 1)\n    })\n    expect(pascalsTriangle).toEqual(expect.arrayContaining(expected))\n  })\n})\n"
  },
  {
    "path": "Maths/test/PerfectCube.test.js",
    "content": "import { perfectCube } from '../PerfectCube'\n\ndescribe('PerfectCube', () => {\n  it('should return true for a perfect cube', () => {\n    expect(perfectCube(125)).toBeTruthy()\n    expect(perfectCube(-125)).toBeTruthy()\n  })\n  it('should return false for a non perfect cube', () => {\n    expect(perfectCube(100)).toBeFalsy()\n    expect(perfectCube(Infinity)).toBeFalsy()\n  })\n})\n"
  },
  {
    "path": "Maths/test/PerfectNumber.test.js",
    "content": "import { perfectNumber } from '../PerfectNumber'\n\ndescribe('PerfectNumber', () => {\n  it('should return true for a perfect cube', () => {\n    expect(perfectNumber(28)).toBeTruthy()\n  })\n  it('should return false for a non perfect cube', () => {\n    expect(perfectNumber(10)).toBeFalsy()\n  })\n})\n"
  },
  {
    "path": "Maths/test/PerfectSquare.test.js",
    "content": "import { perfectSquare } from '../PerfectSquare'\n\ndescribe('PerfectSquare', () => {\n  it('should return true for a perfect square', () => {\n    expect(perfectSquare(16)).toBeTruthy()\n  })\n  it('should return false for a non perfect square', () => {\n    expect(perfectSquare(10)).toBeFalsy()\n    expect(perfectSquare(Infinity)).toBeFalsy()\n  })\n})\n"
  },
  {
    "path": "Maths/test/PermutationAndCombination.test.js",
    "content": "import {\n  factorial,\n  permutation,\n  combination\n} from '../PermutationAndCombination'\n\ndescribe('Factorial', () => {\n  it('factorial(5)', () => {\n    expect(factorial(5)).toBe(120)\n  })\n})\n\ndescribe('Permutation', () => {\n  it('permutation(5, 2)', () => {\n    expect(permutation(5, 2)).toBe(20)\n  })\n})\n\ndescribe('Combination', () => {\n  it('combination(5, 2)', () => {\n    expect(combination(5, 2)).toBe(10)\n  })\n})\n"
  },
  {
    "path": "Maths/test/PiApproximationMonteCarlo.test.js",
    "content": "import { piEstimation } from '../PiApproximationMonteCarlo'\n\ndescribe('PiApproximationMonteCarlo', () => {\n  it('should be between the range of 2 to 4', () => {\n    const pi = piEstimation()\n    const piRange = pi >= 2 && pi <= 4\n    expect(piRange).toBeTruthy()\n  })\n})\n"
  },
  {
    "path": "Maths/test/Polynomial.test.js",
    "content": "import { Polynomial } from '../Polynomial'\n\ndescribe('Polynomial', () => {\n  it('should not return a expression for zero', () => {\n    const polynomial = new Polynomial([0])\n    expect(polynomial.display()).toBe('')\n  })\n  it('should not return an expression for zero values', () => {\n    const polynomial = new Polynomial([0, 0, 0, 0, 0])\n    expect(polynomial.display()).toBe('')\n  })\n  it('should return an expression for single a non zero value', () => {\n    const polynomial = new Polynomial([9])\n    expect(polynomial.display()).toBe('(9)')\n  })\n  it('should return an expression for two values', () => {\n    const polynomial = new Polynomial([3, 2])\n    expect(polynomial.display()).toBe('(2x) + (3)')\n  })\n  it('should return an expression for values including zero', () => {\n    const polynomial = new Polynomial([0, 2])\n    expect(polynomial.display()).toBe('(2x)')\n  })\n  it('should return an expression and evaluate it', () => {\n    const polynomial = new Polynomial([1, 2, 3, 4])\n    expect(polynomial.display()).toBe('(4x^3) + (3x^2) + (2x) + (1)')\n    expect(polynomial.evaluate(2)).toEqual(49)\n  })\n  it('should evaluate 0 for zero values', () => {\n    const polynomial = new Polynomial([0, 0, 0, 0])\n    expect(polynomial.evaluate(5)).toEqual(0)\n  })\n  it('should evaluate for negative values', () => {\n    const polynomial = new Polynomial([-1, -3, -4, -7])\n    expect(polynomial.evaluate(-5)).toBe(789)\n  })\n})\n"
  },
  {
    "path": "Maths/test/Pow.test.js",
    "content": "import { powLinear, powFaster } from '../Pow'\n\ndescribe('Testing powLinear function', () => {\n  it('should return 1 for numbers with exponent 0', () => {\n    expect(powLinear(2, 0)).toBe(1)\n  })\n\n  it('should return 0.5 for numbers with exponent -1', () => {\n    expect(powLinear(2, -1)).toBe(0.5)\n  })\n\n  it('should return 0 for numbers with base 0', () => {\n    expect(powLinear(0, 23)).toBe(0)\n  })\n\n  it('should return the base to the exponent power', () => {\n    expect(powLinear(24, 4)).toBe(331776)\n  })\n})\n\ndescribe('Testing powFaster function', () => {\n  it('should return 1 for numbers with exponent 0', () => {\n    expect(powFaster(2, 0)).toBe(1)\n  })\n\n  it('should return 0.5 for numbers with exponent -1', () => {\n    expect(powFaster(2, -1)).toBe(0.5)\n  })\n\n  it('should return 0 for numbers with base 0', () => {\n    expect(powFaster(0, 23)).toBe(0)\n  })\n\n  it('should return the base to the exponent power', () => {\n    expect(powFaster(24, 4)).toBe(331776)\n  })\n\n  it('should return the result in O(lonN) complexity', () => {\n    expect(powFaster(2, 64)).toBe(18446744073709552000) // execution time Math. log2(64) -> 6\n  })\n})\n"
  },
  {
    "path": "Maths/test/PowLogarithmic.test.js",
    "content": "import { powLogarithmic } from '../PowLogarithmic'\n\ndescribe('PowLogarithmic', () => {\n  it('should return 1 for numbers with exponent 0', () => {\n    expect(powLogarithmic(2, 0)).toBe(1)\n  })\n\n  it('should return 0 for numbers with base 0', () => {\n    expect(powLogarithmic(0, 23)).toBe(0)\n  })\n\n  it('should return the base to the exponent power', () => {\n    expect(powLogarithmic(24, 4)).toBe(331776)\n  })\n})\n"
  },
  {
    "path": "Maths/test/PrimeCheck.test.js",
    "content": "import { PrimeCheck } from '../PrimeCheck'\n\ndescribe('PrimeCheck', () => {\n  it('should return true for Prime Numbers', () => {\n    expect(PrimeCheck(1000003)).toBeTruthy()\n  })\n  it('should return false for Non Prime Numbers', () => {\n    expect(PrimeCheck(1000001)).toBeFalsy()\n  })\n  it('should return false for 1 and 0', () => {\n    expect(PrimeCheck(1)).toBeFalsy()\n    expect(PrimeCheck(0)).toBeFalsy()\n  })\n})\n"
  },
  {
    "path": "Maths/test/PrimeFactors.test.js",
    "content": "import { PrimeFactors } from '../PrimeFactors'\n\ndescribe('EulersTotient', () => {\n  it('should return the prime factors for 100', () => {\n    expect(PrimeFactors(100)).toEqual([2, 2, 5, 5])\n  })\n\n  it('should return the prime factors for 2560', () => {\n    expect(PrimeFactors(2560)).toEqual([2, 2, 2, 2, 2, 2, 2, 2, 2, 5])\n  })\n})\n"
  },
  {
    "path": "Maths/test/QuadraticRoots.test.js",
    "content": "import { quadraticRoots } from '../QuadraticRoots.js'\n\ndescribe('quadratic roots', () => {\n  it('returns an array with two real roots when the discriminant is positive', () => {\n    expect(quadraticRoots(1, -3, 2)).toEqual([2, 1])\n  })\n  it('returns an array with one real root when the discriminant is zero', () => {\n    expect(quadraticRoots(1, -2, 1)).toEqual([1])\n  })\n  it('returns an empty array indicating no real roots when the discriminant is negative', () => {\n    expect(quadraticRoots(1, 2, 5)).toEqual([])\n  })\n})\n"
  },
  {
    "path": "Maths/test/RadianToDegree.test.js",
    "content": "import { radianToDegree } from '../RadianToDegree'\n\ntest('should convert radian to degree:', () => {\n  const degreeEqual = radianToDegree(0)\n  expect(degreeEqual).toBe(0)\n})\n\ntest('should convert radian to degree:', () => {\n  const degreeEqual = radianToDegree(Math.PI / 4)\n  expect(degreeEqual).toBe(45)\n})\n\ntest('should convert radian to degree:', () => {\n  const degreeEqual = radianToDegree(Math.PI / 2)\n  expect(degreeEqual).toBe(90)\n})\n\ntest('should convert radian to degree:', () => {\n  const degreeEqual = radianToDegree(Math.PI)\n  expect(degreeEqual).toBe(180)\n})\n"
  },
  {
    "path": "Maths/test/ReverseNumber.test.js",
    "content": "import { ReverseNumber } from '../ReverseNumber'\n\ndescribe('ReverseNumber', () => {\n  it.each([\n    [0, 0],\n    [10, 1],\n    [123, 321],\n    [100001, 100001]\n  ])('check with %j', (input, expected) => {\n    expect(expected).toEqual(ReverseNumber(input))\n  })\n\n  it('should throw when input is not a number', () => {\n    expect(() => ReverseNumber('100')).toThrowError()\n  })\n})\n"
  },
  {
    "path": "Maths/test/ReversePolishNotation.test.js",
    "content": "import { calcRPN } from '../ReversePolishNotation'\n\ndescribe('ReversePolishNotation', () => {\n  it('should evaluate correctly for two values', () => {\n    expect(calcRPN('2 3 +')).toEqual(5)\n  })\n  it(\"should evaluate' for multiple values\", () => {\n    expect(calcRPN('2 2 2 * +')).toEqual(6)\n    expect(calcRPN('6 9 7 + 2 / + 3 *')).toEqual(42)\n  })\n})\n"
  },
  {
    "path": "Maths/test/RowEchelon.test.js",
    "content": "import { rowEchelon } from '../RowEchelon'\ndescribe('Determinant', () => {\n  const tolerance = 0.000001\n  test.each([\n    [\n      [\n        [8, 1, 3, 5],\n        [4, 6, 8, 2],\n        [3, 5, 6, 8]\n      ],\n      [\n        [1, 0.125, 0.375, 0.625],\n        [0, 1, 1.18182, -0.09091],\n        [0, 0, 1, -11.0769]\n      ]\n    ],\n    [\n      [\n        [6, 8, 1, 3, 5],\n        [1, 4, 6, 8, 2],\n        [0, 3, 5, 6, 8],\n        [2, 5, 9, 7, 8],\n        [5, 5, 7, 0, 1]\n      ],\n      [\n        [1, 1.33333, 0.16667, 0.5, 0.83333],\n        [0, 1, 2.1875, 2.8125, 0.4375],\n        [0, 0, 1, 1.56, -4.28003],\n        [0, 0, 0, 1, -3.3595],\n        [0, 0, 0, 0, 1]\n      ]\n    ],\n    [\n      [\n        [1, 3, 5],\n        [6, 8, 2],\n        [5, 6, 8],\n        [7, 9, 9],\n        [5, 0, 6]\n      ],\n      [\n        [1, 3, 5],\n        [0, 1, 2.8],\n        [0, 0, 1],\n        [0, 0, 0],\n        [0, 0, 0]\n      ]\n    ],\n    [\n      [\n        [0, 7, 8, 1, 3, 5],\n        [0, 6, 4, 6, 8, 2],\n        [0, 7, 3, 5, 6, 8],\n        [6, 8, 1, 0, 0, 4],\n        [3, 3, 5, 7, 3, 1],\n        [1, 2, 1, 0, 9, 7],\n        [8, 8, 0, 2, 3, 1]\n      ],\n      [\n        [1, 1.33333, 0.16667, 0, 0, 0.66667],\n        [0, 1, 0.66667, 1, 1.33333, 0.33333],\n        [0, 0, 1, 1.2, 1.99999, -3.4],\n        [0, 0, 0, 1, 1.3, -1.4],\n        [0, 0, 0, 0, 1, -2.32854],\n        [0, 0, 0, 0, 0, 1],\n        [0, 0, 0, 0, 0, 0]\n      ]\n    ]\n  ])('Should return the matrix in row echelon form.', (matrix, expected) => {\n    for (let i = 0; i < matrix.length; i++) {\n      for (let j = 0; j < matrix[i].length; j++) {\n        expect(rowEchelon(matrix)[i][j]).toBeCloseTo(expected[i][j], tolerance)\n      }\n    }\n  })\n\n  test.each([\n    [\n      [\n        [8, 1, 3, 5],\n        [4, 6, 8, 2, 7],\n        [3, 5, 6, 8]\n      ],\n      'Input is not a valid 2D matrix.'\n    ]\n  ])('Should return the error message.', (matrix, expected) => {\n    expect(() => rowEchelon(matrix)).toThrowError(expected)\n  })\n})\n"
  },
  {
    "path": "Maths/test/ShorsAlgorithm.test.js",
    "content": "import { ShorsAlgorithm } from '../ShorsAlgorithm'\nimport { fermatPrimeCheck } from '../FermatPrimalityTest'\n\ndescribe(\"Shor's Algorithm\", () => {\n  const N = 10 // number of tests\n  const max = 35000 // max value to factorize\n  const min = 1000 // min value to factorize\n\n  for (let i = 0; i < N; i++) {\n    while (true) {\n      const num = Math.floor(Math.random() * max) + min\n      // num must be composite, don't care for false negatives\n      if (fermatPrimeCheck(num, 1)) continue\n\n      it('should find a non-trivial factor of ' + num, () => {\n        const f = ShorsAlgorithm(num)\n\n        // should not be trivial\n        expect(f).not.toEqual(1)\n        expect(f).not.toEqual(num)\n\n        // should be a factor\n        expect(num % f).toEqual(0)\n      })\n\n      break\n    }\n  }\n})\n"
  },
  {
    "path": "Maths/test/SieveOfEratosthenes.test.js",
    "content": "import { sieveOfEratosthenes } from '../SieveOfEratosthenes'\n\ndescribe('sieveOfEratosthenes', () => {\n  test('returns an empty array for max < 2', () => {\n    expect(sieveOfEratosthenes(1)).toEqual([])\n  })\n\n  test('returns [2] for max = 2', () => {\n    expect(sieveOfEratosthenes(2)).toEqual([2])\n  })\n\n  test('returns [2, 3] for max = 3', () => {\n    expect(sieveOfEratosthenes(3)).toEqual([2, 3])\n  })\n\n  test('returns [2, 3, 5, 7] for max = 10', () => {\n    expect(sieveOfEratosthenes(10)).toEqual([2, 3, 5, 7])\n  })\n\n  test('returns [2, 3, 5, 7, 11, 13, 17, 19] for max = 20', () => {\n    expect(sieveOfEratosthenes(20)).toEqual([2, 3, 5, 7, 11, 13, 17, 19])\n  })\n\n  test('returns [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] for max = 30', () => {\n    expect(sieveOfEratosthenes(30)).toEqual([\n      2, 3, 5, 7, 11, 13, 17, 19, 23, 29\n    ])\n  })\n})\n"
  },
  {
    "path": "Maths/test/Signum.test.js",
    "content": "import { signum } from '../Signum'\n\ndescribe('The sign of a number', () => {\n  it('Sign of 10', () => {\n    expect(signum(10)).toBe(1)\n  })\n\n  it('Sign of 0', () => {\n    expect(signum(0)).toBe(0)\n  })\n\n  it('Sign of -420', () => {\n    expect(signum(-420)).toBe(-1)\n  })\n\n  it('Sign of NaN', () => {\n    expect(signum(NaN)).toBe(NaN)\n  })\n})\n"
  },
  {
    "path": "Maths/test/SimpsonIntegration.test.js",
    "content": "import { integralEvaluation } from '../SimpsonIntegration'\n\ntest('Should return the integral of f(x) = sqrt(x) in [1, 3] to be equal 2.797434', () => {\n  const result = integralEvaluation(16, 1, 3, (x) => {\n    return Math.sqrt(x)\n  })\n  expect(Number(result.toPrecision(7))).toBe(2.797434)\n})\n\ntest('Should return the integral of f(x) = sqrt(x) + x^2 in [1, 3] to be equal 11.46410161', () => {\n  const result = integralEvaluation(64, 1, 3, (x) => {\n    return Math.sqrt(x) + Math.pow(x, 2)\n  })\n  expect(Number(result.toPrecision(10))).toBe(11.46410161)\n})\n\ntest('Should return the integral of f(x) = log(x) + Pi*x^3 in [5, 12] to be equal 15809.9141543', () => {\n  const result = integralEvaluation(128, 5, 12, (x) => {\n    return Math.log(x) + Math.PI * Math.pow(x, 3)\n  })\n  expect(Number(result.toPrecision(12))).toBe(15809.9141543)\n})\n"
  },
  {
    "path": "Maths/test/Softmax.test.js",
    "content": "import { Softmax } from '../Softmax'\n\ndescribe('Softmax', () => {\n  it('should return equal distribution of 1 for equal input values', () => {\n    expect(Softmax([1, 1])).toEqual([0.5, 0.5])\n    expect(Softmax([1, 1, 1, 1])).toEqual([0.25, 0.25, 0.25, 0.25])\n  })\n\n  it('should return values which sum to the value of 1', () => {\n    expect(Softmax([1, 2, 3, 4]).reduce((a, b) => a + b, 0)).toEqual(1)\n  })\n})\n"
  },
  {
    "path": "Maths/test/SquareRoot.test.js",
    "content": "import { sqrt } from '../SquareRoot'\n\ntest('Check SquareRoot of 4 is 2', () => {\n  const res = sqrt(4, 10)\n  expect(res).toBeCloseTo(2)\n})\n\ntest('Check SquareRoot of 2 is 1.4142135', () => {\n  const res = sqrt(2, 10)\n  expect(res).toBeCloseTo(1.4142135)\n})\n\ntest('Check SquareRoot of 3.2 is 1.788854381999832', () => {\n  const res = sqrt(3.2, 10)\n  expect(res).toBeCloseTo(1.788854381999832)\n})\n\ntest('Check SquareRoot of 1 is 1', () => {\n  const res = sqrt(1, 10)\n  expect(res).toBe(1)\n})\n\ntest('Check SquareRoot of 144 is 12', () => {\n  const res = sqrt(144, 10)\n  expect(res).toBeCloseTo(12)\n})\n\ntest('Check SquareRoot of 0 is 0', () => {\n  const res = sqrt(0, 10)\n  expect(res).toBeCloseTo(0)\n})\n\ntest('Check SquareRoot of 1000 is 31.62277', () => {\n  const res = sqrt(1000, 10)\n  expect(res).toBeCloseTo(31.62277)\n})\n"
  },
  {
    "path": "Maths/test/SquareRootLogarithmic.test.js",
    "content": "import { squareRootLogarithmic } from '../SquareRootLogarithmic'\n\ndescribe('SquareRootLogarithmic', () => {\n  test('Finding the square root of a positive integer', () => {\n    expect(squareRootLogarithmic(4)).toEqual(2)\n    expect(squareRootLogarithmic(16)).toEqual(4)\n    expect(squareRootLogarithmic(8)).toEqual(2)\n  })\n  test('Throwing an exception', () => {\n    expect(() => squareRootLogarithmic('not a number')).toThrow()\n    expect(() => squareRootLogarithmic(true)).toThrow()\n  })\n})\n"
  },
  {
    "path": "Maths/test/SumOfDigits.test.js",
    "content": "import {\n  sumOfDigitsUsingLoop,\n  sumOfDigitsUsingRecursion,\n  sumOfDigitsUsingString\n} from '../SumOfDigits'\n\ntest('Testing on sumOfDigitsUsingLoop', () => {\n  const sum = sumOfDigitsUsingLoop(123)\n  expect(sum).toBe(6)\n})\n\ntest('Testing on sumOfDigitsUsingRecursion', () => {\n  const sum = sumOfDigitsUsingRecursion(123)\n  expect(sum).toBe(6)\n})\n\ntest('Testing on sumOfDigitsUsingString', () => {\n  const sum = sumOfDigitsUsingString(123)\n  expect(sum).toBe(6)\n})\n"
  },
  {
    "path": "Maths/test/SumOfGeometricProgression.test.js",
    "content": "import { sumOfGeometricProgression } from '../SumOfGeometricProgression'\n\ndescribe('Sum Of Geometric Progression', () => {\n  it('should return the sum of a finite GP', () => {\n    expect(sumOfGeometricProgression(100, 1.5, 4)).toBe(812.5)\n  })\n\n  it('should return the sum of an infinite GP', () => {\n    expect(sumOfGeometricProgression(2, 0.5, Infinity)).toBe(4)\n  })\n\n  it('should throw when series diverges', () => {\n    expect(() => sumOfGeometricProgression(1, 1, Infinity)).toThrowError()\n  })\n})\n"
  },
  {
    "path": "Maths/test/TwoSum.test.js",
    "content": "import { TwoSum } from '../TwoSum.js'\ndescribe('Two Sum', () => {\n  const testCasesWithoutSolution = [\n    [[8], 8],\n    [[3, 3, 3, 3], 19]\n  ]\n  const testCasesWithSolution = [\n    [[2, 7, 11, 15], 9, [0, 1]],\n    [[15, 2, 11, 7], 13, [1, 2]],\n    [[2, 7, 11, 15], 17, [0, 3]],\n    [[7, 15, 11, 2], 18, [0, 2]],\n    [[2, 7, 11, 15], 26, [2, 3]]\n  ]\n\n  test.each(testCasesWithoutSolution)(\n    'Should return an empty array if there is no solution',\n    (nums, target) => {\n      expect(TwoSum(nums, target)).toEqual([])\n    }\n  )\n\n  test.each(testCasesWithSolution)(\n    'Should return the indices of two numbers that add up to the target',\n    (nums, target, expected) => {\n      expect(TwoSum(nums, target)).toEqual(expected)\n    }\n  )\n})\n"
  },
  {
    "path": "Maths/test/Volume.test.js",
    "content": "import * as volume from '../Volume'\n\ntest('Testing on volCuboid', () => {\n  const volCuboid = volume.volCuboid(2.0, 5.0, 3)\n  expect(volCuboid).toBe(30.0)\n})\n\ntest('Testing on volCube', () => {\n  const volCube = volume.volCube(2.0)\n  expect(volCube).toBe(8.0)\n})\n\ntest('Testing on volCone', () => {\n  const volCone = volume.volCone(3.0, 8.0)\n  expect(volCone).toBe(75.39822368615503)\n})\n\ntest('Testing on volPyramid', () => {\n  const volPyramid = volume.volPyramid(2.0, 3.0, 8.0)\n  expect(volPyramid).toBe(16.0)\n})\n\ntest('Testing on volCylinder', () => {\n  const volCylinder = volume.volCylinder(3.0, 8.0)\n  expect(volCylinder).toBe(226.1946710584651)\n})\n\ntest('Testing on volTriangularPrism', () => {\n  const volTriangularPrism = volume.volTriangularPrism(3.0, 6.0, 8.0)\n  expect(volTriangularPrism).toBe(72.0)\n})\n\ntest('Testing on volPentagonalPrism', () => {\n  const volPentagonalPrism = volume.volPentagonalPrism(1.0, 4.0, 8.0)\n  expect(volPentagonalPrism).toBe(80.0)\n})\n\ntest('Testing on volSphere', () => {\n  const volSphere = volume.volSphere(4.0)\n  expect(volSphere).toBe(268.082573106329)\n})\n\ntest('Testing on volHemisphere', () => {\n  const volHemisphere = volume.volHemisphere(4.0)\n  expect(volHemisphere).toBe(134.0412865531645)\n})\n"
  },
  {
    "path": "Maths/test/WhileLoopFactorial.test.js",
    "content": "import { factorialize } from '../WhileLoopFactorial'\n\nfunction testFactorial(n, expected) {\n  test('Testing on ' + n + '!', () => {\n    expect(factorialize(n)).toBe(expected)\n  })\n}\n\ntestFactorial(3, 6)\ntestFactorial(7, 5040)\ntestFactorial(0, 1)\ntestFactorial(12, 479001600)\n"
  },
  {
    "path": "Maths/test/ZellersCongruenceAlgorithm.test.js",
    "content": "import { zellersCongruenceAlgorithm } from '../ZellersCongruenceAlgorithm'\n\nfunction testZeller(day, month, year, expected) {\n  test('Testing on ' + day + '/' + month + '/' + year, () => {\n    expect(zellersCongruenceAlgorithm(day, month, year)).toBe(expected)\n  })\n}\n\ntest('Testing on this/should/throw', () => {\n  expect(() => {\n    zellersCongruenceAlgorithm('this', 'should', 'error')\n  }).toThrowError(new TypeError('Arguments are not all numbers.'))\n})\ntestZeller(25, 1, 2013, 'Friday')\ntestZeller(26, 1, 2013, 'Saturday')\ntestZeller(16, 4, 2022, 'Saturday')\ntestZeller(25, 4, 2022, 'Monday')\n"
  },
  {
    "path": "Maths/test/isPalindromeIntegerNumber.test.js",
    "content": "import { isPalindromeIntegerNumber } from '../isPalindromeIntegerNumber'\n\ndescribe('isPalindromeIntegerNumber', () => {\n  it('expects to return true when length of input is 1', () => {\n    expect(isPalindromeIntegerNumber(6)).toEqual(true)\n  })\n\n  it('expects to return true when input is palindrome', () => {\n    expect(isPalindromeIntegerNumber(121)).toEqual(true)\n    expect(isPalindromeIntegerNumber(12321)).toEqual(true)\n    expect(isPalindromeIntegerNumber(1221)).toEqual(true)\n  })\n\n  it('expects to return false when input is not palindrome', () => {\n    expect(isPalindromeIntegerNumber(189)).toEqual(false)\n  })\n\n  it('expects to return false when input is minus', () => {\n    expect(isPalindromeIntegerNumber(-121)).toEqual(false)\n    expect(isPalindromeIntegerNumber(-12321)).toEqual(false)\n  })\n\n  it('expects to return false when input is not integer number', () => {\n    expect(isPalindromeIntegerNumber(123.456)).toEqual(false)\n  })\n\n  it('expects to throw error when input is not a number', () => {\n    expect(() => isPalindromeIntegerNumber(undefined)).toThrowError()\n    expect(() => isPalindromeIntegerNumber({ key: 'val' })).toThrowError()\n    expect(() => isPalindromeIntegerNumber([])).toThrowError()\n  })\n})\n"
  },
  {
    "path": "Navigation/Haversine.js",
    "content": "/**\n * @function HaversineDistance\n * @description Calculate the distance between two coordinates using the haversine formula\n * @param {Integer} latitude1 - The input integer\n * @param {Integer} latitude2 - The input integer\n * @param {Integer} longitude1 - The input integer\n * @param {Integer} longitude2 - The input integer\n * @return {Integer} Haversine Distance.\n * @see [Haversine_Distance](https://pt.wikipedia.org/wiki/F%C3%B3rmula_de_Haversine)\n */\nconst haversineDistance = (\n  latitude1 = 0,\n  longitude1 = 0,\n  latitude2 = 0,\n  longitude2 = 0\n) => {\n  validateLatOrLong(latitude1)\n  validateLatOrLong(latitude2)\n  validateLatOrLong(longitude1)\n  validateLatOrLong(longitude2)\n  const earthRadius = 6371e3 // 6,371km\n  const pi = Math.PI\n  const cos1 = (latitude1 * pi) / 180.0\n  const cos2 = (latitude2 * pi) / 180.0\n  const deltaLatitude = ((latitude2 - latitude1) * pi) / 180.0\n  const deltaLongitude = ((longitude2 - longitude1) * pi) / 180.0\n\n  const alpha =\n    Math.sin(deltaLatitude / 2) * Math.sin(deltaLatitude / 2) +\n    Math.cos(cos1) *\n      Math.cos(cos2) *\n      Math.sin(deltaLongitude / 2) *\n      Math.sin(deltaLongitude / 2)\n  const constant = 2 * Math.atan2(Math.sqrt(alpha), Math.sqrt(1 - alpha))\n  return earthRadius * constant\n}\n\nconst validateLatOrLong = (value) => {\n  if (typeof value !== 'number') {\n    throw new TypeError('The value of latitude or longitude should be a number')\n  }\n}\n\nexport { haversineDistance }\n"
  },
  {
    "path": "Navigation/test/Haversine.test.js",
    "content": "import { haversineDistance } from '../Haversine'\n\ndescribe('Testing the haversine distance calculator', () => {\n  it('Calculate distance', () => {\n    const distance = haversineDistance(64.1265, -21.8174, 40.7128, -74.006)\n    expect(distance).toBe(4208198.758424171)\n  })\n  it('Test validation, expect throw', () => {\n    expect(() =>\n      haversineDistance(64.1265, -21.8174, 40.7128, '74.0060')\n    ).toThrow()\n  })\n})\n"
  },
  {
    "path": "Project-Euler/Problem001.js",
    "content": "// https://projecteuler.net/problem=1\n/* Multiples of 3 and 5\nIf 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.\nFind the sum of all the multiples of 3 or 5 below the provided parameter value number.\n*/\n\n// 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.\nconst multiplesThreeAndFive = (num) => {\n  if (num < 1) throw new Error('No natural numbers exist below 1')\n  num -= 1\n  let sum = 0\n\n  // The nSum function calculates the sum of the first n numbers in the sequence with a common difference of num.\n  // Here, n is denoted as frequency.\n  const nSum = (num, frequency) => (frequency * (frequency + 1) * num) >> 1\n\n  sum += nSum(3, Math.floor(num / 3))\n  sum += nSum(5, Math.floor(num / 5))\n  sum -= nSum(15, Math.floor(num / 15))\n  return sum\n}\n\nexport { multiplesThreeAndFive }\n"
  },
  {
    "path": "Project-Euler/Problem002.js",
    "content": "// https://projecteuler.net/problem=2\nconst SQ5 = 5 ** 0.5 // Square root of 5\nconst PHI = (1 + SQ5) / 2 // definition of PHI\n\n// theoretically it should take O(1) constant amount of time as long\n// arithmetic calculations are considered to be in constant amount of time\nexport const EvenFibonacci = (limit) => {\n  if (limit < 1)\n    throw new Error(\"Fibonacci sequence limit can't be less than 1\")\n\n  const highestIndex = Math.floor(Math.log(limit * SQ5) / Math.log(PHI))\n  const n = Math.floor(highestIndex / 3)\n  return Math.floor(\n    ((PHI ** (3 * n + 3) - 1) / (PHI ** 3 - 1) -\n      ((1 - PHI) ** (3 * n + 3) - 1) / ((1 - PHI) ** 3 - 1)) /\n      SQ5\n  )\n}\n"
  },
  {
    "path": "Project-Euler/Problem003.js",
    "content": "// https://projecteuler.net/problem=3\n\nexport const largestPrime = (num = 600851475143) => {\n  let newnum = num\n  let largestFact = 0\n  let counter = 2\n  while (counter * counter <= newnum) {\n    if (newnum % counter === 0) {\n      newnum = newnum / counter\n    } else {\n      counter++\n    }\n  }\n  if (newnum > largestFact) {\n    largestFact = newnum\n  }\n  return largestFact\n}\n"
  },
  {
    "path": "Project-Euler/Problem004.js",
    "content": "// https://projecteuler.net/problem=4\n/* A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.\n  Find the largest palindrome made from the product of two 3-digit numbers.\n*/\nexport const largestPalindromic = (digits) => {\n  let i\n  let n\n  let m\n  let d\n  let limit\n  let number = 0\n\n  for (i = 1; i < digits; i++) {\n    number = 10 * number + 9\n  }\n  const inf = number // highest (digits - 1) number, in this example highest 2 digit number\n  const sup = 10 * number + 9 // highest (digits) number, in this example highest 3 digit number\n\n  const isPalindromic = (n) => {\n    let p = 0\n    const q = n\n    let r\n    while (n > 0) {\n      r = n % 10\n      p = 10 * p + r\n      n = Math.floor(n / 10)\n    }\n    return p === q // returning whether the number is palindromic or not\n  }\n\n  for (n = sup * sup, m = inf * inf; n > m; n--) {\n    if (isPalindromic(n)) {\n      limit = Math.ceil(Math.sqrt(n))\n      d = sup\n      while (d >= limit) {\n        if (n % d === 0 && n / d > inf) {\n          return n\n        }\n        d -= 1\n      }\n    }\n  }\n  return NaN // returning not a number, if any such case arise\n}\n"
  },
  {
    "path": "Project-Euler/Problem005.js",
    "content": "/*\nSmallest multiple\n\n2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.\nWhat is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?\n*/\n\nexport const findSmallestMultiple = (maxDivisor) => {\n  const divisors = Array.from({ length: maxDivisor }, (_, i) => i + 1)\n  let num = maxDivisor + 1\n  let result\n\n  while (!result) {\n    const isDivisibleByAll = divisors.every((divisor) => num % divisor === 0)\n    if (isDivisibleByAll) result = num\n    else num++\n  }\n\n  return result\n}\n"
  },
  {
    "path": "Project-Euler/Problem006.js",
    "content": "// https://projecteuler.net/problem=6\n\nexport const squareDifference = (num = 100) => {\n  let sumOfSquares = (num * (num + 1) * (2 * num + 1)) / 6\n  let sums = (num * (num + 1)) / 2\n\n  return sums ** 2 - sumOfSquares // difference of square of the total sum and sum of squares\n}\n"
  },
  {
    "path": "Project-Euler/Problem007.js",
    "content": "import { PrimeCheck } from '../Maths/PrimeCheck.js'\n\n/**\n * Find nth Prime Number\n *\n * P.S.(Project Euler - 007):\n * By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.\n * What is the 10001st prime number?\n *\n * @param {Number} n\n * @returns {Number} returns the nth prime number\n */\nexport const nthPrime = (n) => {\n  if (n < 1) {\n    throw new Error('Invalid Input')\n  }\n\n  let count = 0\n  let candidateValue = 1\n  while (count < n) {\n    candidateValue++\n    if (PrimeCheck(candidateValue)) {\n      count++\n    }\n  }\n  return candidateValue\n}\n"
  },
  {
    "path": "Project-Euler/Problem008.js",
    "content": "// Problem: https://projecteuler.net/problem=8\n\nconst largestAdjacentNumber = (grid, consecutive) => {\n  grid = grid.split('\\n').join('')\n  const splitGrid = grid.split('\\n')\n  let largestProd = 0\n\n  for (const row in splitGrid) {\n    const currentRow = splitGrid[row].split('').map((x) => Number(x))\n\n    for (let i = 0; i < currentRow.length - consecutive; i++) {\n      const combine = currentRow.slice(i, i + consecutive)\n\n      if (!combine.includes(0)) {\n        const product = combine.reduce(function (a, b) {\n          return a * b\n        })\n\n        if (largestProd < product) largestProd = product\n      }\n    }\n  }\n  return largestProd\n}\n\nexport { largestAdjacentNumber }\n"
  },
  {
    "path": "Project-Euler/Problem009.js",
    "content": "/*\nSpecial Pythagorean triplet\n\nA Pythagorean triplet is a set of three natural numbers, a < b < c, for which,\n\na^2 + b^2 = c^2\nFor example, 32 + 42 = 9 + 16 = 25 = 52.\n\nThere exists exactly one Pythagorean triplet for which a + b + c = 1000.\nFind the product abc.\n*/\n\nconst isPythagoreanTriplet = (a, b, c) =>\n  Math.pow(a, 2) + Math.pow(b, 2) === Math.pow(c, 2)\n\nexport const findSpecialPythagoreanTriplet = () => {\n  for (let a = 0; a < 1000; a++) {\n    for (let b = a + 1; b < 1000; b++) {\n      for (let c = b + 1; c < 1000; c++) {\n        if (isPythagoreanTriplet(a, b, c) && a + b + c === 1000) {\n          return a * b * c\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "Project-Euler/Problem010.js",
    "content": "// https://projecteuler.net/problem=10\n\nconst isPrime = (number) => {\n  if (number === 2) return true\n  if (number % 2 === 0) return false\n\n  for (let j = 3; j * j <= number; j += 2) {\n    if (number % j === 0) {\n      return false\n    }\n  }\n  return true\n}\n\nconst calculateSumOfPrimeNumbers = (maxNumber) => {\n  let sum = 0\n  for (let i = maxNumber - 1; i >= 2; i--) {\n    if (isPrime(parseInt(i)) === true) {\n      sum += i\n    }\n  }\n  return sum\n}\nexport { calculateSumOfPrimeNumbers }\n"
  },
  {
    "path": "Project-Euler/Problem011.js",
    "content": "/*\n *\n * In the 20×20 grid below, four numbers along a diagonal line have been marked in red.\n *\n *            08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08\n *            49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00\n *            81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65\n *            52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91\n *            22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80\n *            24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50\n *            32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70\n *            67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21\n *            24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72\n *            21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95\n *            78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92\n *            16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57\n *            86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58\n *            19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40\n *            04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66\n *            88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69\n *            04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36\n *            20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16\n *            20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54\n *            01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48\n *\n * The product of these numbers is 26 × 63 × 78 × 14 = 1788696.\n *\n * What is the greatest product of four adjacent numbers in the\n * same direction (up, down, left, right, or diagonally) in the 20×20 grid?\n */\n\nexport function largestProductInAGrid(arr) {\n  let max = 0\n  const k = 4\n\n  const dx = [1, 0, 1, -1]\n  const dy = [0, 1, 1, 1]\n\n  for (let y = 0; y < arr.length; y++) {\n    for (let x = 0; x < arr[y].length; x++) {\n      for (let d = 0; d < 4; d++) {\n        let p = 1\n        for (let i = 0; i < k; i++) {\n          p *= get(arr, y + i * dy[d], x + i * dx[d])\n        }\n        max = Math.max(p, max)\n      }\n    }\n  }\n  return max\n}\n\nfunction get(arr, y, x) {\n  if (y >= 0 && y < arr.length && x >= 0 && x < arr[y].length) {\n    return arr[y][x]\n  }\n\n  return 0\n}\n"
  },
  {
    "path": "Project-Euler/Problem012.js",
    "content": "/**\n * Problem 12 - Highly divisible triangular number\n *\n * https://projecteuler.net/problem=11\n *\n * The sequence of triangle numbers is generated by adding the natural numbers.\n * So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28.\n *\n * The first ten terms would be: 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...\n * Let us list the factors of the first seven triangle numbers:\n *\n * 1: 1\n * 3: 1,3\n * 6: 1,2,3,6\n * 10: 1,2,5,10\n * 15: 1,3,5,15\n * 21: 1,3,7,21\n * 28: 1,2,4,7,14,28\n *\n * We can see that 28 is the first triangle number to have over five divisors.\n *\n * What is the value of the first triangle number to have over five hundred divisors?\n */\n\n/**\n * Gets number of divisors of a given number\n * @params num The number whose divisors to find\n */\nconst getNumOfDivisors = (num) => {\n  // initialize numberOfDivisors\n  let numberOfDivisors = 0\n\n  // if one divisor less than sqrt(num) exists\n  // then another divisor greater than sqrt(n) exists and its value is num/i\n  const sqrtNum = Math.sqrt(num)\n  for (let i = 0; i <= sqrtNum; i++) {\n    // check if i divides num\n    if (num % i === 0) {\n      if (i === sqrtNum) {\n        // if both divisors are equal, i.e., num is perfect square, then only 1 divisor\n        numberOfDivisors++\n      } else {\n        // 2 divisors, one of them is less than sqrt(n), other greater than sqrt(n)\n        numberOfDivisors += 2\n      }\n    }\n  }\n  return numberOfDivisors\n}\n\n/**\n * Loops till first triangular number with 500 divisors is found\n */\nconst firstTriangularWith500Divisors = () => {\n  let triangularNum\n  // loop forever until numOfDivisors becomes greater than or equal to 500\n  for (let n = 1; ; n++) {\n    // nth triangular number is (1/2)*n*(n+1) by Arithmetic Progression\n    triangularNum = (1 / 2) * n * (n + 1)\n    if (getNumOfDivisors(triangularNum) >= 500) return triangularNum\n  }\n}\n\nexport { firstTriangularWith500Divisors }\n"
  },
  {
    "path": "Project-Euler/Problem013.js",
    "content": "/**\n * Work out the first ten digits of the sum of the following one-hundred 50-digit numbers.\n */\n\nexport function largeSum(bignum) {\n  const nums = []\n  for (let i = 0; i < bignum.length; i += 50) {\n    nums.push(bignum.slice(i, i + 50))\n  }\n\n  let pos = nums[0].length\n  let ret = ''\n  let num = 0\n\n  while (pos--) {\n    for (let i = nums.length; i--; ) {\n      num += +nums[i].charAt(pos)\n    }\n    ret = (num % 10) + ret\n    num = (num / 10) | 0\n  }\n\n  if (num > 0) {\n    ret = num + ret\n  }\n  return ret.slice(0, 10)\n}\n"
  },
  {
    "path": "Project-Euler/Problem014.js",
    "content": "/*\nLongest Collatz sequence\n\nThe following iterative sequence is defined for the set of positive integers:\n\nn → n/2 (n is even)\nn → 3n + 1 (n is odd)\n\nUsing the rule above and starting with 13, we generate the following sequence:\n\n13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1\nIt can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.\n\nWhich starting number, under one million, produces the longest chain?\n\nNOTE: Once the chain starts the terms are allowed to go above one million.\n*/\n\nconst getCollatzSequenceLength = (num, seqLength) => {\n  if (num === 1) {\n    return seqLength\n  } else {\n    let newElement\n    if (num % 2 === 0) {\n      newElement = num / 2\n    } else {\n      newElement = 3 * num + 1\n    }\n    seqLength++\n    return getCollatzSequenceLength(newElement, seqLength)\n  }\n}\n\nexport const findLongestCollatzSequence = (limit = 1000000) => {\n  let startingPointForLargestSequence = 1\n  let largestSequenceLength = 1\n  for (let i = 2; i < limit; i++) {\n    const currentSequenceLength = getCollatzSequenceLength(i, 1)\n    if (currentSequenceLength > largestSequenceLength) {\n      startingPointForLargestSequence = i\n      largestSequenceLength = currentSequenceLength\n    }\n  }\n  return startingPointForLargestSequence\n}\n"
  },
  {
    "path": "Project-Euler/Problem015.js",
    "content": "// https://projecteuler.net/problem=15\n/* Starting in the top left corner of a 2×2 grid, and only being able to move to\nthe right and down, there are exactly 6 routes to the bottom right corner.\nHow many such routes are there through a 20×20 grid?\n*/\n\n// A lattice path is composed of horizontal and vertical lines that pass through lattice points.\n\nexport const latticePath = (gridSize) => {\n  let paths\n  for (let i = 1, paths = 1; i <= gridSize; i++) {\n    paths = (paths * (gridSize + i)) / i\n  }\n  // The total number of paths can be found using the binomial coefficient (b+a)/a.\n  return paths\n}\n\n// > latticePath(20))\n// 137846528820\n"
  },
  {
    "path": "Project-Euler/Problem016.js",
    "content": "/**\n * Problem 16 - Power digit sum\n *\n * @see {@link https://projecteuler.net/problem=16}\n *\n * 2¹⁵ = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.\n *\n * What is the sum of the digits of the number 2¹⁰⁰⁰ ?\n */\n\n/**\n * Returns the power digit sum of n^pow.\n *\n * @param {number} [n=2]\n * @param {number} [pow=1000]\n * @returns {number}\n */\nconst powerDigitSum = function (n = 2, pow = 1000) {\n  // The idea is to consider each digit (d*10^exp) separately, right-to-left.\n  // digits = [units, tens, ...]\n\n  const digits = [n]\n  let p = 1\n\n  while (++p <= pow) {\n    let carry = 0\n    for (let exp = 0; exp < digits.length; exp++) {\n      const prod = digits[exp] * n + carry\n      carry = Math.floor(prod / 10)\n      digits[exp] = prod % 10\n    }\n    while (carry > 0) {\n      digits.push(carry % 10)\n      carry = Math.floor(carry / 10)\n    }\n  }\n\n  // (digits are reversed but we only want the sum so it doesn't matter)\n\n  return digits.reduce((prev, current) => prev + current, 0)\n}\n\nexport { powerDigitSum }\n"
  },
  {
    "path": "Project-Euler/Problem017.js",
    "content": "/**\n * Problem 17 - Number letter counts\n *\n * @see {@link https://projecteuler.net/problem=17}\n *\n * If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.\n * If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?\n *\n * @author Chetan07j\n */\n\n// Array of number word length from 0 -> 19\nconst ones = [4, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8]\n\n// Array for tens from 20, 30, 40, 50, 60, 70, 80, 90 in words length\nconst tens = [6, 6, 5, 5, 5, 7, 6, 6]\n\n// Word length for words thousand, hundred, and\nconst thousandLength = 8\nconst hundredLength = 7\nconst andLength = 3\n\n/**\n * Function to convert number to word\n *\n * This function is called recursively to handle thousand and its sub part\n */\nconst numberToWordLength = (n) => {\n  let count = 0\n\n  // If number is < 20 then return its corresponding value from ones\n  if (n < 20) {\n    return ones[n]\n  }\n\n  /**\n   * To calculate tens value \"n / 10 - 2\" is performed, which might return decimal value\n   * to extract proper integer value Math.floor is added\n   * Here  \"-2\" is performed as our tens array start with index 0\n   * To get appropriate value from that for our number it is required\n   * e.g.,\n   * -> 34 -> 34/10= 3.4 -> Math.floor(3.4) = 3\n   * -> ones[3] = 5 // this is wrong\n   * -> 3 - 2 = 1 -> ones[1] = 6\n   *\n   * To find ones part, unit is identified by n % 10\n   * If > 0 then ones word is appended to tens word otherwise nothing\n   * e.g.,\n   * 1. 34 -> 10\n   * 2. 30 -> 6\n   */\n  if (n >= 20 && n < 100) {\n    const unit = n % 10\n    return tens[Math.floor(n / 10 - 2)] + (unit !== 0 ? ones[unit] : 0)\n  }\n\n  // Find thousand, hundred and sub part\n  const hundred = Math.floor(n / 100) % 10\n  const thousand = Math.floor(n / 1000)\n  const sub = n % 100\n\n  // Find ones for thousand part number\n  // e.g., thousand = 2 => inWord = twothousand\n  if (n > 999) {\n    count += numberToWordLength(thousand) + thousandLength\n  }\n\n  // Find ones for hundred part number\n  // e.g., hundred = 1 => inWord = onehundred\n  if (hundred !== 0) {\n    count += ones[hundred] + hundredLength\n  }\n\n  // Find and part of number\n  // e.g., 922 => ninehundred\"andtwentytwo\"\n  if (sub !== 0) {\n    count += andLength + numberToWordLength(sub)\n  }\n\n  // return number in word format\n  return count\n}\n\n/**\n * Function responsible for calculating total number word length\n * for provided input number\n * Validation is performed for input\n * Loop is executed to find total word length for given number range\n * starting from 1\n *\n *\n * @param {number} number\n * @returns {number}\n */\nconst countNumberWordLength = (number) => {\n  let count = 0\n\n  // Not a number check\n  if (Number.isNaN(parseInt(number))) {\n    throw new Error('Invalid input, please provide valid number')\n  }\n\n  // Number should be greater than 1\n  if (number < 1) {\n    throw new Error('Please provide number greater that 1')\n  }\n\n  // Loop to calculate word length by calling {@link numberToWord}\n  for (let i = 1; i <= number; i++) {\n    count += numberToWordLength(i)\n  }\n\n  // return final count for number word length\n  return count\n}\n\nexport { countNumberWordLength }\n"
  },
  {
    "path": "Project-Euler/Problem018.js",
    "content": "/**\n * @file Provides solution for Project Euler Problem 18 - Maximum path sum I\n * @author Eric Lavault {@link https://github.com/lvlte}\n * @license MIT\n */\n\n/**\n * Problem 18 - Maximum path sum I\n *\n * @see {@link https://projecteuler.net/problem=18}\n *\n * By starting at the top of the triangle below and moving to adjacent numbers\n * on the row below, the maximum total from top to bottom is 23 :\n *\n *                            3\n *                           7 4\n *                          2 4 6\n *                         8 5 9 3\n *\n * That is, 3 + 7 + 4 + 9 = 23.\n *\n * Find the maximum total from top to bottom of the triangle below :\n *\n *                            75\n *                           95 64\n *                         17 47 82\n *                        18 35 87 10\n *                      20 04 82 47 65\n *                     19 01 23 75 03 34\n *                   88 02 77 73 07 63 67\n *                  99 65 04 28 06 16 70 92\n *                41 41 26 56 83 40 80 70 33\n *               41 48 72 33 47 32 37 16 94 29\n *             53 71 44 65 25 43 91 52 97 51 14\n *            70 11 33 28 77 73 17 78 39 68 17 57\n *          91 71 52 38 17 14 91 43 58 50 27 29 48\n *         63 66 04 68 89 53 67 30 73 16 69 87 40 31\n *       04 62 98 27 23 09 70 98 73 93 38 53 60 04 23\n *\n * NOTE: As there are only 16384 routes, it is possible to solve this problem\n * by trying every route. However, Problem 67, is the same challenge with a\n * triangle containing one-hundred rows; it cannot be solved by brute force,\n * and requires a clever method! ;o)\n */\n\nconst triangle = `\n75\n95 64\n17 47 82\n18 35 87 10\n20 04 82 47 65\n19 01 23 75 03 34\n88 02 77 73 07 63 67\n99 65 04 28 06 16 70 92\n41 41 26 56 83 40 80 70 33\n41 48 72 33 47 32 37 16 94 29\n53 71 44 65 25 43 91 52 97 51 14\n70 11 33 28 77 73 17 78 39 68 17 57\n91 71 52 38 17 14 91 43 58 50 27 29 48\n63 66 04 68 89 53 67 30 73 16 69 87 40 31\n04 62 98 27 23 09 70 98 73 93 38 53 60 04 23\n`\n\nexport const maxPathSum = function (grid = triangle) {\n  /**\n   * If we reduce the problem to its simplest form, considering :\n   *\n   *         7      -> The max sum depends on the two adjacent numbers below 7,\n   *        2 4        not 7 itself.\n   *\n   *    obviously 4 > 2 therefore the max sum is 7 + 4 = 11\n   *\n   *                       6\n   * Likewise, with :     4 6     6 > 4 therefore the max sum is 6 + 6 = 12\n   *\n   * Now, let's say we are given :\n   *\n   *         3\n   *        7 6\n   *       2 4 6\n   *\n   *    and we decompose it into sub-problems such that each one fits the simple\n   *    case above, we got :\n   *\n   *         .           .           3\n   *        7 .         . 6         ? ?\n   *       2 4 .       . 4 6       . . .\n   *\n   *    Again, considering any number, the best path depends on the two adjacent\n   *    numbers below it, not the number itself. That's why we have to compute\n   *    the max sum from bottom to top, replacing each number with the sum of\n   *    that number plus the greatest of the two adjacent numbers computed from\n   *    the previous row.\n   *\n   *          .          .              3              15\n   *        11 .        . 12    ->    11 12    ->    x   x\n   *       x  x .      . x  x        x  x  x        x  x  x\n   *\n   * We are simplifying a complicated problem by breaking it down into simpler\n   * sub-problems in a recursive manner, this is called Dynamic Programming.\n   */\n\n  grid = grid\n    .split(/\\r\\n|\\n/)\n    .filter((l) => l)\n    .map((r) => r.split(' ').map((n) => +n))\n\n  for (let i = grid.length - 2; i >= 0; i--) {\n    for (let j = 0; j < grid[i].length; j++) {\n      grid[i][j] += Math.max(grid[i + 1][j], grid[i + 1][j + 1])\n    }\n  }\n\n  return grid[0][0]\n}\n"
  },
  {
    "path": "Project-Euler/Problem019.js",
    "content": "/**\n * Problem 19 - Counting Sundays\n *\n * @see {@link https://projecteuler.net/problem=19}\n *\n * You are given the following information, but you may prefer to do some research for yourself.\n * 1 Jan 1900 was a Monday.\n * Thirty days has September,\n * April, June and November.\n * All the rest have thirty-one,\n * Saving February alone,\n * Which has twenty-eight, rain or shine.\n * And on leap years, twenty-nine.\n * A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.\n * How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?\n *\n * @author ddaniel27\n */\nimport { isLeapYear } from '../Maths/LeapYear'\n\nfunction problem19() {\n  let sundaysCount = 0 // Count of Sundays\n  let dayOfWeek = 2 // 1st Jan 1900 was a Monday, so 1st Jan 1901 was a Tuesday\n\n  for (let year = 1901; year <= 2000; year++) {\n    for (let month = 1; month <= 12; month++) {\n      if (dayOfWeek === 0) {\n        // If it's a Sunday (0 is Sunday, 1 is Monday, ..., 6 is Saturday)\n        sundaysCount++\n      }\n\n      let daysInMonth = 31\n      if (month === 4 || month === 6 || month === 9 || month === 11) {\n        // April, June, September, November\n        daysInMonth = 30\n      } else if (month === 2) {\n        // February\n        daysInMonth = isLeapYear(year) ? 29 : 28\n      }\n\n      dayOfWeek = (dayOfWeek + daysInMonth) % 7 // Calculate the day of the week\n    }\n  }\n\n  return sundaysCount\n}\n\nexport { problem19 }\n"
  },
  {
    "path": "Project-Euler/Problem020.js",
    "content": "/**\n * Problem 20 - Factorial digit sum\n *\n * @see {@link https://projecteuler.net/problem=20}\n *\n * n! means n × (n − 1) × ... × 3 × 2 × 1\n *\n * For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800,\n * and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27\n *\n * Find the sum of the digits in the number 100!\n */\n\nconst factorialDigitSum = (n = 100) => {\n  // Consider each digit*10^exp separately, right-to-left ([units, tens, ...]).\n  const digits = [1]\n\n  for (let x = 2; x <= n; x++) {\n    let carry = 0\n    for (let exp = 0; exp < digits.length; exp++) {\n      const prod = digits[exp] * x + carry\n      carry = Math.floor(prod / 10)\n      digits[exp] = prod % 10\n    }\n    while (carry > 0) {\n      digits.push(carry % 10)\n      carry = Math.floor(carry / 10)\n    }\n  }\n\n  // (digits are reversed but we only want the sum so it doesn't matter)\n\n  return digits.reduce((prev, current) => prev + current, 0)\n}\n\nexport { factorialDigitSum }\n"
  },
  {
    "path": "Project-Euler/Problem021.js",
    "content": "import { aliquotSum } from '../Maths/AliquotSum.js'\n\n/**\n * Problem 21 - Amicable numbers\n *\n * @see {@link https://projecteuler.net/problem=21}\n *\n * Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n).\n * If d(a) = b and d(b) = a, where a != b, then a and b are an amicable pair and each of a and b are called amicable numbers.\n * For example, the proper divisors of 220 are 1,2,4,5,10,11,20,22,44,55 and 110; therefore d(220) = 284.\n * The proper divisors of 284 are 1,2,4,71 and 142; so d(284) = 220.\n * Evaluate the sum of all amicable numbers under 10000\n *\n * @author PraneethJain\n */\n\nfunction problem21(n) {\n  if (n < 2) {\n    throw new Error('Invalid Input')\n  }\n\n  let result = 0\n  for (let a = 2; a < n; ++a) {\n    const b = aliquotSum(a) // Sum of all proper divisors of a\n    // Check if b > a to ensure each pair isn't counted twice, and check if sum of proper divisors of b is equal to a\n    if (b > a && aliquotSum(b) === a) {\n      result += a + b\n    }\n  }\n  return result\n}\n\nexport { problem21 }\n"
  },
  {
    "path": "Project-Euler/Problem023.js",
    "content": "/**\n * Problem 23 - Non-Abundant Sums\n *\n * @see {@link https://projecteuler.net/problem=23}\n *\n * A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.\n *\n * A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.\n *\n * As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.\n *\n * Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.\n *\n */\n\n/**\n * collect the abundant numbers, generate and store their sums with each other, and check for numbers not in the list of sums, adds them and returns their sum.\n * @param {number} [n = 28123]\n * @returns {number}\n */\n\nfunction sumOfNonAbundantNumbers(n = 28123) {\n  const abundantNumbers = [] // array to store the abundant numbers\n  const sumOfAbundantNumbers = {} // instead of an array, checking an object takes way less time. sets may be used as well.\n  let sum = 0\n\n  for (let i = 1; i <= n; i++) {\n    if (isAbundant(i)) {\n      abundantNumbers.push(i) // collect the abundant numbers\n      abundantNumbers.forEach((num) => {\n        // collect their sums\n        const sum = num + i\n        sumOfAbundantNumbers[sum] = true\n      })\n    }\n  }\n\n  for (let i = 1; i <= n; i++) {\n    if (!sumOfAbundantNumbers[i]) {\n      // if the number is not found in the list of sums, then it is added\n      sum += i\n    }\n  }\n\n  return sum\n}\n\n/**\n * generates the divisors of the number and checks if it is abundant\n * @param {number} number\n * @returns {bool}\n */\n\nfunction isAbundant(number) {\n  let sum = 0\n  for (let i = 1; i <= number / 2; i++) {\n    if (number % i === 0) {\n      // generate divisors\n      sum += i // calculate their sums\n    }\n  }\n  return sum > number\n}\n\nexport { sumOfNonAbundantNumbers }\n"
  },
  {
    "path": "Project-Euler/Problem025.js",
    "content": "/**\n* Problem 25 - 1000-digit Fibonacci number\n*\n* @see {@link https://projecteuler.net/problem=25}\n*\n* The Fibonacci sequence is defined by the recurrence relation:\n*\n* Fn = Fn−1 + Fn−2, where F1 = 1 and F2 = 1.\n*\n* Hence the first 12 terms will be:\n*\n* F1 = 1\n* F2 = 1\n* F3 = 2\n* F4 = 3\n* F5 = 5\n* F6 = 8\n* F7 = 13\n* F8 = 21\n* F9 = 34\n* F10 = 55\n* F11 = 89\n* F12 = 144\n* The 12th term, F12, is the first term to contain three digits.\n\n* What is the index of the first term in the Fibonacci sequence to contain 1000 digits?\n*/\n\n// brute force method\n\nfunction fibonacciIndex(t = 1000) {\n  const digits = 10n ** BigInt(t - 1)\n  let fib0 = BigInt(0)\n  let fib1 = BigInt(1)\n  let index = 1\n  while (fib1 < digits) {\n    // using this to compare number of digits instead of .toString() significantly improved run time\n    const tempfib = fib1\n    fib1 = fib1 + fib0\n    fib0 = tempfib\n    index += 1\n  }\n  return index\n}\n\nexport { fibonacciIndex }\n"
  },
  {
    "path": "Project-Euler/Problem028.js",
    "content": "/**\n * Problem 28 - Number spiral diagonals\n *\n * @see {@link https://projecteuler.net/problem=28}\n *\n * Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is formed as follows:\n *\n * 21 22 23 24 25\n * 20 07 08 09 10\n * 19 06 01 02 11\n * 18 05 04 03 12\n * 17 16 15 14 13\n *\n * It can be verified that the sum of the numbers on the diagonals is 101.\n * What is the sum of the numbers on the diagonals in a 1001 by 1001 spiral formed in the same way?\n *\n * @author ddaniel27\n */\n\nfunction problem28(dim) {\n  if (dim % 2 === 0) {\n    throw new Error('Dimension must be odd')\n  }\n  if (dim < 1) {\n    throw new Error('Dimension must be positive')\n  }\n\n  let result = 1\n  for (let i = 3; i <= dim; i += 2) {\n    /**\n     * Adding more dimensions to the matrix, we will find at the top-right corner the follow sequence:\n     * 01, 09, 25, 49, 81, 121, 169, ...\n     * So this can be expressed as:\n     * i^2, where i is all odd numbers\n     *\n     * Also, we can know which numbers are in each corner dimension\n     * Just develop the sequence counter clockwise from top-right corner like this:\n     * First corner: i^2\n     * Second corner: i^2 - (i - 1) | The \"i - 1\" is the distance between corners in each dimension\n     * Third corner: i^2 - 2 * (i - 1)\n     * Fourth corner: i^2 - 3 * (i - 1)\n     *\n     * Doing the sum of each corner and simplifying, we found that the result for each dimension is:\n     * sumDim = 4 * i^2 + 6 * (1 - i)\n     *\n     * In this case I skip the 1x1 dim matrix because is trivial, that's why I start in a 3x3 matrix\n     */\n    result += 4 * i * i + 6 * (1 - i) // Calculate sum of each dimension corner\n  }\n  return result\n}\n\nexport { problem28 }\n"
  },
  {
    "path": "Project-Euler/Problem035.js",
    "content": "/**\n * Problem 35 - Circular primes\n *\n * @see {@link https://projecteuler.net/problem=35}\n *\n * The number, 197, is called a circular prime because all rotations of the digits: 197, 971, and 719, are themselves prime.\n * There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, and 97.\n * How many circular primes are there below one million?\n *\n * @author ddaniel27\n */\nimport { sieveOfEratosthenes } from '../Maths/SieveOfEratosthenes'\n\nfunction problem35(n) {\n  if (n < 2) {\n    throw new Error('Invalid input')\n  }\n  // Get a list of primes without 0, 2, 4, 5, 6, 8; this discards the circular primes 2 & 5\n  const list = sieveOfEratosthenes(n).filter(\n    (prime) => !prime.toString().match(/[024568]/)\n  )\n\n  const result = list.filter((number, _idx, arr) => {\n    const str = String(number)\n    for (let i = 0; i < str.length; i++) {\n      // Get all rotations of the number\n      const rotation = str.slice(i) + str.slice(0, i)\n      if (!arr.includes(Number(rotation))) {\n        // Check if the rotation is prime\n        return false\n      }\n    }\n    return true // If all rotations are prime, then the number is circular prime\n  })\n\n  return result.length + 2 // Add 2 to the result because the circular primes 2 & 5 were discarded\n}\n\nexport { problem35 }\n"
  },
  {
    "path": "Project-Euler/Problem044.js",
    "content": "/**\n * Problem 44 - Pentagon numbers\n *\n * @see {@link https://projecteuler.net/problem=44}\n *\n * Pentagonal numbers are generated by the formula, Pn=n(3n−1)/2. The first ten pentagonal numbers are:\n * 1, 5, 12, 22, 35, 51, 70, 92, 117, 145, ...\n * It can be seen that P4 + P7 = 22 + 70 = 92 = P8. However, their difference, 70 − 22 = 48, is not pentagonal.\n * Find the pair of pentagonal numbers, Pj and Pk, for which their sum and difference are pentagonal and D = |Pk − Pj| is minimised; what is the value of D?\n *\n * @author ddaniel27\n */\n\nfunction problem44(k) {\n  if (k < 1) {\n    throw new Error('Invalid Input')\n  }\n\n  while (true) {\n    k++\n    const n = (k * (3 * k - 1)) / 2 // calculate Pk\n\n    for (let j = k - 1; j > 0; j--) {\n      const m = (j * (3 * j - 1)) / 2 // calculate all Pj < Pk\n      if (isPentagonal(n - m) && isPentagonal(n + m)) {\n        // Check sum and difference\n        return n - m // return D\n      }\n    }\n  }\n}\n\n/**\n * Function to check if a number is pentagonal or not\n * This function solves n\n * applying the solution for a quadratic function\n * @see {@link https://en.wikipedia.org/wiki/Quadratic_function}\n */\n\nfunction isPentagonal(n) {\n  const pent = (Math.sqrt(24 * n + 1) + 1) / 6\n  return pent === Math.floor(pent)\n}\n\nexport { problem44 }\n"
  },
  {
    "path": "Project-Euler/test/Problem001.test.js",
    "content": "import { multiplesThreeAndFive } from '../Problem001.js'\n\ndescribe('Sum of multiples of 3 or 5', () => {\n  it('should throw error when number is negative number', () => {\n    expect(() => multiplesThreeAndFive(-24)).toThrowError(\n      'No natural numbers exist below 1'\n    )\n  })\n  it('should throw error when number is 0', () => {\n    expect(() => multiplesThreeAndFive(0)).toThrowError(\n      'No natural numbers exist below 1'\n    )\n  })\n  test('if the number is greater than 0', () => {\n    expect(multiplesThreeAndFive(10)).toBe(23)\n  })\n  // Project Euler Condition Check\n  test('if the number is 1000', () => {\n    expect(multiplesThreeAndFive(1000)).toBe(233168)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem002.test.js",
    "content": "import { EvenFibonacci } from '../Problem002'\n\ndescribe('Even Fibonacci numbers', () => {\n  it('should throw error when limit is less than 1', () => {\n    expect(() => EvenFibonacci(-1)).toThrowError(\n      \"Fibonacci sequence limit can't be less than 1\"\n    )\n  })\n  test('when limit is greater than 0', () => {\n    expect(EvenFibonacci(40)).toBe(44)\n  })\n  // Project Euler Condition Check\n  test('when limit is 4 million', () => {\n    expect(EvenFibonacci(4e6)).toBe(4613732)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem003.test.js",
    "content": "import { largestPrime } from '../Problem003.js'\n\ndescribe('Largest prime factor', () => {\n  test('if the number is 13195', () => {\n    expect(largestPrime(13195)).toBe(29)\n  })\n  // Project Euler Condition Check\n  test('if the number is 600851475143', () => {\n    // Default value is same as the tested value\n    expect(largestPrime()).toBe(6857)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem004.test.js",
    "content": "import { largestPalindromic } from '../Problem004.js'\n\ndescribe('Largest Palindromic Number', () => {\n  test('if digit is 2', () => {\n    expect(largestPalindromic(2)).toBe(9009)\n  })\n  // Project Euler Condition Check\n  test('if digit is 3', () => {\n    expect(largestPalindromic(3)).toBe(906609)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem005.test.js",
    "content": "import { expect } from 'vitest'\nimport { findSmallestMultiple } from '../Problem005.js'\n\ndescribe.concurrent('Find smallest multiple', () => {\n  test.each([\n    [10, 2520],\n    [15, 360360],\n    [20, 232792560]\n  ])('max divisor -> %i, smallest multiple -> %i', (a, expected) => {\n    expect(findSmallestMultiple(a)).toBe(expected)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem006.test.js",
    "content": "import { squareDifference } from '../Problem006.js'\n\ndescribe('Square Difference', () => {\n  test('difference between the sum of the squares of the first ten natural numbers and the square of the sum', () => {\n    expect(squareDifference(10)).toBe(2640)\n  })\n  // Project Euler Condition Check\n  test('difference between the sum of the squares of the first one hundred natural numbers and the square of the sum', () => {\n    expect(squareDifference()).toBe(25164150)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem007.test.js",
    "content": "import { nthPrime } from '../Problem007.js'\n\ndescribe('checking nth prime number', () => {\n  it('should be invalid input if number is negative', () => {\n    expect(() => nthPrime(-3)).toThrowError('Invalid Input')\n  })\n  it('should be invalid input if number is 0', () => {\n    expect(() => nthPrime(0)).toThrowError('Invalid Input')\n  })\n  test('if the number is greater than 0', () => {\n    expect(nthPrime(10)).toBe(29)\n  })\n  // Project Euler Condition Check\n  test('if the number is 10001', () => {\n    expect(nthPrime(10001)).toBe(104743)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem008.test.js",
    "content": "import { largestAdjacentNumber } from '../Problem008'\n\nconst grid1 = `73167176531330624919225119674426574742355349194934\n96983520312774506326239578318016984801869478851843\n85861560789112949495459501737958331952853208805511\n12540698747158523863050715693290963295227443043557\n66896648950445244523161731856403098711121722383113\n38991007832084782777189757278819047278899274961949\n30358907296290491560440772390713810515859307960866\n70172427121883998797908792274921901699720888093776\n65727333001053367881220235421809751254540594752243\n82834772897718748193457134085784719857638187485919\n53697817977846174064955149290862569321978468622482\n83972241375657056057490261407972968652414535100474\n82166370484403199890008895243450658541227588666881\n83247832478757285710958372981577583275832789327921\n17866458359124566529476545682848912883142607690042\n24219022671055626321111109370544217506941658960408\n84327878357761783787589375857378271083787811983779\n84580156166097919133875499200524063689912560717606\n05886116467109405077541002256983155200055935729725\n82347875831098357801578571807585817518287829189189`\n\nconst grid2 = `73167176531330624919225119674426574742355349194934\n96983520312774506326239578318016984801869478851843\n85861560789112949495459501737958331952853208805511\n12540698747158523863050715693290963295227443043557\n66896648950445244523161731856403098711121722383113\n62229893423380308135336276614282806444486645238749\n30358907296290491560440772390713810515859307960866\n70172427121883998797908792274921901699720888093776\n65727333001053367881220235421809751254540594752243\n52584907711670556013604839586446706324415722155397\n53697817977846174064955149290862569321978468622482\n83972241375657056057490261407972968652414535100474\n82166370484403199890008895243450658541227588666881\n16427171479924442928230863465674813919123162824586\n17866458359124566529476545682848912883142607690042\n24219022671055626321111109370544217506941658960408\n07198403850962455444362981230987879927244284909188\n84580156166097919133875499200524063689912560717606\n05886116467109405077541002256983155200055935729725\n71636269561882670428252483600823257530420752963450`\n\nconst grid3 = `89125732138957892357892768971807934878999818278898\n48327483578957875827583295789187588875238579887789\n74358275778171870973857835738758275210873583758279\n81347834738473878758758373857893758787772897580719\n81232847857895758758987587501087575387538183787098\n17047878395783578750837100983787587582797837508298\n42894789325732857893759187987487489748377578791989\n82147328972387832578327581919827382758932789798289\n83243289473847328974832947832748932472387895738978\n84738294738973289578753287582375238957573297892398\n29383748329748397483274832748327477575018978975289\n48327483758375846372864736476478364783647463278787\n73281473847832974328758975890189373857875875895898\n74328978748329789357389578329758329758937893758979\n81738957389579287598217589127589375893275987359889\n71890743894732897510875895783297591085738975837897\n10783974839479879857895789758975981735870175835789\n01494787857897583758975849758475107589754897589789\n09939858758919788017587897587387585775289757982898\n74718478978758758975897589789789798789178957789789`\n\nconst grid4 = `99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999\n99999999999999999999999999999999999999999999999999`\n\ndescribe('checkLargestAdjacentNumberProduct', () => {\n  it('Random Example', () => {\n    const RESULT = largestAdjacentNumber(grid1, 13)\n    expect(RESULT).toBe(23514624000)\n  })\n  it('Problem statement Example', () => {\n    const RESULT = largestAdjacentNumber(grid2, 13)\n    expect(RESULT).toBe(23514624000)\n  })\n  it('Random Example 2', () => {\n    const RESULT = largestAdjacentNumber(grid3, 13)\n    expect(RESULT).toBe(580717154304)\n  })\n  it('Example with all 9', () => {\n    const RESULT = largestAdjacentNumber(grid4, 13)\n    expect(RESULT).toBe(2541865828329)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem009.test.js",
    "content": "import { findSpecialPythagoreanTriplet } from '../Problem009.js'\n\ndescribe('Pythagorean Triplet', () => {\n  // Project Euler Condition Check\n  test('the multiplication of the pythagorean triplet where a + b + c = 1000', () => {\n    expect(findSpecialPythagoreanTriplet()).toBe(31875000)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem010.test.js",
    "content": "import { calculateSumOfPrimeNumbers } from '../Problem010'\n\ndescribe('checkAnagram', () => {\n  it('Return the sum of prime numbers up to but less than 14', () => {\n    const SUT = calculateSumOfPrimeNumbers(14)\n    expect(SUT).toBe(41)\n  })\n  it('Return the sum of prime numbers up to but less than 10', () => {\n    const SUT = calculateSumOfPrimeNumbers(10)\n    expect(SUT).toBe(17)\n  })\n  it('Return the sum of prime numbers up to but less than 100', () => {\n    const SUT = calculateSumOfPrimeNumbers(100)\n    expect(SUT).toBe(1060)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem011.test.js",
    "content": "import { largestProductInAGrid } from '../Problem011.js'\n\nconst arr = [\n  [8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 50, 77, 91, 8],\n  [\n    49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 4, 56, 62, 0\n  ],\n  [\n    81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 3, 49, 13, 36,\n    65\n  ],\n  [52, 70, 95, 23, 4, 60, 11, 42, 69, 24, 68, 56, 1, 32, 56, 71, 37, 2, 36, 91],\n  [\n    22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33, 13,\n    80\n  ],\n  [\n    24, 47, 32, 60, 99, 3, 45, 2, 44, 75, 33, 53, 78, 36, 84, 20, 35, 17, 12, 50\n  ],\n  [\n    32, 98, 81, 28, 64, 23, 67, 10, 26, 38, 40, 67, 59, 54, 70, 66, 18, 38, 64,\n    70\n  ],\n  [\n    67, 26, 20, 68, 2, 62, 12, 20, 95, 63, 94, 39, 63, 8, 40, 91, 66, 49, 94, 21\n  ],\n  [\n    24, 55, 58, 5, 66, 73, 99, 26, 97, 17, 78, 78, 96, 83, 14, 88, 34, 89, 63,\n    72\n  ],\n  [21, 36, 23, 9, 75, 0, 76, 44, 20, 45, 35, 14, 0, 61, 33, 97, 34, 31, 33, 95],\n  [78, 17, 53, 28, 22, 75, 31, 67, 15, 94, 3, 80, 4, 62, 16, 14, 9, 53, 56, 92],\n  [\n    16, 39, 5, 42, 96, 35, 31, 47, 55, 58, 88, 24, 0, 17, 54, 24, 36, 29, 85, 57\n  ],\n  [86, 56, 0, 48, 35, 71, 89, 7, 5, 44, 44, 37, 44, 60, 21, 58, 51, 54, 17, 58],\n  [\n    19, 80, 81, 68, 5, 94, 47, 69, 28, 73, 92, 13, 86, 52, 17, 77, 4, 89, 55, 40\n  ],\n  [4, 52, 8, 83, 97, 35, 99, 16, 7, 97, 57, 32, 16, 26, 26, 79, 33, 27, 98, 66],\n  [\n    88, 36, 68, 87, 57, 62, 20, 72, 3, 46, 33, 67, 46, 55, 12, 32, 63, 93, 53,\n    69\n  ],\n  [\n    4, 42, 16, 73, 38, 25, 39, 11, 24, 94, 72, 18, 8, 46, 29, 32, 40, 62, 76, 36\n  ],\n  [\n    20, 69, 36, 41, 72, 30, 23, 88, 34, 62, 99, 69, 82, 67, 59, 85, 74, 4, 36,\n    16\n  ],\n  [\n    20, 73, 35, 29, 78, 31, 90, 1, 74, 31, 49, 71, 48, 86, 81, 16, 23, 57, 5, 54\n  ],\n  [1, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 1, 89, 19, 67, 48]\n]\n\ndescribe('Checking Largest Product In A Grid', () => {\n  // Project Euler Condition Check\n  test('Test Euler Condition', () => {\n    expect(largestProductInAGrid(arr)).toBe(70600674)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem012.test.js",
    "content": "import { firstTriangularWith500Divisors } from '../Problem012'\n\ndescribe('checkFirstTriangularWith500Divisors()', () => {\n  it('Problem Statement Answer', () => {\n    const firstTriangular = firstTriangularWith500Divisors()\n    expect(firstTriangular).toBe(76576500)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem013.test.js",
    "content": "import { largeSum } from '../Problem013.js'\n\nconst bignum =\n  '37107287533902102798797998220837590246510135740250463769376774900097126481248969700780504170182605387432498619952474105947423330951305812372661730962991942213363574161572522430563301811072406154908250230675882075393461711719803104210475137780632466768926167069662363382013637841838368417873436172675728112879812849979408065481931592621691275889832738442742289174325203219235894228767964876702721893184745144573600130643909116721685684458871160315327670386486105843025439939619828917593665686757934951621764571418565606295021572231965867550793241933316490635246274190492910143244581382266334794475817892575867718337217661963751590579239728245598838407582035653253593990084026335689488301894586282278288018119938482628201427819413994056758715117009439035398664372827112653829987240784473053190104293586865155060062958648615320752733719591914205172558297169388870771546649911559348760353292171497005693854370070576826684624621495650076471787294438377604532826541087568284431911906346940378552177792951453612327252500029607107508256381565671088525835072145876576172410976447339110607218265236877223636045174237069058518606604482076212098132878607339694128114266041808683061932846081119106155694051268969251934325451728388641918047049293215058642563049483624672216484350762017279180399446930047329563406911573244438690812579451408905770622942919710792820955037687525678773091862540744969844508330393682126183363848253301546861961243487676812975343759465158038628759287849020152168555482871720121925776695478182833757993103614740356856449095527097864797581167263201004368978425535399209318374414978068609844840309812907779179908821879532736447567559084803087086987551392711854517078544161852424320693150332599594068957565367821070749269665376763262354472106979395067965269474259770973916669376304263398708541052684708299085211399427365734116182760315001271653786073615010808570091499395125570281987460043753582903531743471732693212357815498262974255273730794953759765105305946966067683156574377167401875275889028025717332296191766687138199318110487701902712526768027607800301367868099252546340106163286652636270218540497705585629946580636237993140746255962240744869082311749777923654662572469233228109171419143028819710328859780666976089293863828502533340334413065578016127815921815005561868836468420090470230530811728164304876237919698424872550366387845831148769693215490281042402013833512446218144177347063783299490636259666498587618221225225512486764533677201869716985443124195724099139590089523100588229554825530026352078153229679624948164195386821877476085327132285723110424803456124867697064507995236377742425354112916842768655389262050249103265729672370191327572567528565324825826546309220705859652229798860272258331913126375147341994889534765745501184957014548792889848568277260777137214037988797153829820378303147352772158034814451349137322665138134829543829199918180278916522431027392251122869539409579530664052326325380441000596549391598795936352974615218550237130764225512118369380358038858490341698116222072977186158236678424689157993532961922624679571944012690438771072750481023908955235974572318970677254791506150550495392297953090112996751986188088225875314529584099251203829009407770775672113067397083047244838165338735023408456470580773088295917476714036319800818712901187549131054712658197623331044818386269515456334926366572897563400500428462801835170705278318394258821455212272512503275512160354698120058176216521282765275169129689778932238195734329339946437501907836945765883352399886755061649651847751807381688378610915273579297013376217784275219262340194239963916804498399317331273132924185707147349566916674687634660915035914677504995186714302352196288948901024233251169136196266227326746080059154747183079839286853520694694454072476841822524674417161514036427982273348055556214818971426179103425986472045168939894221798260880768528778364618279934631376775430780936333301898264209010848802521674670883215120185883543223812876952786713296124747824645386369930090493103636197638780396218407357239979422340623539380833965132740801111666627891981488087797941876876144230030984490851411606618262936828367647447792391803351109890697907148578694408955299065364044742557608365997664579509666024396409905389607120198219976047599490197230297649139826800329731560371200413779037855660850892521673093931987275027546890690370753941304265231501194809377245048795150954100921645863754710598436791786391670211874924319957006419179697775990283006991536871371193661495281130587638027841075444973307840789923115535562561142322423255033685442488917353448899115014406480203690680639606723221932041495354150312888033953605329934036800697771065056663195481234880673210146739058568557934581403627822703280826165707739483275922328459417065250945123252306082291880205877731971983945018088807242966198081119777158542502016545090413245809786882778948721859617721078384350691861554356628840622574736922845095162084960398013400172393067166682355524525280460972253503534226472524250874054075591789781264330331690'\n\ndescribe('checking Large Sum', () => {\n  // Project Euler Condition Check\n  test('Test Euler Condition', () => {\n    expect(largeSum(bignum)).toBe('5537376230')\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem014.test.js",
    "content": "import { expect } from 'vitest'\nimport { findLongestCollatzSequence } from '../Problem014.js'\n\ndescribe('Longest Collatz Sequence', () => {\n  test.each([\n    [2, 1],\n    [13, 9],\n    [1000000, 837799]\n  ])(\n    'if limit is %i, then the Longest Collatz Sequence will be %i',\n    (a, expected) => {\n      expect(findLongestCollatzSequence(a)).toBe(expected)\n    }\n  )\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem016.test.js",
    "content": "import { powerDigitSum } from '../Problem016'\n\ndescribe('Check Problem 16 - Power digit sum', () => {\n  it('Power digit sum of 2^15', () => {\n    expect(powerDigitSum(2, 15)).toBe(26)\n  })\n\n  it('Power digit sum of 2^1000', () => {\n    expect(powerDigitSum()).toBe(1366)\n    expect(powerDigitSum(2, 1000)).toBe(1366)\n  })\n\n  it('Power digit sum of 3^5000', () => {\n    expect(powerDigitSum(3, 5000)).toBe(11097)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem017.test.js",
    "content": "import { countNumberWordLength } from '../Problem017.js'\n\ndescribe('Number letter count', () => {\n  test.each([\n    [5, 19],\n    [100, 864],\n    [1000, 21124]\n  ])('Number letter count from 1 to %i', (n, expected) => {\n    expect(countNumberWordLength(n)).toBe(expected)\n  })\n\n  test.each([\n    ['test', 'Invalid input, please provide valid number'],\n    [0, 'Please provide number greater that 1']\n  ])('Should throw an error for input %i', (n, expected) => {\n    expect(() => countNumberWordLength(n)).toThrowError(expected)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem018.test.js",
    "content": "import { maxPathSum } from '../Problem018'\n\nconst example = `\n3\n7 4\n2 4 6\n8 5 9 3\n`\n\ndescribe('Check Problem 18 - Maximum path sum I', () => {\n  it('Check example', () => {\n    expect(maxPathSum(example)).toBe(23)\n  })\n\n  it('Check solution', () => {\n    expect(maxPathSum()).toBe(1074)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem019.test.js",
    "content": "import { problem19 } from '../Problem019.js'\n\ndescribe('checking sundays during the twentieth century', () => {\n  // Project Euler Challenge Check\n  test('result should be 171', () => {\n    expect(problem19()).toBe(171)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem020.test.js",
    "content": "import { factorialDigitSum } from '../Problem020'\n\ndescribe('Check Problem 20 - Factorial digit sum', () => {\n  it('Factorial digit sum of 10!', () => {\n    expect(factorialDigitSum(10)).toBe(27)\n  })\n\n  it('Factorial digit sum of 100!', () => {\n    expect(factorialDigitSum()).toBe(648)\n    expect(factorialDigitSum(100)).toBe(648)\n  })\n\n  it('Factorial digit sum of 1000!', () => {\n    expect(factorialDigitSum(1000)).toBe(10539)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem021.test.js",
    "content": "import { problem21 } from '../Problem021.js'\n\ndescribe('check sum of amicable numbers under n', () => {\n  test('should be invalid input if number is negative', () => {\n    expect(() => problem21(-1)).toThrowError('Invalid Input')\n  })\n  test('should be invalid input if number is 0', () => {\n    expect(() => problem21(0)).toThrowError('Invalid Input')\n  })\n  // Project Euler Condition Check\n  test('if the number is greater or equal to 1', () => {\n    expect(problem21(10000)).toBe(31626)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem023.test.js",
    "content": "import { sumOfNonAbundantNumbers } from '../Problem023'\n\ndescribe('Check Problem 23 - Non-Abundant Sums', () => {\n  it('Sum of all positive integers <= 10000 which cannot be written as the sum of two abundant numbers', () => {\n    expect(sumOfNonAbundantNumbers(10000)).toBe(3731004)\n  })\n\n  it('Sum of all positive integers <= n which cannot be written as the sum of two abundant numbers', () => {\n    expect(sumOfNonAbundantNumbers(15000)).toBe(4039939)\n  })\n\n  it('Sum of all positive integers <= n which cannot be written as the sum of two abundant numbers', () => {\n    expect(sumOfNonAbundantNumbers(20000)).toBe(4159710)\n  })\n\n  it('Sum of all positive integers <= n which cannot be written as the sum of two abundant numbers', () => {\n    expect(sumOfNonAbundantNumbers(28123)).toBe(4179871)\n  })\n\n  it('Sum of all positive integers <= n which cannot be written as the sum of two abundant numbers', () => {\n    expect(sumOfNonAbundantNumbers(30000)).toBe(4179871)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem025.test.js",
    "content": "import { fibonacciIndex } from '../Problem025'\n\ndescribe('Check Problem 25 - 1000 digit Fibonnaci number', () => {\n  it('First term of the Fibonnaci sequence containing 3 digits', () => {\n    expect(fibonacciIndex(3)).toBe(12)\n  })\n\n  it('First term of the Fibonnaci sequence containing 10 digits', () => {\n    expect(fibonacciIndex(10)).toBe(45)\n  })\n\n  it('First term of the Fibonnaci sequence containing 50 digits', () => {\n    expect(fibonacciIndex(50)).toBe(237)\n  })\n\n  it('First term of the Fibonnaci sequence containing 100 digits', () => {\n    expect(fibonacciIndex(100)).toBe(476)\n  })\n\n  it('First term of the Fibonnaci sequence containing 1000 digits', () => {\n    expect(fibonacciIndex(1000)).toBe(4782)\n  })\n\n  it('First term of the Fibonnaci sequence containing 10000 digits', () => {\n    expect(fibonacciIndex(10000)).toBe(47847)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem028.test.js",
    "content": "import { problem28 } from '../Problem028.js'\n\ndescribe('checking number spiral diagonals', () => {\n  it('should be invalid input if number is negative', () => {\n    expect(() => problem28(-3)).toThrowError('Dimension must be positive')\n  })\n  it('should be invalid input if number is not odd', () => {\n    expect(() => problem28(4)).toThrowError('Dimension must be odd')\n  })\n  test('if the number is equal to 5 result should be 101', () => {\n    expect(problem28(5)).toBe(101)\n  })\n  // Project Euler Condition Check\n  test('if the number is equal to 1001 result should be 669171001', () => {\n    expect(problem28(1001)).toBe(669171001)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem035.test.js",
    "content": "import { problem35 } from '../Problem035.js'\n\ndescribe('checking circular primes', () => {\n  it('should be invalid input if number is negative', () => {\n    expect(() => problem35(-3)).toThrowError('Invalid input')\n  })\n  it('should be invalid input if number is 0', () => {\n    expect(() => problem35(0)).toThrowError('Invalid input')\n  })\n  // Project Euler Condition Check\n  test('if the number is equal to 100 result should be 13', () => {\n    expect(problem35(100)).toBe(13)\n  })\n  // Project Euler Challenge Check\n  test('if the number is equal to one million result should be 55', () => {\n    expect(problem35(1000000)).toBe(55)\n  })\n})\n"
  },
  {
    "path": "Project-Euler/test/Problem044.test.js",
    "content": "import { problem44 } from '../Problem044.js'\n\ndescribe('checking nth prime number', () => {\n  test('should be invalid input if number is negative', () => {\n    expect(() => problem44(-3)).toThrowError('Invalid Input')\n  })\n  test('should be invalid input if number is 0', () => {\n    expect(() => problem44(0)).toThrowError('Invalid Input')\n  })\n  // Project Euler Condition Check\n  test('if the number is greater or equal to 1', () => {\n    expect(problem44(1)).toBe(5482660)\n  })\n  // Project Euler Second Value for Condition Check\n  test('if the number is greater or equal to 2167', () => {\n    expect(problem44(2167)).toBe(8476206790)\n  })\n})\n"
  },
  {
    "path": "README.md",
    "content": "# The Algorithms - JavaScript\n\n<!-- Front Matter -->\n\nJavaScript Repository of TheAlgorithms, which implements various algorithms and data structures in JavaScript.\n\n<div align=\"center\">\n\n[![JavaScript Banner][banner]](DIRECTORY.md)\n\n[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/TheAlgorithms/JavaScript)\n[![Checks][checks]][actions]\n[![codecov](https://codecov.io/gh/TheAlgorithms/JavaScript/graph/badge.svg?token=8VeZwL31KZ)](https://codecov.io/gh/TheAlgorithms/JavaScript)\n[![Contributions Welcome][welcome]](CONTRIBUTING.md)\n[![standard.js][standard-logo]][standard-js]\n[![Discord chat][chat]][discord-server]\n\n</div>\n\n---\n\n<!-- Disclaimer -->\n\n<h4 align=\"center\">\n  These implementations are for demonstrative purposes only. Dedicated implementations of these algorithms and data\n  structures are much better for performance and security reasons. We also do not provide any guarantee for api stability.\n</h4>\n\n---\n\n<!-- Body -->\n\nBefore contributing to this repository, make sure to read our [Contribution Guidelines](CONTRIBUTING.md). You can look\nat other [TheAlgorithms Repositories][repositories] or the [issues with a \"help wanted\" label][help-wanted] for\ninspiration regarding what to implement. Our maintainers will guide you through how to make your contribution properly\nif you make any mistakes. The names of the maintainers of this repository are listed in the\n[CODEOWNERS file](.github/CODEOWNERS).\n\nYou can find a list of the algorithms currently in the repository in the [directory](DIRECTORY.md). Explanations of\nmany of the algorithms can be found in the [wiki][explanation].\n\n---\n\n<!-- Banner Image -->\n\n[banner]: https://user-images.githubusercontent.com/68542775/167072911-dc31eac8-6885-4a05-9c25-279ecce22a79.png\n\n<!-- Badge Links -->\n\n[standard-logo]: https://img.shields.io/badge/code%20style-standardjs-%23f3df49\n[chat]: https://img.shields.io/discord/808045925556682782.svg?logo=discord&colorB=7289DA\n[welcome]: https://img.shields.io/static/v1.svg?label=Contributions&message=Welcome&color=0059b3\n[checks]: https://img.shields.io/github/actions/workflow/status/TheAlgorithms/JavaScript/Ci.yml?branch=master&label=checks\n\n<!-- External Links -->\n\n[standard-js]: https://standardjs.com/\n[discord-server]: https://the-algorithms.com/discord/\n[actions]: https://github.com/TheAlgorithms/JavaScript/actions\n[explanation]: https://github.com/TheAlgorithms/JavaScript/wiki\n[repositories]: https://github.com/orgs/TheAlgorithms/repositories\n[help-wanted]: https://github.com/TheAlgorithms/JavaScript/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22\n\n## Thanks to all the contributors ❤️\n\n<a href = \"https://github.com/TheAlgorithms/JavaScript/graphs/contributors\">\n  <img src = \"https://contrib.rocks/image?repo=TheAlgorithms/JavaScript\"/>\n</a>\n"
  },
  {
    "path": "Recursive/BinaryEquivalent.js",
    "content": "/*\n * Problem Statement: Given a positive number `num`, find it's binary equivalent using recursion\n *\n * What is Binary Equivalent?\n * - In binary number system, a number is represented in terms of 0s and 1s,\n *   for example:\n *    - Binary Of 2 = 10\n *    - Binary of 3 = 11\n *    - Binary of 4 = 100\n *\n * Reference on how to find Binary Equivalent\n * - https://byjus.com/maths/decimal-to-binary/\n *\n */\n\nexport const binaryEquivalent = (num) => {\n  if (num === 0 || num === 1) {\n    return String(num)\n  }\n  return binaryEquivalent(Math.floor(num / 2)) + String(num % 2)\n}\n"
  },
  {
    "path": "Recursive/BinarySearch.js",
    "content": "/**\n * @function BinarySearch\n * @description Search the integer inside the sorted integers array using Binary Search Algorithm.\n * @param {Integer[]} arr - sorted array of integers\n * @param {Integer} low - The input integer\n * @param {Integer} high - The input integer\n * @param {Integer} searchValue - The input integer\n * @return {Integer} - return index of searchValue if found else return -1.\n * @see [BinarySearch](https://en.wikipedia.org/wiki/Binary_search_algorithm)\n */\n\nconst binarySearch = (arr, searchValue, low = 0, high = arr.length - 1) => {\n  // base case\n  if (high < low || arr.length === 0) return -1\n\n  const mid = low + Math.floor((high - low) / 2)\n\n  // If the element is present at the middle\n  if (arr[mid] === searchValue) {\n    return mid\n  }\n\n  // If element is smaller than mid, then\n  // it can only be present in left subarray\n  if (arr[mid] > searchValue) {\n    return binarySearch(arr, searchValue, low, mid - 1)\n  }\n\n  // Else the element can only be present in right subarray\n  return binarySearch(arr, searchValue, mid + 1, high)\n}\n\nexport { binarySearch }\n"
  },
  {
    "path": "Recursive/Factorial.js",
    "content": "/**\n * @function Factorial\n * @description function to find factorial using recursion.\n * @param {Integer} n - The input integer\n * @return {Integer} - Factorial of n.\n * @see [Factorial](https://en.wikipedia.org/wiki/Factorial)\n * @example 5! = 1*2*3*4*5 = 120\n * @example 2! = 1*2 = 2\n */\n\nconst factorial = (n) => {\n  if (!Number.isInteger(n) || n < 0) {\n    throw new RangeError('Input should be a non-negative whole number')\n  }\n\n  if (n === 0) {\n    return 1\n  }\n\n  return n * factorial(n - 1)\n}\n\nexport { factorial }\n"
  },
  {
    "path": "Recursive/FibonacciNumberRecursive.js",
    "content": "/**\n * @function Fibonacci\n * @description Function to return the N-th Fibonacci number.\n * @param {Integer} n - The input integer\n * @return {Integer} - Return the N-th Fibonacci number\n * @see [Fibonacci](https://en.wikipedia.org/wiki/Fibonacci_number)\n */\n\nconst fibonacci = (n) => {\n  if (n < 2) {\n    return n\n  }\n  return fibonacci(n - 2) + fibonacci(n - 1)\n}\n\nexport { fibonacci }\n"
  },
  {
    "path": "Recursive/FloodFill.js",
    "content": "/**\n * Flood fill.\n *\n * Flood fill, also called seed fill, is an algorithm that determines and alters the area connected to a given node in a\n * multi-dimensional array with some matching attribute. It is used in the \"bucket\" fill tool of paint programs to fill\n * connected, similarly-colored areas with a different color.\n *\n * (description adapted from https://en.wikipedia.org/wiki/Flood_fill)\n * @see https://www.techiedelight.com/flood-fill-algorithm/\n */\n\nconst neighborOffsets = [\n  [-1, -1],\n  [-1, 0],\n  [-1, 1],\n  [0, -1],\n  [0, 1],\n  [1, -1],\n  [1, 0],\n  [1, 1]\n]\n\nfunction isInside(rgbData, location) {\n  const x = location[0]\n  const y = location[1]\n  return x >= 0 && x < rgbData.length && y >= 0 && y < rgbData[0].length\n}\n\nfunction checkLocation(rgbData, location) {\n  if (!isInside(rgbData, location)) {\n    throw new Error('location should point to a pixel within the rgbData')\n  }\n}\n\nfunction* neighbors(rgbData, location) {\n  for (const offset of neighborOffsets) {\n    const neighborLocation = [location[0] + offset[0], location[1] + offset[1]]\n    if (isInside(rgbData, neighborLocation)) {\n      yield neighborLocation\n    }\n  }\n}\n\n/**\n * Implements the flood fill algorithm through a breadth-first approach using a queue.\n *\n * @param rgbData The image to which the algorithm is applied.\n * @param location The start location on the image.\n * @param targetColor The old color to be replaced.\n * @param replacementColor The new color to replace the old one.\n */\nexport function breadthFirstSearch(\n  rgbData,\n  location,\n  targetColor,\n  replacementColor\n) {\n  checkLocation(rgbData, location)\n\n  const queue = []\n  queue.push(location)\n\n  while (queue.length > 0) {\n    breadthFirstFill(rgbData, location, targetColor, replacementColor, queue)\n  }\n}\n\n/**\n * Implements the flood fill algorithm through a depth-first approach using recursion.\n *\n * @param rgbData The image to which the algorithm is applied.\n * @param location The start location on the image.\n * @param targetColor The old color to be replaced.\n * @param replacementColor The new color to replace the old one.\n */\nexport function depthFirstSearch(\n  rgbData,\n  location,\n  targetColor,\n  replacementColor\n) {\n  checkLocation(rgbData, location)\n\n  depthFirstFill(rgbData, location, targetColor, replacementColor)\n}\n\n/**\n * Utility-function to implement the breadth-first loop.\n *\n * @param rgbData The image to which the algorithm is applied.\n * @param location The start location on the image.\n * @param targetColor The old color to be replaced.\n * @param replacementColor The new color to replace the old one.\n * @param queue The locations that still need to be visited.\n */\nfunction breadthFirstFill(\n  rgbData,\n  location,\n  targetColor,\n  replacementColor,\n  queue\n) {\n  const currentLocation = queue[0]\n  queue.shift()\n\n  if (rgbData[currentLocation[0]][currentLocation[1]] === targetColor) {\n    rgbData[currentLocation[0]][currentLocation[1]] = replacementColor\n    for (const neighborLocation of neighbors(rgbData, currentLocation)) {\n      queue.push(neighborLocation)\n    }\n  }\n}\n\n/**\n * Utility-function to implement the depth-first loop.\n *\n * @param rgbData The image to which the algorithm is applied.\n * @param location The start location on the image.\n * @param targetColor The old color to be replaced.\n * @param replacementColor The new color to replace the old one.\n */\nfunction depthFirstFill(rgbData, location, targetColor, replacementColor) {\n  if (rgbData[location[0]][location[1]] === targetColor) {\n    rgbData[location[0]][location[1]] = replacementColor\n    for (const neighborLocation of neighbors(rgbData, location)) {\n      depthFirstFill(rgbData, neighborLocation, targetColor, replacementColor)\n    }\n  }\n}\n"
  },
  {
    "path": "Recursive/KochSnowflake.js",
    "content": "/**\n * The Koch snowflake is a fractal curve and one of the earliest fractals to have been described.\n *\n * The Koch snowflake can be built up iteratively, in a sequence of stages. The first stage is an equilateral triangle,\n * and each successive stage is formed by adding outward bends to each side of the previous stage, making smaller\n * equilateral triangles. This can be achieved through the following steps for each line:\n * 1. divide the line segment into three segments of equal length.\n * 2. draw an equilateral triangle that has the middle segment from step 1 as its base and points outward.\n * 3. remove the line segment that is the base of the triangle from step 2.\n *\n * (description adapted from https://en.wikipedia.org/wiki/Koch_snowflake)\n * (for a more detailed explanation and an implementation in the Processing language, see\n * https://natureofcode.com/book/chapter-8-fractals/ #84-the-koch-curve-and-the-arraylist-technique).\n */\n\n/** Class to handle the vector calculations. */\nexport class Vector2 {\n  constructor(x, y) {\n    this.x = x\n    this.y = y\n  }\n\n  /**\n   * Vector addition\n   *\n   * @param vector The vector to be added.\n   * @returns The sum-vector.\n   */\n  add(vector) {\n    const x = this.x + vector.x\n    const y = this.y + vector.y\n    return new Vector2(x, y)\n  }\n\n  /**\n   * Vector subtraction\n   *\n   * @param vector The vector to be subtracted.\n   * @returns The difference-vector.\n   */\n  subtract(vector) {\n    const x = this.x - vector.x\n    const y = this.y - vector.y\n    return new Vector2(x, y)\n  }\n\n  /**\n   * Vector scalar multiplication\n   *\n   * @param scalar The factor by which to multiply the vector.\n   * @returns The scaled vector.\n   */\n  multiply(scalar) {\n    const x = this.x * scalar\n    const y = this.y * scalar\n    return new Vector2(x, y)\n  }\n\n  /**\n   * Vector rotation (see https://en.wikipedia.org/wiki/Rotation_matrix)\n   *\n   * @param angleInDegrees The angle by which to rotate the vector.\n   * @returns The rotated vector.\n   */\n  rotate(angleInDegrees) {\n    const radians = (angleInDegrees * Math.PI) / 180\n    const ca = Math.cos(radians)\n    const sa = Math.sin(radians)\n    const x = ca * this.x - sa * this.y\n    const y = sa * this.x + ca * this.y\n    return new Vector2(x, y)\n  }\n}\n\n/**\n * Go through the number of iterations determined by the argument \"steps\".\n *\n * Be careful with high values (above 5) since the time to calculate increases exponentially.\n *\n * @param initialVectors The vectors composing the shape to which the algorithm is applied.\n * @param steps The number of iterations.\n * @returns The transformed vectors after the iteration-steps.\n */\nexport function iterate(initialVectors, steps) {\n  let vectors = initialVectors\n  for (let i = 0; i < steps; i++) {\n    vectors = iterationStep(vectors)\n  }\n\n  return vectors\n}\n\n/**\n * Loops through each pair of adjacent vectors.\n *\n * Each line between two adjacent vectors is divided into 4 segments by adding 3 additional vectors in-between the\n * original two vectors. The vector in the middle is constructed through a 60 degree rotation so it is bent outwards.\n *\n * @param vectors The vectors composing the shape to which the algorithm is applied.\n * @returns The transformed vectors after the iteration-step.\n */\nfunction iterationStep(vectors) {\n  const newVectors = []\n  for (let i = 0; i < vectors.length - 1; i++) {\n    const startVector = vectors[i]\n    const endVector = vectors[i + 1]\n    newVectors.push(startVector)\n    const differenceVector = endVector.subtract(startVector).multiply(1 / 3)\n    newVectors.push(startVector.add(differenceVector))\n    newVectors.push(\n      startVector.add(differenceVector).add(differenceVector.rotate(60))\n    )\n    newVectors.push(startVector.add(differenceVector.multiply(2)))\n  }\n\n  newVectors.push(vectors[vectors.length - 1])\n  return newVectors\n}\n"
  },
  {
    "path": "Recursive/KochSnowflake.manual-test.js",
    "content": "import { Vector2, iterate } from './KochSnowflake'\n\n/**\n * Method to render the Koch snowflake to a canvas.\n *\n * @param canvasWidth The width of the canvas.\n * @param steps The number of iterations.\n * @returns The canvas of the rendered Koch snowflake.\n */\nfunction getKochSnowflake(canvasWidth = 600, steps = 5) {\n  if (canvasWidth <= 0) {\n    throw new Error('canvasWidth should be greater than zero')\n  }\n\n  const offsetX = canvasWidth / 10.0\n  const offsetY = canvasWidth / 3.7\n  const vector1 = new Vector2(offsetX, offsetY)\n  const vector2 = new Vector2(\n    canvasWidth / 2,\n    Math.sin(Math.PI / 3) * canvasWidth * 0.8 + offsetY\n  )\n  const vector3 = new Vector2(canvasWidth - offsetX, offsetY)\n  const initialVectors = []\n  initialVectors.push(vector1)\n  initialVectors.push(vector2)\n  initialVectors.push(vector3)\n  initialVectors.push(vector1)\n  const vectors = iterate(initialVectors, steps)\n  return drawToCanvas(vectors, canvasWidth, canvasWidth)\n}\n\n/**\n * Utility-method to render the Koch snowflake to a canvas.\n *\n * @param vectors The vectors defining the edges to be rendered.\n * @param canvasWidth The width of the canvas.\n * @param canvasHeight The height of the canvas.\n * @returns The canvas of the rendered edges.\n */\nfunction drawToCanvas(vectors, canvasWidth, canvasHeight) {\n  const canvas = document.createElement('canvas')\n  canvas.width = canvasWidth\n  canvas.height = canvasHeight\n\n  // Draw the edges\n  const ctx = canvas.getContext('2d')\n  ctx.beginPath()\n  ctx.moveTo(vectors[0].x, vectors[0].y)\n  for (let i = 1; i < vectors.length; i++) {\n    ctx.lineTo(vectors[i].x, vectors[i].y)\n  }\n  ctx.stroke()\n\n  return canvas\n}\n\n// plot the results if the script is executed in a browser with a window-object\nif (typeof window !== 'undefined') {\n  const canvas = getKochSnowflake()\n  document.body.append(canvas)\n}\n"
  },
  {
    "path": "Recursive/LetterCombination.js",
    "content": "/*\n *\n *  Letter Combinations of a Phone Number\n *\n *  Given a string containing digits from 2-9 inclusive,\n *  return all possible letter combinations that the number could represent.\n *  Return the answer in any order.\n\n *  A mapping of digits to letters (just like on the telephone buttons) is given below.\n *  Note that 1 does not map to any letters.\n *  More info: https://leetcode.com/problems/letter-combinations-of-a-phone-number/\n */\n\n/*\n * @param {string} digits\n * @returns {string[]} all the possible combinations\n */\n\nconst letterCombinations = (digits) => {\n  const length = digits?.length\n  const result = []\n  if (!length) {\n    return result\n  }\n  const digitMap = {\n    2: 'abc',\n    3: 'def',\n    4: 'ghi',\n    5: 'jkl',\n    6: 'mno',\n    7: 'pqrs',\n    8: 'tuv',\n    9: 'wxyz'\n  }\n\n  const combinations = (index, combination) => {\n    let letter\n    let letterIndex\n    if (index >= length) {\n      result.push(combination)\n      return\n    }\n    const digit = digitMap[digits[index]]\n    letterIndex = 0\n    while ((letter = digit[letterIndex++])) {\n      combinations(index + 1, combination + letter)\n    }\n  }\n  combinations(0, '')\n  return result\n}\n\nexport { letterCombinations }\n"
  },
  {
    "path": "Recursive/Palindrome.js",
    "content": "/**\n * @function Palindrome\n * @description Check whether the given string is Palindrome or not.\n * @param {String} str - The input string\n * @return {Boolean}.\n * @see [Palindrome](https://en.wikipedia.org/wiki/Palindrome)\n */\n\nconst palindrome = (str) => {\n  if (typeof str !== 'string') {\n    throw new TypeError('Invalid Input')\n  }\n\n  if (str.length <= 1) {\n    return true\n  }\n\n  if (str[0] !== str[str.length - 1]) {\n    return false\n  } else {\n    return palindrome(str.slice(1, str.length - 1))\n  }\n}\n\nexport { palindrome }\n"
  },
  {
    "path": "Recursive/PalindromePartitioning.js",
    "content": "import { palindrome } from './Palindrome'\n\n/*\n * Given a string s, return all possible palindrome partitionings of s.\n * A palindrome partitioning partitions a string into palindromic substrings.\n * @see https://www.cs.columbia.edu/~sedwards/classes/2021/4995-fall/proposals/Palindrome.pdf\n */\nconst partitionPalindrome = (s) => {\n  const result = []\n  backtrack(s, [], result)\n  return result\n}\n\nconst backtrack = (s, path, result) => {\n  if (s.length === 0) {\n    result.push([...path])\n    return\n  }\n\n  for (let i = 0; i < s.length; i++) {\n    const prefix = s.substring(0, i + 1)\n    if (palindrome(prefix)) {\n      path.push(prefix)\n      backtrack(s.substring(i + 1), path, result)\n      path.pop()\n    }\n  }\n}\n\nexport default partitionPalindrome\n"
  },
  {
    "path": "Recursive/Partition.js",
    "content": "/**\n * @function canPartition\n * @description Check whether it is possible to partition the given array into two equal sum subsets using recursion.\n * @param {number[]} nums - The input array of numbers.\n * @param {number} index - The current index in the array being considered.\n * @param {number} target - The target sum for each subset.\n * @return {boolean}.\n * @see [Partition Problem](https://en.wikipedia.org/wiki/Partition_problem)\n */\n\nconst canPartition = (nums, index = 0, target = 0) => {\n  if (!Array.isArray(nums)) {\n    throw new TypeError('Invalid Input')\n  }\n\n  const sum = nums.reduce((acc, num) => acc + num, 0)\n\n  if (sum % 2 !== 0) {\n    return false\n  }\n\n  if (target === sum / 2) {\n    return true\n  }\n\n  if (index >= nums.length || target > sum / 2) {\n    return false\n  }\n\n  // Include the current number in the first subset and check if a solution is possible.\n  const withCurrent = canPartition(nums, index + 1, target + nums[index])\n\n  // Exclude the current number from the first subset and check if a solution is possible.\n  const withoutCurrent = canPartition(nums, index + 1, target)\n\n  return withCurrent || withoutCurrent\n}\n\nexport { canPartition }\n"
  },
  {
    "path": "Recursive/SubsequenceRecursive.js",
    "content": "/*\n * Problem Statement: Find all distinct, non-empty subsequence of given string in lexicographical order using recursive approach.\n *\n * What is subsequence?\n * A Subsequence is sequence obtained by deleting some or no elements without changing the order of elements\n * Example: Given a string = \"abcd\"\n * 1. \"abc\" is a subsequence\n * 2. \"abd\" is a subsequence\n * 3. But \"ba\" is not a subsequence (because order is changed)\n *\n * What is lexicographical order?\n * In simple terms, lexicographical order is dictionary order.\n * Example: Given a string = \"abcd\"\n * 1. \"abc\" will come before \"abcd\".\n * 2. \"abd\" will come before \"ac\".\n *\n * References for meaning of subsequence & lexicographical:\n * https://en.wikipedia.org/wiki/Subsequence\n * https://en.wikipedia.org/wiki/Lexicographic_order\n */\n\nexport const subsequence = (str, seq, low, output = []) => {\n  if (low <= str.length && str.length !== 0) {\n    output.push(seq)\n  }\n  for (let i = low; i < str.length; i++) {\n    subsequence(str, seq + str[i], i + 1, output)\n  }\n  return output\n}\n"
  },
  {
    "path": "Recursive/TowerOfHanoi.js",
    "content": "// wiki - https://en.wikipedia.org/wiki/Tower_of_Hanoi\n// Recursive Javascript function to solve tower of hanoi\n\nexport function TowerOfHanoi(n, from, to, aux, output = []) {\n  if (n === 1) {\n    output.push(`Move disk 1 from rod ${from} to rod ${to}`)\n    return output\n  }\n  TowerOfHanoi(n - 1, from, aux, to, output)\n  output.push(`Move disk ${n} from rod ${from} to rod ${to}`)\n  TowerOfHanoi(n - 1, aux, to, from, output)\n  return output\n}\n\n// Driver code (A, C, B are the name of rods)\n\n// const n = 4\n// TowerOfHanoi(n, 'A', 'C', 'B')\n"
  },
  {
    "path": "Recursive/test/BinaryEquivalent.test.js",
    "content": "import { binaryEquivalent } from '../BinaryEquivalent'\n\nconst tests = [\n  {\n    test: 2,\n    expectedValue: '10'\n  },\n  {\n    test: 0,\n    expectedValue: '0'\n  },\n  {\n    test: 543,\n    expectedValue: '1000011111'\n  },\n  {\n    test: 4697621023,\n    expectedValue: '100011000000000000000001000011111'\n  }\n]\n\ndescribe('Binary Equivalent', () => {\n  test.each(tests)(\n    'of $test should be $expectedValue',\n    ({ test, expectedValue }) => {\n      expect(binaryEquivalent(test)).toBe(expectedValue)\n    }\n  )\n})\n"
  },
  {
    "path": "Recursive/test/BinarySearch.test.js",
    "content": "import { binarySearch } from '../BinarySearch'\n\ndescribe('BinarySearch', () => {\n  const arr = [2, 3, 4, 10, 25, 40, 45, 60, 100, 501, 700, 755, 800, 999]\n  const low = 0\n  const high = arr.length - 1\n\n  it('should return index 3 for searchValue 10', () => {\n    const searchValue = 10\n    expect(binarySearch(arr, searchValue, low, high)).toBe(3)\n  })\n\n  it('should return index 0 for searchValue 2', () => {\n    const searchValue = 2\n    expect(binarySearch(arr, searchValue, low, high)).toBe(0)\n  })\n\n  it('should return index 13 for searchValue 999', () => {\n    const searchValue = 999\n    expect(binarySearch(arr, searchValue, low, high)).toBe(13)\n  })\n\n  it('should return -1 for searchValue 1', () => {\n    const searchValue = 1\n    expect(binarySearch(arr, searchValue, low, high)).toBe(-1)\n  })\n\n  it('should return -1 for searchValue 1000', () => {\n    const searchValue = 1000\n    expect(binarySearch(arr, searchValue, low, high)).toBe(-1)\n  })\n})\n"
  },
  {
    "path": "Recursive/test/Factorial.test.js",
    "content": "import { factorial } from '../Factorial'\n\ndescribe('Factorial', () => {\n  it('should return factorial 1 for value \"0\"', () => {\n    expect(factorial(0)).toBe(1)\n  })\n\n  it('should return factorial 120 for value \"5\"', () => {\n    expect(factorial(5)).toBe(120)\n  })\n\n  it('Throw Error for Invalid Input', () => {\n    expect(() => factorial('-')).toThrow(\n      'Input should be a non-negative whole number'\n    )\n    expect(() => factorial(null)).toThrow(\n      'Input should be a non-negative whole number'\n    )\n    expect(() => factorial(undefined)).toThrow(\n      'Input should be a non-negative whole number'\n    )\n    expect(() => factorial(3.142)).toThrow(\n      'Input should be a non-negative whole number'\n    )\n    expect(() => factorial(-1)).toThrow(\n      'Input should be a non-negative whole number'\n    )\n  })\n})\n"
  },
  {
    "path": "Recursive/test/FibonacciNumberRecursive.test.js",
    "content": "import { fibonacci } from '../FibonacciNumberRecursive'\n\ndescribe('FibonacciNumberRecursive', () => {\n  it('should return 0', () => {\n    expect(fibonacci(0)).toBe(0)\n  })\n\n  it('should return 1', () => {\n    expect(fibonacci(1)).toBe(1)\n  })\n\n  it('should return 5', () => {\n    expect(fibonacci(5)).toBe(5)\n  })\n\n  it('should return 9', () => {\n    expect(fibonacci(9)).toBe(34)\n  })\n})\n"
  },
  {
    "path": "Recursive/test/FloodFill.test.js",
    "content": "import { breadthFirstSearch, depthFirstSearch } from '../FloodFill'\n\n// some constants\nconst black = [0, 0, 0]\nconst green = [0, 255, 0]\nconst violet = [255, 0, 255]\nconst white = [255, 255, 255]\nconst orange = [255, 128, 0]\n\ndescribe('FloodFill', () => {\n  it('should calculate the correct colors using breadth-first approach', () => {\n    expect(testBreadthFirst([1, 1], green, orange, [1, 1])).toEqual(orange)\n    expect(testBreadthFirst([1, 1], green, orange, [0, 1])).toEqual(violet)\n    expect(testBreadthFirst([1, 1], green, orange, [6, 4])).toEqual(white)\n  })\n\n  it('should calculate the correct colors using depth-first approach', () => {\n    expect(testDepthFirst([1, 1], green, orange, [1, 1])).toEqual(orange)\n    expect(testDepthFirst([1, 1], green, orange, [0, 1])).toEqual(violet)\n    expect(testDepthFirst([1, 1], green, orange, [6, 4])).toEqual(white)\n  })\n})\n\ndescribe.each([breadthFirstSearch, depthFirstSearch])('%o', (floodFillFun) => {\n  it.each([\n    [1, -1],\n    [-1, 1],\n    [0, 7],\n    [7, 0]\n  ])('throws for start position [%i, %i]', (location) => {\n    expect(() =>\n      floodFillFun(generateTestRgbData(), location, green, orange)\n    ).toThrowError()\n  })\n})\n\n/**\n * Utility-function to test the function \"breadthFirstSearch\".\n *\n * @param fillLocation The start location on the image where the flood fill is applied.\n * @param targetColor The old color to be replaced.\n * @param replacementColor The new color to replace the old one.\n * @param testLocation The location of the color to be checked.\n * @return The color at testLocation.\n */\nfunction testBreadthFirst(\n  fillLocation,\n  targetColor,\n  replacementColor,\n  testLocation\n) {\n  const rgbData = generateTestRgbData()\n  breadthFirstSearch(rgbData, fillLocation, targetColor, replacementColor)\n  return rgbData[testLocation[0]][testLocation[1]]\n}\n\n/**\n * Utility-function to test the function \"depthFirstSearch\".\n *\n * @param fillLocation The start location on the image where the flood fill is applied.\n * @param targetColor The old color to be replaced.\n * @param replacementColor The new color to replace the old one.\n * @param testLocation The location of the color to be checked.\n * @return The color at testLocation.\n */\nfunction testDepthFirst(\n  fillLocation,\n  targetColor,\n  replacementColor,\n  testLocation\n) {\n  const rgbData = generateTestRgbData()\n  depthFirstSearch(rgbData, fillLocation, targetColor, replacementColor)\n  return rgbData[testLocation[0]][testLocation[1]]\n}\n\n/**\n * Generates the rgbData-matrix for the tests.\n *\n * @return example rgbData-matrix.\n */\nfunction generateTestRgbData() {\n  const layout = [\n    [violet, violet, green, green, black, green, green],\n    [violet, green, green, black, green, green, green],\n    [green, green, green, black, green, green, green],\n    [black, black, green, black, white, white, green],\n    [violet, violet, black, violet, violet, white, white],\n    [green, green, green, violet, violet, violet, violet],\n    [violet, violet, violet, violet, violet, violet, violet]\n  ]\n\n  // transpose layout-matrix so the x-index comes before the y-index\n  const transposed = []\n  for (let x = 0; x < layout[0].length; x++) {\n    transposed[x] = []\n    for (let y = 0; y < layout.length; y++) {\n      transposed[x][y] = layout[y][x]\n    }\n  }\n\n  return transposed\n}\n"
  },
  {
    "path": "Recursive/test/KochSnowflake.test.js",
    "content": "import { iterate, Vector2 } from '../KochSnowflake'\n\ndescribe('KochSnowflake', () => {\n  it('should produce the correctly-transformed vectors', () => {\n    expect(iterate([new Vector2(0, 0), new Vector2(1, 0)], 1)[0]).toEqual({\n      x: 0,\n      y: 0\n    })\n\n    expect(iterate([new Vector2(0, 0), new Vector2(1, 0)], 1)[1]).toEqual({\n      x: 1 / 3,\n      y: 0\n    })\n\n    expect(iterate([new Vector2(0, 0), new Vector2(1, 0)], 1)[2]).toEqual({\n      x: 1 / 2,\n      y: Math.sin(Math.PI / 3) / 3\n    })\n\n    expect(iterate([new Vector2(0, 0), new Vector2(1, 0)], 1)[3]).toEqual({\n      x: 2 / 3,\n      y: 0\n    })\n\n    expect(iterate([new Vector2(0, 0), new Vector2(1, 0)], 1)[4]).toEqual({\n      x: 1,\n      y: 0\n    })\n  })\n})\n"
  },
  {
    "path": "Recursive/test/LetterCombination.test.js",
    "content": "import { letterCombinations } from '../LetterCombination'\n\ndescribe('Letter Combinations', () => {\n  it('should return empty array if provided string is not valid', () => {\n    const result = letterCombinations('')\n    expect(Array.isArray(result)).toBe(true)\n    expect(result.length).toBe(0)\n  })\n\n  it('should return empty array if provided string is empty', () => {\n    const result = letterCombinations(null)\n    expect(Array.isArray(result)).toBe(true)\n    expect(result.length).toBe(0)\n  })\n\n  it('should return letter combination of 234', () => {\n    const result = letterCombinations('234')\n    expect(result).toEqual([\n      'adg',\n      'adh',\n      'adi',\n      'aeg',\n      'aeh',\n      'aei',\n      'afg',\n      'afh',\n      'afi',\n      'bdg',\n      'bdh',\n      'bdi',\n      'beg',\n      'beh',\n      'bei',\n      'bfg',\n      'bfh',\n      'bfi',\n      'cdg',\n      'cdh',\n      'cdi',\n      'ceg',\n      'ceh',\n      'cei',\n      'cfg',\n      'cfh',\n      'cfi'\n    ])\n  })\n})\n"
  },
  {
    "path": "Recursive/test/Palindrome.test.js",
    "content": "import { palindrome } from '../Palindrome'\n\ndescribe('Palindrome', () => {\n  it('expects to return true for palindrome string', () => {\n    const isPalindrome = palindrome('madam')\n    expect(isPalindrome).toBe(true)\n  })\n\n  it('expects to return true for Empty String', () => {\n    const isPalindrome = palindrome('')\n    expect(isPalindrome).toBe(true)\n  })\n\n  it('expects to return false for non-palindrome string', () => {\n    const isPalindrome = palindrome('foobar')\n    expect(isPalindrome).toBe(false)\n  })\n\n  it('Throw Error for Invalid Input', () => {\n    expect(() => palindrome(123)).toThrow('Invalid Input')\n    expect(() => palindrome(null)).toThrow('Invalid Input')\n    expect(() => palindrome(undefined)).toThrow('Invalid Input')\n  })\n})\n"
  },
  {
    "path": "Recursive/test/PalindromePartitioning.test.js",
    "content": "import partitionPalindrome from '../PalindromePartitioning'\n\ndescribe('Palindrome Partitioning', () => {\n  it('should return all possible palindrome partitioning of s', () => {\n    expect(partitionPalindrome('aab')).toEqual([\n      ['a', 'a', 'b'],\n      ['aa', 'b']\n    ])\n    expect(partitionPalindrome('a')).toEqual([['a']])\n    expect(partitionPalindrome('ab')).toEqual([['a', 'b']])\n  })\n})\n"
  },
  {
    "path": "Recursive/test/Partition.test.js",
    "content": "import { canPartition } from '../Partition'\n\ndescribe('Partition (Recursive)', () => {\n  it('expects to return true for an array that can be partitioned', () => {\n    const result = canPartition([1, 5, 11, 5])\n    expect(result).toBe(true)\n  })\n\n  it('expects to return false for an array that cannot be partitioned', () => {\n    const result = canPartition([1, 2, 3, 5])\n    expect(result).toBe(false)\n  })\n\n  it('expects to return true for an empty array (0 elements)', () => {\n    const result = canPartition([])\n    expect(result).toBe(true)\n  })\n\n  it('Throw Error for Invalid Input', () => {\n    expect(() => canPartition(123)).toThrow('Invalid Input')\n    expect(() => canPartition(null)).toThrow('Invalid Input')\n    expect(() => canPartition(undefined)).toThrow('Invalid Input')\n  })\n})\n"
  },
  {
    "path": "Search/BinarySearch.js",
    "content": "/* Binary Search: https://en.wikipedia.org/wiki/Binary_search_algorithm\n *\n * Search a sorted array by repeatedly dividing the search interval\n * in half. Begin with an interval covering the whole array. If the value of the\n * search key is less than the item in the middle of the interval, narrow the interval\n * to the lower half. Otherwise narrow it to the upper half. Repeatedly check until the\n * value is found or the interval is empty.\n */\n\nfunction binarySearchRecursive(arr, x, low = 0, high = arr.length - 1) {\n  const mid = Math.floor(low + (high - low) / 2)\n\n  if (high >= low) {\n    if (arr[mid] === x) {\n      // item found => return its index\n      return mid\n    }\n\n    if (x < arr[mid]) {\n      // arr[mid] is an upper bound for x, so if x is in arr => low <= x < mid\n      return binarySearchRecursive(arr, x, low, mid - 1)\n    } else {\n      // arr[mid] is a lower bound for x, so if x is in arr => mid < x <= high\n      return binarySearchRecursive(arr, x, mid + 1, high)\n    }\n  } else {\n    // if low > high => we have searched the whole array without finding the item\n    return -1\n  }\n}\nfunction binarySearchIterative(arr, x, low = 0, high = arr.length - 1) {\n  while (high >= low) {\n    const mid = Math.floor(low + (high - low) / 2)\n\n    if (arr[mid] === x) {\n      // item found => return its index\n      return mid\n    }\n\n    if (x < arr[mid]) {\n      // arr[mid] is an upper bound for x, so if x is in arr => low <= x < mid\n      high = mid - 1\n    } else {\n      // arr[mid] is a lower bound for x, so if x is in arr => mid < x <= high\n      low = mid + 1\n    }\n  }\n  // if low > high => we have searched the whole array without finding the item\n  return -1\n}\n\nexport { binarySearchIterative, binarySearchRecursive }\n"
  },
  {
    "path": "Search/ExponentialSearch.js",
    "content": "/**\n * Exponential Search\n *\n * The algorithm consists of two stages. The first stage determines a\n * range in which the search key would reside if it were in the list.\n * In the second stage, a binary search is performed on this range.\n *\n *\n *\n */\n\nfunction binarySearch(arr, value, floor, ceiling) {\n  // Middle index\n  const mid = Math.floor((floor + ceiling) / 2)\n\n  // If value is at the mid position return this position\n  if (arr[mid] === value) {\n    return mid\n  }\n\n  if (floor > ceiling) return -1\n\n  // If the middle element is great than the value\n  // search the left part of the array\n  if (arr[mid] > value) {\n    return binarySearch(arr, value, floor, mid - 1)\n    // If the middle element is lower than the value\n    // search the right part of the array\n  } else {\n    return binarySearch(arr, value, mid + 1, ceiling)\n  }\n}\n\nfunction exponentialSearch(arr, length, value) {\n  // If value is the first element of the array return this position\n  if (arr[0] === value) {\n    return 0\n  }\n\n  // Find range for binary search\n  let i = 1\n  while (i < length && arr[i] <= value) {\n    i = i * 2\n  }\n\n  // Call binary search for the range found above\n  return binarySearch(arr, value, i / 2, Math.min(i, length))\n}\n\nexport { binarySearch, exponentialSearch }\n\n// const arr = [2, 3, 4, 10, 40, 65, 78, 100]\n// const value = 78\n// const result = exponentialSearch(arr, arr.length, value)\n"
  },
  {
    "path": "Search/FibonacciSearch.js",
    "content": "/****************************************************************************\n * Fibonacci Search JavaScript Implementation\n * Author   Alhassan Atama Isiaka\n * Version v1.0.0\n * Copyright 2020\n * https://github.com/komputarist\n *\n * This implementation is based on Generalizing the Fibonacci search we\n * define the Fibonacci search of degree K. Like the Fibonacci search,\n * which it reduces to for K = 2, the Fibonacci search of degree K\n * involves only addition and subtraction.\n *  Capocelli R.M. (1991) A Generalization of the Fibonacci Search. In:\n * Bergum G.E., Philippou A.N., Horadam A.F. (eds) Applications of Fibonacci\n * Numbers. Springer, Dordrecht. https://doi.org/10.1007/978-94-011-3586-3_9\n *\n * This snippet is free. Feel free to improve on it\n *\n * We define a function fibonacciSearch() that takes an array of numbers,\n * the item (number) to be searched for and the length of the items in the array\n ****************************************************************************/\n\nexport const fibonacciSearch = (arr, x, n) => {\n  let fib2 = 0 // (K-2)'th Fibonacci Number\n  let fib1 = 1 // (K-1)'th Fibonacci Number.\n  let fibK = fib2 + fib1 // Kth Fibonacci\n\n  /* We want to store the smallest fibonacci number smaller such that\n    number is greater than or equal to n, we use fibK for this */\n  while (fibK < n) {\n    fib2 = fib1\n    fib1 = fibK\n    fibK = fib2 + fib1\n  }\n  //  This marks the eliminated range from front\n  let offset = -1\n\n  /* while there are elements to be checked. We compare arr[fib2] with x.\n    When fibM becomes 1, fib2 becomes 0 */\n\n  while (fibK > 1) {\n    // Check if fibK is a valid location\n    const i = Math.min(offset + fib2, n - 1)\n\n    /*  If x is greater than the value at\n      index fib2, Partition the subarray array\n      from offset to i */\n    if (arr[i] < x) {\n      fibK = fib1\n      fib1 = fib2\n      fib2 = fibK - fib1\n      offset = i\n      /* If x is greater than the value at\n            index fib2, cut the subarray array\n            from offset to i */\n    } else if (arr[i] > x) {\n      fibK = fib2\n      fib1 = fib1 - fib2\n      fib2 = fibK - fib1\n    } else {\n      //  return index for found element\n      return i\n    }\n  }\n\n  //    comparing the last element with x */\n  if (fib1 && arr[offset + 1] === x) {\n    return offset + 1\n  }\n  //    element not found. return -1\n  return -1\n}\n\n// Example\n// const myArray = [10, 22, 35, 40, 45, 50, 80, 82, 85, 90, 100]\n// const n = myArray.length\n// const x = 90\n// const fibFinder = fibonacciSearch(myArray, x, n)\n"
  },
  {
    "path": "Search/InterpolationSearch.js",
    "content": "/**\n * Interpolation Search\n *\n * Time Complexity:\n * -Best case: O(1)\n * -Worst case: O(n)\n * -O((log(log(n))) If the data are uniformly distributed\n *\n *\n */\n\nexport function interpolationSearch(arr, key) {\n  const length = arr.length - 1\n  let low = 0\n  let high = length\n  let position = -1\n  let delta = -1\n\n  // Because the array is sorted the key must be between low and high\n  while (low <= high && key >= arr[low] && key <= arr[high]) {\n    delta = (key - arr[low]) / (arr[high] - arr[low])\n    position = low + Math.floor((high - low) * delta)\n\n    // Target found return its position\n    if (arr[position] === key) {\n      return position\n    }\n\n    // If the key is larger then it is in the upper part of the array\n    if (arr[position] < key) {\n      low = position + 1\n      // If the key is smaller then it is in the lower part of the array\n    } else {\n      high = position - 1\n    }\n  }\n\n  return -1\n}\n"
  },
  {
    "path": "Search/JumpSearch.js",
    "content": "/* The Jump Search algorithm allows to combine a linear search with a speed optimization.\n * This means that instead of going 1 by 1, we will increase the step of √n and increase that\n * step of √n which make the step getting bigger and bigger.\n * The asymptotic analysis of Jump Search is o(√n). Like the binary search, it needs to be sorted.\n * The advantage against binary search is that Jump Search traversed back only once.\n */\n\nconst jumpSearch = (arr, value) => {\n  const length = arr.length\n  let step = Math.floor(Math.sqrt(length))\n  let lowerBound = 0\n  while (arr[Math.min(step, length) - 1] < value) {\n    lowerBound = step\n    step += step\n    if (lowerBound >= length) {\n      return -1\n    }\n  }\n\n  const upperBound = Math.min(step, length)\n  while (arr[lowerBound] < value) {\n    lowerBound++\n    if (lowerBound === upperBound) {\n      return -1\n    }\n  }\n  if (arr[lowerBound] === value) {\n    return lowerBound\n  }\n  return -1\n}\n\nexport { jumpSearch }\n"
  },
  {
    "path": "Search/LinearSearch.js",
    "content": "/*\n * Linear search or sequential search is a method for finding a target\n * value within a list. It sequentially checks each element of the list\n * for the target value until a match is found or until all the elements\n * have been searched.\n *\n * @see https://en.wikipedia.org/wiki/Linear_search\n */\nfunction SearchArray(searchNum, ar, output = (v) => console.log(v)) {\n  const position = Search(ar, searchNum)\n  if (position !== -1) {\n    output('The element was found at ' + (position + 1))\n  } else {\n    output('The element not found')\n  }\n}\n\n// Search “theArray” for the specified “key” value\nfunction Search(theArray, key) {\n  for (let n = 0; n < theArray.length; n++) {\n    if (theArray[n] === key) {\n      return n\n    }\n  }\n  return -1\n}\n\nexport { SearchArray, Search }\n\n// const ar = [1, 2, 3, 4, 5, 6, 7, 8, 9]\n// SearchArray(3, ar)\n// SearchArray(4, ar)\n// SearchArray(11, ar)\n"
  },
  {
    "path": "Search/Minesweeper.js",
    "content": "/*\n * Author: IcarusTheFly (https://github.com/IcarusTheFly)\n * Minesweeper explanation can be found in: https://en.wikipedia.org/wiki/Minesweeper_(video_game)\n * This function will take a rectangular matrix filled with boolean values - the value for a cell\n * with a mine will be true, otherwise it will be false.\n * As a result it will return a rectangular matrix where each cell will have an integer that\n * counts all the mines in the adjacent cells\n * Two cells should share at least one corner to be considered adjacent\n */\n\n/**\n * @function minesweeper\n * @description It counts the amount of mines surrounding every cell and returns a formatted matrix\n * @param {boolean[][]} matrix\n * @returns {number[][]} Matrix of numbers with the amount of mines surrounding each cell\n */\n\nexport const minesweeper = (matrix) => {\n  const arrResult = []\n  for (let x = 0; x < matrix.length; x++) {\n    const arrLine = []\n    for (let y = 0; y < matrix[x].length; y++) {\n      let minesInCell = 0\n      for (let xi = x - 1; xi <= x + 1; xi++) {\n        if (matrix[xi] !== undefined) {\n          for (let yi = y - 1; yi <= y + 1; yi++) {\n            if ((xi !== x || yi !== y) && matrix[xi][yi] === true) {\n              minesInCell++\n            }\n          }\n        }\n      }\n      arrLine.push(minesInCell)\n    }\n    arrResult.push(arrLine)\n  }\n  return arrResult\n}\n"
  },
  {
    "path": "Search/QuickSelectSearch.js",
    "content": "/*\n * Places the `k` smallest elements in `array` in the first `k` indices: `[0..k-1]`\n * Modifies the passed in array *in place*\n * Returns a slice of the wanted elements for convenience\n * Efficient mainly because it never performs a full sort.\n *\n * The only guarantees are that:\n *\n * - The `k`th element is in its final sort index (if the array were to be sorted)\n * - All elements before index `k` are smaller than the `k`th element\n *\n * [Reference](http://en.wikipedia.org/wiki/Quickselect)\n */\nexport function quickSelectSearch(array, k) {\n  if (!array || array.length <= k) {\n    throw new Error('Invalid arguments')\n  }\n\n  let from = 0\n  let to = array.length - 1\n  while (from < to) {\n    let left = from\n    let right = to\n    const pivot = array[Math.ceil((left + right) * 0.5)]\n\n    while (left < right) {\n      if (array[left] >= pivot) {\n        const tmp = array[left]\n        array[left] = array[right]\n        array[right] = tmp\n        --right\n      } else {\n        ++left\n      }\n    }\n\n    if (array[left] > pivot) {\n      --left\n    }\n\n    if (k <= left) {\n      to = left\n    } else {\n      from = left + 1\n    }\n  }\n  return array\n}\n\n/* ---------------------------------- Test ---------------------------------- */\n\n// const arr = [1121111, 21, 333, 41, 5, 66, 7777, 28, 19, 11110]\n// quickSelectSearch(arr, 5) // [ 19, 21, 28, 41, 5, 66, 333, 11110, 1121111, 7777 ]\n// quickSelectSearch(arr, 2) // [ 19, 5, 21, 41, 28, 333, 11110, 1121111, 7777, 66 ]\n// quickSelectSearch(arr, 7) // [ 19, 5, 21, 41, 28, 66, 333, 7777, 11110, 1121111 ]\n"
  },
  {
    "path": "Search/RabinKarp.js",
    "content": "/*\n * Implements the Rabin-Karp algorithm for pattern searching.\n *\n * The Rabin-Karp algorithm is a string searching algorithm that uses hashing to find patterns in strings.\n * It is faster than naive string matching algorithms because it avoids comparing every character in the text.\n *\n * This implementation uses a rolling hash function to efficiently compute the hash values of substrings.\n * It also uses a modulo operator to reduce the size of the hash values, which helps to prevent hash collisions.\n *\n * The algorithm returns an array of indices where the pattern is found in the text. If the pattern is not\n * found, the algorithm returns an empty array.\n *\n * [Reference](https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm)\n */\n\nconst BASE = 256 // The number of characters in the alphabet\nconst MOD = 997 // A prime number used for the hash function\n\nfunction rabinKarpSearch(text, pattern) {\n  const patternLength = pattern.length\n  const textLength = text.length\n  const hashPattern = hash(pattern, patternLength)\n  const hashText = []\n  const indices = []\n\n  // Calculate the hash of the first substring in the text\n  hashText[0] = hash(text, patternLength)\n\n  // Precompute BASE^(patternLength-1) % MOD\n  const basePow = Math.pow(BASE, patternLength - 1) % MOD\n\n  for (let i = 1; i <= textLength - patternLength + 1; i++) {\n    // Update the rolling hash by removing the first character\n    // and adding the next character in the text\n    hashText[i] =\n      (BASE * (hashText[i - 1] - text.charCodeAt(i - 1) * basePow) +\n        text.charCodeAt(i + patternLength - 1)) %\n      MOD\n\n    // In case of hash collision, check character by character\n    if (hashText[i] < 0) {\n      hashText[i] += MOD\n    }\n\n    // Check if the hashes match and perform a character-wise comparison\n    if (hashText[i] === hashPattern) {\n      if (text.substring(i, i + patternLength) === pattern) {\n        indices.push(i) // Store the index where the pattern is found\n      }\n    }\n  }\n\n  return indices\n}\n\nfunction hash(str, length) {\n  let hashValue = 0\n  for (let i = 0; i < length; i++) {\n    hashValue = (hashValue * BASE + str.charCodeAt(i)) % MOD\n  }\n  return hashValue\n}\n\nexport { rabinKarpSearch }\n"
  },
  {
    "path": "Search/SlidingWindow.js",
    "content": "/**\n * Sliding Window:\n * This pattern involve creating a window which can either be\n * an array or numbers from one position to another.\n *\n * Depending on a certain condition, the window either increases\n * or closes (and a new window is created).\n *\n * Very useful for keeping track of a subset of data in an\n * array/string etc.\n *\n * Time Complexity: Best - O(n);\n *\n * Examples:\n * maxSubarraySum([1,2,5,2,8,1,5],2) // returns 10\n * maxSubarraySum([1,2,5,2,8,1,5],15) // returns null\n * maxSubarraySum([5,2,6,9],3) // returns 17\n * @param {[Int]} arr - An array of integers on which we will perform the test.\n * @param {Int} num - An integer that displays the size of the window you want to check.\n * @returns {Int / Null} - Returns a total of N consecutive numbers or null\n */\n\nfunction slidingWindow(arr, num) {\n  // Edge Case:\n  // If the length of the array shorter than the window size (num) return null.\n  if (arr.length < num) return null\n  // The highest amount of consecutive numbers\n  let maxSum = 0\n  // Temp amount of consecutive numbers - For comparative purposes\n  let tempSum = 0\n  // loop over the array {num} times and save their total amount in {maxSum}\n  for (let i = 0; i < num; i++) {\n    maxSum += arr[i]\n  }\n  // initialize {tempSum} to {maxSum}.\n  tempSum = maxSum\n  // loop over the array n times\n  for (let i = num; i < arr.length; i++) {\n    // Add the next num in the array and remove the first one\n    tempSum = tempSum - arr[i - num] + arr[i]\n    // save the largest number between {maxNum} and {tempNum} in maxSum.\n    maxSum = Math.max(maxSum, tempSum)\n  }\n  return maxSum\n}\n\nexport { slidingWindow }\n"
  },
  {
    "path": "Search/StringSearch.js",
    "content": "/*\n * String Search\n */\n\nfunction makeTable(str) {\n  // create a table of size equal to the length of `str`\n  // table[i] will store the prefix of the longest prefix of the substring str[0..i]\n  const table = new Array(str.length)\n  let maxPrefix = 0\n  // the longest prefix of the substring str[0] has length\n  table[0] = 0\n\n  // for the substrings the following substrings, we have two cases\n  for (let i = 1; i < str.length; i++) {\n    // case 1. the current character doesn't match the last character of the longest prefix\n    while (maxPrefix > 0 && str.charAt(i) !== str.charAt(maxPrefix)) {\n      // if that is the case, we have to backtrack, and try find a character  that will be equal to the current character\n      // if we reach 0, then we couldn't find a character\n      maxPrefix = table[maxPrefix - 1]\n    }\n    // case 2. The last character of the longest prefix matches the current character in `str`\n    if (str.charAt(maxPrefix) === str.charAt(i)) {\n      // if that is the case, we know that the longest prefix at position i has one more character.\n      // for example consider `.` be any character not contained in the set [a.c]\n      // str = abc....abc\n      // consider `i` to be the last character `c` in `str`\n      // maxPrefix = will be 2 (the first `c` in `str`)\n      // maxPrefix now will be 3\n      maxPrefix++\n      // so the max prefix for table[9] is 3\n    }\n    table[i] = maxPrefix\n  }\n  return table\n}\n\n// Find all the words that matches in a given string `str`\nexport function stringSearch(str, word) {\n  // find the prefix table in O(n)\n  const prefixes = makeTable(word)\n  const matches = []\n\n  // `j` is the index in `P`\n  let j = 0\n  // `i` is the index in `S`\n  let i = 0\n  while (i < str.length) {\n    // Case 1.  S[i] == P[j] so we move to the next index in `S` and `P`\n    if (str.charAt(i) === word.charAt(j)) {\n      i++\n      j++\n    }\n    // Case 2.  `j` is equal to the length of `P`\n    // that means that we reached the end of `P` and thus we found a match\n    // Next we have to update `j` because we want to save some time\n    // instead of updating to j = 0 , we can jump to the last character of the longest prefix well known so far.\n    // j-1 means the last character of `P` because j is actually `P.length`\n    // e.g.\n    // S =  a b a b d e\n    // P = `a b`a b\n    // we will jump to `a b` and we will compare d and a in the next iteration\n    // a b a b `d` e\n    //     a b `a` b\n    if (j === word.length) {\n      matches.push(i - j)\n      j = prefixes[j - 1]\n      // Case 3.\n      // S[i] != P[j] There's a mismatch!\n    } else if (str.charAt(i) !== word.charAt(j)) {\n      // if we  found at least a character in common, do the same thing as in case 2\n      if (j !== 0) {\n        j = prefixes[j - 1]\n      } else {\n        // else j = 0, and we can move to the next character S[i+1]\n        i++\n      }\n    }\n  }\n\n  return matches\n}\n\n// stringSearch('Hello search the position of me', 'pos')\n"
  },
  {
    "path": "Search/TernarySearch.js",
    "content": "/* Ternary search is similar to binary search but it divides the sorted array\n * into three parts and determines which part the key lies in. The array will\n * be divided into three intervals by using two middle points, mid1 and mid2.\n * The value of the key will first be compared with the two mid points, the value\n * will be returned if there is a match. Then, if the value of the key is less\n * than mid1, narrow the interval to the first part. Else, if the value of the\n * key is greater than mid2, narrow the interval to the third part. Otherwise,\n * narrow the interval to the middle part. Repeat the steps until the value is\n * found or the interval is empty (value not found after checking all elements).\n *\n * Reference: https://www.geeksforgeeks.org/ternary-search/\n */\n\nfunction ternarySearchRecursive(arr, key, low = 0, high = arr.length - 1) {\n  if (high >= low) {\n    // find the mid1 and mid2\n    const mid1 = Math.floor(low + (high - low) / 3)\n    const mid2 = Math.floor(high - (high - low) / 3)\n\n    // check if key is found at any mid\n    if (arr[mid1] === key) {\n      // return index of key if found\n      return mid1\n    }\n    if (arr[mid2] === key) {\n      // return index of key if found\n      return mid2\n    }\n\n    // since the key is not found at mid,\n    // check in which region it is present\n    // and repeat the Search operation\n    // in that region\n    if (key < arr[mid1]) {\n      // the key lies in between low and mid1\n      return ternarySearchRecursive(arr, key, low, mid1 - 1)\n    } else if (key > arr[mid2]) {\n      // the key lies in between mid2 and high\n      return ternarySearchRecursive(arr, key, mid2 + 1, high)\n    } else {\n      // the key lies in between mid1 and mid2\n      return ternarySearchRecursive(arr, key, mid1 + 1, mid2 - 1)\n    }\n  } else {\n    // if low > high => we have searched the whole array without finding the item\n    return -1\n  }\n}\n\nfunction ternarySearchIterative(arr, key, low = 0, high = arr.length - 1) {\n  while (high >= low) {\n    // find the mid1 and mid2\n    const mid1 = Math.floor(low + (high - low) / 3)\n    const mid2 = Math.floor(high - (high - low) / 3)\n\n    // check if key is found at any mid\n    if (arr[mid1] === key) {\n      // return index of key if found\n      return mid1\n    }\n    if (arr[mid2] === key) {\n      // return index of key if found\n      return mid2\n    }\n\n    // since the key is not found at mid,\n    // check in which region it is present\n    // and repeat the Search operation\n    // in that region\n    if (key < arr[mid1]) {\n      // the key lies in between low and mid1\n      high = mid1 - 1\n    } else if (key > arr[mid2]) {\n      // the key lies in between mid2 and high\n      low = mid2 + 1\n    } else {\n      // the key lies in between mid1 and mid2\n      low = mid1 + 1\n      high = mid2 - 1\n    }\n  }\n  // the key was not found\n  return -1\n}\n\nexport { ternarySearchRecursive, ternarySearchIterative }\n"
  },
  {
    "path": "Search/UnionFind.js",
    "content": "/**\n * union find data structure for javascript\n *\n * In computer science, a disjoint-set data structure, also called a union–find data structure or merge–find set,\n * is a data structure that stores a collection of disjoint (non-overlapping) sets. Equivalently, it stores a partition\n * of a set into disjoint subsets. It provides operations for adding new sets, merging sets (replacing them by their union),\n * and finding a representative member of a set.\n * The last operation allows to find out efficiently if any two elements are in the same or different sets.\n *\n * Disjoint-set data structures play a key role in Kruskal's algorithm for finding the minimum spanning tree of a graph.\n * The importance of minimum spanning trees means that disjoint-set data structures underlie a wide variety of algorithms.\n * In addition, disjoint-set data structures also have applications to symbolic computation, as well in compilers,\n * especially for register allocation problems.\n *\n * you can learn more on disjoint-set / union–find data structure at https://en.wikipedia.org/wiki/Disjoint-set_data_structure\n */\nfunction UnionFind(n, key) {\n  if (!(this instanceof UnionFind)) return new UnionFind(n)\n  if (key && typeof key !== 'function') {\n    throw new Error('key has to be a function or else left undefined')\n  }\n  let cnt, length\n  // init Union Find with number of distinct groups. Each group will be referred to as index of the array of size 'size' starting at 0.\n  // Provide an optional key function that maps these indices. I.e., for the groups starting with 1 provide function(a){return a-1;}. The default value is function(a){return a;}.\n  key =\n    key ||\n    function (a) {\n      return a\n    }\n  cnt = length = n\n  const id = new Array(n)\n  const sz = new Array(n)\n  for (let i = 0; i < n; i++) {\n    id[i] = i\n    sz[i] = 1\n  }\n  // Returns the number of elements of uf object.\n  this.size = function () {\n    return length\n  }\n  // Returns the number of distinct groups left inside the object.\n  this.count = function () {\n    return cnt\n  }\n  // Return the root (value) of the group in which p is.\n  this.find = function (p) {\n    p = key(p)\n    while (p !== id[p]) {\n      id[p] = id[id[p]]\n      p = id[p]\n    }\n    return p\n  }\n  // Returns true if p and p are both in same group, false otherwise.\n  this.connected = function (p, q) {\n    p = key(p)\n    q = key(q)\n    ensureIndexWithinBounds(p, q)\n    return this.find(p) === this.find(q)\n  }\n  // Combine elements in groups p and q into a single group. In other words connect the two groups.\n  this.union = function (p, q) {\n    p = key(p)\n    q = key(q)\n    ensureIndexWithinBounds(p, q)\n    const i = this.find(p)\n    const j = this.find(q)\n    if (i === j) return\n    if (sz[i] < sz[j]) {\n      id[i] = j\n      sz[j] += sz[i]\n    } else {\n      id[j] = i\n      sz[i] += sz[j]\n    }\n    cnt--\n  }\n  function ensureIndexWithinBounds(args) {\n    for (let i = arguments.length - 1; i >= 0; i--) {\n      const p = arguments[i]\n      if (p >= length)\n        throw new Error(\n          'Index out of bounds. The maximum index can be length-1'\n        )\n    }\n  }\n}\n\nexport { UnionFind }\n"
  },
  {
    "path": "Search/test/BinarySearch.test.js",
    "content": "import { binarySearchIterative, binarySearchRecursive } from '../BinarySearch'\n\nconst arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\nconst stringArr = [\n  'Alpha',\n  'Bravo',\n  'Charlie',\n  'Delta',\n  'Echo',\n  'Foxtrot',\n  'Golf',\n  'Hotel',\n  'India',\n  'Juliet',\n  'Kilo',\n  'Lima',\n  'Mike',\n  'November',\n  'Oscar',\n  'Papa',\n  'Quebec',\n  'Romeo',\n  'Sierra',\n  'Tango',\n  'Uniform',\n  'Victor',\n  'Whiskey',\n  'X-Ray',\n  'Yankee',\n  'Zulu'\n]\n\ndescribe('Binary Search', () => {\n  const funcs = [binarySearchIterative, binarySearchRecursive]\n  for (const func of funcs) {\n    test('expect to return the index of the item in the array', () => {\n      expect(func(arr, 3)).toBe(2)\n    })\n    test('expect to return -1 if not in array', () => {\n      expect(func(arr, 11)).toBe(-1)\n    })\n    test('expect to return the index of the item in the array', () => {\n      expect(func(stringArr, 'Charlie')).toBe(2)\n    })\n    test('expect to return -1 if not in array', () => {\n      expect(func(stringArr, 'Zoft')).toBe(-1)\n    })\n  }\n})\n"
  },
  {
    "path": "Search/test/ExponentialSearch.test.js",
    "content": "import { exponentialSearch } from '../ExponentialSearch'\n\ntest('The Exponential Search of the Array [2, 3, 4, 10, 40, 65, 78, 100] is 6 where the value = 78', () => {\n  const arr = [2, 3, 4, 10, 40, 65, 78, 100]\n  const value = 78\n  const result = exponentialSearch(arr, arr.length, value)\n  expect(result).toEqual(6)\n})\n\ntest('The Exponential Search of the Array [2, 3, 4, 10, 40, 65, 78, 100] is -1 where the value = 178', () => {\n  const arr = [2, 3, 4, 10, 40, 65, 78, 100]\n  const value = 178\n  const result = exponentialSearch(arr, arr.length, value)\n  expect(result).toEqual(-1)\n})\n"
  },
  {
    "path": "Search/test/FibonacciSearch.test.js",
    "content": "import { fibonacciSearch } from '../FibonacciSearch'\n\ntest('fibonacciSearch([10, 22, 35, 40, 45, 50, 80, 82, 85, 90, 100], 90, arr.length) => 9', () => {\n  const arr = [10, 22, 35, 40, 45, 50, 80, 82, 85, 90, 100]\n  const target = 90\n  const res = fibonacciSearch(arr, target, arr.length)\n  expect(res).toEqual(9)\n})\n\ntest('fibonacciSearch([1, 11, 55, 56, 78, 82, 104], 104, arr.length) => 6', () => {\n  const arr = [1, 11, 55, 56, 78, 82, 104]\n  const target = 104\n  const res = fibonacciSearch(arr, target, arr.length)\n  expect(res).toEqual(6)\n})\n\ntest('fibonacciSearch([40, 45, 50, 80, 82, 85, 90, 100]. 190, arr.length) => -1', () => {\n  const arr = [40, 45, 50, 80, 82, 85, 90, 100]\n  const target = 190\n  const res = fibonacciSearch(arr, target, arr.length)\n  expect(res).toEqual(-1)\n})\n"
  },
  {
    "path": "Search/test/InterpolationSearch.test.js",
    "content": "import { interpolationSearch } from '../InterpolationSearch'\n\ntest('interpolationSearch([2, 6, 8, 14, 122, 169], 144) => -1', () => {\n  const array = [2, 6, 8, 14, 122, 169]\n  const key = 144\n  const res = interpolationSearch(array, key)\n  expect(res).toEqual(-1)\n})\n\ntest('interpolationSearch([2, 6, 8, 14, 122, 169], 122) => 4', () => {\n  const array = [2, 6, 8, 14, 122, 169]\n  const key = 122\n  const res = interpolationSearch(array, key)\n  expect(res).toEqual(4)\n})\n"
  },
  {
    "path": "Search/test/LinearSearch.test.js",
    "content": "import { Search as linearSearch } from '../LinearSearch'\n\nconst tests = [\n  {\n    test: {\n      arr: [1, 2, 300, 401, 450, 504, 800, 821, 855, 900, 1002],\n      target: 900\n    },\n    expectedValue: 9\n  },\n  {\n    test: {\n      arr: [1, 104, 110, 4, 44, 55, 56, 78],\n      target: 104\n    },\n    expectedValue: 1\n  },\n  {\n    test: {\n      arr: [-4, 5, 50, 77, 821, 85, 99, 100],\n      target: 192\n    },\n    expectedValue: -1\n  }\n]\n\ndescribe('Linear Search', () => {\n  it.each(tests)(\n    'linearSearch($test.arr, $test.target) => $expectedValue',\n    ({ test, expectedValue }) => {\n      const { arr, target } = test\n      expect(linearSearch(arr, target)).toBe(expectedValue)\n    }\n  )\n})\n"
  },
  {
    "path": "Search/test/Minesweeper.test.js",
    "content": "import { minesweeper } from '../Minesweeper'\n\ndescribe('Testing minesweeper function', () => {\n  it('should return the expected 3x3 array', () => {\n    const input = [\n      [true, false, false],\n      [false, true, false],\n      [false, false, false]\n    ]\n    const expectedOutput = [\n      [1, 2, 1],\n      [2, 1, 1],\n      [1, 1, 1]\n    ]\n    expect(minesweeper(input)).toStrictEqual(expectedOutput)\n  })\n\n  it('should return the expected 3x4 array', () => {\n    const input = [\n      [true, false, false, true],\n      [false, false, true, false],\n      [true, true, false, true]\n    ]\n    const expectedOutput = [\n      [0, 2, 2, 1],\n      [3, 4, 3, 3],\n      [1, 2, 3, 1]\n    ]\n    expect(minesweeper(input)).toStrictEqual(expectedOutput)\n  })\n\n  it('should return the expected 5x2 array', () => {\n    const input = [\n      [true, false],\n      [true, false],\n      [false, true],\n      [false, false],\n      [false, false]\n    ]\n    const expectedOutput = [\n      [1, 2],\n      [2, 3],\n      [2, 1],\n      [1, 1],\n      [0, 0]\n    ]\n    expect(minesweeper(input)).toStrictEqual(expectedOutput)\n  })\n\n  it('should return the correct result when there are no mines', () => {\n    const input = [\n      [false, false, false],\n      [false, false, false]\n    ]\n    const expectedOutput = [\n      [0, 0, 0],\n      [0, 0, 0]\n    ]\n    expect(minesweeper(input)).toStrictEqual(expectedOutput)\n  })\n\n  it('should return the correct result when there are mines in every cell', () => {\n    const input = [\n      [true, true, true],\n      [true, true, true],\n      [true, true, true]\n    ]\n    const expectedOutput = [\n      [3, 5, 3],\n      [5, 8, 5],\n      [3, 5, 3]\n    ]\n    expect(minesweeper(input)).toStrictEqual(expectedOutput)\n  })\n})\n"
  },
  {
    "path": "Search/test/RabinKarp.test.js",
    "content": "import { rabinKarpSearch } from '../RabinKarp'\n\ndescribe('Rabin-Karp Search', function () {\n  it('should find the pattern in the text', function () {\n    const text = 'ABABDABACDABABCABAB'\n    const pattern = 'DAB'\n    const expected = [4, 9]\n\n    const result = rabinKarpSearch(text, pattern)\n    expect(result).to.deep.equal(expected)\n  })\n\n  it('should handle multiple occurrences of the pattern', function () {\n    const text = 'ABABABABABAB'\n    const pattern = 'ABAB'\n    const expected = [2, 4, 6, 8]\n\n    const result = rabinKarpSearch(text, pattern)\n    expect(result).to.deep.equal(expected)\n  })\n\n  it('should handle pattern not found', function () {\n    const text = 'ABCD'\n    const pattern = 'XYZ'\n    const expected = []\n\n    const result = rabinKarpSearch(text, pattern)\n    expect(result).to.deep.equal(expected)\n  })\n})\n"
  },
  {
    "path": "Search/test/SlidingWindow.test.js",
    "content": "import { slidingWindow } from '../SlidingWindow'\n\ntest('expect to return the largest sum of sequence in the array', () => {\n  const sum = slidingWindow([1, 2, 5, 2, 8, 1, 5], 2)\n  expect(sum).toBe(10)\n})\n\ntest('expect to return the largest sum of sequence in the array', () => {\n  const sum = slidingWindow([5, 2, 6, 9], 3)\n  expect(sum).toBe(17)\n})\n\ntest('expect to return null when the sequence size is larger then the array length', () => {\n  const sum = slidingWindow([1, 2, 5, 2, 8, 1, 5], 15)\n  expect(sum).toBe(null)\n})\n"
  },
  {
    "path": "Search/test/TernarySearch.test.js",
    "content": "import {\n  ternarySearchRecursive,\n  ternarySearchIterative\n} from '../TernarySearch'\n\ntest('should return the index of a number in an array of numbers:', () => {\n  const indexNumber = ternarySearchRecursive([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3)\n  expect(indexNumber).toBe(2)\n})\n\ntest('should return the index of a number in an array of numbers:', () => {\n  const indexNumber = ternarySearchIterative([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 8)\n  expect(indexNumber).toBe(7)\n})\n\ntest('should return the index of a number in an array of numbers:', () => {\n  const indexNumber = ternarySearchRecursive([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 0)\n  expect(indexNumber).toBe(-1)\n})\n\ntest('should return the index of a number in an array of numbers:', () => {\n  const indexNumber = ternarySearchIterative(\n    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],\n    12\n  )\n  expect(indexNumber).toBe(-1)\n})\n\ntest('should return the index of a string in an array of strings:', () => {\n  const indexNumber = ternarySearchRecursive(\n    ['Ali', 'Cathrynli', 'Josuke', 'Thomas'],\n    'Cathrynli'\n  )\n  expect(indexNumber).toBe(1)\n})\n\ntest('should return the index of a string in an array of strings:', () => {\n  const indexNumber = ternarySearchRecursive(\n    ['Ali', 'Cathrynli', 'Josuke', 'Thomas'],\n    'Josuke'\n  )\n  expect(indexNumber).toBe(2)\n})\n\ntest('should return the index of a string in an array of strings:', () => {\n  const indexNumber = ternarySearchRecursive(\n    ['Ali', 'Cathrynli', 'Josuke', 'Thomas'],\n    'Angela'\n  )\n  expect(indexNumber).toBe(-1)\n})\n"
  },
  {
    "path": "Search/test/UnionFind.test.js",
    "content": "import { UnionFind } from '../UnionFind'\n\nconst uf = new UnionFind(5)\n\ntest('should expose .size():', () => {\n  const size = uf.size()\n  expect(size).toBe(5)\n})\n\ntest('should do .union(num1, num2):', () => {\n  uf.union(1, 2)\n  uf.union(3, 4)\n  uf.union(0, 4)\n  expect(uf.connected(1, 2)).toBe(true)\n  expect(uf.connected(1, 2)).toBe(true)\n\n  expect(uf.connected(3, 4)).toBe(true)\n  expect(uf.connected(3, 0)).toBe(true)\n  expect(uf.connected(4, 0)).toBe(true)\n\n  expect(uf.connected(1, 3)).toBe(false)\n  expect(uf.connected(1, 4)).toBe(false)\n  expect(uf.connected(1, 0)).toBe(false)\n  expect(uf.connected(2, 3)).toBe(false)\n  expect(uf.connected(2, 4)).toBe(false)\n  expect(uf.connected(2, 0)).toBe(false)\n})\n\ntest('.count(), should return the number of disparate groups:', () => {\n  expect(uf.count()).toBe(2)\n})\n\ntest('should check if two components are connected, .connected(num1, num2):', () => {\n  expect(uf.connected(1, 2)).toBe(true)\n  expect(uf.connected(1, 3)).toBe(false)\n})\n\ntest('should find the root of the tree in which the given element lives, .find(num):', () => {\n  expect(uf.find(1)).toBe(1)\n  expect(uf.find(2)).toBe(1)\n  expect(uf.find(3)).toBe(3)\n  expect(uf.find(4)).toBe(3)\n  expect(uf.find(0)).toBe(3)\n})\n\ntest('should always change the id of the smaller tree and preserve the id of the larger one', () => {\n  uf.union(2, 3)\n  expect(uf.count()).toBe(1)\n  expect(uf.find(0)).toBe(3)\n  expect(uf.find(1)).toBe(3)\n  expect(uf.find(2)).toBe(3)\n  expect(uf.find(3)).toBe(3)\n  expect(uf.find(4)).toBe(3)\n})\n"
  },
  {
    "path": "Search/test/jumpSearch.test.js",
    "content": "import { jumpSearch } from '../JumpSearch'\n\ntest('jumpSearch([0, 0, 4, 7, 10, 23, 34, 40, 55, 68, 77, 90], 77) => 10', () => {\n  const arr = [0, 0, 4, 7, 10, 23, 34, 40, 55, 68, 77, 90]\n  const res = jumpSearch(arr, 77)\n  expect(res).toEqual(10)\n})\n\ntest('jumpSearch([11, 12, 15, 65, 78, 90], 4) => -1', () => {\n  const arr = [11, 12, 15, 65, 78, 90]\n  const res = jumpSearch(arr, 4)\n  expect(res).toEqual(-1)\n})\n\ntest('jumpSearch([11, 12, 15, 65, 78, 90], 11) => 0', () => {\n  const arr = [11, 12, 15, 65, 78, 90]\n  const res = jumpSearch(arr, 11)\n  expect(res).toEqual(0)\n})\n"
  },
  {
    "path": "Sliding-Windows/LongestSubarrayWithSumAtMost.js",
    "content": "/**\n * Function to find the longest subarray with a sum <= target.\n *\n * @param {number[]} arr - The input array of numbers.\n * @param {number} target - The target sum for the dynamic window.\n * @returns {number} - The length of the longest subarray with a sum <= target.\n */\nexport function longestSubarrayWithSumAtMost(arr, target) {\n  let maxLength = 0\n  let windowSum = 0\n  let left = 0\n  for (let right = 0; right < arr.length; right++) {\n    windowSum += arr[right]\n    while (windowSum > target) {\n      windowSum -= arr[left]\n      left++\n    }\n    maxLength = Math.max(maxLength, right - left + 1)\n  }\n  return maxLength\n}\n"
  },
  {
    "path": "Sliding-Windows/MaxSumSubarrayFixed.js",
    "content": "/**\n * Function to find the maximum sum of a subarray of fixed size k.\n *\n * @param {number[]} arr - The input array of numbers.\n * @param {number} k - The fixed size of the subarray.\n * @returns {number} - The maximum sum of any subarray of size k.\n * @throws {RangeError} - If k is larger than the array length or less than 1.\n */\nexport function maxSumSubarrayFixed(arr, k) {\n  if (k > arr.length || k < 1) {\n    throw new RangeError(\n      'Subarray size k must be between 1 and the length of the array'\n    )\n  }\n  let maxSum = 0\n  let windowSum = 0\n  for (let i = 0; i < k; i++) {\n    windowSum += arr[i]\n  }\n  maxSum = windowSum\n  for (let i = k; i < arr.length; i++) {\n    windowSum += arr[i] - arr[i - k]\n    maxSum = Math.max(maxSum, windowSum)\n  }\n  return maxSum\n}\n"
  },
  {
    "path": "Sliding-Windows/test/LongestSubarrayWithSumAtMost.test.js",
    "content": "import { longestSubarrayWithSumAtMost } from '../LongestSubarrayWithSumAtMost'\n\ndescribe('Dynamic-size Sliding Window - longestSubarrayWithSumAtMost', () => {\n  it('should return the longest subarray length with sum <= target', () => {\n    const arr = [1, 2, 3, 4, 5]\n    const target = 7\n    const result = longestSubarrayWithSumAtMost(arr, target)\n    expect(result).toBe(3)\n  })\n\n  it('should return the full array length if the entire sum is within the target', () => {\n    const arr = [1, 1, 1, 1]\n    const target = 4\n    const result = longestSubarrayWithSumAtMost(arr, target)\n    expect(result).toBe(4)\n  })\n\n  it('should return 0 if no subarray meets the sum condition', () => {\n    const arr = [5, 6, 7]\n    const target = 3\n    const result = longestSubarrayWithSumAtMost(arr, target)\n    expect(result).toBe(0)\n  })\n})\n"
  },
  {
    "path": "Sliding-Windows/test/MaxSumSubarrayFixed.test.js",
    "content": "import { maxSumSubarrayFixed } from '../MaxSumSubarrayFixed'\n\ndescribe('Fixed-size Sliding Window - maxSumSubarrayFixed', () => {\n  it('should return the maximum sum of a subarray of size k', () => {\n    const arr = [2, 1, 5, 1, 3, 2]\n    const k = 3\n    const result = maxSumSubarrayFixed(arr, k)\n    expect(result).toBe(9)\n  })\n\n  it('should throw a RangeError if k is larger than the array length', () => {\n    const arr = [2, 1, 5]\n    const k = 4\n    expect(() => maxSumSubarrayFixed(arr, k)).toThrow(RangeError)\n  })\n\n  it('should throw a RangeError if k is less than 1', () => {\n    const arr = [2, 1, 5]\n    const k = 0\n    expect(() => maxSumSubarrayFixed(arr, k)).toThrow(RangeError)\n  })\n})\n"
  },
  {
    "path": "Sorts/AlphaNumericalSort.js",
    "content": "/*\n  https://en.wikipedia.org/wiki/Natural_sort_order\n\n  In computing, natural sort order (or natural sorting) is the ordering of strings in alphabetical order,\n  except that multi-digit numbers are treated atomically, i.e., as if they were a single character. Natural sort order\n  has been promoted as being more human-friendly (\"natural\") than machine-oriented, pure alphabetical sort order.[1]\n\n  For example, in alphabetical sorting, \"z11\" would be sorted before \"z2\" because the \"1\" in the first string is sorted as smaller\n  than \"2\", while in natural sorting \"z2\" is sorted before \"z11\" because \"2\" is treated as smaller than \"11\".\n\n  Alphabetical sorting:\n  1.z11\n  2.z2\n\n  Natural sorting:\n  1. z2\n  2. z11\n\n  P.S. use this function, as there are a lot of implementations on the stackoverflow and other forums, but many of them don't work correctly (can't pass all my tests)\n\n*/\n\nconst alphaNumericalSort = (a, b) => {\n  /*\n    https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare\n\n    The localeCompare() method returns a number indicating whether a reference string comes before, or after, or is the same as the given string in sort order.\n\n    The new locales and options arguments let applications specify the language whose sort order should be used and customize the behavior of the function.\n    In older implementations, which ignore the locales and options arguments, the locale and sort order used are entirely implementation-dependent.\n    Syntax:\n    localeCompare(compareString, locales, options)\n\n  */\n  return a.localeCompare(b, undefined, { numeric: true })\n}\n\nexport { alphaNumericalSort }\n"
  },
  {
    "path": "Sorts/BeadSort.js",
    "content": "/**\n * Bead Sort, also known as Gravity sort.\n *\n * This algorithm was inspired from natural phenomena and was designed keeping in mind objects (or beads) falling under\n * the influence of gravity.\n *\n * NOTE: It only works for arrays of positive integers.\n *\n * Wikipedia: https://en.wikipedia.org/wiki/Bead_sort\n */\nexport function beadSort(sequence) {\n  /* Let's ensure our sequence has only Positive Integers */\n  if (sequence.some((integer) => integer < 0)) {\n    throw RangeError('Sequence must be a list of Positive integers Only!')\n  }\n\n  const sequenceLength = sequence.length\n  const max = Math.max(...sequence)\n\n  // Set initial Grid\n  const grid = sequence.map((number) => {\n    const maxArr = new Array(max)\n\n    for (let i = 0; i < number; i++) {\n      maxArr[i] = '*'\n    }\n\n    return maxArr\n  })\n\n  // Drop the Beads!\n  for (let col = 0; col < max; col++) {\n    let beadsCount = 0\n\n    for (let row = 0; row < sequenceLength; row++) {\n      if (grid[row][col] === '*') {\n        beadsCount++\n      }\n    }\n\n    for (let row = sequenceLength - 1; row > -1; row--) {\n      if (beadsCount) {\n        grid[row][col] = '*'\n        beadsCount--\n      } else {\n        grid[row][col] = undefined\n      }\n    }\n  }\n\n  /* Finally, let's turn our Bead rows into their Respective Numbers */\n  return grid.map((beadArray) => {\n    const beadsArray = beadArray.filter((bead) => bead === '*')\n    return beadsArray.length\n  })\n}\n"
  },
  {
    "path": "Sorts/BinaryInsertionSort.js",
    "content": "/**\n * Pure Implementation of Binary Search Algorithm\n *\n * Binary insertion sort is a sorting algorithm similar to insertion sort,\n * but instead of using linear search to find the position\n * where the element should be inserted, we use binary search.\n * Thus, we reduce the number of comparisons for inserting one element from O(N)\n * (Time complexity in Insertion Sort) to O(log N).\n *\n */\n\n/**\n * Search the key element in the array from start position to end position.\n *\n * @param {Array} array Array of numbers.\n * @param {Number} key Value to be searched\n * @param {Number} start start index position of array\n * @param {Number} end end index position of array\n * @return {Number} Position of the key element\n */\nfunction binarySearch(array, key, start, end) {\n  if (start === end) {\n    if (array[start] > key) {\n      return start\n    } else {\n      return start + 1\n    }\n  }\n\n  if (start > end) {\n    return start\n  }\n\n  const mid = Math.floor((start + end) / 2)\n\n  if (array[mid] < key) {\n    return binarySearch(array, key, mid + 1, end)\n  } else if (array[mid] > key) {\n    return binarySearch(array, key, start, mid - 1)\n  } else {\n    return mid\n  }\n}\n\n/**\n * Binary Insertion Sort\n *\n * @param {Array} list List to be sorted.\n * @return {Array} The sorted list.\n */\nexport function binaryInsertionSort(array) {\n  const totalLength = array.length\n  for (let i = 1; i < totalLength; i += 1) {\n    const key = array[i]\n    const indexPosition = binarySearch(array, key, 0, i - 1)\n    array.splice(i, 1)\n    array.splice(indexPosition, 0, key)\n  }\n  return array\n}\n"
  },
  {
    "path": "Sorts/BogoSort.js",
    "content": "/**\n * Checks whether the given array is sorted in ascending order.\n */\nexport function isSorted(array) {\n  const length = array.length\n  for (let i = 0; i < length - 1; i++) {\n    if (array[i] > array[i + 1]) {\n      return false\n    }\n  }\n  return true\n}\n\n/**\n * Shuffles the given array randomly in place.\n */\nfunction shuffle(array) {\n  for (let i = array.length - 1; i; i--) {\n    const m = Math.floor(Math.random() * i)\n    const n = array[i - 1]\n    array[i - 1] = array[m]\n    array[m] = n\n  }\n}\n\n/**\n * Implementation of the bogosort algorithm.\n *\n * This sorting algorithm randomly rearranges the array until it is sorted.\n *\n * For more information see: https://en.wikipedia.org/wiki/Bogosort\n */\nexport function bogoSort(items) {\n  while (!isSorted(items)) {\n    shuffle(items)\n  }\n  return items\n}\n"
  },
  {
    "path": "Sorts/BubbleSort.js",
    "content": "/* Bubble Sort is an algorithm to sort an array. It\n *  compares adjacent element and swaps their position\n *  The big O on bubble sort in worst and best case is O(N^2).\n *  Not efficient.\n *  Somehow if the array is sorted or nearly sorted then we can optimize bubble sort by adding a flag.\n *\n *  In bubble sort, we keep iterating while something was swapped in\n *  the previous inner-loop iteration. By swapped I mean, in the\n *  inner loop iteration, we check each number if the number proceeding\n *  it is greater than itself, if so we swap them.\n *\n *  Wikipedia: https://en.wikipedia.org/wiki/Bubble_sort\n *  Animated Visual: https://www.toptal.com/developers/sorting-algorithms/bubble-sort\n */\n\n/**\n * Using 2 for loops.\n */\nexport function bubbleSort(items) {\n  const length = items.length\n  let noSwaps\n\n  for (let i = length; i > 0; i--) {\n    // flag for optimization\n    noSwaps = true\n    // Number of passes\n    for (let j = 0; j < i - 1; j++) {\n      // Compare the adjacent positions\n      if (items[j] > items[j + 1]) {\n        // Swap the numbers\n        ;[items[j], items[j + 1]] = [items[j + 1], items[j]]\n        noSwaps = false\n      }\n    }\n    if (noSwaps) {\n      break\n    }\n  }\n\n  return items\n}\n\n/**\n * Using a while loop and a for loop.\n */\nexport function alternativeBubbleSort(arr) {\n  let swapped = true\n\n  while (swapped) {\n    swapped = false\n    for (let i = 0; i < arr.length - 1; i++) {\n      if (arr[i] > arr[i + 1]) {\n        ;[arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]\n        swapped = true\n      }\n    }\n  }\n\n  return arr\n}\n"
  },
  {
    "path": "Sorts/BucketSort.js",
    "content": "/**\n * BucketSort implementation.\n *\n * Wikipedia says: Bucket sort, or bin sort, is a sorting algorithm that works by distributing the elements of an array\n * into a number of buckets. Each bucket is then sorted individually, either using a different sorting algorithm, or by\n * recursively applying the bucket sorting algorithm. It is a distribution sort, and is a cousin of radix sort in the\n * most to least significant digit flavour. Bucket sort is a generalization of pigeonhole sort. Bucket sort can be\n * implemented with comparisons and therefore can also be considered a comparison sort algorithm. The computational\n * complexity estimates involve the number of buckets.\n *\n * @see https://en.wikipedia.org/wiki/Bucket_sort#:~:text=Bucket%20sort%2C%20or%20bin%20sort,applying%20the%20bucket%20sorting%20algorithm.&text=Sort%20each%20non%2Dempty%20bucket.\n *\n * Time Complexity of Solution:\n * Best Case O(n); Average Case O(n); Worst Case O(n)\n *\n * @param {number[]} list The array of numbers to be sorted.\n * @param {number} size The size of the buckets used. If not provided, size will be 5.\n * @return {number[]} An array of numbers sorted in increasing order.\n */\nexport function bucketSort(list, size) {\n  if (undefined === size) {\n    size = 5\n  }\n  if (list.length === 0) {\n    return list\n  }\n  let min = list[0]\n  let max = list[0]\n  // find min and max\n  for (let iList = 0; iList < list.length; iList++) {\n    if (list[iList] < min) {\n      min = list[iList]\n    } else if (list[iList] > max) {\n      max = list[iList]\n    }\n  }\n  // how many buckets we need\n  const count = Math.floor((max - min) / size) + 1\n\n  // create buckets\n  const buckets = []\n  for (let iCount = 0; iCount < count; iCount++) {\n    buckets.push([])\n  }\n\n  // bucket fill\n  for (let iBucket = 0; iBucket < list.length; iBucket++) {\n    const key = Math.floor((list[iBucket] - min) / size)\n    buckets[key].push(list[iBucket])\n  }\n  const sorted = []\n  // now sort every bucket and merge it to the sorted list\n  for (let iBucket = 0; iBucket < buckets.length; iBucket++) {\n    const arr = buckets[iBucket].sort((a, b) => a - b)\n    for (let iSorted = 0; iSorted < arr.length; iSorted++) {\n      sorted.push(arr[iSorted])\n    }\n  }\n  return sorted\n}\n"
  },
  {
    "path": "Sorts/CocktailShakerSort.js",
    "content": "/**\n * Cocktail Shaker Sort is an algorithm that is a Bidirectional Bubble Sort.\n *\n * The algorithm extends bubble sort by operating in two directions.\n * While it improves on bubble sort by more quickly moving items to the beginning of the list, it provides only marginal\n * performance improvements.\n *\n * Wikipedia (Cocktail Shaker Sort): https://en.wikipedia.org/wiki/Cocktail_shaker_sort\n * Wikipedia (Bubble Sort): https://en.wikipedia.org/wiki/Bubble_sort\n */\nexport function cocktailShakerSort(items) {\n  for (let i = items.length - 1; i > 0; i--) {\n    let j\n\n    // Backwards\n    for (j = items.length - 1; j > i; j--) {\n      if (items[j] < items[j - 1]) {\n        ;[items[j], items[j - 1]] = [items[j - 1], items[j]]\n      }\n    }\n\n    // Forwards\n    for (j = 0; j < i; j++) {\n      if (items[j] > items[j + 1]) {\n        ;[items[j], items[j + 1]] = [items[j + 1], items[j]]\n      }\n    }\n  }\n\n  return items\n}\n"
  },
  {
    "path": "Sorts/CombSort.js",
    "content": "/**\n * Comb sort improves on bubble sort.\n *\n * The basic idea is to eliminate turtles, or small values\n * near the end of the list, since in a bubble sort these slow the sorting\n * down tremendously. Rabbits, large values around the beginning of the list,\n * do not pose a problem in bubble sort.\n *\n * In bubble sort, when any two elements are compared, they always have a\n * gap (distance from each other) of 1. The basic idea of comb sort is\n * that the gap can be much more than 1. The inner loop of bubble sort,\n * which does the actual swap, is modified such that gap between swapped\n * elements goes down (for each iteration of outer loop) in steps of\n * a \"shrink factor\" k: [ n/k, n/k2, n/k3, ..., 1 ].\n *\n * Wikipedia: https://en.wikipedia.org/wiki/Comb_sort\n */\n\n/**\n * combSort returns an array of numbers sorted in increasing order.\n *\n * @param {number[]} list The array of numbers to sort.\n * @return {number[]} The array of numbers sorted in increasing order.\n */\nfunction combSort(list) {\n  if (list.length === 0) {\n    return list\n  }\n  const shrink = 1.3\n  let gap = list.length\n  let isSwapped = true\n  let i = 0\n\n  while (gap > 1 || isSwapped) {\n    // Update the gap value for a next comb\n    gap = parseInt(parseFloat(gap) / shrink, 10)\n\n    isSwapped = false\n    i = 0\n\n    while (gap + i < list.length) {\n      if (list[i] > list[i + gap]) {\n        ;[list[i], list[i + gap]] = [list[i + gap], list[i]]\n        isSwapped = true\n      }\n      i += 1\n    }\n  }\n  return list\n}\n\nexport { combSort }\n"
  },
  {
    "path": "Sorts/CountingSort.js",
    "content": "/**\n * Counting sort is an algorithm for sorting a collection\n * of objects according to keys that are small integers.\n *\n * It is an integer sorting algorithm.\n *\n * Wikipedia: https://en.wikipedia.org/wiki/Counting_sort\n * Animated Visual: https://www.cs.usfca.edu/~galles/visualization/CountingSort.html\n */\n\nexport const countingSort = (arr, min, max) => {\n  // Create an auxiliary resultant array\n  const res = []\n  // Create and initialize the frequency[count] array\n  const count = new Array(max - min + 1).fill(0)\n  // Populate the freq array\n  for (let i = 0; i < arr.length; i++) {\n    count[arr[i] - min]++\n  }\n  // Create a prefix sum array out of the frequency[count] array\n  count[0] -= 1\n  for (let i = 1; i < count.length; i++) {\n    count[i] += count[i - 1]\n  }\n  // Populate the result array using the prefix sum array\n  for (let i = arr.length - 1; i >= 0; i--) {\n    res[count[arr[i] - min]] = arr[i]\n    count[arr[i] - min]--\n  }\n  return res\n}\n\n/**\n * Implementation of Counting Sort\n */\n// const array = [3, 0, 2, 5, 4, 1]\n// countingSort(array, 0, 5)\n"
  },
  {
    "path": "Sorts/CycleSort.js",
    "content": "/**\n * Cycle sort is an in-place, unstable sorting algorithm,\n * a comparison sort that is theoretically optimal in terms of the total\n * number of writes to the original array, unlike any other in-place sorting\n * algorithm. It is based on the idea that the permutation to be sorted can\n * be factored into cycles, which can individually be rotated to give a sorted result.\n *\n * Wikipedia: https://en.wikipedia.org/wiki/Cycle_sort\n */\n\n/**\n * cycleSort takes an input array of numbers and returns the array sorted in increasing order.\n *\n * @param {number[]} list An array of numbers to be sorted.\n * @return {number[]} An array of numbers sorted in increasing order.\n */\nfunction cycleSort(list) {\n  for (let cycleStart = 0; cycleStart < list.length; cycleStart++) {\n    let value = list[cycleStart]\n    let position = cycleStart\n\n    // search position\n    for (let i = cycleStart + 1; i < list.length; i++) {\n      if (list[i] < value) {\n        position++\n      }\n    }\n    // if it is the same, continue\n    if (position === cycleStart) {\n      continue\n    }\n    while (value === list[position]) {\n      position++\n    }\n\n    const oldValue = list[position]\n    list[position] = value\n    value = oldValue\n\n    // rotate the rest\n    while (position !== cycleStart) {\n      position = cycleStart\n      for (let i = cycleStart + 1; i < list.length; i++) {\n        if (list[i] < value) {\n          position++\n        }\n      }\n      while (value === list[position]) {\n        position++\n      }\n      const oldValueCycle = list[position]\n      list[position] = value\n      value = oldValueCycle\n    }\n  }\n  return list\n}\n\nexport { cycleSort }\n"
  },
  {
    "path": "Sorts/DutchNationalFlagSort.js",
    "content": "/**\n * @function dutchNationalFlagSort\n * @description Dutch National Flag Sort is an algorithm to sort an array containing 0s, 1s, and 2s in linear time.\n    Time complexity of Dutch National Flag Sort Algorithm is O(n).\n    Auxiliary Space required for Dutch National Flag Sort Algorithm is O(1).\n * @param {Integer[]} nums - Array of integers containing 0s, 1s, and 2s.\n * @return {Integer[]} - Array of integers sorted in non-decreasing order.\n * @see [Dutch National Flag Sort](https://en.wikipedia.org/wiki/Dutch_national_flag_problem)\n */\nexport function dutchNationalFlagSort(nums) {\n  let low = 0\n  let mid = 0\n  let high = nums.length - 1\n\n  while (mid <= high) {\n    switch (nums[mid]) {\n      case 0:\n        ;[nums[low], nums[mid]] = [nums[mid], nums[low]]\n        low++\n        mid++\n        break\n      case 1:\n        mid++\n        break\n      case 2:\n        ;[nums[mid], nums[high]] = [nums[high], nums[mid]]\n        high--\n        break\n    }\n  }\n\n  return nums\n}\n"
  },
  {
    "path": "Sorts/FindSecondLargestElement.js",
    "content": "/*\n * Find Second Largest is a real technical interview question.\n * Chances are you will be asked to find the second largest value\n * inside of an array of numbers. You must also be able to filter\n * out duplicate values.  It's important to know how to do this with\n * clean code that is also easy to explain.\n *\n * Resources:\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set\n */\n\nconst secondLargestElement = (array) => {\n  const largestElement = Math.max(...array)\n  let element = -Number.MAX_VALUE\n\n  for (let i = 0; i < array.length; i++) {\n    if (element < array[i] && array[i] !== largestElement) {\n      element = array[i]\n    }\n  }\n\n  return element\n}\n\nexport { secondLargestElement }\n"
  },
  {
    "path": "Sorts/FisherYatesShuffle.js",
    "content": "export const shuffle = (array) => {\n  let maxLength = array.length\n  let temp\n  let idx\n\n  // While there remain elements to shuffle...\n  while (maxLength) {\n    // Pick a remaining element...\n    idx = Math.floor(Math.random() * maxLength--)\n\n    // And swap it with the current element\n    temp = array[maxLength]\n    array[maxLength] = array[idx]\n    array[idx] = temp\n  }\n\n  return array\n}\n"
  },
  {
    "path": "Sorts/FlashSort.js",
    "content": "/**\n * Flashsort is a distribution sorting algorithm showing linear\n * computational complexity O(n) for uniformly distributed\n * data sets and relatively little additional memory requirement.\n *\n * Wikipedia: https://en.wikipedia.org/wiki/Flashsort\n */\n\nexport function flashSort(arr) {\n  let max = 0\n  let min = arr[0]\n  const n = arr.length\n  const m = ~~(0.45 * n)\n  const l = new Array(m)\n\n  for (let i = 1; i < n; ++i) {\n    if (arr[i] < min) {\n      min = arr[i]\n    }\n    if (arr[i] > arr[max]) {\n      max = i\n    }\n  }\n\n  if (min === arr[max]) {\n    return arr\n  }\n\n  const c1 = (m - 1) / (arr[max] - min)\n\n  for (let k = 0; k < m; k++) {\n    l[k] = 0\n  }\n\n  for (let j = 0; j < n; ++j) {\n    const k = ~~(c1 * (arr[j] - min))\n    ++l[k]\n  }\n\n  for (let p = 1; p < m; ++p) {\n    l[p] = l[p] + l[p - 1]\n  }\n\n  let hold = arr[max]\n  arr[max] = arr[0]\n  arr[0] = hold\n\n  // permutation\n  let move = 0\n  let t\n  let flash\n  let j = 0\n  let k = m - 1\n\n  while (move < n - 1) {\n    while (j > l[k] - 1) {\n      ++j\n      k = ~~(c1 * (arr[j] - min))\n    }\n    if (k < 0) break\n    flash = arr[j]\n    while (j !== l[k]) {\n      k = ~~(c1 * (flash - min))\n      hold = arr[(t = --l[k])]\n      arr[t] = flash\n      flash = hold\n      ++move\n    }\n  }\n\n  // insertion\n  for (j = 1; j < n; j++) {\n    hold = arr[j]\n    let i = j - 1\n    while (i >= 0 && arr[i] > hold) {\n      arr[i + 1] = arr[i--]\n    }\n    arr[i + 1] = hold\n  }\n  return arr\n}\n\n/**\n * Implementation of Flash Sort\n */\n// const array = [3, 0, 2, 5, -1, 4, 1, -2]\n// flashSort(array)\n"
  },
  {
    "path": "Sorts/GnomeSort.js",
    "content": "/*\n * Gnome sort is a sort algorithm that moving an element to its proper place is accomplished by a series of swap\n * more information: https://en.wikipedia.org/wiki/Gnome_sort\n *\n */\nexport function gnomeSort(items) {\n  if (items.length <= 1) {\n    return\n  }\n\n  let i = 1\n\n  while (i < items.length) {\n    if (items[i - 1] <= items[i]) {\n      i++\n    } else {\n      ;[items[i], items[i - 1]] = [items[i - 1], items[i]]\n\n      i = Math.max(1, i - 1)\n    }\n  }\n  return items\n}\n\n// Implementation of gnomeSort\n\n// const ar = [5, 6, 7, 8, 1, 2, 12, 14]\n// gnomeSort(ar)\n"
  },
  {
    "path": "Sorts/HeapSort.js",
    "content": "/*\n * Build a max heap out of the array. A heap is a specialized tree like\n * data structure that satisfies the heap property. The heap property\n * for max heap is the following: \"if P is a parent node of C, then the\n * key (the value) of node P is greater than the key of node C\"\n * Source: https://en.wikipedia.org/wiki/Heap_(data_structure)\n */\n/* eslint no-extend-native: [\"off\", { \"exceptions\": [\"Object\"] }] */\nArray.prototype.heapify = function (index, heapSize) {\n  let largest = index\n  const leftIndex = 2 * index + 1\n  const rightIndex = 2 * index + 2\n\n  if (leftIndex < heapSize && this[leftIndex] > this[largest]) {\n    largest = leftIndex\n  }\n\n  if (rightIndex < heapSize && this[rightIndex] > this[largest]) {\n    largest = rightIndex\n  }\n\n  if (largest !== index) {\n    const temp = this[largest]\n    this[largest] = this[index]\n    this[index] = temp\n\n    this.heapify(largest, heapSize)\n  }\n}\n\n/*\n * Heap sort sorts an array by building a heap from the array and\n * utilizing the heap property.\n * For more information see: https://en.wikipedia.org/wiki/Heapsort\n */\nexport function heapSort(items) {\n  const length = items.length\n\n  for (let i = Math.floor(length / 2) - 1; i > -1; i--) {\n    items.heapify(i, length)\n  }\n  for (let j = length - 1; j > 0; j--) {\n    const tmp = items[0]\n    items[0] = items[j]\n    items[j] = tmp\n    items.heapify(0, j)\n  }\n  return items\n}\n\n// Implementation of heapSort\n\n// const ar = [5, 6, 7, 8, 1, 2, 12, 14]\n// heapSort(ar)\n"
  },
  {
    "path": "Sorts/HeapSortV2.js",
    "content": "let arrayLength = 0\n\n/* to create MAX  array */\n\nfunction heapRoot(input, i) {\n  const left = 2 * i + 1\n  const right = 2 * i + 2\n  let max = i\n\n  if (left < arrayLength && input[left] > input[max]) {\n    max = left\n  }\n\n  if (right < arrayLength && input[right] > input[max]) {\n    max = right\n  }\n\n  if (max !== i) {\n    swap(input, i, max)\n    heapRoot(input, max)\n  }\n}\n\nfunction swap(input, indexA, indexB) {\n  ;[input[indexA], input[indexB]] = [input[indexB], input[indexA]]\n}\n\nexport function heapSort(input) {\n  arrayLength = input.length\n\n  for (let i = Math.floor(arrayLength / 2); i >= 0; i -= 1) {\n    heapRoot(input, i)\n  }\n\n  for (let i = input.length - 1; i > 0; i--) {\n    swap(input, 0, i)\n    arrayLength--\n\n    heapRoot(input, 0)\n  }\n  return input\n}\n"
  },
  {
    "path": "Sorts/InsertionSort.js",
    "content": "/* In insertion sort, we divide the initial unsorted array into two parts;\n * sorted part and unsorted part. Initially the sorted part just has one\n * element (Array of only 1 element is a sorted array). We then pick up\n * element one by one from unsorted part; insert into the sorted part at\n * the correct position and expand sorted part one element at a time.\n */\n\nexport function insertionSort(unsortedList) {\n  const len = unsortedList.length\n  for (let i = 1; i < len; i++) {\n    let j\n    const tmp = unsortedList[i] // Copy of the current element.\n    /* Check through the sorted part and compare with the number in tmp. If large, shift the number */\n    for (j = i - 1; j >= 0 && unsortedList[j] > tmp; j--) {\n      // Shift the number\n      unsortedList[j + 1] = unsortedList[j]\n    }\n    // Insert the copied number at the correct position\n    // in sorted part.\n    unsortedList[j + 1] = tmp\n  }\n}\n\n/**\n * @function insertionSortAlternativeImplementation\n * @description InsertionSort is a stable sorting algorithm\n * @param {Integer[]} array - Array of integers\n * @return {Integer[]} - Sorted array\n * @see [InsertionSort](https://en.wikipedia.org/wiki/Quicksort)\n */\n\n/*\n  * Big-O Analysis\n      * Time Complexity\n        - O(N^2) on average and worst case scenario\n        - O(N) on best case scenario (when input array is already almost sorted)\n      * Space Complexity\n        - O(1)\n*/\n\nexport function insertionSortAlternativeImplementation(array) {\n  const length = array.length\n  if (length < 2) return array\n\n  for (let i = 1; i < length; i++) {\n    // Take current element in array\n    const currentItem = array[i]\n    // Take index of previous element in array\n    let j = i - 1\n\n    // While j >= 0 and previous element is greater than current element\n    while (j >= 0 && array[j] > currentItem) {\n      // Move previous, greater element towards the unsorted part\n      array[j + 1] = array[j]\n      j--\n    }\n    // Insert currentItem number at the correct position in sorted part.\n    array[j + 1] = currentItem\n  }\n  // Return array sorted in ascending order\n  return array\n}\n"
  },
  {
    "path": "Sorts/IntroSort.js",
    "content": "/**\n * @function Introsort (As implemented in STD C++ Lib)\n * The function performs introsort which is used in\n * C++ Standard LIbrary, the implementation is inspired from]\n * library routine itself.\n * ALGORITHM:\n * 1) It performs quicksort on array until the recursion depth\n *    exceeds a pre determined limit.\n * 2) If the limit is reached it switches to heapsort\n * 3) For array size less than a threshold(16) directly\n *    does insertion sort on array\n * @param {Array} array the array to be sorted\n * @param {Function} compare the comparison function\n *\n * @see [Introsort](https://en.wikipedia.org/wiki/Introsort)\n * @author [Lakhan Nad](https://github.com/Lakhan-Nad)\n */\nfunction introsort(array, compare) {\n  /**\n   * @function Default Comparison Function\n   * This function is same as implemented by\n   * Array.sort method\n   * @see [StackOverflow](https://stackoverflow.com/questions/47334234/how-to-implement-array-prototype-sort-default-compare-function)\n   * @param {*} a variable 1\n   * @param {*} b variable 2\n   * @returns {Number}\n   * -1 if a is less than b\n   *  0 if a is equal to b\n   *  1 if a greater than b\n   */\n  const defaultComparator = function (x, y) {\n    if (x === undefined && y === undefined) return 0\n    if (x === undefined) return 1\n    if (y === undefined) return -1\n    const xString = toString(x)\n    const yString = toString(y)\n    if (xString < yString) return -1\n    if (xString > yString) return 1\n    return 0\n  }\n  /**\n   * @function helper function for defaultComparator\n   * Converts a given object to String\n   * @throws TypeError()\n   * @param {Object} obj\n   * @returns {String} String representation of given object\n   */\n  const toString = function (obj) {\n    if (obj === null) return 'null'\n    if (typeof obj === 'boolean' || typeof obj === 'number') {\n      return obj.toString()\n    }\n    if (typeof obj === 'string') return obj\n    if (typeof obj === 'symbol') throw new TypeError()\n    return obj.toString()\n  }\n  /**\n   * Checks if the value passed is an array\n   * or not\n   */\n  if (Array.isArray(array) === false) {\n    return\n  }\n  /**\n   * If the compare parameter is not a function\n   * or not passed at all use default comparator\n   * function\n   */\n  if (typeof compare !== 'function') {\n    compare = defaultComparator // If compare is not a comparator function\n  }\n  /**\n   * Use a closure to define the whole sort\n   * implementation this is done through\n   * [IIFE](https://en.wikipedia.org/wiki/Immediately_invoked_function_expression)\n   */\n  return (function (array, comparator) {\n    const swap = function (index1, index2) {\n      const temp = array[index1]\n      array[index1] = array[index2]\n      array[index2] = temp\n    }\n    /**\n     * @constant THRESHOLD\n     * If the length of array is less than\n     * this then we simply perform insertion sort\n     */\n    const THRESHOLD = 16\n    /**\n     * @constant TUNEMAXDEPTH\n     * Constant used to increase or decrease value\n     * of maxDepth\n     */\n    const TUNEMAXDEPTH = 1\n    const len = array.length\n    /**\n     * Return if array is only of length 1\n     * Array of size 1 is always sorted\n     */\n    if (len === 1) {\n      return\n    }\n    /**\n     * Calculate maxDepth = log2(len)\n     * Taken from implementation in stdc++\n     */\n    const maxDepth = Math.floor(Math.log2(len)) * TUNEMAXDEPTH\n    /**\n     * The very first call to quicksort\n     * this initiates sort routine\n     */\n    quickSort(0, len, maxDepth)\n    /**\n     * A final check call to insertion sort\n     * on sorted array\n     */\n    insertionSort(0, len)\n    /** *********************  Implementation of various routines  **************************/\n    /**\n     * @function\n     * This is recursive quicksort implementation in array\n     * of segment [start,last-1]\n     * [QuickSort](https://en.wikipedia.org/wiki/Quicksort)\n     * @param {Number} start the start index of array segment to be sorted\n     * @param {Number} last  one more than the last index of array segment\n     * @param {Number} depth this measures how many recursive calls are done\n     */\n    function quickSort(start, last, depth) {\n      if (last - start <= THRESHOLD) {\n        insertionSort(start, last)\n        return\n      } else if (depth <= 0) {\n        heapSort(start, last)\n        return\n      }\n      let pivot = (last + start) >> 1\n      pivot = partition(start, last, pivot)\n      quickSort(start, pivot, depth - 1)\n      quickSort(pivot + 1, last, depth - 1)\n    }\n    /**\n     * @function Helper function to quicksort\n     * @param {Number} start the start of array segment to partition\n     * @param {Number} last  one more than last index of the array segment\n     * @param {Number} pivot the index of pivot to be used\n     * @returns {Number} the index of pivot after partition\n     */\n    function partition(start, last, pivot) {\n      swap(start, pivot)\n      pivot = start\n      let lo = start\n      let hi = last\n      while (true) {\n        lo++\n        while (comparator(array[lo], array[pivot]) <= 0 && lo !== last) {\n          lo++\n        }\n        hi--\n        while (comparator(array[hi], array[pivot]) > 0 && hi !== start) {\n          hi--\n        }\n        if (lo >= hi) {\n          break\n        }\n        swap(lo, hi)\n      }\n      swap(start, hi)\n      return hi\n    }\n    /**\n     * @function\n     * Performs insertion sort on array of range\n     * [start, last-1]\n     * @param {Number} start the first index of array segment to be sorted\n     * @param {Number} last  one more than last index of array to be sorted\n     */\n    function insertionSort(start, last) {\n      let i, j\n      for (i = start + 1; i < last; i++) {\n        j = i - 1\n        while (j >= 0 && comparator(array[j], array[j + 1]) > 0) {\n          swap(j, j + 1)\n          j--\n        }\n      }\n    }\n    /**\n     * @function\n     * Performs heapsort in array segment of range [start, last-1]\n     * [HeapSort](https://en.wikipedia.org/wiki/Heapsort)\n     * @param {Number} start the first index of array segment to be sorted\n     * @param {Number} last  one more than last index of array to be sorted\n     */\n    function heapSort(start, last) {\n      let x = (last + start) >> 1\n      while (x - start >= 0) {\n        heapify(x, start, last)\n        x--\n      }\n      x = last - 1\n      while (x - start > 0) {\n        swap(start, x)\n        heapify(start, start, x)\n        x--\n      }\n    }\n    /**\n     * @function Helper function to heapsort routine\n     * @param {Number} cur the index we need to heapify\n     * @param {Number} start the start index of array segment that cur belongs to\n     * @param {Number} last  one more than last index of segment that cur belongs to\n     */\n    function heapify(cur, start, last) {\n      const size = last - start\n      let max, lt, rt\n      cur = cur - start\n      while (true) {\n        max = cur\n        lt = 2 * max + 1\n        rt = 2 * max + 2\n        if (\n          lt < size &&\n          comparator(array[start + max], array[start + lt]) < 0\n        ) {\n          max = lt\n        }\n        if (\n          rt < size &&\n          comparator(array[start + max], array[start + rt]) < 0\n        ) {\n          max = rt\n        }\n        if (max !== cur) {\n          swap(start + cur, start + max)\n          cur = max\n        } else {\n          break\n        }\n      }\n    }\n  })(array, compare)\n}\n\n/**\n * @example Demo run of the sort routine\n * The data is randomly generated\n * Returns 'RIGHT:)' if the sort routine worked as expected,\n *         'WRONG!!' otherwise\n */\nfunction demo1() {\n  const data = []\n  const size = 1000000\n  let i = 0\n  let temp\n  const c = function (a, b) {\n    return a - b\n  }\n  for (i = 0; i < size; i++) {\n    temp = Math.random() * Number.MAX_SAFE_INTEGER\n    data.push(temp)\n  }\n  introsort(data, c)\n  let faulty = false\n  for (i = 1; i < size; i++) {\n    if (data[i] < data[i - 1]) {\n      faulty = true\n      break\n    }\n  }\n  if (faulty) {\n    return 'WRONG!!'\n  } else {\n    return 'RIGHT:)'\n  }\n}\n\n/**\n * @example Demo run of the sort routine\n * using the default compare function and\n * comparing the results with Array.sort\n */\nfunction demo2() {\n  const data = []\n  const data2 = []\n  const size = 1000000\n  let i = 0\n  let temp\n  for (i = 0; i < size; i++) {\n    temp = Math.random() * Number.MAX_SAFE_INTEGER\n    data.push(temp)\n    data2.push(temp)\n  }\n  introsort(data)\n  data2.sort()\n  let faulty = false\n  for (i = 1; i < size; i++) {\n    if (data[i] !== data2[i]) {\n      faulty = true\n      break\n    }\n  }\n  if (faulty) {\n    return 'WRONG Implemented Comparator!!'\n  } else {\n    return 'Comparator Works Fine:)'\n  }\n}\n\nexport { introsort, demo1, demo2 }\n"
  },
  {
    "path": "Sorts/MergeSort.js",
    "content": "/*\n * MergeSort implementation.\n *\n * Merge Sort is an algorithm where the main list is divided down into two half sized lists, which then have merge sort\n * called on these two smaller lists recursively until there is only a sorted list of one.\n *\n * On the way up the recursive calls, the lists will be merged together inserting\n * the smaller value first, creating a larger sorted list.\n */\n\n/**\n * Sort and merge two given arrays.\n *\n * @param {Array} list1 Sublist to break down.\n * @param {Array} list2 Sublist to break down.\n * @return {Array} The merged list.\n */\nexport function merge(list1, list2) {\n  const results = []\n  let i = 0\n  let j = 0\n\n  while (i < list1.length && j < list2.length) {\n    if (list1[i] < list2[j]) {\n      results.push(list1[i++])\n    } else {\n      results.push(list2[j++])\n    }\n  }\n\n  return results.concat(list1.slice(i), list2.slice(j))\n}\n\n/**\n * Break down the lists into smaller pieces to be merged.\n *\n * @param {Array} list List to be sorted.\n * @return {Array} The sorted list.\n */\nexport function mergeSort(list) {\n  if (list.length < 2) return list\n\n  const listHalf = Math.floor(list.length / 2)\n  const subList1 = list.slice(0, listHalf)\n  const subList2 = list.slice(listHalf, list.length)\n\n  return merge(mergeSort(subList1), mergeSort(subList2))\n}\n"
  },
  {
    "path": "Sorts/OddEvenSort.js",
    "content": "/*\n  odd–even sort or odd–even transposition sort\n  is a relatively simple sorting algorithm, developed originally for use on parallel processors with local interconnections.\n  It is a comparison sort related to bubble sort, with which it shares many characteristics.\n\n   for more information : https://en.wikipedia.org/wiki/Odd%E2%80%93even_sort\n*/\n\n// Helper function to swap array items\nfunction swap(arr, i, j) {\n  const tmp = arr[i]\n  arr[i] = arr[j]\n  arr[j] = tmp\n}\n\nexport function oddEvenSort(arr) {\n  let sorted = false\n  while (!sorted) {\n    sorted = true\n    for (let i = 1; i < arr.length - 1; i += 2) {\n      if (arr[i] > arr[i + 1]) {\n        swap(arr, i, i + 1)\n        sorted = false\n      }\n    }\n    for (let i = 0; i < arr.length - 1; i += 2) {\n      if (arr[i] > arr[i + 1]) {\n        swap(arr, i, i + 1)\n        sorted = false\n      }\n    }\n  }\n  return arr\n}\n"
  },
  {
    "path": "Sorts/PancakeSort.js",
    "content": "/*\n * Unlike a traditional sorting algorithm, which attempts to sort with the fewest\n * comparisons possible, the goal of pancake sort is to sort the sequence in as few reversals as\n * possible. The idea is to do something similar to Selection Sort. We one by one place\n * maximum element at the end and reduce the size of current array by one.\n *\n * Source: https://www.geeksforgeeks.org/pancake-sorting/\n *\n * This sorting algorithm is inspired by the pancake problem (hence the name),\n * where a spatula can be placed anywhere between two pancakes and flip all pancakes\n * above.\n *\n * The interesting about this algorithm (besides its name) is that instead of comparisons,\n * the algorithm relies on flipping an array.\n *\n * Source: https://en.wikipedia.org/wiki/Pancake_sorting#The_original_pancake_problem\n *\n */\n\n/**\n * Unlike Array.prototype.reverse, flipArray reverses only a subarray of the given\n * array, determined by the parameters startIndex and endIndex\n *\n * @param {number[]} array The array to flip\n * @param {number} startIndex The start of the subarray\n * @param {number} endIndex The end of the subarray\n * @returns The flipped array\n */\nexport function flipArray(array, startIndex, endIndex) {\n  while (startIndex < endIndex) {\n    // swap front and back of the subarray\n    const temp = array[startIndex]\n    array[startIndex] = array[endIndex]\n    array[endIndex] = temp\n\n    // essentially reducing the problem to a smaller subarray\n    startIndex++\n    endIndex--\n  }\n\n  return array\n}\n\n/**\n * Returns the index of the maximum number of a subarray in a given array\n *\n * @param {number[]} array The array to found the maximum number's index\n * @param {*} startIndex The start of the subarray\n * @param {*} endIndex The end of the subarray\n * @returns The index of the maximum number\n */\nexport function findMax(array, startIndex, endIndex) {\n  let maxIndex = 0\n  for (let i = startIndex; i <= endIndex; i++) {\n    if (array[i] > array[maxIndex]) maxIndex = i\n  }\n\n  return maxIndex\n}\n\n/**\n * The Pancake Sort algorithm.\n *\n * Note that even though it's a completely different concept of sorting an\n * array, it's rather simple!\n *\n * @param {number[]} array The array to sort\n * @returns The sorted array\n */\nexport function pancakeSort(array) {\n  for (let subarraySize = array.length; subarraySize > 1; subarraySize--) {\n    const maximumIndex = findMax(array, 0, subarraySize - 1)\n\n    if (maximumIndex !== subarraySize - 1) {\n      flipArray(array, 0, maximumIndex)\n      flipArray(array, 0, subarraySize - 1)\n    }\n  }\n\n  return array\n}\n"
  },
  {
    "path": "Sorts/PigeonHoleSort.js",
    "content": "/*\nhttps://en.wikipedia.org/wiki/Pigeonhole_sort\n\n*Pigeonhole sorting is a sorting algorithm that is suitable\n* for sorting lists of elements where the number of elements\n* (n) and the length of the range of possible key values (N)\n* are approximately the same.\n */\nexport function pigeonHoleSort(arr) {\n  let min = arr[0]\n  let max = arr[0]\n\n  for (let i = 0; i < arr.length; i++) {\n    if (arr[i] > max) {\n      max = arr[i]\n    }\n    if (arr[i] < min) {\n      min = arr[i]\n    }\n  }\n\n  const range = max - min + 1\n  const pigeonhole = Array(range).fill(0)\n\n  for (let i = 0; i < arr.length; i++) {\n    pigeonhole[arr[i] - min]++\n  }\n\n  let index = 0\n\n  for (let j = 0; j < range; j++) {\n    while (pigeonhole[j]-- > 0) {\n      arr[index++] = j + min\n    }\n  }\n  return arr\n}\n"
  },
  {
    "path": "Sorts/QuickSort.js",
    "content": "/**\n * @function QuickSort\n * @description Quick sort is a comparison sorting algorithm that uses a divide and conquer strategy.\n * @param {Integer[]} items - Array of integers\n * @return {Integer[]} - Sorted array.\n * @see [QuickSort](https://en.wikipedia.org/wiki/Quicksort)\n */\nfunction quickSort(items) {\n  const length = items.length\n\n  if (length <= 1) {\n    return items\n  }\n  const PIVOT = items[0]\n  const GREATER = []\n  const LESSER = []\n\n  for (let i = 1; i < length; i++) {\n    if (items[i] > PIVOT) {\n      GREATER.push(items[i])\n    } else {\n      LESSER.push(items[i])\n    }\n  }\n\n  const sorted = [...quickSort(LESSER), PIVOT, ...quickSort(GREATER)]\n  return sorted\n}\n\nexport { quickSort }\n"
  },
  {
    "path": "Sorts/QuickSortRecursive.js",
    "content": "/*\n    Quicksort is the most popular sorting algorithm and there have\n    lots of different implementations but the \"recursive\" or \"Partition in place\"\n    is one of the most efficient implementations below we have discussed how to\n    implement it.\n\n    Partition in place => \"in place\" Partition in place indicates that we\n    do not need any other space to store the auxiliary array and the term\n    \"partition\" denotes that we split the list into two parts one is less\n    than the pivot and the other is greater than the pivot and repeats this\n    process recursively and breaks the problem into sub-problems and makes\n    it singular so that the behavior or \"divide and conquer\" get involved\n    too.\n\n    Problem & Source of Explanation => https://www.cs.auckland.ac.nz/software/AlgAnim/qsort1a.html\n*/\n\n/**\n * Partition in place QuickSort.\n * @param {number[]} inputList list of values.\n * @param {number} low lower index for partition.\n * @param {number} high higher index for partition.\n */\nconst quickSort = (inputList, low, high) => {\n  if (!Array.isArray(inputList)) {\n    throw new TypeError('Please input a valid list or array.')\n  }\n  if (low < high) {\n    // get the partition index.\n    const pIndex = partition(inputList, low, high)\n    // recursively call the quickSort method again.\n    quickSort(inputList, low, pIndex - 1)\n    quickSort(inputList, pIndex + 1, high)\n  }\n  return inputList\n}\n\n/**\n * Partition In Place method.\n * @param {number[]} partitionList list for partitioning.\n * @param {number} low lower index for partition.\n * @param {number} high higher index for partition.\n * @returns {number} `pIndex` pivot index value.\n */\nconst partition = (partitionList, low, high) => {\n  const pivot = partitionList[high]\n  let pIndex = low\n  for (let index = low; index <= high - 1; index++) {\n    if (partitionList[index] < pivot) {\n      // swap variables using array destructuring\n      ;[partitionList[index], partitionList[pIndex]] = [\n        partitionList[pIndex],\n        partitionList[index]\n      ]\n      pIndex += 1\n    }\n  }\n  ;[partitionList[pIndex], partitionList[high]] = [\n    partitionList[high],\n    partitionList[pIndex]\n  ]\n  return pIndex\n}\n\nexport { quickSort }\n"
  },
  {
    "path": "Sorts/RadixSort.js",
    "content": "/*\n * Radix sorts an integer array without comparing the integers.\n * It groups the integers by their digits which share the same\n * significant position.\n * For more information see: https://en.wikipedia.org/wiki/Radix_sort\n */\nexport function radixSort(items, RADIX) {\n  // default radix is then because we usually count to base 10\n  if (RADIX === undefined || RADIX < 1) {\n    RADIX = 10\n  }\n\n  let maxLength = false\n  let placement = 1\n\n  while (!maxLength) {\n    maxLength = true\n    const buckets = []\n\n    for (let i = 0; i < RADIX; i++) {\n      buckets.push([])\n    }\n\n    for (let j = 0; j < items.length; j++) {\n      const tmp = items[j] / placement\n      buckets[Math.floor(tmp % RADIX)].push(items[j])\n      if (maxLength && tmp > 0) {\n        maxLength = false\n      }\n    }\n\n    let a = 0\n    for (let b = 0; b < RADIX; b++) {\n      const buck = buckets[b]\n      for (let k = 0; k < buck.length; k++) {\n        items[a] = buck[k]\n        a++\n      }\n    }\n    placement *= RADIX\n  }\n  return items\n}\n"
  },
  {
    "path": "Sorts/SelectionSort.js",
    "content": "/* The selection sort algorithm sorts an array by repeatedly finding the minimum element\n *(considering ascending order) from unsorted part and putting it at the beginning. The\n *algorithm maintains two subarrays in a given array.\n *1) The subarray which is already sorted.\n *2) Remaining subarray which is unsorted.\n *\n *In every iteration of selection sort, the minimum element (considering ascending order)\n *from the unsorted subarray is picked and moved to the sorted subarray.\n */\n\nexport const selectionSort = (list) => {\n  if (!Array.isArray(list)) {\n    throw new TypeError('Given input is not an array')\n  }\n  const items = [...list] // We don't want to modify the original array\n  const length = items.length\n  for (let i = 0; i < length - 1; i++) {\n    if (typeof items[i] !== 'number') {\n      throw new TypeError('One of the items in your array is not a number')\n    }\n    // Number of passes\n    let min = i // min holds the current minimum number position for each pass; i holds the Initial min number\n    for (let j = i + 1; j < length; j++) {\n      // Note that j = i + 1 as we only need to go through unsorted array\n      if (items[j] < items[min]) {\n        // Compare the numbers\n        min = j // Change the current min number position if a smaller num is found\n      }\n    }\n    if (min !== i) {\n      // After each pass, if the current min num != initial min num, exchange the position.\n      // Swap the numbers\n      ;[items[i], items[min]] = [items[min], items[i]]\n    }\n  }\n  return items\n}\n"
  },
  {
    "path": "Sorts/ShellSort.js",
    "content": "/*\n * Shell Sort sorts an array based on  insertion sort algorithm\n * more information: https://en.wikipedia.org/wiki/Shellsort\n *\n */\nexport function shellSort(items) {\n  let interval = 1\n\n  while (interval < items.length / 3) {\n    interval = interval * 3 + 1\n  }\n\n  while (interval > 0) {\n    for (let outer = interval; outer < items.length; outer++) {\n      const value = items[outer]\n      let inner = outer\n\n      while (inner > interval - 1 && items[inner - interval] >= value) {\n        items[inner] = items[inner - interval]\n        inner = inner - interval\n      }\n      items[inner] = value\n    }\n    interval = (interval - 1) / 3\n  }\n  return items\n}\n"
  },
  {
    "path": "Sorts/SimplifiedWiggleSort.js",
    "content": "/*\n * Wiggle sort sorts the array into a wave like array.\n * An array ‘arr[0..n-1]’ is sorted in wave form if arr[0] <= arr[1] >= arr[2] <= arr[3] >= arr[4] <= …..\n * KEEP IN MIND: there are also more strict definitions of wiggle sort which use\n * the rule arr[0] < arr[1] > arr[2] < arr[3] > arr[4] < … but this function\n * allows for equality of values next to each other.\n */\nimport { quickSelectSearch } from '../Search/QuickSelectSearch.js'\n\nexport const simplifiedWiggleSort = function (arr) {\n  // find Median using QuickSelect\n  let median = quickSelectSearch(arr, Math.floor(arr.length / 2.0))\n  median = median[Math.floor(arr.length / 2.0)]\n\n  const sorted = new Array(arr.length)\n\n  let smallerThanMedianIndx = 0\n  let greaterThanMedianIndx = arr.length - 1 - (arr.length % 2)\n\n  for (let i = 0; i < arr.length; i++) {\n    if (arr[i] > median) {\n      sorted[greaterThanMedianIndx] = arr[i]\n      greaterThanMedianIndx -= 2\n    } else {\n      if (smallerThanMedianIndx < arr.length) {\n        sorted[smallerThanMedianIndx] = arr[i]\n        smallerThanMedianIndx += 2\n      } else {\n        sorted[greaterThanMedianIndx] = arr[i]\n        greaterThanMedianIndx -= 2\n      }\n    }\n  }\n\n  return sorted\n}\n"
  },
  {
    "path": "Sorts/StoogeSort.js",
    "content": "/*\n * Stooge Sort sorts an array based on divide and conquer principle\n * note the exceptionally bad time complexity\n * more information: https://en.wikipedia.org/wiki/Stooge_sort\n *\n */\nexport function stoogeSort(items, leftEnd, rightEnd) {\n  if (items[rightEnd - 1] < items[leftEnd]) {\n    const temp = items[leftEnd]\n    items[leftEnd] = items[rightEnd - 1]\n    items[rightEnd - 1] = temp\n  }\n  const length = rightEnd - leftEnd\n  if (length > 2) {\n    const third = Math.floor(length / 3)\n    stoogeSort(items, leftEnd, rightEnd - third)\n    stoogeSort(items, leftEnd + third, rightEnd)\n    stoogeSort(items, leftEnd, rightEnd - third)\n  }\n  return items\n}\n"
  },
  {
    "path": "Sorts/SwapSort.js",
    "content": "/**\n * @function SwapSort\n * @description Swap Sort is an algorithm to find the number of swaps required to sort an array.\n    Time complexity of Swap Sort Algorithm is O(nlogn).\n    Auxiliary Space required for Swap Sort Algorithm is O(n).\n * @param {Integer[]} items - Array of integers\n * @return {Integer} - Number of swaps required to sort the array.\n * @see [SwapSort](https://www.geeksforgeeks.org/minimum-number-swaps-required-sort-array/)\n */\n\nexport function minSwapsToSort(items) {\n  const sortedArray = items.slice()\n  sortedArray.sort()\n  const indexMap = {}\n  for (let i = 0; i < items.length; i++) {\n    indexMap[items[i]] = i\n  }\n  let swaps = 0\n  for (let i = 0; i < items.length; i++) {\n    if (items[i] !== sortedArray[i]) {\n      const temp = items[i]\n      items[i] = items[indexMap[sortedArray[i]]]\n      items[indexMap[sortedArray[i]]] = temp\n\n      indexMap[temp] = indexMap[sortedArray[i]]\n      indexMap[sortedArray[i]] = i\n      swaps++\n    }\n  }\n  return swaps\n}\n"
  },
  {
    "path": "Sorts/TimSort.js",
    "content": "/**\n *  @function Timsort is a hybrid stable sorting algorithm, derived from merge sort and insertion sort,\n *  designed to perform well on many kinds of real-world data.\n *  It was implemented by Tim Peters in 2002 for use in the Python programming language.\n *  It is also used to sort arrays of non-primitive type in Java SE 7,\n *  on the Android platform, in GNU Octave, on V8, Swift and Rust.\n *  1) It sorts small partitions using Insertion Sort.\n *  2) Merges the partition using Merge Sort.\n *  @see [Timsort](https://en.wikipedia.org/wiki/Timsort)\n *  @param {Array} array\n */\n\nconst Timsort = (array) => {\n  // Default size of a partition\n  const RUN = 32\n  const n = array.length\n  // Sorting the partitions using Insertion Sort\n  for (let i = 0; i < n; i += RUN) {\n    InsertionSort(array, i, Math.min(i + RUN - 1, n - 1))\n  }\n  for (let size = RUN; size < n; size *= 2) {\n    for (let left = 0; left < n; left += 2 * size) {\n      const mid = left + size - 1\n      const right = Math.min(left + 2 * size - 1, n - 1)\n      Merge(array, left, mid, right)\n    }\n  }\n  return array\n}\n\n/**\n * @function performs insertion sort on the partition\n * @param {Array} array array to be sorted\n * @param {Number} left left index of partition\n * @param {Number} right right index of partition\n */\n\nconst InsertionSort = (array, left, right) => {\n  for (let i = left + 1; i <= right; i++) {\n    const key = array[i]\n    let j = i - 1\n    while (j >= left && array[j] > key) {\n      array[j + 1] = array[j]\n      j--\n    }\n    array[j + 1] = key\n  }\n}\n\n/**\n * @function merges two sorted partitions\n * @param {Array} array array to be sorted\n * @param {Number} left left index of partition\n * @param {Number} mid mid index of partition\n * @param {Number} right right index of partition\n */\n\nconst Merge = (array, left, mid, right) => {\n  if (mid >= right) return\n  const len1 = mid - left + 1\n  const len2 = right - mid\n  const larr = Array(len1)\n  const rarr = Array(len2)\n  for (let i = 0; i < len1; i++) {\n    larr[i] = array[left + i]\n  }\n  for (let i = 0; i < len2; i++) {\n    rarr[i] = array[mid + 1 + i]\n  }\n  let i = 0\n  let j = 0\n  let k = left\n  while (i < larr.length && j < rarr.length) {\n    if (larr[i] < rarr[j]) {\n      array[k++] = larr[i++]\n    } else {\n      array[k++] = rarr[j++]\n    }\n  }\n  while (i < larr.length) {\n    array[k++] = larr[i++]\n  }\n  while (j < rarr.length) {\n    array[k++] = rarr[j++]\n  }\n}\n\n/**\n * @example Test of Timsort functions.\n * Data is randomly generated.\n * Return \"RIGHT\" if it works as expected,\n * otherwise \"FAULTY\"\n */\nconst demo = () => {\n  const size = 1000000\n  const data = Array(size)\n  for (let i = 0; i < size; i++) {\n    data[i] = Math.random() * Number.MAX_SAFE_INTEGER\n  }\n  const isSorted = function (array) {\n    const n = array.length\n    for (let i = 0; i < n - 1; i++) {\n      if (array[i] > array[i + 1]) return false\n    }\n    return true\n  }\n  Timsort(data)\n  if (isSorted(data)) {\n    return 'RIGHT'\n  } else {\n    return 'FAULTY'\n  }\n}\n\nexport { Timsort, demo }\n"
  },
  {
    "path": "Sorts/TopologicalSort.js",
    "content": "export function TopologicalSorter() {\n  const graph = {}\n  let isVisitedNode\n  let finishTimeCount\n  let finishingTimeList\n  let nextNode\n\n  this.addOrder = function (nodeA, nodeB) {\n    nodeA = String(nodeA)\n    nodeB = String(nodeB)\n    graph[nodeA] = graph[nodeA] || []\n    graph[nodeA].push(nodeB)\n  }\n\n  this.sortAndGetOrderedItems = function () {\n    isVisitedNode = Object.create(null)\n    finishTimeCount = 0\n    finishingTimeList = []\n\n    for (const node in graph) {\n      if (\n        Object.prototype.hasOwnProperty.call(graph, node) &&\n        !isVisitedNode[node]\n      ) {\n        dfsTraverse(node)\n      }\n    }\n\n    finishingTimeList.sort(function (item1, item2) {\n      return item1.finishTime > item2.finishTime ? -1 : 1\n    })\n\n    return finishingTimeList.map(function (value) {\n      return value.node\n    })\n  }\n\n  function dfsTraverse(node) {\n    isVisitedNode[node] = true\n    if (graph[node]) {\n      for (let i = 0; i < graph[node].length; i++) {\n        nextNode = graph[node][i]\n        if (isVisitedNode[nextNode]) continue\n        dfsTraverse(nextNode)\n      }\n    }\n\n    finishingTimeList.push({\n      node,\n      finishTime: ++finishTimeCount\n    })\n  }\n}\n\n/* TEST */\n// const topoSorter = new TopologicalSorter()\n// topoSorter.addOrder(5, 2)\n// topoSorter.addOrder(5, 0)\n// topoSorter.addOrder(4, 0)\n// topoSorter.addOrder(4, 1)\n// topoSorter.addOrder(2, 3)\n// topoSorter.addOrder(3, 1)\n// topoSorter.sortAndGetOrderedItems()\n"
  },
  {
    "path": "Sorts/test/AlphaNumericalSort.test.js",
    "content": "import { alphaNumericalSort } from '../AlphaNumericalSort'\n\ndescribe('alphaNumericalComparer', () => {\n  test('given array of eng symbols return correct sorted array', () => {\n    const src = ['b', 'a', 'c']\n    src.sort(alphaNumericalSort)\n    expect(src).toEqual(['a', 'b', 'c'])\n  })\n\n  test('given array of numbers return correct sorted array', () => {\n    const src = ['15', '0', '5']\n    src.sort(alphaNumericalSort)\n    expect(src).toEqual(['0', '5', '15'])\n  })\n\n  test('correct sort with numbers and strings', () => {\n    const src = ['3', 'a1b15c', 'z', 'a1b14c']\n    src.sort(alphaNumericalSort)\n    expect(src).toEqual(['3', 'a1b14c', 'a1b15c', 'z'])\n  })\n\n  test('correct sort with long numbers', () => {\n    const src = [\n      'abc999999999999999999999999999999999cba',\n      'abc999999999999999999999999999999990cba',\n      'ab'\n    ]\n    src.sort(alphaNumericalSort)\n    expect(src).toEqual([\n      'ab',\n      'abc999999999999999999999999999999990cba',\n      'abc999999999999999999999999999999999cba'\n    ])\n  })\n\n  test('correct sort with z prefix', () => {\n    const src = ['z', 'abc003def', 'abc1def', 'a']\n    src.sort(alphaNumericalSort)\n    expect(src).toEqual(['a', 'abc1def', 'abc003def', 'z'])\n  })\n\n  test('correct sort with other language', () => {\n    const src = ['а10б', 'а2б', 'в10г', 'в05г']\n    src.sort(alphaNumericalSort)\n    expect(src).toEqual(['а2б', 'а10б', 'в05г', 'в10г'])\n  })\n})\n"
  },
  {
    "path": "Sorts/test/BeadSort.test.js",
    "content": "import { beadSort } from '../BeadSort'\n\ndescribe('BeadSort', () => {\n  it('should sort arrays correctly', () => {\n    expect(beadSort([5, 4, 3, 2, 1])).toEqual([1, 2, 3, 4, 5])\n    expect(beadSort([7, 9, 4, 3, 5])).toEqual([3, 4, 5, 7, 9])\n  })\n\n  it('should throw a RangeError when the array contains negative integers', () => {\n    expect(() => beadSort([-1, 5, 8, 4, 3, 19])).toThrow(RangeError)\n  })\n})\n"
  },
  {
    "path": "Sorts/test/BinaryInsertionSort.test.js",
    "content": "import { binaryInsertionSort } from '../BinaryInsertionSort'\n\ndescribe('BinaryInsertionSort', () => {\n  it('should sort arrays correctly', () => {\n    expect(binaryInsertionSort([5, 4, 3, 2, 1])).toEqual([1, 2, 3, 4, 5])\n    expect(binaryInsertionSort([7, 9, 4, 3, 5])).toEqual([3, 4, 5, 7, 9])\n  })\n})\n"
  },
  {
    "path": "Sorts/test/BogoSort.test.js",
    "content": "import { bogoSort, isSorted } from '../BogoSort'\n\ndescribe('isSorted', () => {\n  it('should return true for empty arrays', () => {\n    expect(isSorted([])).toBe(true)\n  })\n\n  it('should return true for single-element arrays', () => {\n    expect(isSorted([1])).toBe(true)\n  })\n\n  it('should return true for arrays that are properly sorted', () => {\n    expect(isSorted([1, 2, 3])).toBe(true)\n  })\n\n  it('should return false for arrays that are not properly sorted', () => {\n    expect(isSorted([3, 2, 1])).toBe(false)\n  })\n})\n\ndescribe('bogoSort', () => {\n  it('should (eventually) sort the array', () => {\n    expect(bogoSort([5, 6, 7, 8, 1, 2, 12, 14])).toEqual([\n      1, 2, 5, 6, 7, 8, 12, 14\n    ])\n  })\n})\n"
  },
  {
    "path": "Sorts/test/BubbleSort.test.js",
    "content": "import { alternativeBubbleSort, bubbleSort } from '../BubbleSort'\n\ndescribe('bubbleSort', () => {\n  it('should sort arrays correctly', () => {\n    expect(bubbleSort([5, 4, 1, 2, 3])).toEqual([1, 2, 3, 4, 5])\n    expect(bubbleSort([])).toEqual([])\n    expect(bubbleSort([1, 2, 3])).toEqual([1, 2, 3])\n    expect(bubbleSort([5, 6, 7, 8, 1, 2, 12, 14])).toEqual([\n      1, 2, 5, 6, 7, 8, 12, 14\n    ])\n    expect(bubbleSort([5, 6, 7, 8, 9, 4])).toEqual([4, 5, 6, 7, 8, 9])\n    expect(bubbleSort([20, 30, 40])).toEqual([20, 30, 40])\n    expect(bubbleSort([2, 1, 3])).toEqual([1, 2, 3])\n    expect(bubbleSort([10, 15, 16, 100])).toEqual([10, 15, 16, 100])\n    expect(bubbleSort([10, 9, 11])).toEqual([9, 10, 11])\n    expect(bubbleSort([10, 9, 12])).toEqual([9, 10, 12])\n    expect(bubbleSort([3, 2, 1])).toEqual([1, 2, 3])\n    expect(bubbleSort([10, 9, 8])).toEqual([8, 9, 10])\n  })\n})\n\ndescribe('alternativeBubbleSort', () => {\n  it('should sort arrays correctly', () => {\n    expect(alternativeBubbleSort([5, 4, 1, 2, 3])).toEqual([1, 2, 3, 4, 5])\n    expect(alternativeBubbleSort([])).toEqual([])\n    expect(alternativeBubbleSort([1, 2, 3])).toEqual([1, 2, 3])\n    expect(alternativeBubbleSort([5, 6, 7, 8, 1, 2, 12, 14])).toEqual([\n      1, 2, 5, 6, 7, 8, 12, 14\n    ])\n  })\n})\n"
  },
  {
    "path": "Sorts/test/BucketSort.test.js",
    "content": "import { bucketSort } from '../BucketSort'\n\ndescribe('Tests for bucketSort function', () => {\n  it('should correctly sort an input list that is sorted backwards', () => {\n    const array = [5, 4, 3, 2, 1]\n    expect(bucketSort(array)).toEqual([1, 2, 3, 4, 5])\n  })\n\n  it('should correctly sort an input list that is unsorted', () => {\n    const array = [15, 24, 3, 2224, 1]\n    expect(bucketSort(array)).toEqual([1, 3, 15, 24, 2224])\n  })\n\n  describe('Variations of input array lengths', () => {\n    it('should return an empty list with the input list is an empty list', () => {\n      expect(bucketSort([])).toEqual([])\n    })\n\n    it('should correctly sort an input list of length 1', () => {\n      expect(bucketSort([100])).toEqual([100])\n    })\n\n    it('should correctly sort an input list of an odd length', () => {\n      expect(bucketSort([101, -10, 321])).toEqual([-10, 101, 321])\n    })\n\n    it('should correctly sort an input list of an even length', () => {\n      expect(bucketSort([40, 42, 56, 45, 12, 3])).toEqual([\n        3, 12, 40, 42, 45, 56\n      ])\n    })\n  })\n\n  describe('Variations of input array elements', () => {\n    it('should correctly sort an input list that contains only positive numbers', () => {\n      expect(bucketSort([50, 33, 11, 2])).toEqual([2, 11, 33, 50])\n    })\n\n    it('should correctly sort an input list that contains only negative numbers', () => {\n      expect(bucketSort([-1, -21, -2, -35])).toEqual([-35, -21, -2, -1])\n    })\n\n    it('should correctly sort an input list that contains only a mix of positive and negative numbers', () => {\n      expect(bucketSort([-40, 42, 56, -45, 12, -3])).toEqual([\n        -45, -40, -3, 12, 42, 56\n      ])\n    })\n\n    it('should correctly sort an input list that contains only whole numbers', () => {\n      expect(bucketSort([11, 3, 12, 4, -15])).toEqual([-15, 3, 4, 11, 12])\n    })\n\n    it('should correctly sort an input list that contains only decimal numbers', () => {\n      expect(bucketSort([1.0, 1.42, 2.56, 33.45, 13.12, 2.3])).toEqual([\n        1.0, 1.42, 2.3, 2.56, 13.12, 33.45\n      ])\n    })\n\n    it('should correctly sort an input list that contains only a mix of whole and decimal', () => {\n      expect(bucketSort([32.4, 12.42, 56, 45, 12, 3])).toEqual([\n        3, 12, 12.42, 32.4, 45, 56\n      ])\n    })\n\n    it('should correctly sort an input list that contains only fractional numbers', () => {\n      expect(bucketSort([0.98, 0.4259, 0.56, -0.456, -0.12, 0.322])).toEqual([\n        -0.456, -0.12, 0.322, 0.4259, 0.56, 0.98\n      ])\n    })\n\n    it('should correctly sort an input list that contains only a mix of whole, decimal, and fractional', () => {\n      expect(bucketSort([-40, -0.222, 5.6, -4.5, 12, 0.333])).toEqual([\n        -40, -4.5, -0.222, 0.333, 5.6, 12\n      ])\n    })\n\n    it('should correctly sort an input list that contains duplicates', () => {\n      expect(bucketSort([4, 3, 4, 2, 1, 2])).toEqual([1, 2, 2, 3, 4, 4])\n    })\n  })\n})\n"
  },
  {
    "path": "Sorts/test/CocktailShakerSort.test.js",
    "content": "import { cocktailShakerSort } from '../CocktailShakerSort'\n\ndescribe('CocktailShakerSort', () => {\n  it('should sort arrays correctly', () => {\n    expect(cocktailShakerSort([5, 4, 1, 2, 3])).toEqual([1, 2, 3, 4, 5])\n    expect(cocktailShakerSort([1, 2, 3])).toEqual([1, 2, 3])\n    expect(cocktailShakerSort([5, 6, 7, 8, 1, 2, 12, 14])).toEqual([\n      1, 2, 5, 6, 7, 8, 12, 14\n    ])\n  })\n\n  it('should work for empty arrays, too', () => {\n    expect(cocktailShakerSort([])).toEqual([])\n  })\n})\n"
  },
  {
    "path": "Sorts/test/CombSort.test.js",
    "content": "import { combSort } from '../CombSort'\n\ndescribe('combSort function', () => {\n  it('should correctly sort an input list that is sorted backwards', () => {\n    const array = [5, 4, 3, 2, 1]\n    expect(combSort(array)).toEqual([1, 2, 3, 4, 5])\n  })\n\n  it('should correctly sort an input list that is unsorted', () => {\n    const array = [15, 24, 3, 2224, 1]\n    expect(combSort(array)).toEqual([1, 3, 15, 24, 2224])\n  })\n\n  describe('Variations of input array lengths', () => {\n    it('should return an empty list with the input list is an empty list', () => {\n      expect(combSort([])).toEqual([])\n    })\n\n    it('should correctly sort an input list of length 1', () => {\n      expect(combSort([100])).toEqual([100])\n    })\n\n    it('should correctly sort an input list of an odd length', () => {\n      expect(combSort([101, -10, 321])).toEqual([-10, 101, 321])\n    })\n\n    it('should correctly sort an input list of an even length', () => {\n      expect(combSort([40, 42, 56, 45, 12, 3])).toEqual([3, 12, 40, 42, 45, 56])\n    })\n  })\n\n  describe('Variations of input array elements', () => {\n    it('should correctly sort an input list that contains only positive numbers', () => {\n      expect(combSort([50, 33, 11, 2])).toEqual([2, 11, 33, 50])\n    })\n\n    it('should correctly sort an input list that contains only negative numbers', () => {\n      expect(combSort([-1, -21, -2, -35])).toEqual([-35, -21, -2, -1])\n    })\n\n    it('should correctly sort an input list that contains only a mix of positive and negative numbers', () => {\n      expect(combSort([-40, 42, 56, -45, 12, -3])).toEqual([\n        -45, -40, -3, 12, 42, 56\n      ])\n    })\n\n    it('should correctly sort an input list that contains only whole numbers', () => {\n      expect(combSort([11, 3, 12, 4, -15])).toEqual([-15, 3, 4, 11, 12])\n    })\n\n    it('should correctly sort an input list that contains only decimal numbers', () => {\n      expect(combSort([1.0, 1.42, 2.56, 33.45, 13.12, 2.3])).toEqual([\n        1.0, 1.42, 2.3, 2.56, 13.12, 33.45\n      ])\n    })\n\n    it('should correctly sort an input list that contains only a mix of whole and decimal', () => {\n      expect(combSort([32.4, 12.42, 56, 45, 12, 3])).toEqual([\n        3, 12, 12.42, 32.4, 45, 56\n      ])\n    })\n\n    it('should correctly sort an input list that contains only fractional numbers', () => {\n      expect(combSort([0.98, 0.4259, 0.56, -0.456, -0.12, 0.322])).toEqual([\n        -0.456, -0.12, 0.322, 0.4259, 0.56, 0.98\n      ])\n    })\n\n    it('should correctly sort an input list that contains only a mix of whole, decimal, and fractional', () => {\n      expect(combSort([-40, -0.222, 5.6, -4.5, 12, 0.333])).toEqual([\n        -40, -4.5, -0.222, 0.333, 5.6, 12\n      ])\n    })\n\n    it('should correctly sort an input list that contains duplicates', () => {\n      expect(combSort([4, 3, 4, 2, 1, 2])).toEqual([1, 2, 2, 3, 4, 4])\n    })\n  })\n})\n"
  },
  {
    "path": "Sorts/test/CountingSort.test.js",
    "content": "import { countingSort } from '../CountingSort'\n\ntest('The countingSort of the array [3, 0, 2, 5, 4, 1] is [0, 1, 2, 3, 4, 5]', () => {\n  const array = [3, 0, 2, 5, 4, 1]\n  const res = countingSort(array, 0, 5)\n  expect(res).toEqual([0, 1, 2, 3, 4, 5])\n})\n\ntest('The countingSort of the array [6, 4, 2, 1, 3, 5] is [1, 2, 3, 4, 5, 6]', () => {\n  const array = [6, 4, 2, 1, 3, 5]\n  const res = countingSort(array, 1, 6)\n  expect(res).toEqual([1, 2, 3, 4, 5, 6])\n})\n\ntest('The countingSort of the array [11, 14, 12, 15, 16, 13] is [11, 12, 13, 14, 15, 16]', () => {\n  const array = [11, 14, 12, 15, 16, 13]\n  const res = countingSort(array, 11, 16)\n  expect(res).toEqual([11, 12, 13, 14, 15, 16])\n})\n\ntest('The countingSort of the array [13, 18, 2, 15, 43, 11] is [2, 11, 13, 15, 18, 43]', () => {\n  const array = [13, 18, 2, 15, 43, 11]\n  const res = countingSort(array, 2, 43)\n  expect(res).toEqual([2, 11, 13, 15, 18, 43])\n})\n"
  },
  {
    "path": "Sorts/test/CycleSort.test.js",
    "content": "import { cycleSort } from '../CycleSort'\n\ndescribe('cycleSort function', () => {\n  it('should correctly sort an input list that is sorted backwards', () => {\n    const array = [5, 4, 3, 2, 1]\n    expect(cycleSort(array)).toEqual([1, 2, 3, 4, 5])\n  })\n\n  it('should correctly sort an input list that is unsorted', () => {\n    const array = [15, 24, 3, 2224, 1]\n    expect(cycleSort(array)).toEqual([1, 3, 15, 24, 2224])\n  })\n\n  describe('Variations of input array lengths', () => {\n    it('should return an empty list with the input list is an empty list', () => {\n      expect(cycleSort([])).toEqual([])\n    })\n\n    it('should correctly sort an input list of length 1', () => {\n      expect(cycleSort([100])).toEqual([100])\n    })\n\n    it('should correctly sort an input list of an odd length', () => {\n      expect(cycleSort([101, -10, 321])).toEqual([-10, 101, 321])\n    })\n\n    it('should correctly sort an input list of an even length', () => {\n      expect(cycleSort([40, 42, 56, 45, 12, 3])).toEqual([\n        3, 12, 40, 42, 45, 56\n      ])\n    })\n  })\n\n  describe('Variations of input array elements', () => {\n    it('should correctly sort an input list that contains only positive numbers', () => {\n      expect(cycleSort([50, 33, 11, 2])).toEqual([2, 11, 33, 50])\n    })\n\n    it('should correctly sort an input list that contains only negative numbers', () => {\n      expect(cycleSort([-1, -21, -2, -35])).toEqual([-35, -21, -2, -1])\n    })\n\n    it('should correctly sort an input list that contains only a mix of positive and negative numbers', () => {\n      expect(cycleSort([-40, 42, 56, -45, 12, -3])).toEqual([\n        -45, -40, -3, 12, 42, 56\n      ])\n    })\n\n    it('should correctly sort an input list that contains only whole numbers', () => {\n      expect(cycleSort([11, 3, 12, 4, -15])).toEqual([-15, 3, 4, 11, 12])\n    })\n\n    it('should correctly sort an input list that contains only decimal numbers', () => {\n      expect(cycleSort([1.0, 1.42, 2.56, 33.45, 13.12, 2.3])).toEqual([\n        1.0, 1.42, 2.3, 2.56, 13.12, 33.45\n      ])\n    })\n\n    it('should correctly sort an input list that contains only a mix of whole and decimal', () => {\n      expect(cycleSort([32.4, 12.42, 56, 45, 12, 3])).toEqual([\n        3, 12, 12.42, 32.4, 45, 56\n      ])\n    })\n\n    it('should correctly sort an input list that contains only fractional numbers', () => {\n      expect(cycleSort([0.98, 0.4259, 0.56, -0.456, -0.12, 0.322])).toEqual([\n        -0.456, -0.12, 0.322, 0.4259, 0.56, 0.98\n      ])\n    })\n\n    it('should correctly sort an input list that contains only a mix of whole, decimal, and fractional', () => {\n      expect(cycleSort([-40, -0.222, 5.6, -4.5, 12, 0.333])).toEqual([\n        -40, -4.5, -0.222, 0.333, 5.6, 12\n      ])\n    })\n\n    it('should correctly sort an input list that contains duplicates', () => {\n      expect(cycleSort([4, 3, 4, 2, 1, 2])).toEqual([1, 2, 2, 3, 4, 4])\n    })\n  })\n})\n"
  },
  {
    "path": "Sorts/test/DutchNationalFlagSort.test.js",
    "content": "import { dutchNationalFlagSort } from '../DutchNationalFlagSort'\n\ndescribe('DutchNationalFlagSort', () => {\n  it('should sort arrays correctly', () => {\n    expect(dutchNationalFlagSort([2, 0, 2, 1, 1, 0])).toEqual([\n      0, 0, 1, 1, 2, 2\n    ])\n    expect(dutchNationalFlagSort([2, 1, 0])).toEqual([0, 1, 2])\n    expect(dutchNationalFlagSort([1, 0, 0, 0, 1])).toEqual([0, 0, 0, 1, 1])\n  })\n})\n"
  },
  {
    "path": "Sorts/test/FindSecondLargestElement.test.js",
    "content": "import { secondLargestElement } from '../FindSecondLargestElement'\n\ntest('The second largest element of the array [1, 2, 3, 4, 5] is 4', () => {\n  const array = [1, 2, 3, 4, 5]\n  const res = secondLargestElement(array)\n  expect(res).toEqual(4)\n})\n\ntest('The second largest element of the array [-1, -2, -3, -4, -5] is -2', () => {\n  const array = [-1, -2, -3, -4, -5]\n  const res = secondLargestElement(array)\n  expect(res).toEqual(-2)\n})\n"
  },
  {
    "path": "Sorts/test/FisherYatesShuffle.test.js",
    "content": "import { shuffle } from '../FisherYatesShuffle'\n\ndescribe('shuffle', () => {\n  it('expects to have a new array with same size', () => {\n    const fibonacci = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]\n    const mixedArray = shuffle(fibonacci)\n\n    expect(mixedArray).toHaveLength(fibonacci.length)\n  })\n\n  it('expects to have a new array with same values', () => {\n    const fibonacci = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]\n    const mixedArray = shuffle(fibonacci)\n\n    expect(mixedArray).toContain(0)\n    expect(mixedArray).toContain(1)\n    expect(mixedArray).toContain(2)\n    expect(mixedArray).toContain(3)\n    expect(mixedArray).toContain(5)\n    expect(mixedArray).toContain(8)\n    expect(mixedArray).toContain(13)\n    expect(mixedArray).toContain(21)\n    expect(mixedArray).toContain(34)\n    expect(mixedArray).toContain(55)\n    expect(mixedArray).toContain(89)\n  })\n})\n"
  },
  {
    "path": "Sorts/test/FlashSort.test.js",
    "content": "import { flashSort } from '../FlashSort'\n\ntest('The flash sort of the array [3, 0, 2, 5, -1, 4, 1, -2] is [-2, -1, 0, 1, 2, 3, 4, 5]', () => {\n  const array = [3, 0, 2, 5, -1, 4, 1, -2]\n  const res = flashSort(array)\n  expect(res).toEqual([-2, -1, 0, 1, 2, 3, 4, 5])\n})\n\ntest('The flash sort of the array [-3, 0, 2, -5, -1, 4, 1, -2] is [-5, -3, -2, -1, 0, 1, 2, 4]', () => {\n  const array = [-3, 0, 2, -5, -1, 4, 1, -2]\n  const res = flashSort(array)\n  expect(res).toEqual([-5, -3, -2, -1, 0, 1, 2, 4])\n})\n\ntest('The flash sort of the array [13, 0, 12, 5, -1, 14, 1, -2] is [-2, -1, 0, 1, 5, 12, 13, 14]', () => {\n  const array = [13, 0, 12, 5, -1, 14, 1, -2]\n  const res = flashSort(array)\n  expect(res).toEqual([-2, -1, 0, 1, 5, 12, 13, 14])\n})\n\ntest('The flash sort of the array [-3, 0, -2, -5, -1, -4, -1, -2] is [-5, -4, -3, -2, -2, -1, -1, 0]', () => {\n  const array = [-3, 0, -2, -5, -1, -4, -1, -2]\n  const res = flashSort(array)\n  expect(res).toEqual([-5, -4, -3, -2, -2, -1, -1, 0])\n})\n"
  },
  {
    "path": "Sorts/test/GnomeSort.test.js",
    "content": "import { gnomeSort } from '../GnomeSort'\n\ntest('The gnomeSort of the array [5, 4, 3, 2, 1] is [1, 2, 3, 4, 5]', () => {\n  const arr = [5, 4, 3, 2, 1]\n  const res = gnomeSort(arr)\n  expect(res).toEqual([1, 2, 3, 4, 5])\n})\n\ntest('The gnomeSort of the array [-5, 4, -3, 2, -1] is [-5, -3, -1, 2, 4]', () => {\n  const arr = [-5, 4, -3, 2, -1]\n  const res = gnomeSort(arr)\n  expect(res).toEqual([-5, -3, -1, 2, 4])\n})\n\ntest('The gnomeSort of the array [15, 4, -13, 2, -11] is [-13, -11, 2, 4, 15]', () => {\n  const arr = [15, 4, -13, 2, -11]\n  const res = gnomeSort(arr)\n  expect(res).toEqual([-13, -11, 2, 4, 15])\n})\n"
  },
  {
    "path": "Sorts/test/HeapSort.test.js",
    "content": "import { heapSort } from '../HeapSort'\n\ntest('The HeapSort of the array [5, 4, 3, 2, 1] is [1, 2, 3, 4, 5]', () => {\n  const array = [5, 4, 3, 2, 1]\n  const res = heapSort(array)\n  expect(res).toEqual([1, 2, 3, 4, 5])\n})\n\ntest('The HeapSort of the array [-5, -4, -3, -2, -1] is [-5, -4, -3, -2, -1]', () => {\n  const array = [-5, -4, -3, -2, -1]\n  const res = heapSort(array)\n  expect(res).toEqual([-5, -4, -3, -2, -1])\n})\n\ntest('The HeapSort of the array [50, 43, 31, 52, 91] is [31, 43, 50, 52, 91]', () => {\n  const array = [50, 43, 31, 52, 91]\n  const res = heapSort(array)\n  expect(res).toEqual([31, 43, 50, 52, 91])\n})\n\ntest('The HeapSort of the array [] is []', () => {\n  const array = []\n  const res = heapSort(array)\n  expect(res).toEqual([])\n})\n"
  },
  {
    "path": "Sorts/test/HeapSortV2.test.js",
    "content": "import { heapSort } from '../HeapSortV2'\n\ntest('The heapSort of the array [4, 3, 2, 1] is [1, 2, 3, 4]', () => {\n  const arr = [4, 3, 2, 1]\n  const res = heapSort(arr)\n  expect(res).toEqual([1, 2, 3, 4])\n})\n\ntest('The heapSort of the array [] is []', () => {\n  const arr = []\n  const res = heapSort(arr)\n  expect(res).toEqual([])\n})\n\ntest('The heapSort of the array [41, 31, 32, 31] is [31, 31, 32, 41]', () => {\n  const arr = [41, 31, 32, 31]\n  const res = heapSort(arr)\n  expect(res).toEqual([31, 31, 32, 41])\n})\n"
  },
  {
    "path": "Sorts/test/InsertionSort.test.js",
    "content": "import { insertionSortAlternativeImplementation } from '../InsertionSort'\n\ndescribe('insertionSortAlternativeImplementation', () => {\n  it('expects to work with empty array', () => {\n    expect(insertionSortAlternativeImplementation([])).toEqual([])\n  })\n\n  it('expects to return input array when array.length is less than 2', () => {\n    const input = [3]\n    expect(insertionSortAlternativeImplementation(input)).toEqual(input)\n  })\n\n  it('expects to return array sorted in ascending order', () => {\n    expect(insertionSortAlternativeImplementation([14, 11])).toEqual([11, 14])\n    expect(insertionSortAlternativeImplementation([21, 22, 23])).toEqual([\n      21, 22, 23\n    ])\n    expect(insertionSortAlternativeImplementation([1, 3, 2, 3, 7, 2])).toEqual([\n      1, 2, 2, 3, 3, 7\n    ])\n    expect(insertionSortAlternativeImplementation([1, 6, 4, 5, 9, 2])).toEqual([\n      1, 2, 4, 5, 6, 9\n    ])\n  })\n})\n"
  },
  {
    "path": "Sorts/test/MergeSort.test.js",
    "content": "import { merge, mergeSort } from '../MergeSort'\n\ndescribe('merge', () => {\n  it('should merge arrays correctly', () => {\n    expect(merge([5, 4], [1, 2, 3])).toEqual([1, 2, 3, 5, 4])\n    expect(merge([], [1, 2])).toEqual([1, 2])\n    expect(merge([1, 2, 3], [1])).toEqual([1, 1, 2, 3])\n    expect(merge([], [])).toEqual([])\n  })\n})\n\ndescribe('MergeSort', () => {\n  it('should work for empty arrays', () => {\n    expect(mergeSort([])).toEqual([])\n  })\n\n  it('should sort arrays correctly', () => {\n    expect(mergeSort([5, 4])).toEqual([4, 5])\n    expect(mergeSort([8, 4, 10, 15, 9])).toEqual([4, 8, 9, 10, 15])\n    expect(mergeSort([1, 2, 3])).toEqual([1, 2, 3])\n    expect(mergeSort([10, 5, 3, 8, 2, 6, 4, 7, 9, 1])).toEqual([\n      1, 2, 3, 4, 5, 6, 7, 8, 9, 10\n    ])\n  })\n})\n"
  },
  {
    "path": "Sorts/test/OddEvenSort.test.js",
    "content": "import { oddEvenSort } from '../OddEvenSort'\n\ntest('The OddEvenSort of the array [5, 4, 3, 2, 1] is [1, 2, 3, 4, 5]', () => {\n  const arr = [5, 4, 3, 2, 1]\n  const res = oddEvenSort(arr)\n  expect(res).toEqual([1, 2, 3, 4, 5])\n})\n\ntest('The OddEvenSort of the array [] is []', () => {\n  const arr = []\n  const res = oddEvenSort(arr)\n  expect(res).toEqual([])\n})\n\ntest('The OddEvenSort of the array [10, 14, 12, 20] is [10, 12, 14, 20]', () => {\n  const arr = [10, 14, 12, 20]\n  const res = oddEvenSort(arr)\n  expect(res).toEqual([10, 12, 14, 20])\n})\n\ntest('The OddEvenSort of the array [166, 169, 144] is [144, 166, 169]', () => {\n  const arr = [166, 169, 144]\n  const res = oddEvenSort(arr)\n  expect(res).toEqual([144, 166, 169])\n})\n"
  },
  {
    "path": "Sorts/test/PancakeSort.test.js",
    "content": "import { flipArray, findMax, pancakeSort } from '../PancakeSort'\n\ndescribe('flipArray', () => {\n  it('should flip any subarray of any array', () => {\n    expect(flipArray([1, 2, 3, 4], 0, 3)).toEqual([4, 3, 2, 1])\n    expect(flipArray([1, 2, 3, 4, 5], 2, 4)).toEqual([1, 2, 5, 4, 3])\n    expect(flipArray([], 0, 0)).toEqual([])\n  })\n})\n\ndescribe('findMax', () => {\n  it('should find the index of the maximum value in any subarray of any array', () => {\n    expect(findMax([1, 3, 2, 5], 0, 3)).toEqual(3)\n    expect(findMax([1, 3, 2, 5], 0, 2)).toEqual(1)\n  })\n})\n\ndescribe('pancakeSort', () => {\n  it('should sort any array', () => {\n    expect(pancakeSort([4, 3, 2, 1])).toEqual([1, 2, 3, 4])\n    expect(pancakeSort([3, 1, 4, 2])).toEqual([1, 2, 3, 4])\n    expect(pancakeSort([100, 1000, 10, 1])).toEqual([1, 10, 100, 1000])\n  })\n})\n"
  },
  {
    "path": "Sorts/test/PigeonHoleSort.test.js",
    "content": "import { pigeonHoleSort } from '../PigeonHoleSort'\n\ntest('The pigeonHoleSort of the array [1, 4, 3, 2] is [1, 2, 3, 4]', () => {\n  const arr = [1, 4, 3, 2]\n  const res = pigeonHoleSort(arr)\n  expect(res).toEqual([1, 2, 3, 4])\n})\n\ntest('The pigeonHoleSort of the array [5, 4, 1, 2] is [1, 2, 4, 5]', () => {\n  const arr = [5, 4, 1, 2]\n  const res = pigeonHoleSort(arr)\n  expect(res).toEqual([1, 2, 4, 5])\n})\n\ntest('The pigeonHoleSort of the array [18, 31, 29, 35, 11] is [11, 18, 29, 31, 35]', () => {\n  const arr = [18, 31, 29, 35, 11]\n  const res = pigeonHoleSort(arr)\n  expect(res).toEqual([11, 18, 29, 31, 35])\n})\n"
  },
  {
    "path": "Sorts/test/QuickSort.test.js",
    "content": "import { quickSort } from '../QuickSort'\n\ndescribe('QuickSort', () => {\n  it('should work for empty arrays', () => {\n    expect(quickSort([])).toEqual([])\n  })\n\n  it('should sort arrays correctly', () => {\n    expect(quickSort([5, 4, 3, 10, 2, 1])).toEqual([1, 2, 3, 4, 5, 10])\n    expect(quickSort([5, 4])).toEqual([4, 5])\n    expect(quickSort([1, 2, 3])).toEqual([1, 2, 3])\n    expect(quickSort([0, 5, 3, 2, 2])).toEqual([0, 2, 2, 3, 5])\n  })\n})\n"
  },
  {
    "path": "Sorts/test/QuickSortRecursive.test.js",
    "content": "import { quickSort } from '../QuickSortRecursive'\n\ndescribe('QuickSortRecursive | Partition In Place Method', () => {\n  it('Expectedly, throw some error if we pass a non-array input', () => {\n    expect(() => quickSort('xyz', 0, 2)).toThrow(\n      'Please input a valid list or array.'\n    )\n    expect(() => quickSort(null, 0, 4)).toThrow(\n      'Please input a valid list or array.'\n    )\n    expect(() => quickSort(55, 0, 2)).toThrow(\n      'Please input a valid list or array.'\n    )\n  })\n\n  it('Expectedly, the quickSort method will sort the unsorted list in ascending order', () => {\n    const unSortArray = [5, 9, 3, 4, 6, 2, 0, 1, 7, 8]\n    const sortedExpectedArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n    expect(quickSort(unSortArray, 0, unSortArray.length - 1)).toEqual(\n      sortedExpectedArray\n    )\n  })\n\n  it('Expectedly, the quickSort method will arrange the list of character values in dictionary order.', () => {\n    const unSortList = ['d', 'e', 'c', 'a', 'f', 'b']\n    const sortedExpectedList = ['a', 'b', 'c', 'd', 'e', 'f']\n    expect(quickSort(unSortList, 0, unSortList.length - 1)).toEqual(\n      sortedExpectedList\n    )\n  })\n})\n"
  },
  {
    "path": "Sorts/test/RadixSort.test.js",
    "content": "import { radixSort } from '../RadixSort'\n\ntest('The RadixSort of the array [4, 3, 2, 1] is [1, 2, 3, 4]', () => {\n  const arr = [4, 3, 2, 1]\n  const res = radixSort(arr, 10)\n  expect(res).toEqual([1, 2, 3, 4])\n})\n\ntest('The RadixSort of the array [] is []', () => {\n  const arr = []\n  const res = radixSort(arr, 10)\n  expect(res).toEqual([])\n})\n\ntest('The RadixSort of the array [14, 16, 10, 12] is [10, 12, 14, 16]', () => {\n  const arr = [14, 16, 10, 12]\n  const res = radixSort(arr, 10)\n  expect(res).toEqual([10, 12, 14, 16])\n})\n"
  },
  {
    "path": "Sorts/test/SecondLargestElement.test.js",
    "content": "import { secondLargestElement } from '../FindSecondLargestElement'\n\ntest('The second largest element of the array [100, 200, 300, 400] is 300', () => {\n  const array = [100, 200, 300, 400]\n  const res = secondLargestElement(array)\n  expect(res).toBe(300)\n})\n\ntest('The second largest element of the array [1100, 2400, 1300, 4002] is 2400', () => {\n  const array = [1100, 2400, 1300, 4002]\n  const res = secondLargestElement(array)\n  expect(res).toBe(2400)\n})\n\ntest('The second largest element of the array [10, 20, 39, 34] is 34', () => {\n  const array = [10, 20, 39, 34]\n  const res = secondLargestElement(array)\n  expect(res).toBe(34)\n})\n\ntest('The second largest element of the array [1, 20, 3, 40] is 20', () => {\n  const array = [1, 20, 3, 40]\n  const res = secondLargestElement(array)\n  expect(res).toBe(20)\n})\n"
  },
  {
    "path": "Sorts/test/SelectionSort.test.js",
    "content": "import { selectionSort } from '../SelectionSort'\n\ndescribe('selectionSort', () => {\n  it('expects to return the array sorted in ascending order', () => {\n    const toSort = [5, 6, 7, 8, 1, 2, 12, 14]\n    const expected = [1, 2, 5, 6, 7, 8, 12, 14]\n\n    expect(selectionSort(toSort)).toEqual(expected)\n  })\n\n  it('expects to throw if it is not a valid array', () => {\n    expect(() => selectionSort('abc')).toThrow('Given input is not an array')\n    expect(() => selectionSort(123)).toThrow('Given input is not an array')\n    expect(() => selectionSort({})).toThrow('Given input is not an array')\n    expect(() => selectionSort(null)).toThrow('Given input is not an array')\n    expect(() => selectionSort()).toThrow('Given input is not an array')\n  })\n\n  it('expects to throw if one of the elements in the array is not a number', () => {\n    expect(() => selectionSort([1, 'x', 2])).toThrow(\n      'One of the items in your array is not a number'\n    )\n  })\n})\n"
  },
  {
    "path": "Sorts/test/ShellSort.test.js",
    "content": "import { shellSort } from '../ShellSort'\n\ntest('The ShellSort of the array [5, 4, 3, 2, 1] is [1, 2, 3, 4, 5]', () => {\n  const arr = [5, 4, 3, 2, 1]\n  const res = shellSort(arr)\n  expect(res).toEqual([1, 2, 3, 4, 5])\n})\n\ntest('The ShellSort of the array [] is []', () => {\n  const arr = []\n  const res = shellSort(arr)\n  expect(res).toEqual([])\n})\n\ntest('The ShellSort of the array [15, 24, 31, 42, 11] is [11, 15, 24, 31, 42]', () => {\n  const arr = [15, 24, 31, 42, 11]\n  const res = shellSort(arr)\n  expect(res).toEqual([11, 15, 24, 31, 42])\n})\n\ntest('The ShellSort of the array [121, 190, 169] is [121, 169, 190]', () => {\n  const arr = [121, 190, 169]\n  const res = shellSort(arr)\n  expect(res).toEqual([121, 169, 190])\n})\n"
  },
  {
    "path": "Sorts/test/SimplifiedWiggleSort.test.js",
    "content": "import { simplifiedWiggleSort } from '../SimplifiedWiggleSort.js'\n\ndescribe('simplified wiggle sort', () => {\n  test('simplified wiggle sort for chars', () => {\n    const src = ['a', 'b', 'c']\n    expect(simplifiedWiggleSort(src)).toEqual(['a', 'c', 'b'])\n  })\n\n  test('wiggle sort with duplicates, even array', () => {\n    const src = [2, 2, 1, 3]\n    expect(simplifiedWiggleSort(src)).toEqual([1, 3, 2, 2])\n  })\n\n  test('wiggle sort with duplicates, odd array', () => {\n    const src = [1, 1, 1, 2, 4]\n    expect(simplifiedWiggleSort(src)).toEqual([1, 4, 1, 2, 1])\n  })\n\n  test(\n    'simplified wiggle sort which leads to equal values next to ' +\n      'each other',\n    () => {\n      const src = [3, 3, 5, 1]\n      expect(simplifiedWiggleSort(src)).toEqual([1, 5, 3, 3])\n    }\n  )\n})\n"
  },
  {
    "path": "Sorts/test/StoogeSort.test.js",
    "content": "import { stoogeSort } from '../StoogeSort'\n\ntest('The StoogeSort of the array [1, 6, 4, 7, 2] is [1, 2, 4, 6, 7]', () => {\n  const arr = [1, 6, 4, 7, 2]\n  const res = stoogeSort(arr, 0, arr.length)\n  expect(res).toEqual([1, 2, 4, 6, 7])\n})\n\ntest('The StoogeSort of the array [] is []', () => {\n  const arr = []\n  const res = stoogeSort(arr, 0, arr.length)\n  expect(res).toEqual([])\n})\n\ntest('The StoogeSort of the array [46, 15, 49, 65, 23] is [15, 23, 46, 49, 65]', () => {\n  const arr = [46, 15, 49, 65, 23]\n  const res = stoogeSort(arr, 0, arr.length)\n  expect(res).toEqual([15, 23, 46, 49, 65])\n})\n\ntest('The StoogeSort of the array [136, 459, 132, 566, 465] is [132, 136, 459, 465, 566]', () => {\n  const arr = [136, 459, 132, 566, 465]\n  const res = stoogeSort(arr, 0, arr.length)\n  expect(res).toEqual([132, 136, 459, 465, 566])\n})\n\ntest('The StoogeSort of the array [45, 3, 156, 1, 56] is [1, 3, 45, 56, 156]', () => {\n  const arr = [45, 3, 156, 1, 56]\n  const res = stoogeSort(arr, 0, arr.length)\n  expect(res).toEqual([1, 3, 45, 56, 156])\n})\n"
  },
  {
    "path": "Sorts/test/SwapSort.test.js",
    "content": "import { minSwapsToSort } from '../SwapSort'\n\ndescribe('SwapSort', () => {\n  it('should work for empty arrays', () => {\n    expect(minSwapsToSort([])).toEqual(0)\n  })\n\n  it('should work for sorted arrays', () => {\n    expect(minSwapsToSort([1, 2, 3, 4, 5, 6])).toEqual(0)\n  })\n\n  it('should return correct results', () => {\n    expect(minSwapsToSort([7, 6, 2, 5, 11, 0])).toEqual(2)\n    expect(minSwapsToSort([3, 3, 2, 1, 0])).toEqual(2)\n    expect(minSwapsToSort([3, 0, 2, 1, 9, 8, 7, 6])).toEqual(4)\n    expect(minSwapsToSort([1, 0, 14, 0, 8, 6, 8])).toEqual(3)\n  })\n})\n"
  },
  {
    "path": "Sorts/test/TimSort.test.js",
    "content": "import { Timsort } from '../TimSort'\n\ntest('The Timsort of the array [5, 4, 3, 2, 1] is [1, 2, 3, 4, 5]', () => {\n  const arr = [5, 4, 3, 2, 1]\n  const res = Timsort(arr)\n  expect(res).toEqual([1, 2, 3, 4, 5])\n})\n\ntest('The Timsort of the array [] is []', () => {\n  const arr = []\n  const res = Timsort(arr)\n  expect(res).toEqual([])\n})\n\ntest('The Timsort of the array [-5, -4, -3, -2, -1] is [-5, -4, -3, -2, -1]', () => {\n  const arr = [-5, -4, -3, -2, -1]\n  const res = Timsort(arr)\n  expect(res).toEqual([-5, -4, -3, -2, -1])\n})\n\ntest('The Timsort of the array [9, 0, -5, -11, 3] is [-11, -5, 0, 3, 9]', () => {\n  const arr = [9, 0, -5, -11, 3]\n  const res = Timsort(arr)\n  expect(res).toEqual([-11, -5, 0, 3, 9])\n})\n"
  },
  {
    "path": "String/AlphaNumericPalindrome.js",
    "content": "/**\n * @function alphaNumericPalindrome\n * @description alphaNumericPalindrome should return true if the string has alphanumeric characters that are palindrome irrespective of special characters and the letter case.\n * @param {string} str the string to check\n * @returns {boolean}\n * @see [Palindrome](https://en.wikipedia.org/wiki/Palindrome)\n * @example\n * The function alphaNumericPalindrome() receives a string with varying formats\n * like \"racecar\", \"RaceCar\", and \"race CAR\"\n * The string can also have special characters\n * like \"2A3*3a2\", \"2A3 3a2\", and \"2_A3*3#A2\"\n *\n * But the catch is, we have to check only if the alphanumeric characters\n * are palindrome i.e remove spaces, symbols, punctuation etc\n * and the case of the characters doesn't matter\n */\nconst alphaNumericPalindrome = (str) => {\n  if (typeof str !== 'string') {\n    throw new TypeError('Argument should be string')\n  }\n\n  // removing all the special characters and turning everything to lowercase\n  const newStr = str.replace(/[^a-z0-9]+/gi, '').toLowerCase()\n  const midIndex = newStr.length >> 1 // x >> y = floor(x / 2^y)\n\n  for (let i = 0; i < midIndex; i++) {\n    if (newStr.at(i) !== newStr.at(~i)) {\n      // ~n = -(n + 1)\n      return false\n    }\n  }\n\n  return true\n}\n\nexport default alphaNumericPalindrome\n"
  },
  {
    "path": "String/AlternativeStringArrange.js",
    "content": "// Alternative arrange the two given strings in one string in O(n) time complexity.\n\n// Problem Source & Explanation: https://www.geeksforgeeks.org/alternatively-merge-two-strings-in-java/\n\n/**\n * Alternative arrange the two given strings in one string in O(n) time complexity.\n * @param {String} str1 first input string\n * @param {String} str2 second input string\n * @returns `String` return one alternative arrange string.\n */\nconst AlternativeStringArrange = (str1, str2) => {\n  // firstly, check that both inputs are strings.\n  if (typeof str1 !== 'string' || typeof str2 !== 'string') {\n    return 'Not string(s)'\n  }\n\n  // output string value.\n  let outStr = ''\n\n  // get first string length.\n  const firstStringLength = str1.length\n  // get second string length.\n  const secondStringLength = str2.length\n  // absolute length for operation.\n  const absLength =\n    firstStringLength > secondStringLength\n      ? firstStringLength\n      : secondStringLength\n\n  // Iterate the character count until the absolute count is reached.\n  for (let charCount = 0; charCount < absLength; charCount++) {\n    // If firstStringLength is lesser than the charCount it means they are able to re-arrange.\n    if (charCount < firstStringLength) {\n      outStr += str1[charCount]\n    }\n\n    // If secondStringLength is lesser than the charCount it means they are able to re-arrange.\n    if (charCount < secondStringLength) {\n      outStr += str2[charCount]\n    }\n  }\n\n  // return the output string.\n  return outStr\n}\n\nexport { AlternativeStringArrange }\n"
  },
  {
    "path": "String/BoyerMoore.js",
    "content": "/*\n *\n *\n *Implementation of the Boyer-Moore String Search Algorithm.\n *The Boyer–Moore string search algorithm allows linear time in\n *search by skipping indices when searching inside a string for a pattern.\n *\n *\n *\n *\n **/\nconst buildBadMatchTable = (str) => {\n  const tableObj = {}\n  const strLength = str.length\n  for (let i = 0; i < strLength - 1; i++) {\n    tableObj[str[i]] = strLength - 1 - i\n  }\n  if (tableObj[str[strLength - 1]] === undefined) {\n    tableObj[str[strLength - 1]] = strLength\n  }\n  return tableObj\n}\n\nconst boyerMoore = (str, pattern) => {\n  const badMatchTable = buildBadMatchTable(pattern)\n  let offset = 0\n  const patternLastIndex = pattern.length - 1\n  const maxOffset = str.length - pattern.length\n  // if the offset is bigger than maxOffset, cannot be found\n  while (offset <= maxOffset) {\n    let scanIndex = 0\n    while (pattern[scanIndex] === str[scanIndex + offset]) {\n      if (scanIndex === patternLastIndex) {\n        // found at this index\n        return offset\n      }\n      scanIndex++\n    }\n    const badMatchString = str[offset + patternLastIndex]\n    if (badMatchTable[badMatchString]) {\n      // increase the offset if it exists\n      offset += badMatchTable[badMatchString]\n    } else {\n      offset++\n    }\n  }\n  return -1\n}\nexport { boyerMoore }\n"
  },
  {
    "path": "String/CheckAnagram.js",
    "content": "// An [Anagram](https://en.wikipedia.org/wiki/Anagram) is a string that is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once. Anagram check is not case-sensitive;\n/**\n * @function checkAnagramRegex\n * @param {string} str1\n * @param {string} str2\n * @returns {boolean}\n * @description - check anagram with the help of Regex\n * @example - checkAnagramRegex('node', 'deno') => true\n * @example - checkAnagramRegex('Eleven plus two', 'Twelve plus one') => true\n */\nconst checkAnagramRegex = (str1, str2) => {\n  // check that inputs are strings.\n  if (typeof str1 !== 'string' || typeof str2 !== 'string') {\n    throw new TypeError('Both arguments should be strings.')\n  }\n\n  // If both strings have not same lengths then they can not be anagram.\n  if (str1.length !== str2.length) {\n    return false\n  }\n\n  /**\n   * str1 converted to an array and traverse each letter of str1 by reduce method\n   * reduce method return string which is empty or not.\n   */\n  return ![...str1].reduce(\n    (str2Acc, cur) => str2Acc.replace(new RegExp(cur, 'i'), ''), // remove the similar letter from str2Acc in case-insensitive\n    str2\n  )\n}\n\n/**\n * @function checkAnagramMap\n * @description - check anagram via using HashMap\n * @param {string} str1\n * @param {string} str2\n * @returns {boolean}\n * @example - checkAnagramMap('node', 'deno') => true\n * @example - checkAnagramMap('Eleven plus two', 'Twelve plus one') => true\n */\nconst checkAnagramMap = (str1, str2) => {\n  // check that inputs are strings.\n  if (typeof str1 !== 'string' || typeof str2 !== 'string') {\n    throw new TypeError('Both arguments should be strings.')\n  }\n\n  // If both strings have not same lengths then they can not be anagram.\n  if (str1.length !== str2.length) {\n    return false\n  }\n\n  const str1List = Array.from(str1.toUpperCase()) // str1 to array\n\n  // get the occurrences of str1 characters by using HashMap\n  const str1Occurs = str1List.reduce(\n    (map, char) => map.set(char, map.get(char) + 1 || 1),\n    new Map()\n  )\n\n  for (const char of str2.toUpperCase()) {\n    // if char has not exist to the map it's return false\n    if (!str1Occurs.has(char)) {\n      return false\n    }\n\n    let getCharCount = str1Occurs.get(char)\n    str1Occurs.set(char, --getCharCount)\n\n    getCharCount === 0 && str1Occurs.delete(char)\n  }\n\n  return true\n}\n\nexport { checkAnagramRegex, checkAnagramMap }\n"
  },
  {
    "path": "String/CheckCamelCase.js",
    "content": "// CheckCamelCase method checks the given string is in camelCase or not.\n\n// Problem Source & Explanation: https://en.wikipedia.org/wiki/Camel_case\n\n/**\n * checkCamelCase method returns true if the string in camelCase, else return the false.\n * @param {String} varName the name of the variable to check.\n * @returns `Boolean` return true if the string is in camelCase, else return false.\n */\nconst checkCamelCase = (varName) => {\n  // firstly, check that input is a string or not.\n  if (typeof varName !== 'string') {\n    throw new TypeError('Argument is not a string.')\n  }\n\n  const pat = /^[a-z][A-Za-z]*$/\n  return pat.test(varName)\n}\n\nexport { checkCamelCase }\n"
  },
  {
    "path": "String/CheckExceeding.js",
    "content": "/**\n * @function checkExceeding\n * @description - Exceeding words are words where the gap between two adjacent characters is increasing. The gap is the distance in ascii\n * @param {string} str\n * @returns {boolean}\n * @example - checkExceeding('delete') => true, ascii difference - [1, 7, 7, 15, 15] which is incremental\n * @example - checkExceeding('update') => false, ascii difference - [5, 12, 3, 19, 15] which is not incremental\n */\nconst checkExceeding = (str) => {\n  if (typeof str !== 'string') {\n    throw new TypeError('Argument is not a string')\n  }\n\n  const upperChars = str.toUpperCase().replace(/[^A-Z]/g, '') // remove all from str except A to Z alphabets\n\n  const adjacentDiffList = []\n\n  for (let i = 0; i < upperChars.length - 1; i++) {\n    // destructuring current char & adjacent char by index, cause in javascript String is an object.\n    const { [i]: char, [i + 1]: adjacentChar } = upperChars\n\n    if (char !== adjacentChar) {\n      adjacentDiffList.push(\n        Math.abs(char.charCodeAt() - adjacentChar.charCodeAt())\n      )\n    }\n  }\n\n  for (let i = 0; i < adjacentDiffList.length - 1; i++) {\n    const { [i]: charDiff, [i + 1]: secondCharDiff } = adjacentDiffList\n\n    if (charDiff > secondCharDiff) {\n      return false\n    }\n  }\n\n  return true\n}\n\nexport { checkExceeding }\n"
  },
  {
    "path": "String/CheckFlatCase.js",
    "content": "// checkFlatCase method checks if the given string is in flatcase or not. Flatcase is a convention\n// where all letters are in lowercase, and there are no spaces between words.\n// thisvariable is an example of flatcase. In camelCase it would be thisVariable, snake_case this_variable and so on.\n\n// Problem Source & Explanation: https://en.wikipedia.org/wiki/Naming_convention_(programming)\n\n/**\n * checkFlatCase method returns true if the string in flatcase, else return the false.\n * @param {string} varname the name of the variable to check.\n * @returns {boolean} return true if the string is in flatcase, else return false.\n */\nconst checkFlatCase = (varname) => {\n  // firstly, check that input is a string or not.\n  if (typeof varname !== 'string') {\n    throw new TypeError('Argument is not a string.')\n  }\n\n  const pat = /^[a-z]*$/\n  return pat.test(varname)\n}\n\nexport { checkFlatCase }\n"
  },
  {
    "path": "String/CheckKebabCase.js",
    "content": "// CheckKebabCase method checks the given string is in kebab-case or not.\n\n// Problem Source & Explanation: https://en.wikipedia.org/wiki/Naming_convention_(programming)\n\n/**\n * CheckKebabCase method returns true if the string in kebab-case, else return the false.\n * @param {String} varName the name of the variable to check.\n * @returns `Boolean` return true if the string is in kebab-case, else return false.\n */\nconst CheckKebabCase = (varName) => {\n  // firstly, check that input is a string or not.\n  if (typeof varName !== 'string') {\n    throw new TypeError('Argument is not a string.')\n  }\n\n  const pat = /(\\w+)-(\\w)([\\w-]*)/\n  return pat.test(varName) && !varName.includes('_')\n}\n\nexport { CheckKebabCase }\n"
  },
  {
    "path": "String/CheckPalindrome.js",
    "content": "// Palindrome check is case sensitive; i.e., Aba is not a palindrome\n// input is a string\nconst checkPalindrome = (str) => {\n  // check that input is a string\n  if (typeof str !== 'string') {\n    return 'Not a string'\n  }\n  if (str.length === 0) {\n    return 'Empty string'\n  }\n  // Reverse only works with array, thus convert the string to array, reverse it and convert back to string\n  // return as palindrome if the reversed string is equal to the input string\n  const reversed = [...str].reverse().join('')\n  return str === reversed ? 'Palindrome' : 'Not a Palindrome'\n}\n\nexport { checkPalindrome }\n"
  },
  {
    "path": "String/CheckPangram.js",
    "content": "/**\n * What is Pangram?\n * Pangram is a sentence that contains all the letters in the alphabet https://en.wikipedia.org/wiki/Pangram\n */\n\n/**\n * @function checkPangramRegex\n * @description - This function check pangram with the help of regex pattern\n * @param {string} string\n * @returns {boolean}\n * @example - checkPangramRegex(\"'The quick brown fox jumps over the lazy dog' is a pangram\") => true\n * @example - checkPangramRegex('\"Waltz, bad nymph, for quick jigs vex.\" is a pangram') => true\n */\nconst checkPangramRegex = (string) => {\n  if (typeof string !== 'string') {\n    throw new TypeError('The given value is not a string')\n  }\n\n  /**\n   * Match all 26 alphabets using regex, with the help of:\n   * Capturing group - () -> Groups multiple tokens together and creates a capture group for extracting a substring or using a backreference.\n   * Character set - [a-z] -> Matches a char in the range a to z in case-insensitive for the 'i' flag\n   * Negative lookahead - (?!) -> Specifies a group that can not match after the main expression (if it matches, the result is discarded).\n   * Dot - . -> Matches any character except linebreaks. Equivalent to\n   * Star - * -> Matches 0 or more of the preceding token.\n   * Numeric reference - \\{$n} -> Matches the results of a capture group. E.g. - \\1  matches the results of the first capture group & \\3 matches the third.\n   */\n  return string.match(/([a-z])(?!.*\\1)/gi).length === 26\n}\n\n/**\n * @function checkPangramSet\n * @description - This function detect the pangram sentence by HashSet\n * @param {string} string\n * @returns {boolean}\n */\nconst checkPangramSet = (string) => {\n  if (typeof string !== 'string') {\n    throw new TypeError('The given value is not a string')\n  }\n\n  const lettersSet = new Set()\n\n  for (const letter of string.toUpperCase()) {\n    if (/[A-Z]/.test(letter)) {\n      // if the letter is a valid uppercase alphabet then the add method insert the letter to the HashSet\n      lettersSet.add(letter)\n    }\n  }\n\n  return lettersSet.size === 26\n}\n\nexport { checkPangramRegex, checkPangramSet }\n"
  },
  {
    "path": "String/CheckPascalCase.js",
    "content": "// CheckPascalCase method checks the given string is in PascalCase or not.\n\n// Problem Source & Explanation: https://www.theserverside.com/definition/Pascal-case\n\n/**\n * CheckPascalCase method returns true if the string in PascalCase, else return the false.\n * @param {String} VarName the name of the variable to check.\n * @returns `Boolean` return true if the string is in PascalCase, else return false.\n */\nconst CheckPascalCase = (VarName) => {\n  // firstly, check that input is a string or not.\n  if (typeof VarName !== 'string') {\n    throw new TypeError('Argument is not a string.')\n  }\n\n  const pat = /^[A-Z][A-Za-z]*$/\n  return pat.test(VarName)\n}\n\nexport { CheckPascalCase }\n"
  },
  {
    "path": "String/CheckRearrangePalindrome.js",
    "content": "/**\n * What is a palindrome? https://en.wikipedia.org/wiki/Palindrome\n * Receives a string and returns whether it can be rearranged to become a palindrome or not\n * The string can only be a palindrome if the count of ALL characters is even or if the ONLY ONE character count is odd\n * Input is a string\n *\n **/\n\nexport const palindromeRearranging = (str) => {\n  // check that input is a string\n  if (typeof str !== 'string') {\n    return 'Not a string'\n  }\n  // Check if is a empty string\n  if (!str) {\n    return 'Empty string'\n  }\n\n  // First obtain the character count for each character in the string and store it in an object.\n  // Filter the object's values to only the odd character counts.\n  const charCounts = [...str].reduce((counts, char) => {\n    counts[char] = counts[char] ? counts[char] + 1 : 1\n    return counts\n  }, {})\n  // If the length of the resulting array is 0 or 1, the string can be a palindrome.\n  return (\n    Object.values(charCounts).filter((count) => count % 2 !== 0).length <= 1\n  )\n}\n\n// testing\n\n// > palindromeRearranging('aaeccrr')\n// true\n\n// > palindromeRearranging('leve')\n// false\n"
  },
  {
    "path": "String/CheckSnakeCase.js",
    "content": "// CheckSnakeCase method checks the given string is in snake_case or not.\n\n// Problem Source & Explanation: https://en.wikipedia.org/wiki/Naming_convention_(programming)\n\n/**\n * checkSnakeCase method returns true if the string in snake_case, else return the false.\n * @param {String} varName the name of the variable to check.\n * @returns `Boolean` return true if the string is in snake_case, else return false.\n */\nconst checkSnakeCase = (varName) => {\n  // firstly, check that input is a string or not.\n  if (typeof varName !== 'string') {\n    throw new TypeError('Argument is not a string.')\n  }\n\n  const pat = /(.*?)_([a-zA-Z])*/\n  return pat.test(varName)\n}\n\nexport { checkSnakeCase }\n"
  },
  {
    "path": "String/CheckWordOccurrence.js",
    "content": "/**\n * @function checkWordOccurrence\n * @description - this function count all the words in a sentence and return an word occurrence object\n * @param {string} str\n * @param {boolean} isCaseSensitive\n * @returns {Object}\n */\nconst checkWordOccurrence = (str, isCaseSensitive = false) => {\n  if (typeof str !== 'string') {\n    throw new TypeError('The first param should be a string')\n  }\n\n  if (typeof isCaseSensitive !== 'boolean') {\n    throw new TypeError('The second param should be a boolean')\n  }\n\n  const modifiedStr = isCaseSensitive ? str.toLowerCase() : str\n\n  return modifiedStr\n    .split(/\\s+/) // remove all spaces and distribute all word in List\n    .reduce((occurrence, word) => {\n      occurrence[word] = occurrence[word] + 1 || 1\n      return occurrence\n    }, {})\n}\n\nexport { checkWordOccurrence }\n"
  },
  {
    "path": "String/CountLetters.js",
    "content": "/**\n * @function countLetters\n * @description Given a string, count the number of each letter.\n * @param {String} str - The input string\n * @return {Object} - Object with letters and number of times\n * @example countLetters(\"hello\") => {h: 1, e: 1, l: 2, o: 1}\n */\n\nconst countLetters = (str) => {\n  const specialChars = /\\W/g\n\n  if (typeof str !== 'string') {\n    throw new TypeError('Input should be a string')\n  }\n\n  if (specialChars.test(str)) {\n    throw new TypeError('Input must not contain special characters')\n  }\n\n  if (/\\d/.test(str)) {\n    throw new TypeError('Input must not contain numbers')\n  }\n\n  const obj = {}\n  for (let i = 0; i < str.toLowerCase().length; i++) {\n    const char = str.toLowerCase().charAt(i)\n    obj[char] = (obj[char] || 0) + 1\n  }\n\n  return obj\n}\n\nexport { countLetters }\n"
  },
  {
    "path": "String/CountSubstrings.js",
    "content": "/**\n * @function countSubstrings\n * @description Given a string of words or phrases, count the occurrences of a substring\n * @param {String} str - The input string\n * @param {String} substring - The substring\n * @return {Number} - The number of substring occurrences\n * @example countSubstrings(\"This is a string\", \"is\") => 2\n * @example countSubstrings(\"Hello\", \"e\") => 1\n */\n\nconst countSubstrings = (str, substring) => {\n  if (typeof str !== 'string' || typeof substring !== 'string') {\n    throw new TypeError('Argument should be string')\n  }\n\n  if (substring.length === 0) return str.length + 1\n\n  let count = 0\n  let position = str.indexOf(substring)\n\n  while (position > -1) {\n    count++\n    position = str.indexOf(substring, position + 1)\n  }\n\n  return count\n}\n\nexport { countSubstrings }\n"
  },
  {
    "path": "String/CountVowels.js",
    "content": "/**\n * @function countVowels\n * @description Given a string of words or phrases, count the number of vowels.\n * @param {String} str - The input string\n * @return {Number} - The number of vowels\n * @example countVowels(\"ABCDE\") => 2\n * @example countVowels(\"Hello\") => 2\n */\n\nconst countVowels = (str) => {\n  if (typeof str !== 'string') {\n    throw new TypeError('Input should be a string')\n  }\n\n  const vowelRegex = /[aeiou]/gi\n  const vowelsArray = str.match(vowelRegex) || []\n\n  return vowelsArray.length\n}\n\nexport { countVowels }\n"
  },
  {
    "path": "String/CreatePermutations.js",
    "content": "/*\na permutation of a set is, loosely speaking, an arrangement of its members into a sequence or linear order, or if the set is already ordered, a rearrangement of its elements.\nThe word \"permutation\" also refers to the act or process of changing the linear order of an ordered set\nMore at : https://en.wikipedia.org/wiki/Permutation\n*/\n\nconst createPermutations = (str) => {\n  // convert string to array\n  const arr = str.split('')\n\n  // get array length\n  const strLen = arr.length\n  // this will hold all the permutations\n  const perms = []\n  let rest\n  let picked\n  let restPerms\n  let next\n\n  // if strLen is zero, return the same string\n  if (strLen === 0) {\n    return [str]\n  }\n  // loop to the length to get all permutations\n  for (let i = 0; i < strLen; i++) {\n    rest = Object.create(arr)\n    picked = rest.splice(i, 1)\n\n    restPerms = createPermutations(rest.join(''))\n\n    for (let j = 0, jLen = restPerms.length; j < jLen; j++) {\n      next = picked.concat(restPerms[j])\n      perms.push(next.join(''))\n    }\n  }\n  return perms\n}\nexport { createPermutations }\n"
  },
  {
    "path": "String/DiceCoefficient.js",
    "content": "/* The Sørensen–Dice coefficient is a statistic used to gauge the similarity of two samples.\n * Applied to strings, it can give you a value between 0 and 1 (included) which tells you how similar they are.\n * Dice coefficient is calculated by comparing the bigrams of both strings,\n * a bigram is a substring of the string of length 2.\n * read more: https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient\n */\n\n// Time complexity: O(m + n), m and n being the sizes of string A and string B\n\n// Find the bistrings of a string and return a hashmap (key => bistring, value => count)\nfunction mapBigrams(string) {\n  const bigrams = new Map()\n  for (let i = 0; i < string.length - 1; i++) {\n    const bigram = string.substring(i, i + 2)\n    const count = bigrams.get(bigram)\n    bigrams.set(bigram, (count || 0) + 1)\n  }\n  return bigrams\n}\n\n// Calculate the number of common bigrams between a map of bigrams and a string\n\nfunction countCommonBigrams(bigrams, string) {\n  let count = 0\n  for (let i = 0; i < string.length - 1; i++) {\n    const bigram = string.substring(i, i + 2)\n    if (bigrams.has(bigram)) count++\n  }\n  return count\n}\n\n// Calculate Dice coeff of 2 strings\nfunction diceCoefficient(stringA, stringB) {\n  if (stringA === stringB) return 1\n  else if (stringA.length < 2 || stringB.length < 2) return 0\n\n  const bigramsA = mapBigrams(stringA)\n\n  const lengthA = stringA.length - 1\n  const lengthB = stringB.length - 1\n\n  let dice = (2 * countCommonBigrams(bigramsA, stringB)) / (lengthA + lengthB)\n\n  // cut 0.xxxxxx to 0.xx for simplicity\n  dice = Math.floor(dice * 100) / 100\n\n  return dice\n}\n\nexport { diceCoefficient }\n"
  },
  {
    "path": "String/FirstUniqueCharacter.js",
    "content": "/**\n * @function firstUniqChar\n * @description Given a string str, find the first non-repeating character in it and return its index. If it does not exist, return -1.\n * @param {String} str - The input string\n * @return {Number} - The index of first unique character.\n * @example firstUniqChar(\"javascript\") => 0\n * @example firstUniqChar(\"sesquipedalian\") => 3\n * @example firstUniqChar(\"aabb\") => -1\n */\n\nconst firstUniqChar = (str) => {\n  if (typeof str !== 'string') {\n    throw new TypeError('Argument should be string')\n  }\n  const count = new Map()\n\n  for (const char of str) {\n    if (!count[char]) {\n      count[char] = 1\n    } else {\n      count[char]++\n    }\n  }\n  for (let i = 0; i < str.length; i++) {\n    if (count[str[i]] === 1) return i\n  }\n  return -1\n}\n\nexport { firstUniqChar }\n"
  },
  {
    "path": "String/FormatPhoneNumber.js",
    "content": "/**\n * @description - function that takes 10 digits and returns a string of the formatted phone number e.g.: 1234567890 -> (123) 456-7890\n * @param {string} phoneNumber\n * @returns {string} - Format to (XXX) XXX-XXXX pattern\n */\nconst formatPhoneNumber = (phoneNumber) => {\n  if (phoneNumber.length !== 10 || isNaN(phoneNumber)) {\n    // return \"Invalid phone number.\"\n    throw new TypeError('Invalid phone number!')\n  }\n\n  let index = 0\n  return '(XXX) XXX-XXXX'.replace(/X/g, () => phoneNumber[index++])\n}\n\nexport default formatPhoneNumber\n"
  },
  {
    "path": "String/GenerateGUID.js",
    "content": "/*\nGenerates a UUID/GUID in Node.Js.\nThe script uses `Math.random` in combination with the timestamp for better randomness.\nThe function generate an RFC4122 (https://www.ietf.org/rfc/rfc4122.txt) version 4 UUID/GUID\n*/\n\nexport const Guid = () => {\n  const pattern = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'\n  let currentDateMilliseconds = new Date().getTime()\n  return pattern.replace(/[xy]/g, (currentChar) => {\n    const randomChar = (currentDateMilliseconds + Math.random() * 16) % 16 | 0\n    currentDateMilliseconds = Math.floor(currentDateMilliseconds / 16)\n    return (\n      currentChar === 'x' ? randomChar : (randomChar & 0x7) | 0x8\n    ).toString(16)\n  })\n}\n\n// > Guid()\n// 'edc848db-3478-1760-8b55-7986003d895f'\n"
  },
  {
    "path": "String/HammingDistance.js",
    "content": "/**\n * Hamming Distance: https://en.wikipedia.org/wiki/Hamming_distance\n *\n *\n * Hamming distance is a metric for comparing two binary data strings.\n *\n * While comparing two binary strings of equal length, Hamming distance\n * is the number of bit positions in which the two bits are different.\n * The Hamming distance between two strings, a and b is denoted as d(a,b)\n */\n\n/**\n * @param {string} a\n * @param {string} b\n * @return {number}\n */\n\nexport const hammingDistance = (a, b) => {\n  if (a.length !== b.length) {\n    throw new Error('Strings must be of the same length')\n  }\n\n  let distance = 0\n\n  for (let i = 0; i < a.length; i += 1) {\n    if (a[i] !== b[i]) {\n      distance += 1\n    }\n  }\n\n  return distance\n}\n"
  },
  {
    "path": "String/IsPalindrome.js",
    "content": "/**\n * @function isPalindromeIterative\n * @description isPalindromeIterative function checks whether the provided input is palindrome or not\n * @param {String | Number} x - The input to check\n * @return {boolean} - Input is palindrome or not\n * @see [Palindrome](https://en.wikipedia.org/wiki/Palindrome)\n */\n\n/*\n  * Big-O Analysis\n      * Time Complexity\n        - O(N) on average and worst case scenario as input is traversed in linear fashion\n        - O(1) on best case scenario if the input already is a string (otherwise toString() method takes O(N))\n               and the first & last characters don't match, triggering an early return\n      * Space Complexity\n        - O(1)\n*/\n\nexport function isPalindromeIterative(x) {\n  if (typeof x !== 'string' && typeof x !== 'number') {\n    throw new TypeError('Input must be a string or a number')\n  }\n\n  // Convert x to string whether it's number or string\n  const string = x.toString()\n  const length = string.length\n\n  if (length === 1) return true\n\n  // Apply two pointers technique to compare first and last elements on each iteration\n  for (let start = 0, end = length - 1; start < end; start++, end--) {\n    // Early return if compared items are different, input is not a palindrome\n    if (string[start] !== string[end]) return false\n  }\n  // If early return in condition inside for loop is not reached, then input is palindrome\n  return true\n}\n"
  },
  {
    "path": "String/KMPPatternSearching.js",
    "content": "// Implementing KMP Search Algorithm to search all the instances of pattern in\n// given text\n// Reference Book: Introduction to Algorithms, CLRS\n\n// Explanation: https://www.topcoder.com/community/competitive-programming/tutorials/introduction-to-string-searching-algorithms/\n\nconst computeLPS = (pattern) => {\n  const lps = Array(pattern.length)\n  lps[0] = 0\n  for (let i = 1; i < pattern.length; i++) {\n    let matched = lps[i - 1]\n    while (matched > 0 && pattern[i] !== pattern[matched]) {\n      matched = lps[matched - 1]\n    }\n    if (pattern[i] === pattern[matched]) {\n      matched++\n    }\n    lps[i] = matched\n  }\n  return lps\n}\n\n/**\n * Returns all indices where pattern starts in text\n * @param {*} text a big text in which pattern string is to find\n * @param {*} pattern the string to find\n */\nconst KMPSearch = (text, pattern) => {\n  if (!pattern || !text) {\n    return [] // no results\n  }\n\n  // lps[i] = length of proper prefix of pattern[0]...pattern[i-1]\n  //          which is also proper suffix of it\n  const lps = computeLPS(pattern)\n  const result = []\n\n  let matched = 0\n  for (let i = 0; i < text.length; i++) {\n    while (matched > 0 && text[i] !== pattern[matched]) {\n      matched = lps[matched - 1]\n    }\n    if (text[i] === pattern[matched]) {\n      matched++\n    }\n    if (matched === pattern.length) {\n      result.push(i - pattern.length + 1)\n      matched = lps[matched - 1]\n    }\n  }\n\n  return result\n}\n\nexport { KMPSearch }\n"
  },
  {
    "path": "String/LengthofLongestSubstringWithoutRepetition.js",
    "content": "/*\n * @description : Given a string, the function finds the length of the longest substring without any repeating characters\n * @param {String} str - The input string\n * @returns {Number} The Length of the longest substring in a given string without repeating characters\n * @example lengthOfLongestSubstring(\"abcabcbb\") => 3\n * @example lengthOfLongestSubstring(\"bbbbb\") => 1\n * @see https://leetcode.com/problems/longest-substring-without-repeating-characters/\n */\n\nconst lengthOfLongestSubstring = (s) => {\n  if (typeof s !== 'string') {\n    throw new TypeError('Invalid Input Type')\n  }\n  let maxLength = 0\n  let start = 0\n  const charMap = new Map()\n  for (let end = 0; end < s.length; end++) {\n    if (charMap.has(s[end])) {\n      start = Math.max(start, charMap.get(s[end]) + 1)\n    }\n    charMap.set(s[end], end)\n    maxLength = Math.max(maxLength, end - start + 1)\n  }\n  return maxLength\n}\n\nexport { lengthOfLongestSubstring }\n"
  },
  {
    "path": "String/LevenshteinDistance.js",
    "content": "/* The Levenshtein distance (a.k.a edit distance) is a\nmeasure of similarity between two strings. It is\ndefined as the minimum number of changes required to\nconvert string a into string b (this is done by\ninserting, deleting or replacing a character in\nstring a).\nThe smaller the Levenshtein distance,\nthe more similar the strings are. This is a very\ncommon problem in the application of Dynamic Programming.\n*/\n\nconst levenshteinDistance = (a, b) => {\n  // Declaring array 'D' with rows = len(a) + 1 and columns = len(b) + 1:\n  const distanceMatrix = Array(b.length + 1)\n    .fill(null)\n    .map(() => Array(a.length + 1).fill(null))\n\n  // Initializing first column:\n  for (let i = 0; i <= a.length; i += 1) {\n    distanceMatrix[0][i] = i\n  }\n\n  // Initializing first row:\n  for (let j = 0; j <= b.length; j += 1) {\n    distanceMatrix[j][0] = j\n  }\n\n  for (let j = 1; j <= b.length; j += 1) {\n    for (let i = 1; i <= a.length; i += 1) {\n      const indicator = a[i - 1] === b[j - 1] ? 0 : 1\n      // choosing the minimum of all three, vis-a-vis:\n      distanceMatrix[j][i] = Math.min(\n        distanceMatrix[j][i - 1] + 1, // deletion\n        distanceMatrix[j - 1][i] + 1, // insertion\n        distanceMatrix[j - 1][i - 1] + indicator // substitution\n      )\n    }\n  }\n\n  return distanceMatrix[b.length][a.length]\n}\n\nexport { levenshteinDistance }\n"
  },
  {
    "path": "String/Lower.js",
    "content": "/**\n * @function lower\n * @description Will convert the entire string to lowercase letters.\n * @param {String} str - The input string\n * @returns {String} Lowercase string\n * @example lower(\"HELLO\") => hello\n * @example lower(\"He_llo\") => he_llo\n */\n\nconst lower = (str) => {\n  if (typeof str !== 'string') {\n    throw new TypeError('Invalid Input Type')\n  }\n\n  return str.replace(/[A-Z]/g, (char) =>\n    String.fromCharCode(char.charCodeAt() + 32)\n  )\n}\n\nexport default lower\n"
  },
  {
    "path": "String/MaxCharacter.js",
    "content": "/**\n * @function maxCharacter\n * @example - Given a string of characters, return the character that appears the most often. Example: input = \"Hello World!\" return \"l\"\n * @param {string} str\n * @param {RegExp} ignorePattern - ignore the char in str that is not required\n * @returns {string} - char\n */\nconst maxCharacter = (str, ignorePattern) => {\n  // initially it's count only alphabets\n  if (typeof str !== 'string') {\n    throw new TypeError('Argument should be a string')\n  } else if (!str) {\n    throw new Error('The param should be a nonempty string')\n  }\n\n  // store all char in occurrence map\n  const occurrenceMap = new Map()\n\n  for (const char of str) {\n    if (!ignorePattern?.test(char)) {\n      occurrenceMap.set(char, occurrenceMap.get(char) + 1 || 1)\n    }\n  }\n\n  // find the max char from the occurrence map\n  let max = { char: '', occur: -Infinity }\n\n  for (const [char, occur] of occurrenceMap) {\n    if (occur > max.occur) {\n      max = { char, occur }\n    }\n  }\n\n  return max.char\n}\n\nexport default maxCharacter\n"
  },
  {
    "path": "String/MaxWord.js",
    "content": "// Given a sentence, return the most occurring word\n\n/**\n * @param {string} sentence - the sentence you want to find the most occurring word\n * @returns {string} - the most occurring word\n *\n * @example\n *     -  maxWord('lala lili lala'); // lala\n */\nconst maxWord = (sentence = '') => {\n  if (typeof sentence !== 'string') {\n    throw new TypeError('the param should be string')\n  }\n\n  if (!sentence) {\n    return null\n  }\n\n  const words = sentence.split(' ')\n  if (words.length < 2) {\n    return words[0]\n  }\n\n  const occurrences = {}\n  words.forEach((word) => {\n    occurrences[word.toLocaleLowerCase()] =\n      occurrences[word.toLocaleLowerCase()] + 1 || 1\n  })\n\n  const max = Object.keys(occurrences).reduce(\n    (n, word) => {\n      if (occurrences[word] > n.count) {\n        return { word, count: occurrences[word] }\n      } else {\n        return n\n      }\n    },\n    { word: '', count: 0 }\n  )\n\n  return max.word\n}\n\nexport { maxWord }\n"
  },
  {
    "path": "String/PatternMatching.js",
    "content": "/*\nPattern matching is case insensitive as\nthe inputs are converted to lower case before the\nalgorithm is run.\n\nThe algorithm will run through the entire text and\nreturn the starting index if the given pattern is\navailable in the text\n*/\nconst checkIfPatternExists = (text, pattern) => {\n  if (typeof text !== 'string' || typeof pattern !== 'string') {\n    throw new TypeError('Given input is not a string')\n  }\n  const textLength = text.length // Store the length of the text in a variable\n  const patternLength = pattern.length // Store the length of the pattern in a variable\n\n  // Iterate through the text until the textlength - patternlength index\n  for (let i = 0; i <= textLength - patternLength; i++) {\n    // For each character in the text check if the subsequent character\n    // are matching the given pattern; if not break from the condition\n    for (let j = 0; j < textLength; j++) {\n      if (text[i + j] !== pattern[j]) break\n\n      // For each iteration of j check if the value of\n      // j + 1 is equal to the length of the pattern\n      if (j + 1 === patternLength) {\n        return `Given pattern is found at index ${i}`\n      }\n    }\n  }\n}\n\nexport { checkIfPatternExists }\n"
  },
  {
    "path": "String/PercentageOfLetters.js",
    "content": "/**\n * @function percentageOfLetter\n * @description Return the percentage of characters in 'str'\n * that equal 'letter' rounded down to the nearest whole percent.\n * More info: https://leetcode.com/problems/percentage-of-letter-in-string/\n * @param {String} str\n * @param {String} letter\n * @returns {Number}\n * @example\n * const str = 'foobar', const letter = 'o'\n * percentageOfLetter(str, letter) // ===> 33\n */\nconst percentageOfLetter = (str, letter) => {\n  if (typeof str !== 'string' || typeof letter !== 'string') {\n    throw new Error('Input data must be strings')\n  }\n  let letterCount = 0\n  // Iterate through the whole given text\n  for (let i = 0; i < str.length; i++) {\n    // Count how often the letter appears in the word\n    letterCount += str[i].toLowerCase() === letter.toLowerCase() ? 1 : 0\n  }\n  const percentage = Math.floor((100 * letterCount) / str.length)\n  return percentage\n}\n\nexport { percentageOfLetter }\n"
  },
  {
    "path": "String/PermutateString.js",
    "content": "'use strict'\n\nconst permutate = (aString) => {\n  if (typeof aString !== 'string' || !aString) {\n    throw new Error('The arg must be a valid, non empty string')\n  }\n  const characters = aString.split('')\n  let permutations = [[characters.shift()]]\n  while (characters.length) {\n    const currentCharacter = characters.shift()\n    permutations = calculateCurrentCharacterPermutation(\n      permutations,\n      currentCharacter\n    )\n  }\n  return permutations\n    .map((character) => character.join(''))\n    .filter((item, index, self) => self.indexOf(item) === index)\n    .sort()\n}\n\nconst calculateCurrentCharacterPermutation = (\n  allPermutations,\n  currentCharacter\n) => {\n  const currentPermutations = []\n  allPermutations.forEach((permutation) => {\n    let index = 0\n    while (index <= permutation.length) {\n      const tmp = [...permutation]\n      tmp.splice(index, 0, currentCharacter)\n      currentPermutations.push(tmp)\n      index++\n    }\n  })\n  return currentPermutations\n}\n\nexport { permutate }\n"
  },
  {
    "path": "String/ReverseString.js",
    "content": "/**\n * A short example showing how to reverse a string.\n */\nfunction ReverseStringIterative(string) {\n  if (typeof string !== 'string') {\n    throw new TypeError('The given value is not a string')\n  }\n  let reversedString = ''\n  let index\n\n  for (index = string.length - 1; index >= 0; index--) {\n    reversedString += string[index]\n  }\n\n  return reversedString\n}\n\n/**\n *\n * @author dev-madhurendra\n * Reverses a number by converting it to a string.\n *\n * @param {string} str - The number to reverse.\n * @returns {string} The reversed number.\n *\n * @example\n * const reversed = reverseString(\"hello\"); // Returns olleh\n */\n\nconst ReverseStringIterativeInplace = (str) => [...str].reverse().join('')\n\nexport { ReverseStringIterative, ReverseStringIterativeInplace }\n"
  },
  {
    "path": "String/ReverseWords.js",
    "content": "/**\n * @function reverseWords\n * @param {string} str\n * @returns {string} - reverse string\n */\nconst reverseWords = (str) => {\n  if (typeof str !== 'string') {\n    throw new TypeError('The given value is not a string')\n  }\n\n  return str\n    .split(/\\s+/) // create an array with each word in string\n    .reduceRight((reverseStr, word) => `${reverseStr} ${word}`, '') // traverse the array from last & create an string\n    .trim() // remove the first useless space\n}\n\nexport default reverseWords\n"
  },
  {
    "path": "String/ScrambleStrings.js",
    "content": "// Problem Statement and Explanation: https://leetcode.com/problems/scramble-string/\n\n/**\n * Given two strings s1 and s2 of the same length, return true if s2 is a scrambled string of s1, otherwise, return false.\n * @param {string} s1\n * @param {string} s2\n * @return {boolean}\n */\n\nconst isScramble = (s1, s2) => {\n  return helper({}, s1, s2)\n}\n\nconst helper = function (dp, s1, s2) {\n  const map = {}\n\n  if (dp[s1 + s2] !== undefined) return dp[s1 + s2]\n  if (s1 === s2) return true\n\n  for (let j = 0; j < s1.length; j++) {\n    if (map[s1[j]] === undefined) map[s1[j]] = 0\n    if (map[s2[j]] === undefined) map[s2[j]] = 0\n    map[s1[j]]++\n    map[s2[j]]--\n  }\n\n  for (const key in map) {\n    if (map[key] !== 0) {\n      dp[s1 + s2] = false\n      return false\n    }\n  }\n\n  for (let i = 1; i < s1.length; i++) {\n    if (\n      (helper(dp, s1.substr(0, i), s2.substr(0, i)) &&\n        helper(dp, s1.substr(i), s2.substr(i))) ||\n      (helper(dp, s1.substr(0, i), s2.substr(s2.length - i)) &&\n        helper(dp, s1.substr(i), s2.substr(0, s2.length - i)))\n    ) {\n      dp[s1 + s2] = true\n      return true\n    }\n  }\n\n  dp[s1 + s2] = false\n  return false\n}\n\nexport { isScramble }\n"
  },
  {
    "path": "String/Upper.js",
    "content": "/**\n * @function upper\n * @description Will convert the entire string to uppercase letters.\n * @param {String} str - The input string\n * @return {String} Uppercase string\n * @example upper(\"hello\") => HELLO\n * @example upper(\"He_llo\") => HE_LLO\n */\nconst upper = (str) => {\n  if (typeof str !== 'string') {\n    throw new TypeError('Argument should be string')\n  }\n\n  return str.replace(/[a-z]/g, (char) =>\n    String.fromCharCode(char.charCodeAt() - 32)\n  )\n}\n\nexport default upper\n"
  },
  {
    "path": "String/ValidateCreditCard.js",
    "content": "/**\n * Validate a given credit card number\n *\n * The core of the validation of credit card numbers is the Luhn algorithm.\n *\n * The validation sum should be completely divisible by 10 which is calculated as follows,\n * every first digit is added directly to the validation sum.\n * For every second digit in the credit card number, the digit is multiplied by 2.\n * If the product is greater than 10 the digits of the product are added.\n * This resultant digit is considered for the validation sum rather than the digit itself.\n *\n * Ref: https://www.geeksforgeeks.org/luhn-algorithm/\n */\n\nconst luhnValidation = (creditCardNumber) => {\n  let validationSum = 0\n  creditCardNumber.split('').forEach((digit, index) => {\n    let currentDigit = parseInt(digit)\n    if (index % 2 === 0) {\n      // Multiply every 2nd digit from the left by 2\n      currentDigit *= 2\n      // if product is greater than 10 add the individual digits of the product to get a single digit\n      if (currentDigit > 9) {\n        currentDigit %= 10\n        currentDigit += 1\n      }\n    }\n    validationSum += currentDigit\n  })\n\n  return validationSum % 10 === 0\n}\n\nconst validateCreditCard = (creditCardString) => {\n  const validStartSubString = ['4', '5', '6', '37', '34', '35'] // Valid credit card numbers start with these numbers\n\n  if (typeof creditCardString !== 'string') {\n    throw new TypeError('The given value is not a string')\n  }\n\n  const errorMessage = `${creditCardString} is an invalid credit card number because `\n  if (isNaN(creditCardString)) {\n    throw new TypeError(errorMessage + 'it has nonnumerical characters.')\n  }\n  const creditCardStringLength = creditCardString.length\n  if (!(creditCardStringLength >= 13 && creditCardStringLength <= 16)) {\n    throw new Error(errorMessage + 'of its length.')\n  }\n  if (\n    !validStartSubString.some((subString) =>\n      creditCardString.startsWith(subString)\n    )\n  ) {\n    throw new Error(errorMessage + 'of its first two digits.')\n  }\n  if (!luhnValidation(creditCardString)) {\n    throw new Error(errorMessage + 'it fails the Luhn check.')\n  }\n\n  return true\n}\n\nexport { validateCreditCard }\n"
  },
  {
    "path": "String/ValidateEmail.js",
    "content": "/**\n * Returns whether the given string is a valid email address or not.\n */\nconst validateEmail = (str) => {\n  if (str === '' || str === null) {\n    throw new TypeError('Email Address String Null or Empty.')\n  }\n\n  return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(str)\n}\n\nexport { validateEmail }\n"
  },
  {
    "path": "String/ZFunction.js",
    "content": "/**\n * @author: Adrito Mukherjee\n * Implementation of ZFunction in JavaScript\n * ZFunction at an index i gives the length of the longest substring starting at i, that is also a prefix of the whole string\n * ZFunction for all indices in a string can be calculated in O(N)\n * @see https://cp-algorithms.com/string/z-function.html\n * @param {String} text The string whose Z Function is to be calculated\n * @return {Array} Returns an array whose i-th index is the value of Z Function for text at index i\n */\n\nfunction zFunction(text) {\n  const length = text.length\n  const zArray = Array(length).fill(0)\n  // Initializing left and right variable to zero\n  let left = 0\n  let right = 0\n  for (let index = 0; index < length; index++) {\n    // If index is less than or equal to right, we reuse the values of zFunction at index right-index+1\n    // It is made sure that value of zFunction at index is not greater than maximum possible value at index\n    if (index <= right) {\n      zArray[index] = Math.min(right - index + 1, zArray[index - left])\n    }\n\n    // After zArray[index] is initialized, we see if we can increase its value by trivially comparing character by character\n    while (\n      index + zArray[index] < length &&\n      text[zArray[index]] === text[index + zArray[index]]\n    ) {\n      zArray[index]++\n    }\n\n    // If index + zArray[index] - 1 is greater than right, we update values of variables left and right\n    if (index + zArray[index] - 1 > right) {\n      left = index\n      right = index + zArray[index] - 1\n    }\n  }\n  return zArray\n}\n\nexport default zFunction\n"
  },
  {
    "path": "String/test/AlphaNumericPalindrome.test.js",
    "content": "import alphaNumericPalindrome from '../AlphaNumericPalindrome'\n\ndescribe('Testing the alpha numeric palindrome', () => {\n  // should return true if the given string has alphanumeric characters that are palindrome irrespective of case and symbols\n  it('Testing with valid alphabetic palindrome', () => {\n    expect(alphaNumericPalindrome('eye')).toBe(true)\n    expect(alphaNumericPalindrome('Madam')).toBe(true)\n    expect(alphaNumericPalindrome('race CAR')).toBe(true)\n    expect(alphaNumericPalindrome('A man, a plan, a canal. Panama')).toBe(true)\n  })\n\n  it('Testing with number and symbol', () => {\n    expect(alphaNumericPalindrome('0_0 (: /-:) 0-0')).toBe(true)\n    expect(alphaNumericPalindrome('03_|53411435|_30')).toBe(true)\n  })\n\n  it('Testing with alphabets and symbols', () => {\n    expect(alphaNumericPalindrome('five|_/|evif')).toBe(true)\n    expect(alphaNumericPalindrome('five|_/|four')).toBe(false)\n  })\n})\n"
  },
  {
    "path": "String/test/AlternativeStringArrange.test.js",
    "content": "import { AlternativeStringArrange } from '../AlternativeStringArrange'\n\ntest('AlternativeStringArrange(Agrtm, loih) -> Algorithm', () => {\n  const str1 = 'Agrtm'\n  const str2 = 'loih'\n  const res = AlternativeStringArrange(str1, str2)\n  expect(res).toEqual('Algorithm')\n})\n\ntest('AlternativeStringArrange(JvSrp, aacit) -> JavaScript', () => {\n  const str1 = 'JvSrp'\n  const str2 = 'aacit'\n  const res = AlternativeStringArrange(str1, str2)\n  expect(res).toEqual('JavaScript')\n})\n\ntest('AlternativeStringArrange(abc, def) -> adbecf', () => {\n  const str1 = 'abc'\n  const str2 = 'def'\n  const res = AlternativeStringArrange(str1, str2)\n  expect(res).toEqual('adbecf')\n})\n"
  },
  {
    "path": "String/test/BoyerMoore.test.js",
    "content": "import { boyerMoore } from '../BoyerMoore'\n\ndescribe('Testing the boyer moore algorithm', () => {\n  it('Testing with alphabetical strings', () => {\n    expect(boyerMoore('THIS IS A TEST TEXT', 'TEST')).toBe(10)\n    expect(boyerMoore('AAIOOOAADDZXYCAADAABAABA', 'AADA')).toBe(14)\n    expect(boyerMoore('Hello World! This is a test case.', 'Boyer')).toBe(-1)\n  })\n\n  it('Testing with alphabets and symbols', () => {\n    expect(boyerMoore('AA&&@_OPOODDA##!', '@_')).toBe(4)\n    expect(boyerMoore('LK_||{{}}[[$($', '||')).toBe(3)\n    expect(boyerMoore('__||{{__+}}[[$($', '-}}')).toBe(-1)\n  })\n})\n"
  },
  {
    "path": "String/test/CheckAnagram.test.js",
    "content": "import { checkAnagramMap, checkAnagramRegex } from '../CheckAnagram'\n\ndescribe('Testing checkAnagramRegex', () => {\n  it.each`\n    inputOne              | inputTwo\n    ${123456}             | ${'abcd'}\n    ${[1, 2, 3, 4, 5, 6]} | ${'abcd'}\n    ${{ test: 'test' }}   | ${'abcd'}\n    ${'abcd'}             | ${123456}\n    ${'abcd'}             | ${[1, 2, 3, 4, 5, 6]}\n    ${'abcd'}             | ${{ test: 'test' }}\n  `(\n    'expects to throw the type Error given values $inputOne and $inputTwo',\n    ({ inputOne, inputTwo }) => {\n      expect(() => checkAnagramRegex(inputOne, inputTwo)).toThrowError()\n    }\n  )\n\n  it('expects to return false if the arguments have different lengths', () => {\n    const SUT = checkAnagramRegex('abs', 'abds')\n    expect(SUT).toBe(false)\n  })\n\n  it('expects to return false if the arguments are not anagrams', () => {\n    const SUT = checkAnagramRegex('abcs', 'abds')\n    expect(SUT).toBe(false)\n  })\n\n  it('expects to return true if the arguments are anagrams', () => {\n    const SUT = checkAnagramRegex('abcd', 'bcad')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return true if the arguments of length 1 and are the same letter', () => {\n    const SUT = checkAnagramRegex('a', 'a')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return true if the arguments of are both empty strings', () => {\n    const SUT = checkAnagramRegex('', '')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return true if the arguments are anagrams with an odd length', () => {\n    const SUT = checkAnagramRegex('abcde', 'edcab')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return true if the arguments are anagrams with an even length', () => {\n    const SUT = checkAnagramRegex('abcdef', 'fedcab')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return false if either argument is an empty string while the other is not', () => {\n    const SUT = checkAnagramRegex('', 'edcab')\n    expect(SUT).toBe(false)\n    const SUT2 = checkAnagramRegex('edcab', '')\n    expect(SUT2).toBe(false)\n  })\n\n  it('expects to return true if the arguments contain the same letters but have unequal case', () => {\n    const SUT = checkAnagramRegex('ABDCE', 'abcde')\n    expect(SUT).toBe(true)\n    const SUT2 = checkAnagramRegex('AbCdE', 'aBCdE')\n    expect(SUT2).toBe(true)\n    const SUT3 = checkAnagramRegex('Eleven plus two', 'Twelve plus one')\n    expect(SUT3).toBe(true)\n  })\n\n  it('expects to return true if the arguments are anagrams and contain number characters', () => {\n    const SUT = checkAnagramRegex('a1b2', '12ba')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return true if the arguments are anagrams and contain space characters', () => {\n    const SUT = checkAnagramRegex('a1 b2', '1 2ba')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return true if the arguments are anagrams and contain punctuation characters', () => {\n    const SUT = checkAnagramRegex('a!1b@2', '1@2ba!')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return false if the arguments contain the same letters but contain a different amount of space characters', () => {\n    const SUT = checkAnagramRegex('ea        cb', 'e cba')\n    expect(SUT).toBe(false)\n  })\n})\n\ndescribe('Testing checkAnagramMap', () => {\n  it.each`\n    inputOne              | inputTwo\n    ${123456}             | ${'abcd'}\n    ${[1, 2, 3, 4, 5, 6]} | ${'abcd'}\n    ${{ test: 'test' }}   | ${'abcd'}\n    ${'abcd'}             | ${123456}\n    ${'abcd'}             | ${[1, 2, 3, 4, 5, 6]}\n    ${'abcd'}             | ${{ test: 'test' }}\n  `(\n    'expects to throw the type Error given values $inputOne and $inputTwo',\n    ({ inputOne, inputTwo }) => {\n      expect(() => checkAnagramMap(inputOne, inputTwo)).toThrowError()\n    }\n  )\n\n  it('expects to return false if the arguments have different lengths', () => {\n    const SUT = checkAnagramMap('abs', 'abds')\n    expect(SUT).toBe(false)\n  })\n\n  it('expects to return false if the arguments are not anagrams', () => {\n    const SUT = checkAnagramMap('abcs', 'abds')\n    expect(SUT).toBe(false)\n  })\n\n  it('expects to return true if the arguments are anagrams', () => {\n    const SUT = checkAnagramMap('abcd', 'bcad')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return true if the arguments of length 1 and are the same letter', () => {\n    const SUT = checkAnagramMap('a', 'a')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return true if the arguments of are both empty strings', () => {\n    const SUT = checkAnagramMap('', '')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return true if the arguments are anagrams with an odd length', () => {\n    const SUT = checkAnagramMap('abcde', 'edcab')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return true if the arguments are anagrams with an even length', () => {\n    const SUT = checkAnagramMap('abcdef', 'fedcab')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return false if either argument is an empty string while the other is not', () => {\n    const SUT = checkAnagramMap('', 'edcab')\n    expect(SUT).toBe(false)\n    const SUT2 = checkAnagramMap('edcab', '')\n    expect(SUT2).toBe(false)\n  })\n\n  it('expects to return true if the arguments contain the same letters but have unequal case', () => {\n    const SUT = checkAnagramMap('ABDCE', 'abcde')\n    expect(SUT).toBe(true)\n    const SUT2 = checkAnagramMap('AbCdE', 'aBCdE')\n    expect(SUT2).toBe(true)\n    const SUT3 = checkAnagramMap('Eleven plus two', 'Twelve plus one')\n    expect(SUT3).toBe(true)\n  })\n\n  it('expects to return true if the arguments are anagrams and contain number characters', () => {\n    const SUT = checkAnagramMap('a1b2', '12ba')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return true if the arguments are anagrams and contain space characters', () => {\n    const SUT = checkAnagramMap('a1 b2', '1 2ba')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return true if the arguments are anagrams and contain punctuation characters', () => {\n    const SUT = checkAnagramMap('a!1b@2', '1@2ba!')\n    expect(SUT).toBe(true)\n  })\n\n  it('expects to return false if the arguments contain the same letters but contain a different amount of space characters', () => {\n    const SUT = checkAnagramMap('ea        cb', 'e cba')\n    expect(SUT).toBe(false)\n  })\n})\n"
  },
  {
    "path": "String/test/CheckCamelCase.test.js",
    "content": "import { checkCamelCase } from '../CheckCamelCase'\ndescribe('checkCamelCase', () => {\n  it('expect to throw an error if input is not a string', () => {\n    expect(() => checkCamelCase(null)).toThrow()\n  })\n\n  it('expects to return true if the input is in camel case format', () => {\n    const value = 'dockerBuild'\n    const result = checkCamelCase(value)\n    expect(result).toBe(true)\n  })\n\n  it('expects to return false if the input is not in camel case format', () => {\n    const value = 'docker_build'\n    const result = checkCamelCase(value)\n    expect(result).toBe(false)\n  })\n\n  it('should throw when input is not a string', () => {\n    expect(() => checkCamelCase(100)).toThrowError()\n  })\n})\n"
  },
  {
    "path": "String/test/CheckExceeding.test.js",
    "content": "import { checkExceeding } from '../CheckExceeding'\n\ndescribe('Testing CheckExceeding function', () => {\n  it('Testing the invalid types', () => {\n    expect(() => checkExceeding(Math.random())).toThrow(\n      'Argument is not a string'\n    )\n    expect(() => checkExceeding(null)).toThrow('Argument is not a string')\n    expect(() => checkExceeding(false)).toThrow('Argument is not a string')\n    expect(() => checkExceeding(false)).toThrow('Argument is not a string')\n  })\n\n  it('Testing with empty string', () => {\n    expect(checkExceeding('')).toBe(true)\n  })\n\n  it('Testing with linear alphabets', () => {\n    expect(checkExceeding('a b c d e ')).toBe(true)\n    expect(checkExceeding('f g h i j ')).toBe(true)\n    expect(checkExceeding('k l m n o ')).toBe(true)\n    expect(checkExceeding('p q r s t ')).toBe(true)\n    expect(checkExceeding('u v w x y z')).toBe(true)\n  })\n\n  it('Testing not exceeding words', () => {\n    expect(checkExceeding('Hello')).toBe(false)\n    expect(checkExceeding('world')).toBe(false)\n    expect(checkExceeding('update')).toBe(false)\n    expect(checkExceeding('university')).toBe(false)\n    expect(checkExceeding('dog')).toBe(false)\n    expect(checkExceeding('exceeding')).toBe(false)\n    expect(checkExceeding('resolved')).toBe(false)\n    expect(checkExceeding('future')).toBe(false)\n    expect(checkExceeding('fixed')).toBe(false)\n    expect(checkExceeding('codes')).toBe(false)\n    expect(checkExceeding('facebook')).toBe(false)\n    expect(checkExceeding('vscode')).toBe(false)\n  })\n\n  it('Testing exceeding words', () => {\n    expect(checkExceeding('bee')).toBe(true) // [ 3 ]\n    expect(checkExceeding('can')).toBe(true) // [ 2, 13 ]\n    expect(checkExceeding('good')).toBe(true) //  [ 8, 11 ]\n    expect(checkExceeding('bad')).toBe(true) // [ 1, 3 ]\n    expect(checkExceeding('play')).toBe(true) // [ 4, 11, 24 ]\n    expect(checkExceeding('delete')).toBe(true) // [1, 7, 7, 15, 15]\n  })\n})\n"
  },
  {
    "path": "String/test/CheckFlatCase.test.js",
    "content": "import { checkFlatCase } from '../CheckFlatCase'\n\ndescribe('checkFlatCase function', () => {\n  it('should return false when the input string is not in flatcase', () => {\n    const actual = checkFlatCase('this is not in flatcase')\n    expect(actual).toBe(false)\n  })\n\n  it('should return true when the input string is a single letter character', () => {\n    const actual = checkFlatCase('a')\n    expect(actual).toBe(true)\n  })\n\n  it('should return true when the input string is a string of lowercase letter characters with no spaces', () => {\n    const actual = checkFlatCase('abcdefghijklmnopqrstuvwxyz')\n    expect(actual).toBe(true)\n  })\n\n  it('should throw when input is not a string', () => {\n    expect(() => checkFlatCase(100)).toThrowError()\n  })\n})\n"
  },
  {
    "path": "String/test/CheckKebabCase.test.js",
    "content": "import { CheckKebabCase } from '../CheckKebabCase'\n\ntest('CheckKebabCase(The-Algorithms) -> true', () => {\n  const word = 'The-Algorithms'\n  const res = CheckKebabCase(word)\n  expect(res).toBeTruthy()\n})\n\ntest('CheckKebabCase(The Algorithms) -> false', () => {\n  const word = 'The Algorithms'\n  const res = CheckKebabCase(word)\n  expect(res).toBeFalsy()\n})\n\ntest('CheckKebabCase throws when input is not a string', () => {\n  expect(() => CheckKebabCase(100)).toThrowError()\n})\n"
  },
  {
    "path": "String/test/CheckPalindrome.test.js",
    "content": "import { checkPalindrome } from '../CheckPalindrome'\n\ndescribe('checkPalindrome', () => {\n  it('expects to return \"Palindrome\" if the given string is a palindrome', () => {\n    const SUT = checkPalindrome('madam')\n    expect(SUT).toBe('Palindrome')\n  })\n  it('expects to return \"Empty string\" if the given string is empty', () => {\n    const SUT = checkPalindrome('')\n    expect(SUT).toBe('Empty string')\n  })\n  it('expects to return \"Not a string\" if the given string is not a string', () => {\n    const SUT = checkPalindrome(123)\n    expect(SUT).toBe('Not a string')\n  })\n})\n"
  },
  {
    "path": "String/test/CheckPangram.test.js",
    "content": "import { checkPangramRegex, checkPangramSet } from '../CheckPangram'\n\ndescribe('Testing checkPangramRegex function', () => {\n  it('\"The quick brown fox jumps over the lazy dog\" is a pangram', () => {\n    expect(\n      checkPangramRegex('The quick brown fox jumps over the lazy dog')\n    ).toBe(true)\n  })\n\n  it('\"Waltz, bad nymph, for quick jigs vex.\" is a pangram', () => {\n    expect(checkPangramRegex('Waltz, bad nymph, for quick jigs vex.')).toBe(\n      true\n    )\n  })\n\n  it('\"Jived fox nymph grabs quick waltz.\" is a pangram', () => {\n    expect(checkPangramRegex('Jived fox nymph grabs quick waltz.')).toBe(true)\n  })\n\n  it('\"My name is Unknown\" is NOT a pangram', () => {\n    expect(checkPangramRegex('My name is Unknown')).toBe(false)\n  })\n\n  it('\"The quick brown fox jumps over the la_y dog\" is NOT a pangram', () => {\n    expect(\n      checkPangramRegex('The quick brown fox jumps over the la_y dog')\n    ).toBe(false)\n  })\n\n  it('Throws an error if given param is not a string', () => {\n    expect(() => {\n      checkPangramRegex(undefined)\n    }).toThrow('The given value is not a string')\n  })\n})\n\ndescribe('Testing checkPangramSet function', () => {\n  it('\"The quick brown fox jumps over the lazy dog\" is a pangram', () => {\n    expect(checkPangramSet('The quick brown fox jumps over the lazy dog')).toBe(\n      true\n    )\n  })\n\n  it('\"Waltz, bad nymph, for quick jigs vex.\" is a pangram', () => {\n    expect(checkPangramSet('Waltz, bad nymph, for quick jigs vex.')).toBe(true)\n  })\n\n  it('\"Jived fox nymph grabs quick waltz.\" is a pangram', () => {\n    expect(checkPangramSet('Jived fox nymph grabs quick waltz.')).toBe(true)\n  })\n\n  it('\"My name is Unknown\" is NOT a pangram', () => {\n    expect(checkPangramSet('My name is Unknown')).toBe(false)\n  })\n\n  it('\"The quick brown fox jumps over the la_y dog\" is NOT a pangram', () => {\n    expect(checkPangramSet('The quick brown fox jumps over the la_y dog')).toBe(\n      false\n    )\n  })\n\n  it('Throws an error if given param is not a string', () => {\n    expect(() => {\n      checkPangramSet(undefined)\n    }).toThrow('The given value is not a string')\n  })\n})\n"
  },
  {
    "path": "String/test/CheckPascalCase.test.js",
    "content": "import { CheckPascalCase } from '../CheckPascalCase'\n\ntest('CheckPascalCase(TheAlgorithms) -> true', () => {\n  const word = 'TheAlgorithms'\n  const res = CheckPascalCase(word)\n  expect(res).toBeTruthy()\n})\n\ntest('CheckPascalCase(theAlgorithms) -> false', () => {\n  const word = 'theAlgorithms'\n  const res = CheckPascalCase(word)\n  expect(res).toBeFalsy()\n})\n\ntest('CheckPascalCase(The Algorithms) -> false', () => {\n  const word = 'The Algorithms'\n  const res = CheckPascalCase(word)\n  expect(res).toBeFalsy()\n})\n\ntest('CheckPascalCase throws when input is not a string', () => {\n  expect(() => CheckPascalCase(100)).toThrowError()\n})\n"
  },
  {
    "path": "String/test/CheckRearrangePalindrome.test.js",
    "content": "import { palindromeRearranging } from '../CheckRearrangePalindrome'\n\ntest('palindromeRearranging(apple) -> false', () => {\n  const word = 'apple'\n  const res = palindromeRearranging(word)\n  expect(res).toBeFalsy()\n})\n\ntest('palindromeRearranging(aapplle) -> true', () => {\n  const word = 'aapplle'\n  const res = palindromeRearranging(word)\n  expect(res).toBeTruthy()\n})\n\ntest('palindromeRearranging(value) -> false', () => {\n  const word = 'value'\n  const res = palindromeRearranging(word)\n  expect(res).toBeFalsy()\n})\n\ntest('palindromeRearranging(aaeccrr) -> true', () => {\n  const word = 'aaeccrr'\n  const res = palindromeRearranging(word)\n  expect(res).toBeTruthy()\n})\n"
  },
  {
    "path": "String/test/CheckSnakeCase.test.js",
    "content": "import { checkSnakeCase } from '../CheckSnakeCase'\ndescribe('checkSnakeCase', () => {\n  it('expect to throw an error if input is not a string', () => {\n    expect(() => checkSnakeCase(0)).toThrow()\n  })\n\n  it('expects to return true if the input is in snake case format', () => {\n    const value = 'docker_build'\n    const result = checkSnakeCase(value)\n    expect(result).toBe(true)\n  })\n\n  it('expects to return false if the input is not in snake case format', () => {\n    const value = 'dockerBuild'\n    const result = checkSnakeCase(value)\n    expect(result).toBe(false)\n  })\n})\n"
  },
  {
    "path": "String/test/CheckWordOcurrence.test.js",
    "content": "import { checkWordOccurrence } from '../CheckWordOccurrence'\n\ndescribe('Testing checkWordOccurrence', () => {\n  it('expects throw on insert wrong string', () => {\n    const value = 123\n\n    expect(() => checkWordOccurrence(value)).toThrow()\n  })\n\n  it('expect throw on insert wrong param for case sensitive', () => {\n    const value = 'hello'\n\n    expect(() => checkWordOccurrence(value, value)).toThrow()\n  })\n\n  it('check occurrence with case sensitive', () => {\n    const stringToTest = 'The quick brown fox jumps over the lazy dog'\n    const expectResult = {\n      The: 1,\n      quick: 1,\n      brown: 1,\n      fox: 1,\n      jumps: 1,\n      over: 1,\n      the: 1,\n      lazy: 1,\n      dog: 1\n    }\n\n    expect(checkWordOccurrence(stringToTest)).toEqual(expectResult)\n  })\n\n  it('check occurrence with case insensitive', () => {\n    const stringToTest = 'The quick brown fox jumps over the lazy dog'\n    const expectResult = {\n      the: 2,\n      quick: 1,\n      brown: 1,\n      fox: 1,\n      jumps: 1,\n      over: 1,\n      lazy: 1,\n      dog: 1\n    }\n\n    expect(checkWordOccurrence(stringToTest, true)).toEqual(expectResult)\n  })\n})\n"
  },
  {
    "path": "String/test/CountLetters.test.js",
    "content": "import { countLetters } from '../CountLetters'\n\ndescribe('CountLetters', () => {\n  it('expect throws on use wrong param', () => {\n    expect(() => countLetters(0)).toThrow()\n  })\n\n  it('expect throws when using a number in the string', () => {\n    expect(() => countLetters('h3llo')).toThrow()\n  })\n\n  it('expect throws when using a special characters in the string', () => {\n    expect(() => countLetters('hello!')).toThrow()\n  })\n\n  it('count the letters in a string. Allows lower case', () => {\n    const value = 'hello'\n    const count = countLetters(value)\n    expect(count).toEqual({ h: 1, e: 1, l: 2, o: 1 })\n  })\n\n  it('count the letters in a string. Allows upper case', () => {\n    const value = 'HELLO'\n    const count = countLetters(value)\n    expect(count).toEqual({ h: 1, e: 1, l: 2, o: 1 })\n  })\n\n  it('count the letters in a string. Allows upper and lower case', () => {\n    const value = 'HelLo'\n    const count = countLetters(value)\n    expect(count).toEqual({ h: 1, e: 1, l: 2, o: 1 })\n  })\n})\n"
  },
  {
    "path": "String/test/CountSubstrings.test.js",
    "content": "import { countSubstrings } from '../CountSubstrings'\n\ndescribe('CountSubstrings', () => {\n  it('count multiple occurrences of substring in a string', () => {\n    const str = 'This is a string'\n    const substring = 'is'\n    const count = countSubstrings(str, substring)\n    expect(count).toBe(2)\n  })\n\n  it('should return 0 when input substring has no occurrences', () => {\n    const str = 'Jurassic Park'\n    const substring = 'World'\n    const count = countSubstrings(str, substring)\n    expect(count).toBe(0)\n  })\n\n  it('should return 1 when input substring is of length 1 that is equal to string', () => {\n    const str = 's'\n    const substring = 's'\n    const count = countSubstrings(str, substring)\n    expect(count).toBe(1)\n  })\n\n  it('should return the correct result when input string contains spaces', () => {\n    const str = 'ab cd ef  ghi'\n    const substring = ' '\n    const count = countSubstrings(str, substring)\n    expect(count).toBe(4)\n  })\n\n  it('should return the correct result when input substring contains number or special characters', () => {\n    const str = 'abc1@2def1@2'\n    const substring = '1@2'\n    const count = countSubstrings(str, substring)\n    expect(count).toBe(2)\n  })\n\n  it('should return string.length + 1 when the input substring is an empty string', () => {\n    const str = 'empty'\n    const substring = ''\n    const count = countSubstrings(str, substring)\n    expect(count).toBe(6)\n  })\n\n  it('should return correct result when input is overlapping substring', () => {\n    const str = 'aaa'\n    const substring = 'aa'\n    const count = countSubstrings(str, substring)\n    expect(count).toBe(2)\n  })\n})\n"
  },
  {
    "path": "String/test/CountVowels.test.js",
    "content": "import { countVowels } from '../CountVowels'\n\ndescribe('CountVowels', () => {\n  it('expect throws on use wrong param', () => {\n    expect(() => countVowels(0)).toThrow()\n  })\n\n  it('count the vowels in a string', () => {\n    const value = 'Mad World'\n    const count = countVowels(value)\n    expect(count).toBe(2)\n  })\n\n  it('should return 0 when input is a string with no vowels', () => {\n    const value = 'bcdfgh'\n    const count = countVowels(value)\n    expect(count).toBe(0)\n  })\n\n  it('should return 1 when input is a string of length 1 that is a vowel', () => {\n    const value = 'a'\n    const count = countVowels(value)\n    expect(count).toBe(1)\n  })\n\n  it('should return the correct result when input is in all uppercase letters', () => {\n    const value = 'ABCDE'\n    const count = countVowels(value)\n    expect(count).toBe(2)\n  })\n\n  it('should return the correct result when input is in all lowercase letters', () => {\n    const value = 'abcdefghi'\n    const count = countVowels(value)\n    expect(count).toBe(3)\n  })\n\n  it('should return the correct result when input string contains spaces', () => {\n    const value = 'abc def   ghi'\n    const count = countVowels(value)\n    expect(count).toBe(3)\n  })\n\n  it('should return the correct result when input contains number characters', () => {\n    const value = 'a1b2c3'\n    const count = countVowels(value)\n    expect(count).toBe(1)\n  })\n\n  it('should return the correct result when input contains punctuation characters', () => {\n    const value = 'a!b.ce)'\n    const count = countVowels(value)\n    expect(count).toBe(2)\n  })\n\n  it('should return 0 when the input is an empty string', () => {\n    const value = ''\n    const count = countVowels(value)\n    expect(count).toBe(0)\n  })\n\n  it('should count multiple occurrences of the same vowel in the input', () => {\n    const value = 'aaaaa'\n    const count = countVowels(value)\n    expect(count).toBe(5)\n  })\n})\n"
  },
  {
    "path": "String/test/CreatePermutations.test.js",
    "content": "import { createPermutations } from '../CreatePermutations'\n\ndescribe('createPermutations', () => {\n  it('expects to generate 6 different combinations', () => {\n    const text = 'abc'\n    const SUT = createPermutations(text)\n    expect(SUT).toStrictEqual(['abc', 'acb', 'bac', 'bca', 'cab', 'cba'])\n  })\n  it('expects to generate 2 different combinations', () => {\n    const text = '12'\n    const SUT = createPermutations(text)\n    expect(SUT).toStrictEqual(['12', '21'])\n  })\n})\n"
  },
  {
    "path": "String/test/DiceCoefficient.test.js",
    "content": "import { diceCoefficient } from '../DiceCoefficient'\n\ndescribe('diceCoefficient', () => {\n  it('should calculate edit distance between two strings', () => {\n    // equal strings return 1 (max possible value)\n    expect(diceCoefficient('abc', 'abc')).toBe(1)\n    expect(diceCoefficient('', '')).toBe(1)\n\n    // string length needs to be at least 2 (unless equal)\n    expect(diceCoefficient('a', '')).toBe(0)\n    expect(diceCoefficient('', 'a')).toBe(0)\n\n    expect(diceCoefficient('skate', 'ate')).toBe(0.66)\n\n    expect(diceCoefficient('money', 'honey')).toBe(0.75)\n\n    expect(diceCoefficient('love', 'hate')).toBe(0)\n\n    expect(diceCoefficient('skilled', 'killed')).toBe(0.9)\n  })\n})\n"
  },
  {
    "path": "String/test/FirstUniqueCharacter.test.js",
    "content": "import { firstUniqChar } from '../FirstUniqueCharacter'\n\ndescribe('firstUniqChar', () => {\n  it('locates the index of first unique character in the string', () => {\n    expect(firstUniqChar('javascript')).toEqual(0)\n    expect(firstUniqChar('sesquipedalian')).toEqual(3)\n    expect(firstUniqChar('aabb')).toEqual(-1)\n  })\n})\n"
  },
  {
    "path": "String/test/FormatPhoneNumber.test.js",
    "content": "import formatPhoneNumber from '../FormatPhoneNumber'\n\ndescribe('Testing the formatPhoneNumber functions', () => {\n  it('expects to throw a type error', () => {\n    expect(() => formatPhoneNumber('1234567')).toThrow('Invalid phone number!')\n    expect(() => formatPhoneNumber('123456text')).toThrow(\n      'Invalid phone number!'\n    )\n    expect(() => formatPhoneNumber(12345)).toThrow('Invalid phone number!')\n  })\n\n  it('expects to return the formatted phone number', () => {\n    expect(formatPhoneNumber('1234567890')).toEqual('(123) 456-7890')\n    expect(formatPhoneNumber('2124323322')).toEqual('(212) 432-3322')\n    expect(formatPhoneNumber('1721543455')).toEqual('(172) 154-3455')\n  })\n})\n"
  },
  {
    "path": "String/test/HammingDistance.test.js",
    "content": "import { hammingDistance } from '../HammingDistance'\n\ntest('should throw an error when trying to compare the strings of different length', () => {\n  const compareStringsOfDifferentLength = () => {\n    hammingDistance('abc', 'abcd')\n  }\n\n  expect(compareStringsOfDifferentLength).toThrowError()\n})\n\ntest('should calculate difference between two strings', () => {\n  expect(hammingDistance('a', 'a')).toBe(0)\n})\n\ntest('should calculate difference between two strings', () => {\n  expect(hammingDistance('abc', 'add')).toBe(2)\n})\n\ntest('should calculate difference between two strings', () => {\n  expect(hammingDistance('1011101', '1001001')).toBe(2)\n})\n"
  },
  {
    "path": "String/test/IsPalindrome.test.js",
    "content": "import { isPalindromeIterative } from '../IsPalindrome'\n\ndescribe('isPalindrome', () => {\n  it('expects to return true with empty string', () => {\n    expect(isPalindromeIterative('')).toEqual(true)\n  })\n\n  it('expects to return true when length of input is 1', () => {\n    const numberInput = 6\n    const stringInput = 'a'\n    expect(isPalindromeIterative(numberInput)).toEqual(true)\n    expect(isPalindromeIterative(stringInput)).toEqual(true)\n  })\n\n  it('expects to return true when input is palindrome', () => {\n    expect(isPalindromeIterative(121)).toEqual(true)\n    expect(isPalindromeIterative('yooy')).toEqual(true)\n    expect(isPalindromeIterative('19noon91')).toEqual(true)\n    expect(isPalindromeIterative('!*tyyt*!')).toEqual(true)\n  })\n\n  it('expects to return false when input is not palindrome', () => {\n    expect(isPalindromeIterative('hello')).toEqual(false)\n    expect(isPalindromeIterative(189)).toEqual(false)\n    expect(isPalindromeIterative('!*98[!')).toEqual(false)\n  })\n\n  it('expects to throw error when input is not a string or a number', () => {\n    expect(() => isPalindromeIterative(undefined)).toThrowError()\n    expect(() => isPalindromeIterative({ key: 'val' })).toThrowError()\n    expect(() => isPalindromeIterative([])).toThrowError()\n  })\n})\n"
  },
  {
    "path": "String/test/KMPPatternSearching.test.js",
    "content": "import { KMPSearch } from '../KMPPatternSearching'\n\ndescribe('KMP Matcher', () => {\n  it('TC1: expects to return matching indices for pattern in text', () => {\n    const text = 'ABC ABCDAB ABCDABCDABDE'\n    const pattern = 'ABCDABD'\n    expect(KMPSearch(text, pattern)).toStrictEqual([15])\n  })\n\n  it('TC2: expects to return matching indices for pattern in text', () => {\n    const text = 'ABC ABCDABD ABCDABCDABDE'\n    const pattern = 'ABCDABD'\n    expect(KMPSearch(text, pattern)).toStrictEqual([4, 16])\n  })\n\n  it('TC3: expects to return matching indices for pattern in text', () => {\n    const text = 'AAAAA'\n    const pattern = 'AAA'\n    expect(KMPSearch(text, pattern)).toStrictEqual([0, 1, 2])\n  })\n\n  it('TC4: expects to return matching indices for pattern in text', () => {\n    const text = 'ABCD'\n    const pattern = 'BA'\n    expect(KMPSearch(text, pattern)).toStrictEqual([])\n  })\n})\n"
  },
  {
    "path": "String/test/LengthofLongestSubstringWithoutRepetition.test.js",
    "content": "import { lengthOfLongestSubstring } from '../LengthofLongestSubstringWithoutRepetition'\n\ndescribe('LengthOfLongestSubstring', () => {\n  it('should throw error if parameter is not string', () => {\n    expect(() => lengthOfLongestSubstring(345)).toThrowError(TypeError)\n    expect(() => lengthOfLongestSubstring(true)).toThrowError(TypeError)\n    expect(() => lengthOfLongestSubstring(null)).toThrowError(TypeError)\n  })\n\n  it('should check substrings containing unique characters', () => {\n    expect(lengthOfLongestSubstring('abcabcbb')).toBe(3)\n    expect(lengthOfLongestSubstring('bbbbb')).toBe(1)\n    expect(lengthOfLongestSubstring('pwwkew')).toBe(3)\n    expect(lengthOfLongestSubstring(' ')).toBe(1)\n    expect(lengthOfLongestSubstring('abcdefghijklmnaaaaa')).toBe(14)\n  })\n\n  it('should give zero for empty strings', () => {\n    expect(lengthOfLongestSubstring('')).toBe(0)\n  })\n\n  it('should be case-sensitive', () => {\n    expect(lengthOfLongestSubstring('AaBbCc')).toBe(6)\n    expect(lengthOfLongestSubstring('AbCdEf')).toBe(6)\n  })\n})\n"
  },
  {
    "path": "String/test/LevenshteinDistance.test.js",
    "content": "import { levenshteinDistance } from '../LevenshteinDistance'\n\ndescribe('levenshteinDistance', () => {\n  it('should calculate edit distance between two strings', () => {\n    expect(levenshteinDistance('', '')).toBe(0)\n    expect(levenshteinDistance('a', '')).toBe(1)\n    expect(levenshteinDistance('', 'a')).toBe(1)\n    expect(levenshteinDistance('abc', '')).toBe(3)\n    expect(levenshteinDistance('', 'abc')).toBe(3)\n\n    // Should just add I to the beginning.\n    expect(levenshteinDistance('igloo', 'gloo')).toBe(1)\n\n    // Should just substitute i with o, m with g and insert e at end\n    expect(levenshteinDistance('firm', 'forge')).toBe(3)\n\n    // Should just substitute f with s, g with t and delete h\n    expect(levenshteinDistance('fighting', 'sitting')).toBe(3)\n\n    // Should add 4 letters b, a, s and e at the beginning.\n    expect(levenshteinDistance('ball', 'baseball')).toBe(4)\n\n    // Should delete 4 letters b, a, s and e at the beginning and replace the last 4 with f, o, o, t\n    expect(levenshteinDistance('baseball', 'foot')).toBe(8)\n  })\n})\n"
  },
  {
    "path": "String/test/Lower.test.js",
    "content": "import lower from '../Lower'\n\ndescribe('Testing the Lower function', () => {\n  it('Test 1: Check by invalid type', () => {\n    expect(() => lower(345)).toThrowError()\n    expect(() => lower(true)).toThrowError()\n    expect(() => lower(null)).toThrowError()\n  })\n\n  it('Test 2: Check by uppercase string', () => {\n    expect(lower('WORLD')).toBe('world')\n    expect(lower('Hello_WORLD')).toBe('hello_world')\n  })\n\n  it('Test 3: Check by lowercase string', () => {\n    expect(lower('hello')).toBe('hello')\n    expect(lower('hello_world')).toBe('hello_world')\n  })\n})\n"
  },
  {
    "path": "String/test/MaxCharacter.test.js",
    "content": "import maxCharacter from '../MaxCharacter'\n\ndescribe('Testing the maxCharacter function', () => {\n  it('Expect throw with wrong arg', () => {\n    expect(() => maxCharacter(123)).toThrow()\n    expect(() => maxCharacter('')).toThrow()\n  })\n\n  it('Check the max character in string', () => {\n    const theString = \"I can't do that\"\n    const maxCharInAllCount = maxCharacter(theString)\n    const maxChar = maxCharacter(theString, /\\s/)\n\n    expect(maxCharInAllCount).toBe(' ')\n    expect(maxChar).toBe('t')\n\n    expect(maxCharacter('!!!Hello, World!!!', /[a-z]/)).toBe('!')\n\n    expect(maxCharacter('!!!Hello, World!!!', /[^a-z]/i)).toBe('l')\n  })\n})\n"
  },
  {
    "path": "String/test/MaxWord.test.js",
    "content": "import { maxWord } from '../MaxWord'\n\ndescribe('Testing the maxWord function', () => {\n  it('Expect throw with non string argument', () => {\n    expect(() => maxWord(10)).toThrow()\n  })\n  it('get the max word', () => {\n    const string = 'be be be be a a banana'\n    const mostOccurringWord = maxWord(string)\n    expect(mostOccurringWord).toBe('be')\n  })\n})\n"
  },
  {
    "path": "String/test/PatternMatching.test.js",
    "content": "import { checkIfPatternExists } from '../PatternMatching'\ndescribe('checkIfPatternExists', () => {\n  it('expects to find a pattern with correct input', () => {\n    const text = 'AABAACAADAABAAAABAA'\n    const pattern = 'AABA'\n    const SUT = checkIfPatternExists(text.toLowerCase(), pattern.toLowerCase())\n    expect(SUT).toBe('Given pattern is found at index 0')\n  })\n  it('expects to return a message when there is no pattern', () => {\n    const text = 'ABCDEFG'\n    const pattern = 'AEG'\n    const SUT = checkIfPatternExists(text.toLowerCase(), pattern.toLowerCase())\n    expect(SUT).toBe(undefined)\n  })\n  it('expects to find a pattern independent of casing', () => {\n    const text = 'AbCAAAAAAB'\n    const pattern = 'abc'\n    const SUT = checkIfPatternExists(text, pattern)\n    expect(SUT).toBe(undefined)\n  })\n  it('expects to throw an error message when given input is not a string', () => {\n    const text = 123444456\n    const pattern = 123\n    expect(() => checkIfPatternExists(text, pattern)).toThrow(\n      'Given input is not a string'\n    )\n  })\n})\n"
  },
  {
    "path": "String/test/PercentageOfLetters.test.js",
    "content": "import { percentageOfLetter } from '../PercentageOfLetters'\n\ndescribe('Percentage of Letters in a String', () => {\n  test('Calculate percent for lower case', () => {\n    expect(percentageOfLetter('foobar', 'o')).toEqual(33)\n    expect(percentageOfLetter('aaabcd', 'a')).toEqual(50)\n  })\n  test('Calculate percent for upper case', () => {\n    expect(percentageOfLetter('foobar', 'o')).toEqual(33)\n    expect(percentageOfLetter('aAabcd', 'a')).toEqual(50)\n  })\n  test('Throwing an exception', () => {\n    expect(() => percentageOfLetter(100, 'string')).toThrow()\n    expect(() => percentageOfLetter('string', true)).toThrow()\n  })\n})\n"
  },
  {
    "path": "String/test/PermutateString.test.js",
    "content": "import { permutate } from '../PermutateString'\n\ndescribe('Permutate a string', () => {\n  it('expects to throw an Error with an empty string', () => {\n    expect(() => {\n      permutate()\n    }).toThrow('The arg must be a valid, non empty string')\n  })\n  it('expects to permute \"no\" into [no, on]', () => {\n    expect(['no', 'on']).toEqual(permutate('no'))\n  })\n  it('expects to permute \"yes\" into [esy, eys, sey, sye, yes, yse]', () => {\n    expect(['esy', 'eys', 'sey', 'sye', 'yes', 'yse']).toEqual(permutate('yes'))\n  })\n  it('expects to permute \"good\" into [dgoo dogo doog gdoo godo good odgo odog ogdo ogod oodg oogd ]', () => {\n    expect([\n      'dgoo',\n      'dogo',\n      'doog',\n      'gdoo',\n      'godo',\n      'good',\n      'odgo',\n      'odog',\n      'ogdo',\n      'ogod',\n      'oodg',\n      'oogd'\n    ]).toEqual(permutate('good'))\n  })\n})\n"
  },
  {
    "path": "String/test/ReverseString.test.js",
    "content": "import {\n  ReverseStringIterative,\n  ReverseStringIterativeInplace\n} from '../ReverseString'\n\ndescribe('ReverseStringIterative', () => {\n  it('expects to reverse a simple string', () => {\n    expect(ReverseStringIterative('reverse')).toEqual('esrever')\n    expect(ReverseStringIterative('some')).toEqual('emos')\n    expect(ReverseStringIterative('string')).toEqual('gnirts')\n    expect(ReverseStringIterative('The Algorithms Javascript')).toEqual(\n      'tpircsavaJ smhtiroglA ehT'\n    )\n  })\n\n  it('expects to reverse a string with spaces in between', () => {\n    expect(ReverseStringIterative('reverse me')).toEqual('em esrever')\n  })\n\n  it('expects to reverse a simple string without capitalizing the first letter', () => {\n    expect(ReverseStringIterative('Javascript')).toEqual('tpircsavaJ')\n  })\n\n  it.each`\n    input\n    ${123456}\n    ${[1, 2, 3, 4, 5, 6]}\n    ${{ test: 'test' }}\n    ${null}\n  `(\n    'expects to throw a type error given a value that is $input',\n    ({ input }) => {\n      expect(() => ReverseStringIterative(input)).toThrow(\n        'The given value is not a string'\n      )\n    }\n  )\n\n  it('expects to return a empty string with an empty string is given', () => {\n    expect(ReverseStringIterative('')).toEqual('')\n  })\n})\n\ndescribe('ReverseStringIterativeInplace', () => {\n  it.each([\n    ['hello', 'olleh'],\n    ['word', 'drow']\n  ])('reverse of %s is %s', (value, expected) => {\n    expect(ReverseStringIterativeInplace(value)).toBe(expected)\n  })\n})\n"
  },
  {
    "path": "String/test/ReverseWords.test.js",
    "content": "import reverseWords from '../ReverseWords'\n\ndescribe('Testing the reverseWords function', () => {\n  it.each`\n    input\n    ${123456}\n    ${[1, 2, 3, 4, 5, 6]}\n    ${{ test: 'test' }}\n    ${null}\n  `(\n    'expects to throw a type error given a value that is $input',\n    ({ input }) => {\n      expect(() => {\n        reverseWords(input)\n      }).toThrow('The given value is not a string')\n    }\n  )\n\n  it('expects to reverse words to return a joined word', () => {\n    expect(reverseWords('I Love JS')).toBe('JS Love I')\n    expect(reverseWords('Hello World')).toBe('World Hello')\n    expect(reverseWords('The Algorithms Javascript')).toBe(\n      'Javascript Algorithms The'\n    )\n  })\n})\n"
  },
  {
    "path": "String/test/ScrambleStrings.test.js",
    "content": "import { isScramble } from '../ScrambleStrings'\n\ndescribe('ScrambleStrings', () => {\n  it('expects to return true for same string', () => {\n    expect(isScramble('a', 'a')).toBe(true)\n  })\n\n  it('expects to return false for non-scrambled strings', () => {\n    expect(isScramble('abcde', 'caebd')).toBe(false)\n  })\n\n  it('expects to return true for scrambled strings', () => {\n    expect(isScramble('great', 'rgeat')).toBe(true)\n  })\n})\n"
  },
  {
    "path": "String/test/Upper.test.js",
    "content": "import upper from '../Upper'\n\ndescribe('Testing the Upper function', () => {\n  it('return uppercase strings', () => {\n    expect(upper('hello')).toBe('HELLO')\n    expect(upper('WORLD')).toBe('WORLD')\n    expect(upper('hello_WORLD')).toBe('HELLO_WORLD')\n  })\n})\n"
  },
  {
    "path": "String/test/ValidateCreditCard.test.js",
    "content": "import { validateCreditCard } from '../ValidateCreditCard'\n\ndescribe('Validate credit card number', () => {\n  it('should throw error if card number is boolean', () => {\n    const invalidCC = true\n    expect(() => validateCreditCard(invalidCC)).toThrow(\n      'The given value is not a string'\n    )\n  })\n  it('returns true if the credit card number is valid', () => {\n    const validCreditCard = '4111111111111111'\n    const validationResult = validateCreditCard(validCreditCard)\n    expect(validationResult).toBe(true)\n  })\n  it('should throw an error on non-numeric character in given credit card number', () => {\n    const nonNumericCCNumbers = ['123ABCDEF', 'ABCDKDKD', 'ADS232']\n    nonNumericCCNumbers.forEach((nonNumericCC) =>\n      expect(() => validateCreditCard(nonNumericCC)).toThrow(\n        `${nonNumericCC} is an invalid credit card number because ` +\n          'it has nonnumerical characters.'\n      )\n    )\n  })\n  it('should throw an error on credit card with invalid length', () => {\n    const ccWithInvalidLength = ['41111', '4111111111111111111111']\n    ccWithInvalidLength.forEach((invalidCC) =>\n      expect(() => validateCreditCard(invalidCC)).toThrow(\n        `${invalidCC} is an invalid credit card number because ` +\n          'of its length.'\n      )\n    )\n  })\n  it('should throw an error on credit card with invalid start substring', () => {\n    const ccWithInvalidStartSubstring = [\n      '12345678912345',\n      '23456789123456',\n      '789123456789123',\n      '891234567891234',\n      '912345678912345',\n      '31345678912345',\n      '32345678912345',\n      '33345678912345',\n      '38345678912345'\n    ]\n    ccWithInvalidStartSubstring.forEach((invalidCC) =>\n      expect(() => validateCreditCard(invalidCC)).toThrow(\n        `${invalidCC} is an invalid credit card number because ` +\n          'of its first two digits.'\n      )\n    )\n  })\n  it('should throw an error on credit card with luhn check fail', () => {\n    const invalidCCs = ['411111111111111', '371211111111111', '49999999999999']\n    invalidCCs.forEach((invalidCC) =>\n      expect(() => validateCreditCard(invalidCC)).toThrow(\n        `${invalidCC} is an invalid credit card number because ` +\n          'it fails the Luhn check.'\n      )\n    )\n  })\n})\n"
  },
  {
    "path": "String/test/ValidateEmail.test.js",
    "content": "import { validateEmail } from '../ValidateEmail'\n\ndescribe('Validation of an Email Address', () => {\n  it('expects to return false', () => {\n    expect(validateEmail('mahfoudh.arous.com')).toEqual(false)\n  })\n\n  it('expects to return false', () => {\n    expect(validateEmail('mahfoudh.arous@com')).toEqual(false)\n  })\n\n  it('expects to return true', () => {\n    expect(validateEmail('mahfoudh.arous@gmail.com')).toEqual(true)\n  })\n\n  it('expects to return true', () => {\n    expect(validateEmail('icristianbaciu@.helsinki.edu')).toEqual(true)\n  })\n\n  it('expects to throw a type error', () => {\n    expect(() => {\n      validateEmail('')\n    }).toThrow('Email Address String Null or Empty.')\n    expect(() => {\n      validateEmail(null)\n    }).toThrow('Email Address String Null or Empty.')\n  })\n})\n"
  },
  {
    "path": "String/test/ZFunction.test.js",
    "content": "import zFunction from '../ZFunction'\n\ntest('Testing zFunction', () => {\n  expect(zFunction('aabxaayaab')).toEqual([10, 1, 0, 0, 2, 1, 0, 3, 1, 0])\n  expect(zFunction('aabxaabxcaabxaabxay')).toEqual([\n    19, 1, 0, 0, 4, 1, 0, 0, 0, 8, 1, 0, 0, 5, 1, 0, 0, 1, 0\n  ])\n})\n"
  },
  {
    "path": "Timing-Functions/GetMonthDays.js",
    "content": "/**\n  function that takes month number and its year and returns the number of days within it\n  * @param monthNumber.\n  * @param year.\n  e.g.: mahfoudh.arous@gmail.com -> true\n  e.g.: mahfoudh.arous.com ->false\n*/\n\nimport { isLeapYear } from '../Maths/LeapYear'\n\nconst getMonthDays = (monthNumber, year) => {\n  const the31DaysMonths = [1, 3, 5, 7, 8, 10, 12]\n  const the30DaysMonths = [4, 6, 9, 11]\n\n  if (\n    !the31DaysMonths.includes(monthNumber) &&\n    !the30DaysMonths.includes(monthNumber) &&\n    monthNumber !== 2\n  ) {\n    throw new TypeError('Invalid Month Number.')\n  }\n\n  if (the31DaysMonths.includes(monthNumber)) {\n    return 31\n  }\n\n  if (the30DaysMonths.includes(monthNumber)) {\n    return 30\n  }\n\n  if (isLeapYear(year)) {\n    return 29\n  }\n\n  return 28\n}\n\nexport { getMonthDays }\n"
  },
  {
    "path": "Timing-Functions/IntervalTimer.js",
    "content": "/**\n * @author Nandan V\n * Sunday, 26 July 2020 8:33 AM\n * @description Singleton class that handles the <b>timing of tests</b> and\n *   specs. <br/> The class is singleton as <u>javascript does not support\n *   multiple timer instances<u/>.\n */\nclass IntervalTimer {\n  /**\n   * @description Constructor for Timer.\n   * @param interval Sets the interval for running the timer.\n   * @param callBack The callback function to be executed.\n   * @return {IntervalTimer} If exists, the existing object.\n   */\n  constructor(interval = 10, callBack = () => {}) {\n    this.prevInterval = 0\n    if (this.instance == null) {\n      this.interval = interval\n      this.callBack = callBack\n      this.instance = this\n    } else {\n      return this.instance\n    }\n  }\n\n  /**\n   * @description Starts the timer.\n   */\n  startTimer() {\n    this.timer = setInterval(this.callBack, this.interval)\n  }\n\n  /**\n   * @description Resets the timer.\n   * @return {number} Elapsed time in milliseconds.\n   */\n  resetTimer() {\n    clearInterval(this.timer)\n    this.callBack = () => {}\n    return this.getElapsedTime()\n  }\n\n  /**\n   * @return {number} Elapsed time in milliseconds since reset.\n   */\n  getElapsedTime(offset = 0) {\n    this.timeElapsed = this.timer - this.prevInterval\n    this.prevInterval = this.timer\n    return this.timeElapsed - offset\n  }\n\n  /**\n   * @return {number} Elapsed time since start.\n   */\n  getRunTime() {\n    return this.timer\n  }\n}\n\n/**\n * @author Nandan V\n * Saturday, 01 August 2020 8:33 AM\n * @description Example usage\n */\nconst ExampleIntervalTimer = function (output = (v) => console.log(v)) {\n  /**\n   * Create am object with default settings.\n   * @type {IntervalTimer} Used to get timing information.\n   */\n  const timer = new IntervalTimer()\n  timer.startTimer()\n\n  // ... Initialization code ...\n  // I generally use it for timing tests in Jasmine JS.\n\n  /**\n   * Gets the runtime till this point.\n   * Can be subtracted from ElapsedTime to offset timing of initialization code.\n   */\n  const initOffset = timer.getRunTime()\n\n  // ... A test ...\n  // The time taken to run the test.\n  output(timer.getElapsedTime(initOffset))\n\n  /**\n   * Returns the elapsed time and resets the timer to 0.\n   */\n  output(timer.resetTimer())\n}\n\nexport { IntervalTimer, ExampleIntervalTimer }\n"
  },
  {
    "path": "Timing-Functions/ParseDate.js",
    "content": "import { getMonthDays } from './GetMonthDays'\n\nfunction checkDate(date) {\n  if (date.day < 1 || date.day > getMonthDays(date.month, date.year)) {\n    throw new Error('Invalid day value.')\n  }\n}\n\nfunction parseDate(dateString) {\n  const regex = /^(\\d{1,2})\\/(\\d{1,2})\\/(\\d{4})$/\n\n  const match = dateString.match(regex)\n\n  if (!match) {\n    throw new Error(\"Invalid date format. Please use 'dd/mm/yyyy'.\")\n  }\n\n  const res = {\n    day: parseInt(match[1], 10),\n    month: parseInt(match[2], 10),\n    year: parseInt(match[3], 10)\n  }\n  checkDate(res)\n  return res\n}\n\nexport { parseDate }\n"
  },
  {
    "path": "Timing-Functions/test/GetMonthDays.test.js",
    "content": "import { getMonthDays } from '../GetMonthDays'\n\ndescribe('Get the Days of a Month', () => {\n  it.each([\n    [1, 2024, 31],\n    [2, 2024, 29],\n    [3, 2024, 31],\n    [4, 2024, 30],\n    [5, 2024, 31],\n    [6, 2024, 30],\n    [7, 2024, 31],\n    [8, 2024, 31],\n    [9, 2024, 30],\n    [10, 2024, 31],\n    [11, 2024, 30],\n    [12, 2024, 31],\n    [1, 2023, 31],\n    [2, 2023, 28],\n    [3, 2023, 31],\n    [4, 2023, 30],\n    [5, 2023, 31],\n    [6, 2023, 30],\n    [7, 2023, 31],\n    [8, 2023, 31],\n    [9, 2023, 30],\n    [10, 2023, 31],\n    [11, 2023, 30],\n    [12, 2023, 31]\n  ])('Month %i in year %i has %i days', (month, year, expected) => {\n    expect(getMonthDays(month, year)).toBe(expected)\n  })\n\n  it('expects to throw a type error', () => {\n    expect(() => {\n      getMonthDays(13, 2020)\n    }).toThrow('Invalid Month Number.')\n  })\n})\n"
  },
  {
    "path": "Timing-Functions/test/ParseDate.test.js",
    "content": "import { parseDate } from '../ParseDate'\n\ndescribe('parseDate', () => {\n  it.each([\n    ['18/03/2024', { year: 2024, month: 3, day: 18 }],\n    ['29/02/2024', { year: 2024, month: 2, day: 29 }],\n    ['28/02/2023', { year: 2023, month: 2, day: 28 }],\n    ['01/12/2024', { year: 2024, month: 12, day: 1 }],\n    ['1/12/2024', { year: 2024, month: 12, day: 1 }],\n    ['10/1/2024', { year: 2024, month: 1, day: 10 }]\n  ])('Returns correct output for %s', (dateString, expected) => {\n    expect(parseDate(dateString)).toStrictEqual(expected)\n  })\n\n  it.each([\n    '18-03-2024',\n    '18.03.2024',\n    '03/2024',\n    '01/02/03/2024',\n    '123/03/2024'\n  ])('Throws for %s', (wrongDateString) => {\n    expect(() => {\n      parseDate(wrongDateString)\n    }).toThrow()\n  })\n\n  it.each([\n    '40/03/2024',\n    '30/02/2024',\n    '29/02/2023',\n    '31/04/2023',\n    '00/01/2024',\n    '01/00/2024',\n    '01/13/2024'\n  ])('Throws for %s', (wrongDateString) => {\n    expect(() => {\n      parseDate(wrongDateString)\n    }).toThrow()\n  })\n})\n"
  },
  {
    "path": "Trees/BreadthFirstTreeTraversal.js",
    "content": "/*\n  Breadth First Tree Traversal or level order traversal implementation in javascript\n  Author: @GerardUbuntu\n*/\n\nclass Node {\n  constructor(data) {\n    this.data = data\n    this.left = null\n    this.right = null\n  }\n}\n\nclass BinaryTree {\n  constructor() {\n    this.root = null\n  }\n\n  breadthFirstIterative() {\n    const traversal = []\n    if (this.root) {\n      traversal.push(this.root)\n    }\n    for (let i = 0; i < traversal.length; i++) {\n      const currentNode = traversal[i]\n      if (currentNode.left) {\n        traversal.push(currentNode.left)\n      }\n      if (currentNode.right) {\n        traversal.push(currentNode.right)\n      }\n      traversal[i] = currentNode.data\n    }\n    return traversal\n  }\n\n  breadthFirstRecursive() {\n    const traversal = []\n    const h = this.getHeight(this.root)\n    for (let i = 0; i !== h; i++) {\n      this.traverseLevel(this.root, i, traversal)\n    }\n    return traversal\n  }\n\n  // Computing the height of the tree\n  getHeight(node) {\n    if (node === null) {\n      return 0\n    }\n    const lheight = this.getHeight(node.left)\n    const rheight = this.getHeight(node.right)\n    return lheight > rheight ? lheight + 1 : rheight + 1\n  }\n\n  traverseLevel(node, levelRemaining, traversal) {\n    if (node === null) {\n      return\n    }\n    if (levelRemaining === 0) {\n      traversal.push(node.data)\n    } else {\n      this.traverseLevel(node.left, levelRemaining - 1, traversal)\n      this.traverseLevel(node.right, levelRemaining - 1, traversal)\n    }\n  }\n}\n\nexport { BinaryTree, Node }\n"
  },
  {
    "path": "Trees/DepthFirstSearch.js",
    "content": "/*\n * Author: Surendra Kumar\n * DFS Algorithm implementation in JavaScript\n * DFS Algorithm for traversing or searching graph data structures.\n */\n\n// traverses a give tree from specified root's value\nfunction traverseDFS(tree, rootValue) {\n  const stack = []\n  const res = []\n  stack.push(searchDFS(tree, rootValue))\n  // if root is not present in the tree, returning empty array\n  if (!stack[0]) return res\n  while (stack.length) {\n    const curr = stack.pop()\n    res.push(curr.value)\n    if (curr.left) {\n      stack.push(tree[curr.left])\n    }\n    if (curr.right) {\n      stack.push(tree[curr.right])\n    }\n  }\n  return res.reverse()\n}\n\nfunction searchDFS(tree, value) {\n  const stack = []\n  stack.push(tree[0])\n  while (stack.length !== 0) {\n    for (let i = 0; i < stack.length; i++) {\n      const node = stack.pop()\n      if (node.value === value) {\n        return node\n      }\n      if (node.right) {\n        stack.push(tree[node.right])\n      }\n      if (node.left) {\n        stack.push(tree[node.left])\n      }\n    }\n  }\n  return null\n}\n\nexport { searchDFS, traverseDFS }\n"
  },
  {
    "path": "Trees/FenwickTree.js",
    "content": "/*\n * Author: Mohit Kumar\n * Fenwick Tree Implementation in JavaScript\n * Fenwick Tree Implementation for finding prefix sum.\n */\n\nclass FenwickTree {\n  constructor(feneickArray, array, n) {\n    for (let i = 1; i <= n; i++) {\n      feneickArray[i] = 0\n    }\n    for (let i = 0; i < n; i++) {\n      this.update(feneickArray, n, i, array[i])\n    }\n  }\n\n  update(feneickArray, n, index, value) {\n    index = index + 1\n    while (index <= n) {\n      feneickArray[index] += value\n      index += index & -index\n    }\n  }\n\n  getPrefixSum(feneickArray, index) {\n    let currSum = 0\n    index = index + 1\n    while (index > 0) {\n      currSum += feneickArray[index]\n      index -= index & -index\n    }\n\n    return currSum\n  }\n}\nexport { FenwickTree }\n"
  },
  {
    "path": "Trees/test/BreadthFirstTreeTraversal.test.js",
    "content": "import { BinaryTree, Node } from '../BreadthFirstTreeTraversal'\n\ndescribe('Breadth First Tree Traversal', () => {\n  const binaryTree = new BinaryTree()\n\n  const root = new Node(7)\n  root.left = new Node(5)\n  root.right = new Node(8)\n  root.left.left = new Node(3)\n  root.left.right = new Node(6)\n  root.left.right.right = new Node(9)\n  binaryTree.root = root\n\n  // Visualization :\n  //\n  //            7\n  //           / \\\n  //          5   8\n  //         / \\\n  //        3   6\n  //             \\\n  //              9\n\n  it('Binary tree - Empty case', () => {\n    const emptyTree = new BinaryTree()\n    expect(emptyTree.breadthFirstIterative()).toStrictEqual([])\n  })\n\n  it('Binary tree - Level order recursive traversal', () => {\n    const traversal = binaryTree.breadthFirstRecursive()\n    expect(traversal).toStrictEqual([7, 5, 8, 3, 6, 9])\n  })\n\n  it('Binary tree - Level order iterative traversal', () => {\n    const traversal = binaryTree.breadthFirstIterative()\n    expect(traversal).toStrictEqual([7, 5, 8, 3, 6, 9])\n  })\n})\n"
  },
  {
    "path": "Trees/test/DepthFirstSearch.test.js",
    "content": "import { searchDFS, traverseDFS } from '../DepthFirstSearch'\n\ndescribe('Depth First Tree Traversal', () => {\n  const tree = [\n    { value: 6, left: 1, right: 2 },\n    { value: 5, left: 3, right: 4 },\n    { value: 7, left: null, right: 5 },\n    { value: 3, left: 6, right: null },\n    { value: 4, left: null, right: null },\n    { value: 9, left: 7, right: 8 },\n    { value: 2, left: 9, right: null },\n    { value: 8, left: null, right: null },\n    { value: 10, left: null, right: null },\n    { value: 1, left: null, right: null }\n  ]\n\n  //            6\n  //           / \\\n  //          5   7\n  //         / \\   \\\n  //        3   4   9\n  //       /       / \\\n  //      2       8   10\n  //     /\n  //    1\n\n  it('should be null if given value is not present in the tree - DF Search', () => {\n    const res = searchDFS(tree, 200)\n    expect(res).toStrictEqual(null)\n  })\n\n  it('should return the node if given value is present in the tree - DF Search', () => {\n    const res = searchDFS(tree, 9)\n    expect(res).toStrictEqual({ value: 9, left: 7, right: 8 })\n  })\n\n  it('should return empty array if given root is not present in the tree - DF Traversal', () => {\n    const traversal = traverseDFS(tree, 200)\n    expect(traversal).toStrictEqual([])\n  })\n\n  it('should return DFT array of given tree from specified root if given root is present in the tree - DF Traversal', () => {\n    const traversal = traverseDFS(tree, 6)\n    expect(traversal).toStrictEqual([1, 2, 3, 4, 5, 8, 10, 9, 7, 6])\n  })\n})\n"
  },
  {
    "path": "Trees/test/FenwickTree.test.js",
    "content": "import { FenwickTree } from '../FenwickTree'\n\ndescribe('Fenwick Tree Implementation', () => {\n  const fenwickArray = new Array(1000)\n  const array = [3, 2, 0, 6, 5, -1, 2]\n  const length = array.length\n\n  const fenwickTree = new FenwickTree(fenwickArray, array, length)\n\n  it('Fenwick Tree - Prefix sum of array', () => {\n    const prefixSum = fenwickTree.getPrefixSum(fenwickArray, 6)\n    expect(prefixSum).toBe(23)\n  })\n\n  array[2] += 6\n  fenwickTree.update(fenwickArray, length, 2, 6)\n\n  it('Fenwick Tree - Prefix sum of Updated array', () => {\n    const prefixSum = fenwickTree.getPrefixSum(fenwickArray, 6)\n    expect(prefixSum).toBe(23)\n  })\n})\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"javascript\",\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"description\": \"A repository for All algorithms implemented in Javascript (for educational purposes only)\",\n  \"scripts\": {\n    \"test\": \"vitest run\",\n    \"test-watch\": \"vitest\",\n    \"style\": \"npx prettier . --write\",\n    \"check-style\": \"npx prettier . --check\",\n    \"prepare\": \"husky install\"\n  },\n  \"author\": \"TheAlgorithms\",\n  \"license\": \"GPL-3.0\",\n  \"devDependencies\": {\n    \"globby\": \"^13.2.2\",\n    \"husky\": \"^8.0.3\",\n    \"prettier\": \"^3.0.3\",\n    \"vitest\": \"^1.2.1\",\n    \"@vitest/coverage-v8\": \"^1.2.1\"\n  },\n  \"engines\": {\n    \"node\": \">=20.6.0\"\n  }\n}\n"
  },
  {
    "path": "vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    globals: true,\n    restoreMocks: true,\n    coverage: {\n      reporter: ['text', 'json', 'html']\n    }\n  }\n})\n"
  }
]