diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 361d1abad..39b9ee544 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -15,12 +15,10 @@ jobs: - name: npm install, build, and test run: | npm install doctest standard --save-dev - npx doctest **/*.js || true # TODO: error: Line 1: Unexpected token >> + npx doctest **/*.js || true # TODO: Add all doctests npx standard npm ci npm run build --if-present - # TODO: Remove the next line when #539 is fixed. - rm Linear-Algebra/test/test.js String/LevenshteinDistance.test.js npm test env: CI: true diff --git a/Ciphers/KeywordShiftedAlphabet.js b/Ciphers/KeywordShiftedAlphabet.js new file mode 100644 index 000000000..1322f1381 --- /dev/null +++ b/Ciphers/KeywordShiftedAlphabet.js @@ -0,0 +1,72 @@ +/** + * Keyword shifted alphabet is a simple cipher using a translation table created with a help of a keyword. + * Keyword must be a word where each character can occur only once. + * To create the translation table, we write all the alphabet characters to the first. + * Second row start with the keyword, then we continue with the rest of the characters that are missing in alphabetical order. + * + * |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| + * |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| + * + * Encryption is then just a matter of writing the matching (same index) letter from the second row instead of the first row: + * 'Hello world' -> 'Aoggj ujngw' + * + * Decryption is then just the reverse process of writing the matching (same index) letter from the first row instead of the second row + * 'Aogg ujngw' -> 'Hello world' + * + * Non alphabetical characters (space, exclamation mark, ...) are kept as they are + */ + +const alphabet = ['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'] + +function checkKeywordValidity (keyword) { + keyword.split('').forEach((char, index) => { + const rest = keyword.slice(0, index) + keyword.slice(index + 1) + if (rest.indexOf(char) !== -1) { + return false + } + }) + return true +} + +function getEncryptedAlphabet (keyword) { + const encryptedAlphabet = keyword.split('') + alphabet.forEach((char) => { + if (encryptedAlphabet.indexOf(char) === -1) { + encryptedAlphabet.push(char) + } + }) + return encryptedAlphabet +} + +function translate (sourceAlphabet, targetAlphabet, message) { + return message.split('').reduce((encryptedMessage, char) => { + const isUpperCase = char === char.toUpperCase() + const encryptedCharIndex = sourceAlphabet.indexOf(char.toLowerCase()) + const encryptedChar = encryptedCharIndex !== -1 ? targetAlphabet[encryptedCharIndex] : char + encryptedMessage += isUpperCase ? encryptedChar.toUpperCase() : encryptedChar + return encryptedMessage + }, '') +} + +function checkInputs (keyword, message) { + if (!keyword || !message) { + throw new Error('Both keyword and message must be specified') + } + + if (!checkKeywordValidity(keyword)) { + throw new Error('Invalid keyword!') + } +} + +function encrypt (keyword, message) { + checkInputs(keyword, message) + return translate(alphabet, getEncryptedAlphabet(keyword.toLowerCase()), message) +} + +function decrypt (keyword, message) { + checkInputs(keyword, message) + return translate(getEncryptedAlphabet(keyword.toLowerCase()), alphabet, message) +} + +console.log(encrypt('keyword', 'Hello world!')) // Prints 'Aoggj ujngw!' +console.log(decrypt('keyword', 'Aoggj ujngw!')) // Prints 'Hello world! diff --git a/Conversions/DecimalToBinary.js b/Conversions/DecimalToBinary.js index a179dbaf2..9c8337b68 100644 --- a/Conversions/DecimalToBinary.js +++ b/Conversions/DecimalToBinary.js @@ -1,5 +1,5 @@ function decimalToBinary (num) { - var bin = [] + const bin = [] while (num > 0) { bin.unshift(num % 2) num >>= 1 // basically /= 2 without remainder if any diff --git a/Conversions/HexToRGB.js b/Conversions/HexToRGB.js index 5ee820b81..56e31abd7 100644 --- a/Conversions/HexToRGB.js +++ b/Conversions/HexToRGB.js @@ -1,12 +1,12 @@ function hexStringToRGB (hexString) { - var r = hexString.substring(0, 2) - var g = hexString.substring(2, 4) - var b = hexString.substring(4, 6) + let r = hexString.substring(0, 2) + let g = hexString.substring(2, 4) + let b = hexString.substring(4, 6) r = parseInt(r, 16) g = parseInt(g, 16) b = parseInt(b, 16) - var obj = { r, g, b } + const obj = { r, g, b } return obj } diff --git a/Conversions/RomanToDecimal.js b/Conversions/RomanToDecimal.js index 24f7b0fe6..6de4afa0c 100644 --- a/Conversions/RomanToDecimal.js +++ b/Conversions/RomanToDecimal.js @@ -1,4 +1,4 @@ -var values = { +const values = { I: 1, V: 5, X: 10, diff --git a/DIRECTORY.md b/DIRECTORY.md index 2f9d60eae..39c52824b 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -16,6 +16,7 @@ ## Ciphers * [CaesarsCipher](https://github.com/TheAlgorithms/Javascript/blob/master/Ciphers/CaesarsCipher.js) * [KeyFinder](https://github.com/TheAlgorithms/Javascript/blob/master/Ciphers/KeyFinder.js) + * [KeywordShiftedAlphabet](https://github.com/TheAlgorithms/Javascript/blob/master/Ciphers/KeywordShiftedAlphabet.js) * [ROT13](https://github.com/TheAlgorithms/Javascript/blob/master/Ciphers/ROT13.js) * [VigenereCipher](https://github.com/TheAlgorithms/Javascript/blob/master/Ciphers/VigenereCipher.js) * [XORCipher](https://github.com/TheAlgorithms/Javascript/blob/master/Ciphers/XORCipher.js) @@ -47,6 +48,7 @@ * [SingleCircularLinkedList](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Linked-List/SingleCircularLinkedList.js.js) * [SinglyLinkList](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Linked-List/SinglyLinkList.js) * Queue + * [CircularQueue](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Queue/CircularQueue.js) * [Queue](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Queue/Queue.js) * [QueueUsing2Stacks](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Queue/QueueUsing2Stacks.js) * Stack @@ -74,11 +76,15 @@ * [MaxNonAdjacentSum](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/MaxNonAdjacentSum.js) * [MinimumCostPath](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/MinimumCostPath.js) * [NumberOfSubsetEqualToGivenSum](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js) + * [Shuf](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/Shuf.js) * [SieveOfEratosthenes](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/SieveOfEratosthenes.js) * [SudokuSolver](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/SudokuSolver.js) * [TrappingRainWater](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/TrappingRainWater.js) * [ZeroOneKnapsack](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/ZeroOneKnapsack.js) +## Geometry + * [ConvexHullGraham](https://github.com/TheAlgorithms/Javascript/blob/master/Geometry/ConvexHullGraham.js) + ## Graphs * [BreadthFirstSearch](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/BreadthFirstSearch.js) * [BreadthFirstShortestPath](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/BreadthFirstShortestPath.js) @@ -88,6 +94,7 @@ * [DepthFirstSearchRecursive](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/DepthFirstSearchRecursive.js) * [Dijkstra](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/Dijkstra.js) * [DijkstraSmallestPath](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/DijkstraSmallestPath.js) + * [FloydWarshall](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/FloydWarshall.js) * [KruskalMST](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/KruskalMST.js) * [NodeNeighbors](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/NodeNeighbors.js) * [NumberOfIslands](https://github.com/TheAlgorithms/Javascript/blob/master/Graphs/NumberOfIslands.js) @@ -113,6 +120,7 @@ * [decimalIsolate](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/decimalIsolate.js) * [DigitSum](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/DigitSum.js) * [EulerMethod](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/EulerMethod.js) + * [EulersTotient](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/EulersTotient.js) * [EulersTotientFunction](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/EulersTotientFunction.js) * [Factorial](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Factorial.js) * [Factors](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Factors.js) @@ -123,6 +131,7 @@ * [isDivisible](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/isDivisible.js) * [isOdd](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/isOdd.js) * [Mandelbrot](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Mandelbrot.js) + * [MatrixExponentiationRecursive](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/MatrixExponentiationRecursive.js) * [MatrixMultiplication](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/MatrixMultiplication.js) * [MeanSquareError](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/MeanSquareError.js) * [ModularBinaryExponentiationRecursive](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/ModularBinaryExponentiationRecursive.js) @@ -137,9 +146,11 @@ * [Polynomial](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Polynomial.js) * [Pow](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Pow.js) * [PrimeCheck](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/PrimeCheck.js) + * [PrimeFactors](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/PrimeFactors.js) * [ReversePolishNotation](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/ReversePolishNotation.js) * [SieveOfEratosthenes](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/SieveOfEratosthenes.js) * [Softmax](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Softmax.js) + * [SquareRoot](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/SquareRoot.js) * test * [Abs](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/Abs.test.js) * [Area](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/test/Area.test.js) @@ -181,6 +192,7 @@ * [Problem014](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem014.js) * [Problem020](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem020.js) * [Problem1](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem1.js) + * [Problem10](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem10.js) * [Problem2](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem2.js) * [Problem3](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem3.js) * [Problem4](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem4.js) @@ -188,6 +200,8 @@ * [Problem6](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem6.js) * [Problem7](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem7.js) * [Problem9](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/Problem9.js) + * test + * [Problem10](https://github.com/TheAlgorithms/Javascript/blob/master/Project-Euler/test/Problem10.test.js) ## Recursive * [BinarySearch](https://github.com/TheAlgorithms/Javascript/blob/master/Recursive/BinarySearch.js) @@ -244,7 +258,7 @@ * [CheckVowels](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckVowels.test.js) * [CheckWordOccurrence](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckWordOccurrence.js) * [CheckWordOcurrence](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckWordOcurrence.test.js) - * [createPurmutations](https://github.com/TheAlgorithms/Javascript/blob/master/String/createPurmutations.js) + * [CreatePermutations](https://github.com/TheAlgorithms/Javascript/blob/master/String/CreatePermutations.js) * [FormatPhoneNumber](https://github.com/TheAlgorithms/Javascript/blob/master/String/FormatPhoneNumber.js) * [FormatPhoneNumber](https://github.com/TheAlgorithms/Javascript/blob/master/String/FormatPhoneNumber.test.js) * [GenerateGUID](https://github.com/TheAlgorithms/Javascript/blob/master/String/GenerateGUID.js) @@ -262,6 +276,7 @@ * [CheckAnagram](https://github.com/TheAlgorithms/Javascript/blob/master/String/test/CheckAnagram.test.js) * [CheckPalindrome](https://github.com/TheAlgorithms/Javascript/blob/master/String/test/CheckPalindrome.test.js) * [CheckPangram](https://github.com/TheAlgorithms/Javascript/blob/master/String/test/CheckPangram.test.js) + * [CreatePermutations](https://github.com/TheAlgorithms/Javascript/blob/master/String/test/CreatePermutations.test.js) * [KMPPatternSearching](https://github.com/TheAlgorithms/Javascript/blob/master/String/test/KMPPatternSearching.test.js) * [PatternMatching](https://github.com/TheAlgorithms/Javascript/blob/master/String/test/PatternMatching.test.js) * [ReverseString](https://github.com/TheAlgorithms/Javascript/blob/master/String/test/ReverseString.test.js) diff --git a/Data-Structures/Linked-List/SinglyLinkList.js b/Data-Structures/Linked-List/SinglyLinkList.js index fbfdacf22..f718962bc 100644 --- a/Data-Structures/Linked-List/SinglyLinkList.js +++ b/Data-Structures/Linked-List/SinglyLinkList.js @@ -10,7 +10,7 @@ // class LinkedList and constructor // Creates a LinkedList -var LinkedList = (function () { +const LinkedList = (function () { function LinkedList () { // Length of linklist and head is null at start this.length = 0 @@ -19,7 +19,7 @@ var LinkedList = (function () { // class node (constructor) // Creating Node with element's value - var Node = (function () { + const Node = (function () { function Node (element) { this.element = element this.next = null @@ -39,12 +39,12 @@ var LinkedList = (function () { // Creates a node and adds it to linklist LinkedList.prototype.add = function (element) { - var node = new Node(element) + const node = new Node(element) // Check if its the first element if (this.head === null) { this.head = node } else { - var currentNode = this.head + let currentNode = this.head // Loop till there is node present in the list while (currentNode.next) { @@ -60,8 +60,8 @@ var LinkedList = (function () { // Removes the node with the value as param LinkedList.prototype.remove = function (element) { - var currentNode = this.head - var previousNode + let currentNode = this.head + let previousNode // Check if the head node is the element to remove if (currentNode.element === element) { @@ -88,8 +88,8 @@ var LinkedList = (function () { // Returns the index of the element passed as param otherwise -1 LinkedList.prototype.indexOf = function (element) { - var currentNode = this.head - var index = -1 + let currentNode = this.head + let index = -1 while (currentNode) { index++ @@ -106,8 +106,8 @@ var LinkedList = (function () { // Returns the element at an index LinkedList.prototype.elementAt = function (index) { - var currentNode = this.head - var count = 0 + let currentNode = this.head + let count = 0 while (count < index) { count++ currentNode = currentNode.next @@ -118,11 +118,11 @@ var LinkedList = (function () { // Adds the element at specified index LinkedList.prototype.addAt = function (index, element) { index-- - var node = new Node(element) + const node = new Node(element) - var currentNode = this.head - var previousNode - var currentIndex = 0 + let currentNode = this.head + let previousNode + let currentIndex = 0 // Check if index is out of bounds of list if (index > this.length) { @@ -153,9 +153,9 @@ var LinkedList = (function () { // Removes the node at specified index LinkedList.prototype.removeAt = function (index) { index-- - var currentNode = this.head - var previousNode - var currentIndex = 0 + let currentNode = this.head + let previousNode + let currentIndex = 0 // Check if index is present in list if (index < 0 || index >= this.length) { @@ -181,8 +181,8 @@ var LinkedList = (function () { // Function to view the LinkedList LinkedList.prototype.view = function () { - var currentNode = this.head - var count = 0 + let currentNode = this.head + let count = 0 while (count < this.length) { count++ console.log(currentNode.element) @@ -195,7 +195,7 @@ var LinkedList = (function () { }()) // Implementation of LinkedList -var linklist = new LinkedList() +const linklist = new LinkedList() linklist.add(2) linklist.add(5) linklist.add(8) diff --git a/Data-Structures/Queue/CircularQueue.js b/Data-Structures/Queue/CircularQueue.js new file mode 100644 index 000000000..72ae57272 --- /dev/null +++ b/Data-Structures/Queue/CircularQueue.js @@ -0,0 +1,108 @@ +// Circular Queues offer a quick to store FIFO data with a maximum size. +// Conserves memory as we only store up to our capacity +// It is opposed to a queue which could continue to grow if input outpaces output +// Doesn’t use dynamic memory so No memory leaks + +class CircularQueue { + constructor (maxLength) { + this.queue = [] + this.front = 0 + this.rear = 0 + this.maxLength = maxLength + } + + // ADD ELEMENTS TO QUEUE + enqueue (value) { + if (this.checkOverflow()) return + if (this.checkEmpty()) { + this.front += 1 + this.rear += 1 + } else { + if (this.rear === this.maxLength) { + this.rear = 1 + } else this.rear += 1 + } + this.queue[this.rear] = value + } + + // REMOVES ELEMENTS + dequeue () { + if (this.checkEmpty()) { + console.log('UNDERFLOW') + return + } + const y = this.queue[this.front] + this.queue[this.front] = '*' + if (this.checkSingleelement()) { + + } else { + if (this.front === this.maxLength) this.front = 1 + else { + this.front += 1 + } + } + + return y // Returns the removed element and replaces it with a star + } + + // checks if the queue is empty or not + checkEmpty () { + if (this.front === 0 && this.rear === 0) { + return true + } + } + + checkSingleelement () { + if (this.front === this.rear && this.rear !== 0) { + this.front = this.rear = 0 + return true + } + } + + // Checks if max capacity of queue has been reached or not + checkOverflow () { + if ((this.front === 1 && this.rear === this.maxLength) || (this.front === this.rear + 1)) { + console.log('CIRCULAR QUEUE OVERFLOW') + return true + } + } + + // Prints the entire array + display () { + for (let index = 1; index < this.queue.length; index++) { + console.log(this.queue[index]) + } + } + + // Displays the length of queue + length () { + return this.queue.length - 1 + } + + // Display the top most value of queue + peek () { + return this.queue[this.front] + } +} + +function main () { + // Star represents blank space + const queue = new CircularQueue(6) // Enter Max Length + queue.enqueue(1) + queue.enqueue(15) + queue.enqueue(176) + queue.enqueue(59) + queue.enqueue(3) + queue.enqueue(55) + + queue.display() + + queue.dequeue() + queue.dequeue() + queue.dequeue() + queue.display() + + console.log(queue.peek()) +} + +main() diff --git a/Data-Structures/Stack/Stack.js b/Data-Structures/Stack/Stack.js index f95b94059..e6b99b40b 100644 --- a/Data-Structures/Stack/Stack.js +++ b/Data-Structures/Stack/Stack.js @@ -8,7 +8,7 @@ // Functions: push, pop, peek, view, length // Creates a stack constructor -var Stack = (function () { +const Stack = (function () { function Stack () { // The top of the Stack this.top = 0 @@ -29,7 +29,7 @@ var Stack = (function () { } this.top-- - var result = this.stack[this.top] + const result = this.stack[this.top] this.stack = this.stack.splice(0, this.top) return result } @@ -46,14 +46,14 @@ var Stack = (function () { // To see all the elements in the stack Stack.prototype.view = function () { - for (var i = 0; i < this.top; i++) { console.log(this.stack[i]) } + for (let i = 0; i < this.top; i++) { console.log(this.stack[i]) } } return Stack }()) // Implementation -var myStack = new Stack() +const myStack = new Stack() myStack.push(1) myStack.push(5) diff --git a/Data-Structures/Tree/BinarySearchTree.js b/Data-Structures/Tree/BinarySearchTree.js index 943332d54..a0965cd94 100644 --- a/Data-Structures/Tree/BinarySearchTree.js +++ b/Data-Structures/Tree/BinarySearchTree.js @@ -11,7 +11,7 @@ */ // class Node -var Node = (function () { +const Node = (function () { // Node in the tree function Node (val) { this.value = val @@ -67,7 +67,7 @@ var Node = (function () { }()) // class Tree -var Tree = (function () { +const Tree = (function () { function Tree () { // Just store the root this.root = null @@ -103,7 +103,7 @@ var Tree = (function () { }()) // Implementation of BST -var bst = new Tree() +const bst = new Tree() bst.addValue(6) bst.addValue(3) bst.addValue(9) diff --git a/Data-Structures/Tree/Trie.js b/Data-Structures/Tree/Trie.js index 010366286..1e00daf53 100644 --- a/Data-Structures/Tree/Trie.js +++ b/Data-Structures/Tree/Trie.js @@ -1,4 +1,4 @@ -var TrieNode = function TrieNode (key, parent) { +const TrieNode = function TrieNode (key, parent) { this.key = key this.count = 0 this.children = Object.create(null) @@ -20,7 +20,7 @@ Trie.findAllWords = function (root, word, output) { if (root.count > 0) { if (typeof output === 'object') { output.push({ word: word, count: root.count }) } } - var key + let key for (key in root.children) { word += key this.findAllWords(root.children[key], word, output) @@ -34,9 +34,9 @@ Trie.prototype.insert = function (word) { this.root.count += 1 return } - var node = this.root - var len = word.length - var i + let node = this.root + const len = word.length + let i for (i = 0; i < len; i++) { if (node.children[word.charAt(i)] === undefined) { node.children[word.charAt(i)] = new TrieNode(word.charAt(i), node) } node = node.children[word.charAt(i)] @@ -46,9 +46,9 @@ Trie.prototype.insert = function (word) { Trie.prototype.findPrefix = function (word) { if (typeof word !== 'string') return null - var node = this.root - var len = word.length - var i + let node = this.root + const len = word.length + let i // After end of this loop node will be at desired prefix for (i = 0; i < len; i++) { if (node.children[word.charAt(i)] === undefined) return null // No such prefix exists @@ -69,9 +69,9 @@ Trie.prototype.remove = function (word, count) { return } - var child = this.root - var len = word.length - var i, key + let child = this.root + const len = word.length + let i, key // child: node which is to be deleted for (i = 0; i < len; i++) { key = word.charAt(i) @@ -93,9 +93,9 @@ Trie.prototype.remove = function (word, count) { } Trie.prototype.findAllWords = function (prefix) { - var output = [] + const output = [] // find the node with provided prefix - var node = this.findPrefix(prefix) + const node = this.findPrefix(prefix) // No such prefix exists if (node === null) return output Trie.findAllWords(node, prefix, output) @@ -104,7 +104,7 @@ Trie.prototype.findAllWords = function (prefix) { Trie.prototype.contains = function (word) { // find the node with given prefix - var node = this.findPrefix(word) + const node = this.findPrefix(word) // No such word exists if (node === null || node.count === 0) return false return true @@ -112,7 +112,7 @@ Trie.prototype.contains = function (word) { Trie.prototype.findOccurences = function (word) { // find the node with given prefix - var node = this.findPrefix(word) + const node = this.findPrefix(word) // No such word exists if (node === null) return 0 return node.count @@ -120,7 +120,7 @@ Trie.prototype.findOccurences = function (word) { // To test (function demo () { - var x = new Trie() + const x = new Trie() x.insert('sheldon') x.insert('hello') x.insert('anyword') diff --git a/Dynamic-Programming/Shuf.js b/Dynamic-Programming/Shuf.js new file mode 100644 index 000000000..a6767c9a6 --- /dev/null +++ b/Dynamic-Programming/Shuf.js @@ -0,0 +1,96 @@ +/* +Given a data set of an unknown size, +Get a random sample in a random order +It'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 +*/ +function shuf (datasetSource, sampleSize) { + const output = fillBaseSample(datasetSource, sampleSize) + + return randomizeOutputFromDataset(datasetSource, output) +} + +/** + * Fills the output if possible, with the minimum number of values + * @param {Iterable.} datasetSource The iterable source of data + * @param {number} sampleSize The size of the sample to extract from the dataset + * @returns {Array.} The random sample, as an array + * @template T + */ +function fillBaseSample (datasetSource, sampleSize) { + let filledIndexes = [] + let output = new Array(sampleSize) + + // Spread data out filling the array + while (true) { + const iterator = datasetSource.next() + if (iterator.done) break + + let insertTo = Math.floor(Math.random() * output.length) + while (filledIndexes.includes(insertTo)) { + insertTo++ + if (insertTo === output.length) { + insertTo = 0 + } + } + output[insertTo] = { + value: iterator.value + } + + filledIndexes = [...filledIndexes, insertTo] + + if (filledIndexes.length === sampleSize) { + break + } + } + + if (filledIndexes.length < output.length) { + // Not a large enough dataset to fill the sample - trim empty values + output = output.filter((_, i) => filledIndexes.includes(i)) + } + + return output.map((o) => o.value) +} + +/** + * Replaces values in the output randomly with new ones from the dataset + * @param {Iterable.} datasetSource The iterable source of data + * @param {Array.} output The output so far, filled with data + * @returns {Array.} The random sample, as an array + * @template T + */ +function randomizeOutputFromDataset (datasetSource, output) { + const newOutput = [...output] + let readSoFar = output.length + + while (true) { + const iterator = datasetSource.next() + if (iterator.done) break + readSoFar++ + + const insertTo = Math.floor(Math.random() * readSoFar) + if (insertTo < newOutput.length) { + newOutput[insertTo] = iterator.value + } + } + + return newOutput +} + +const main = () => { + /** + * Generates a random range of data, with values between 0 and 2^31 - 1 + * @param {number} length The number of data items to generate + * @returns {Iterable} Random iterable data + */ + function * generateRandomData (length) { + const maxValue = Math.pow(2, 31) - 1 + for (let i = 0; i < length; i++) { + yield Math.floor(Math.random() * maxValue) + } + } + + const source = generateRandomData(1000) + const result = shuf(source, 10) + console.log(result) +} +main() diff --git a/Dynamic-Programming/ZeroOneKnapsack.js b/Dynamic-Programming/ZeroOneKnapsack.js index 0274fdefd..f3c47135f 100644 --- a/Dynamic-Programming/ZeroOneKnapsack.js +++ b/Dynamic-Programming/ZeroOneKnapsack.js @@ -50,10 +50,9 @@ const main = () => { arr.push(input[j]) j++ } - const newArr = [] - arr.map(e => { - newArr.push(e.trim().split(' ').map(Number)) - }) + const newArr = arr.map(e => + e.trim().split(' ').map(Number) + ) const cache = [] for (let i = 0; i <= currlen; i++) { const temp = [] diff --git a/Geometry/ConvexHullGraham.js b/Geometry/ConvexHullGraham.js new file mode 100644 index 000000000..304166347 --- /dev/null +++ b/Geometry/ConvexHullGraham.js @@ -0,0 +1,82 @@ +/** + * Author: Arnab Ray + * ConvexHull using Graham Scan + * Wikipedia: https://en.wikipedia.org/wiki/Graham_scan + * Given a set of points in the plane. The Convex hull of the set is the smallest convex polygon that contains all the points of it. + */ + +function compare (a, b) { + // Compare Function to Sort the points, a and b are points to compare + if (a.x < b.x) return -1 + if (a.x === b.x && a.y < b.y) return -1 + return 1 +} +function orientation (a, b, c) { + // Check orientation of Line(a,b) and Line(b,c) + const alpha = (b.y - a.y) / (b.x - a.x) + const beta = (c.y - b.y) / (c.x - b.x) + + // Clockwise + if (alpha > beta) return 1 + // Anticlockwise + else if (beta > alpha) return -1 + // Colinear + return 0 +} + +function convexHull (points) { + const pointsLen = points.length + if (pointsLen <= 2) { + console.log('Minimum of 3 points is required to form closed polygon!') + } + + points.sort(compare) + const p1 = points[0]; const p2 = points[pointsLen - 1] + + // Divide Hull in two halfs + const upperPoints = []; const lowerPoints = [] + + upperPoints.push(p1) + lowerPoints.push(p1) + + for (let i = 1; i < pointsLen; i++) { + if (i === pointsLen - 1 || orientation(p1, points[i], p2) !== -1) { + let upLen = upperPoints.length + + while (upLen >= 2 && orientation(upperPoints[upLen - 2], upperPoints[upLen - 1], points[i]) === -1) { + upperPoints.pop() + upLen = upperPoints.length + } + upperPoints.push(points[i]) + } + if (i === pointsLen - 1 || orientation(p1, points[i], p2) !== 1) { + let lowLen = lowerPoints.length + while (lowLen >= 2 && orientation(lowerPoints[lowLen - 2], lowerPoints[lowLen - 1], points[i]) === 1) { + lowerPoints.pop() + lowLen = lowerPoints.length + } + lowerPoints.push(points[i]) + } + } + const hull = [] + for (let i = 1; i < upperPoints.length - 1; i++) { + hull.push(upperPoints[i]) + } + for (let i = lowerPoints.length - 1; i >= 0; i--) { + hull.push(lowerPoints[i]) + } + console.log('The Convex Hull found is: \n') + console.log(hull) +} + +const points = [ + { x: 0, y: 3 }, + { x: 1, y: 1 }, + { x: 2, y: 2 }, + { x: 4, y: 4 }, + { x: 0, y: 0 }, + { x: 1, y: 2 }, + { x: 3, y: 1 }, + { x: 3, y: 3 }] + +convexHull(points) diff --git a/Graphs/FloydWarshall.js b/Graphs/FloydWarshall.js new file mode 100644 index 000000000..67c41e135 --- /dev/null +++ b/Graphs/FloydWarshall.js @@ -0,0 +1,48 @@ +/* + Source: + https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm + + Complexity: + O(|V|^3) where V is the set of vertices +*/ + +const FloydWarshall = (dist) => { + // Input:- dist: 2D Array where dist[i][j] = edge weight b/w i and j + // Output:- dist: 2D Array where dist[i][j] = shortest dist b/w i and j + const n = dist.length + for (let k = 0; k < n; k++) { + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + if (dist[i][j] > dist[i][k] + dist[k][j]) { + // dist from i to j via k is lesser than the current distance + dist[i][j] = dist[i][k] + dist[k][j] + } + } + } + } + return dist +} + +const main = () => { + // For the following graph (edge weights are shown in brackets) + // 4 1 dist[1][2] = dist[2][1] = 1 + // \ (2)/ \ dist[1][3] = dist[3][1] = 2 + // \ / \(1) dist[1][4] = dist[4][1] = Infinity + // (1)\ / \ dist[3][4] = dist[4][3] = 1 + // 3 2 dist[2][4] = dist[4][2] = Infinity + // dist[2][3] = dist[3][2] = Infinity + // Output should be: + // [ [0, 1, 2, 3], + // [1, 0, 3, 4], + // [2, 3, 0, 1], + // [3, 4, 1, 0] ] + console.log(FloydWarshall( + [[0, 1, 2, Infinity], + [1, 0, Infinity, Infinity], + [2, Infinity, 0, 1], + [Infinity, Infinity, 1, 0] + ] + )) +} + +main() diff --git a/Linear-Algebra/src/la_lib.js b/Linear-Algebra/src/la_lib.js index be9f507de..41f99a307 100644 --- a/Linear-Algebra/src/la_lib.js +++ b/Linear-Algebra/src/la_lib.js @@ -5,13 +5,13 @@ The namespace LinearAlgebra contains useful classes and functions for dealing with linear algebra under JavaScript. */ -var LinearAlgebra; +let LinearAlgebra; (function (LinearAlgebra) { /* class: Vector This class represents a vector of arbitrary size and operations on it. */ - var Vector = /** @class */ (function () { + const Vector = /** @class */ (function () { // constructor function Vector (N, comps) { if (comps === undefined) { @@ -19,7 +19,7 @@ var LinearAlgebra; } this.components = new Array(N) if (comps.length === 0) { - for (var i = 0; i < N; i++) { + for (let i = 0; i < N; i++) { this.components[i] = 0.0 } } else { @@ -37,8 +37,8 @@ var LinearAlgebra; } // computes the eulidean length. Vector.prototype.eulideanLength = function () { - var sum = 0 - for (var i = 0; i < this.components.length; i++) { + let sum = 0 + for (let i = 0; i < this.components.length; i++) { sum += this.components[i] * this.components[i] } return Math.sqrt(sum) @@ -59,9 +59,9 @@ var LinearAlgebra; // vector addition Vector.prototype.add = function (other) { if (this.size() === other.size()) { - var SIZE = this.size() - var ans = new Vector(SIZE) - for (var i = 0; i < SIZE; i++) { + const SIZE = this.size() + const ans = new Vector(SIZE) + for (let i = 0; i < SIZE; i++) { ans.changeComponent(i, (this.components[i] + other.component(i))) } return ans @@ -72,9 +72,9 @@ var LinearAlgebra; // vector subtraction Vector.prototype.sub = function (other) { if (this.size() === other.size()) { - var SIZE = this.size() - var ans = new Vector(SIZE) - for (var i = 0; i < SIZE; i++) { + const SIZE = this.size() + const ans = new Vector(SIZE) + for (let i = 0; i < SIZE; i++) { ans.changeComponent(i, (this.components[i] - other.component(i))) } return ans @@ -84,10 +84,10 @@ var LinearAlgebra; } // dot-product Vector.prototype.dot = function (other) { - var sum = 0 + let sum = 0 if (other.size() === this.size()) { - var SIZE = other.size() - for (var i = 0; i < SIZE; i++) { + const SIZE = other.size() + for (let i = 0; i < SIZE; i++) { sum += this.components[i] * other.component(i) } return sum @@ -97,18 +97,18 @@ var LinearAlgebra; } // scalar multiplication Vector.prototype.scalar = function (s) { - var SIZE = this.size() - var ans = new Vector(SIZE) - for (var i = 0; i < SIZE; i++) { + const SIZE = this.size() + const ans = new Vector(SIZE) + for (let i = 0; i < SIZE; i++) { ans.changeComponent(i, (this.components[i] * s)) } return ans } // returns a string representation of this vector. Vector.prototype.toString = function () { - var ans = '(' - var SIZE = this.components.length - for (var i = 0; i < SIZE; i++) { + let ans = '(' + const SIZE = this.components.length + for (let i = 0; i < SIZE; i++) { if (i < SIZE - 1) { ans += this.components[i] + ',' } else { @@ -121,7 +121,7 @@ var LinearAlgebra; // the One is on position 'pos' Vector.prototype.createUnitBasis = function (pos) { if (pos >= 0 && pos < this.components.length) { - for (var i = 0; i < this.components.length; i++) { + for (let i = 0; i < this.components.length; i++) { if (i === pos) { this.components[i] = 1.0 } else { @@ -135,20 +135,20 @@ var LinearAlgebra; } // normalizes this vector and returns it. Vector.prototype.norm = function () { - var SIZE = this.size() - var quotient = 1.0 / this.eulideanLength() - for (var i = 0; i < SIZE; i++) { + const SIZE = this.size() + const quotient = 1.0 / this.eulideanLength() + for (let i = 0; i < SIZE; i++) { this.components[i] = this.components[i] * quotient } return this } // returns true if the vectors are equal otherwise false. Vector.prototype.equal = function (other) { - var ans = true - var SIZE = this.size() - var EPSILON = 0.001 + let ans = true + const SIZE = this.size() + const EPSILON = 0.001 if (SIZE === other.size()) { - for (var i = 0; i < SIZE; i++) { + for (let i = 0; i < SIZE; i++) { if (Math.abs(this.components[i] - other.component(i)) > EPSILON) { ans = false } @@ -164,8 +164,8 @@ var LinearAlgebra; // -------------- global functions --------------------------------- // returns a unit basis vector of size N with a One on position 'pos' function unitBasisVector (N, pos) { - var ans = new Vector(N) - for (var i = 0; i < N; i++) { + const ans = new Vector(N) + for (let i = 0; i < N; i++) { if (i === pos) { ans.changeComponent(i, 1.0) } else { @@ -177,8 +177,8 @@ var LinearAlgebra; LinearAlgebra.unitBasisVector = unitBasisVector // returns a random vector with integer components (between 'a' and 'b') of size N. function randomVectorInt (N, a, b) { - var ans = new Vector(N) - for (var i = 0; i < N; i++) { + const ans = new Vector(N) + for (let i = 0; i < N; i++) { ans.changeComponent(i, (Math.floor((Math.random() * b) + a))) } return ans @@ -186,8 +186,8 @@ var LinearAlgebra; LinearAlgebra.randomVectorInt = randomVectorInt // returns a random vector with floating point components (between 'a' and 'b') of size N. function randomVectorFloat (N, a, b) { - var ans = new Vector(N) - for (var i = 0; i < N; i++) { + const ans = new Vector(N) + for (let i = 0; i < N; i++) { ans.changeComponent(i, ((Math.random() * b) + a)) } return ans @@ -198,7 +198,7 @@ var LinearAlgebra; class: Matrix This class represents a matrix of arbitrary size and operations on it. */ - var Matrix = /** @class */ (function () { + const Matrix = /** @class */ (function () { // constructor for zero-matrix or fix number matrix. function Matrix (row, col, comps) { if (comps === undefined) { @@ -206,9 +206,9 @@ var LinearAlgebra; } if (comps.length === 0) { this.matrix = [] - var rowVector = [] - for (var i = 0; i < row; i++) { - for (var j = 0; j < col; j++) { + let rowVector = [] + for (let i = 0; i < row; i++) { + for (let j = 0; j < col; j++) { rowVector[j] = 0 } this.matrix[i] = rowVector @@ -238,10 +238,10 @@ var LinearAlgebra; } // returns a string representation of this matrix. Matrix.prototype.toString = function () { - var ans = '' - for (var i = 0; i < this.rows; i++) { + let ans = '' + for (let i = 0; i < this.rows; i++) { ans += '|' - for (var j = 0; j < this.cols; j++) { + for (let j = 0; j < this.cols; j++) { if (j < this.cols - 1) { ans += this.matrix[i][j] + ',' } else { @@ -257,7 +257,7 @@ var LinearAlgebra; } // returns the dimension rows x cols as number array Matrix.prototype.dimension = function () { - var ans = [] + const ans = [] ans[0] = this.rows ans[1] = this.cols return ans @@ -266,9 +266,9 @@ var LinearAlgebra; Matrix.prototype.add = function (other) { if (this.rows === other.dimension()[0] && this.cols === other.dimension()[1]) { - var ans = new Matrix(this.rows, this.cols) - for (var i = 0; i < this.rows; i++) { - for (var j = 0; j < this.cols; j++) { + const ans = new Matrix(this.rows, this.cols) + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.cols; j++) { ans.changeComponent(i, j, (this.matrix[i][j] + other.component(i, j))) } } @@ -279,12 +279,12 @@ var LinearAlgebra; } // returns true if the matrices are equal, otherwise false. Matrix.prototype.equal = function (other) { - var ans = true - var EPSILON = 0.001 + let ans = true + const EPSILON = 0.001 if (this.rows === other.dimension()[0] && this.cols === other.dimension()[1]) { - for (var i = 0; i < this.rows; i++) { - for (var j = 0; j < this.cols; j++) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.cols; j++) { if (Math.abs(this.matrix[i][j] - other.component(i, j)) > EPSILON) { ans = false } @@ -297,9 +297,9 @@ var LinearAlgebra; } // matrix-scalar multiplication Matrix.prototype.scalar = function (c) { - var ans = new Matrix(this.rows, this.cols) - for (var i = 0; i < this.rows; i++) { - for (var j = 0; j < this.cols; j++) { + const ans = new Matrix(this.rows, this.cols) + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.cols; j++) { ans.changeComponent(i, j, (this.matrix[i][j] * c)) } } @@ -309,3 +309,5 @@ var LinearAlgebra; }()) // end of class Matrix LinearAlgebra.Matrix = Matrix })(LinearAlgebra || (LinearAlgebra = {})) // end of namespace LinearAlgebra + +export { LinearAlgebra } diff --git a/Linear-Algebra/test/test.js b/Linear-Algebra/test/test.js index 5f1892db8..1deb0f8b2 100644 --- a/Linear-Algebra/test/test.js +++ b/Linear-Algebra/test/test.js @@ -7,11 +7,12 @@ */ /* eslint-disable */ +import { LinearAlgebra } from "../src/la_lib" + var assert = require('assert') var fs = require('fs') // file is included here -eval(fs.readFileSync('src/la_lib.js') + '') // Tests goes here // creating some vectors diff --git a/Maths/EulersTotient.js b/Maths/EulersTotient.js new file mode 100644 index 000000000..eaf64d904 --- /dev/null +++ b/Maths/EulersTotient.js @@ -0,0 +1,40 @@ +/* + Source: + https://en.wikipedia.org/wiki/Euler%27s_totient_function + + EulersTotient(n) = n * product(1 - 1/p for all prime p dividing n) + + Complexity: + O(sqrt(n)) +*/ + +const EulersTotient = (n) => { + // input: n: int + // output: phi(n): count of numbers b/w 1 and n that are coprime to n + let res = n + for (let i = 2; i * i <= n; i++) { + if (n % i === 0) { + while (n % i === 0) { + n = Math.floor(n / i) + } + // i is a prime diving n, multiply res by 1 - 1/i + // res = res * (1 - 1/i) = res - (res / i) + res = res - Math.floor(res / i) + } + } + if (n > 1) { + res = res - Math.floor(res / n) + } + return res +} + +const main = () => { + // EulersTotient(9) = 6 as 1, 2, 4, 5, 7, and 8 are coprime to 9 + // > 6 + console.log(EulersTotient(9)) + // EulersTotient(10) = 4 as 1, 3, 7, 9 are coprime to 10 + // > 4 + console.log(EulersTotient(10)) +} + +main() diff --git a/Maths/Fibonacci.js b/Maths/Fibonacci.js index 6a204a954..c1b153f24 100644 --- a/Maths/Fibonacci.js +++ b/Maths/Fibonacci.js @@ -63,7 +63,7 @@ const FibonacciDpWithoutRecursion = (number) => { const table = [] table.push(1) table.push(1) - for (var i = 2; i < number; ++i) { + for (let i = 2; i < number; ++i) { table.push(table[i - 1] + table[i - 2]) } return table diff --git a/Maths/MatrixExponentiationRecursive.js b/Maths/MatrixExponentiationRecursive.js new file mode 100644 index 000000000..6ee00aa25 --- /dev/null +++ b/Maths/MatrixExponentiationRecursive.js @@ -0,0 +1,84 @@ +/* + Source: + https://en.wikipedia.org/wiki/Exponentiation_by_squaring + + Complexity: + O(d^3 log n) + where: d is the dimension of the square matrix + n is the power the matrix is raised to +*/ + +const Identity = (n) => { + // Input: n: int + // Output: res: Identity matrix of size n x n + // Complexity: O(n^2) + const res = [] + for (let i = 0; i < n; i++) { + res[i] = [] + for (let j = 0; j < n; j++) { + res[i][j] = i === j ? 1 : 0 + } + } + return res +} + +const MatMult = (matA, matB) => { + // Input: matA: 2D Array of Numbers of size n x n + // matB: 2D Array of Numbers of size n x n + // Output: matA x matB: 2D Array of Numbers of size n x n + // Complexity: O(n^3) + const n = matA.length + const matC = [] + for (let i = 0; i < n; i++) { + matC[i] = [] + for (let j = 0; j < n; j++) { + matC[i][j] = 0 + } + } + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + for (let k = 0; k < n; k++) { + matC[i][j] += matA[i][k] * matB[k][j] + } + } + } + return matC +} + +const MatrixExponentiationRecursive = (mat, m) => { + // Input: mat: 2D Array of Numbers of size n x n + // Output: mat^n: 2D Array of Numbers of size n x n + // Complexity: O(n^3 log m) + if (m === 0) { + // return identity matrix of size n x n + return Identity(mat.length) + } else if (m % 2 === 1) { + // tmp = mat ^ m-1 + const tmp = MatrixExponentiationRecursive(mat, m - 1) + /// return tmp * mat = (mat ^ m-1) * mat = mat ^ m + return MatMult(tmp, mat) + } else { + // tmp = mat ^ m/2 + const tmp = MatrixExponentiationRecursive(mat, m >> 1) + // return tmp * tmp = (mat ^ m/2) ^ 2 = mat ^ m + return MatMult(tmp, tmp) + } +} + +const main = () => { + const mat = [[1, 0, 2], [2, 1, 0], [0, 2, 1]] + + // mat ^ 0 = [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ] + console.log(MatrixExponentiationRecursive(mat, 0)) + + // mat ^ 1 = [ [ 1, 0, 2 ], [ 2, 1, 0 ], [ 0, 2, 1 ] ] + console.log(MatrixExponentiationRecursive(mat, 1)) + + // mat ^ 2 = [ [ 1, 4, 4 ], [ 4, 1, 4 ], [ 4, 4, 1 ] ] + console.log(MatrixExponentiationRecursive(mat, 2)) + + // mat ^ 5 = [ [ 1, 4, 4 ], [ 4, 1, 4 ], [ 4, 4, 1 ] ] + console.log(MatrixExponentiationRecursive(mat, 5)) +} + +main() diff --git a/Maths/Polynomial.js b/Maths/Polynomial.js index 41ec340ee..5df31fdc0 100644 --- a/Maths/Polynomial.js +++ b/Maths/Polynomial.js @@ -32,11 +32,9 @@ class Polynomial { return `(${coefficient}x^${exponent})` } }) - .filter((x) => { - if (x !== '0') { - return x - } - }) + .filter((x) => + x !== '0' + ) .reverse() .join(' + ') } diff --git a/Maths/PrimeCheck.js b/Maths/PrimeCheck.js index c0f626ce6..0922c97ab 100644 --- a/Maths/PrimeCheck.js +++ b/Maths/PrimeCheck.js @@ -11,8 +11,10 @@ const PrimeCheck = (n) => { // output: boolean if (n === 1) return false if (n === 0) return false + if (n === 2) return true + if (n % 2 === 0) return false - for (let i = 2; i * i <= n; i++) { + for (let i = 3; i * i <= n; i += 2) { if (n % i === 0) { return false } diff --git a/Maths/PrimeFactors.js b/Maths/PrimeFactors.js new file mode 100644 index 000000000..66ff1b2a5 --- /dev/null +++ b/Maths/PrimeFactors.js @@ -0,0 +1,33 @@ +/* + Modified from: + https://github.com/TheAlgorithms/Python/blob/master/maths/prime_factors.py +*/ + +const PrimeFactors = (n) => { + // input: n: int + // output: primeFactors: Array of all prime factors of n + const primeFactors = [] + for (let i = 2; i <= n; i++) { + if (n % i === 0) { + while (n % i === 0) { + primeFactors.push(i) + n = Math.floor(n / i) + } + } + } + if (n > 1) { + primeFactors.push(n) + } + return primeFactors +} + +const main = () => { + // PrimeFactors(100) + // > [ 2, 2, 5, 5 ] + console.log(PrimeFactors(100)) + // PrimeFactors(2560) + // > [ 2, 2, 2, 2, 2, 2, 2, 2, 2, 5 ] + console.log(PrimeFactors(2560)) +} + +main() diff --git a/Maths/SieveOfEratosthenes.js b/Maths/SieveOfEratosthenes.js index 9393f58d8..9c6b4b911 100644 --- a/Maths/SieveOfEratosthenes.js +++ b/Maths/SieveOfEratosthenes.js @@ -10,7 +10,15 @@ const sieveOfEratosthenes = (n) => { const sqrtn = Math.ceil(Math.sqrt(n)) for (let i = 2; i <= sqrtn; i++) { if (primes[i]) { - for (let j = 2 * i; j <= n; j += i) { + for (let j = i * i; j <= n; j += i) { + /* + Optimization. + Let j start from i * i, not 2 * i, because smaller multiples of i have been marked false. + + For example, let i = 4. + We do not have to check from 8(4 * 2) to 12(4 * 3) + because they have been already marked false when i=2 and i=3. + */ primes[j] = false } } diff --git a/Maths/SquareRoot.js b/Maths/SquareRoot.js new file mode 100644 index 000000000..be70502da --- /dev/null +++ b/Maths/SquareRoot.js @@ -0,0 +1,19 @@ +/* +* Author: Rak Laptudirm +* +* https://en.wikipedia.org/wiki/Newton%27s_method +* +* Finding the square root of a number using Newton's method. +*/ + +function sqrt (num, precision = 10) { + if (!Number.isFinite(num)) { throw new TypeError(`Expected a number, received ${typeof num}`) } + if (!Number.isFinite(precision)) { throw new TypeError(`Expected a number, received ${typeof precision}`) } + let sqrt = 1 + for (let i = 0; i < precision; i++) { + sqrt -= (sqrt * sqrt - num) / (2 * sqrt) + } + return sqrt +} + +export { sqrt } diff --git a/Project-Euler/Problem10.js b/Project-Euler/Problem10.js new file mode 100644 index 000000000..9d90ee5c3 --- /dev/null +++ b/Project-Euler/Problem10.js @@ -0,0 +1,24 @@ +// https://projecteuler.net/problem=10 + +const isPrime = (number) => { + if (number === 2) return true + if (number % 2 === 0) return false + + for (let j = 3; j * j <= number; j += 2) { + if (number % j === 0) { + return false + } + } + return true +} + +const calculateSumOfPrimeNumbers = (maxNumber) => { + let sum = 0 + for (let i = maxNumber - 1; i >= 2; i--) { + if (isPrime(parseInt(i)) === true) { + sum += i + } + } + return sum +} +export { calculateSumOfPrimeNumbers } diff --git a/Project-Euler/test/Problem10.test.js b/Project-Euler/test/Problem10.test.js new file mode 100644 index 000000000..2c1545cd1 --- /dev/null +++ b/Project-Euler/test/Problem10.test.js @@ -0,0 +1,16 @@ +import { calculateSumOfPrimeNumbers } from '../Problem10' + +describe('checkAnagram', () => { + it('Return the sum of prime numbers upto but less than 14', () => { + const SUT = calculateSumOfPrimeNumbers(14) + expect(SUT).toBe(41) + }) + it('Return the sum of prime numbers upto but less than 10', () => { + const SUT = calculateSumOfPrimeNumbers(10) + expect(SUT).toBe(17) + }) + it('Return the sum of prime numbers upto but less than 100', () => { + const SUT = calculateSumOfPrimeNumbers(100) + expect(SUT).toBe(1060) + }) +}) diff --git a/Search/LinearSearch.js b/Search/LinearSearch.js index 06d9e94a6..6b4211d40 100644 --- a/Search/LinearSearch.js +++ b/Search/LinearSearch.js @@ -5,7 +5,7 @@ * have been searched. */ function SearchArray (searchNum, ar) { - var position = Search(ar, searchNum) + const position = Search(ar, searchNum) if (position !== -1) { console.log('The element was found at ' + (position + 1)) } else { @@ -15,13 +15,13 @@ function SearchArray (searchNum, ar) { // Search “theArray” for the specified “key” value function Search (theArray, key) { - for (var n = 0; n < theArray.length; n++) { + for (let n = 0; n < theArray.length; n++) { if (theArray[n] === key) { return n } } return -1 } -var ar = [1, 2, 3, 4, 5, 6, 7, 8, 9] +const ar = [1, 2, 3, 4, 5, 6, 7, 8, 9] SearchArray(3, ar) SearchArray(4, ar) SearchArray(11, ar) diff --git a/Sorts/GnomeSort.js b/Sorts/GnomeSort.js index d8ccd5ce0..64434d5f8 100644 --- a/Sorts/GnomeSort.js +++ b/Sorts/GnomeSort.js @@ -23,7 +23,7 @@ function gnomeSort (items) { // Implementation of gnomeSort -var ar = [5, 6, 7, 8, 1, 2, 12, 14] +const ar = [5, 6, 7, 8, 1, 2, 12, 14] // Array before Sort console.log(ar) gnomeSort(ar) diff --git a/Sorts/HeapSort.js b/Sorts/HeapSort.js index d7540919e..1f41c8ab0 100644 --- a/Sorts/HeapSort.js +++ b/Sorts/HeapSort.js @@ -50,7 +50,7 @@ function heapSort (items) { // Implementation of heapSort -var ar = [5, 6, 7, 8, 1, 2, 12, 14] +const ar = [5, 6, 7, 8, 1, 2, 12, 14] // Array before Sort console.log(ar) heapSort(ar) diff --git a/Sorts/InsertionSort.js b/Sorts/InsertionSort.js index 15ec02a60..5812acf81 100644 --- a/Sorts/InsertionSort.js +++ b/Sorts/InsertionSort.js @@ -5,11 +5,12 @@ * the correct position and expand sorted part one element at a time. */ function insertionSort (unsortedList) { - var len = unsortedList.length - for (var i = 1; i < len; i++) { - var tmp = unsortedList[i] // Copy of the current element. + const len = unsortedList.length + for (let i = 1; i < len; i++) { + let j + const tmp = unsortedList[i] // Copy of the current element. /* Check through the sorted part and compare with the number in tmp. If large, shift the number */ - for (var j = i - 1; j >= 0 && (unsortedList[j] > tmp); j--) { + for (j = i - 1; j >= 0 && (unsortedList[j] > tmp); j--) { // Shift the number unsortedList[j + 1] = unsortedList[j] } @@ -19,6 +20,6 @@ function insertionSort (unsortedList) { } } -var arr = [5, 3, 1, 2, 4, 8, 3, 8] +const arr = [5, 3, 1, 2, 4, 8, 3, 8] insertionSort(arr) console.log(arr) diff --git a/Sorts/IntroSort.js b/Sorts/IntroSort.js index e7ba322c5..57edb4e8d 100644 --- a/Sorts/IntroSort.js +++ b/Sorts/IntroSort.js @@ -28,12 +28,12 @@ function introsort (array, compare) { * 0 if a is equal to b * 1 if a greater than b */ - var defaultComparator = function (x, y) { + const defaultComparator = function (x, y) { if (x === undefined && y === undefined) return 0 if (x === undefined) return 1 if (y === undefined) return -1 - var xString = toString(x) - var yString = toString(y) + const xString = toString(x) + const yString = toString(y) if (xString < yString) return -1 if (xString > yString) return 1 return 0 @@ -45,7 +45,7 @@ function introsort (array, compare) { * @param {Object} obj * @returns {String} String representation of given object */ - var toString = function (obj) { + const toString = function (obj) { if (obj === null) return 'null' if (typeof obj === 'boolean' || typeof obj === 'number') { return obj.toString() @@ -75,8 +75,8 @@ function introsort (array, compare) { * [IIFE](https://en.wikipedia.org/wiki/Immediately_invoked_function_expression) */ return (function (array, comparator) { - var swap = function (index1, index2) { - var temp = array[index1] + const swap = function (index1, index2) { + const temp = array[index1] array[index1] = array[index2] array[index2] = temp } @@ -85,14 +85,14 @@ function introsort (array, compare) { * If the length of array is less than * this then we simply perform insertion sort */ - var THRESHOLD = 16 + const THRESHOLD = 16 /** * @constant TUNEMAXDEPTH * Constant usec to increase or decrease value * of maxDepth */ - var TUNEMAXDEPTH = 1 - var len = array.length + const TUNEMAXDEPTH = 1 + const len = array.length /** * Return if array is only of length 1 * Array of size 1 is always sorted @@ -104,7 +104,7 @@ function introsort (array, compare) { * Calculate maxDepth = log2(len) * Taken from implementation in stdc++ */ - var maxDepth = Math.floor(Math.log2(len)) * TUNEMAXDEPTH + const maxDepth = Math.floor(Math.log2(len)) * TUNEMAXDEPTH /** * The very first call to quicksort * this initiates sort routine @@ -133,7 +133,7 @@ function introsort (array, compare) { heapSort(start, last) return } - var pivot = (last + start) >> 1 + let pivot = (last + start) >> 1 pivot = partition(start, last, pivot) quickSort(start, pivot, depth - 1) quickSort(pivot + 1, last, depth - 1) @@ -148,8 +148,8 @@ function introsort (array, compare) { function partition (start, last, pivot) { swap(start, pivot) pivot = start - var lo = start - var hi = last + let lo = start + let hi = last while (true) { lo++ while (comparator(array[lo], array[pivot]) <= 0 && lo !== last) { @@ -175,7 +175,7 @@ function introsort (array, compare) { * @param {Number} last one more than last index of array to be sorted */ function insertionSort (start, last) { - var i, j + let i, j for (i = start + 1; i < last; i++) { j = i - 1 while (j >= 0 && comparator(array[j], array[j + 1]) > 0) { @@ -192,7 +192,7 @@ function introsort (array, compare) { * @param {Number} last one more than last index of array to be sorted */ function heapSort (start, last) { - var x = (last + start) >> 1 + let x = (last + start) >> 1 while (x - start >= 0) { heapify(x, start, last) x-- @@ -211,8 +211,8 @@ function introsort (array, compare) { * @param {Number} last one more than last index of segment that cur belongs to */ function heapify (cur, start, last) { - var size = last - start - var max, lt, rt + const size = last - start + let max, lt, rt cur = cur - start while (true) { max = cur @@ -250,9 +250,9 @@ function introsort (array, compare) { (function demo () { const data = [] const size = 1000000 - var i = 0 - var temp - var c = function (a, b) { + let i = 0 + let temp + const c = function (a, b) { return a - b } for (i = 0; i < size; i++) { @@ -260,7 +260,7 @@ function introsort (array, compare) { data.push(temp) } introsort(data, c) - var faulty = false + let faulty = false for (i = 1; i < size; i++) { if (data[i] < data[i - 1]) { faulty = true @@ -283,8 +283,8 @@ function introsort (array, compare) { const data = [] const data2 = [] const size = 1000000 - var i = 0 - var temp + let i = 0 + let temp for (i = 0; i < size; i++) { temp = Math.random() * Number.MAX_SAFE_INTEGER data.push(temp) @@ -292,7 +292,7 @@ function introsort (array, compare) { } introsort(data) data2.sort() - var faulty = false + let faulty = false for (i = 1; i < size; i++) { if (data[i] !== data2[i]) { faulty = true diff --git a/Sorts/MergeSort.js b/Sorts/MergeSort.js index b634704cf..8e2128f04 100644 --- a/Sorts/MergeSort.js +++ b/Sorts/MergeSort.js @@ -35,16 +35,19 @@ */ function merge (list1, list2) { - var results = [] + const results = [] + let i = 0 + let j = 0 - while (list1.length && list2.length) { - if (list1[0] <= list2[0]) { - results.push(list1.shift()) + while (i < list1.length && j < list2.length) { + if (list1[i] < list2[j]) { + results.push(list1[i++]) } else { - results.push(list2.shift()) + results.push(list2[j++]) } } - return results.concat(list1, list2) + + return results.concat(list1.slice(i), list2.slice(j)) } /** @@ -55,15 +58,15 @@ function merge (list1, list2) { function mergeSort (list) { if (list.length < 2) return list - var listHalf = Math.floor(list.length / 2) - var subList1 = list.slice(0, listHalf) - var subList2 = list.slice(listHalf, list.length) + const listHalf = Math.floor(list.length / 2) + const subList1 = list.slice(0, listHalf) + const subList2 = list.slice(listHalf, list.length) return merge(mergeSort(subList1), mergeSort(subList2)) } // Merge Sort Example -var unsortedArray = [10, 5, 3, 8, 2, 6, 4, 7, 9, 1] -var sortedArray = mergeSort(unsortedArray) +const unsortedArray = [10, 5, 3, 8, 2, 6, 4, 7, 9, 1] +const sortedArray = mergeSort(unsortedArray) console.log('Before:', unsortedArray, 'After:', sortedArray) diff --git a/Sorts/QuickSort.js b/Sorts/QuickSort.js index 933b502ca..204e04b1d 100644 --- a/Sorts/QuickSort.js +++ b/Sorts/QuickSort.js @@ -17,16 +17,16 @@ */ function quickSort (items) { - var length = items.length + const length = items.length if (length <= 1) { return items } - var PIVOT = items[0] - var GREATER = [] - var LESSER = [] + const PIVOT = items[0] + const GREATER = [] + const LESSER = [] - for (var i = 1; i < length; i++) { + for (let i = 1; i < length; i++) { if (items[i] > PIVOT) { GREATER.push(items[i]) } else { @@ -34,7 +34,7 @@ function quickSort (items) { } } - var sorted = quickSort(LESSER) + let sorted = quickSort(LESSER) sorted.push(PIVOT) sorted = sorted.concat(quickSort(GREATER)) @@ -43,7 +43,7 @@ function quickSort (items) { // Implementation of quick sort -var ar = [0, 5, 3, 2, 2] +let ar = [0, 5, 3, 2, 2] // Array before Sort console.log(ar) ar = quickSort(ar) diff --git a/Sorts/RadixSort.js b/Sorts/RadixSort.js index b6eb208e9..3696aba96 100644 --- a/Sorts/RadixSort.js +++ b/Sorts/RadixSort.js @@ -10,29 +10,29 @@ function radixSort (items, RADIX) { RADIX = 10 } - var maxLength = false - var placement = 1 + let maxLength = false + let placement = 1 while (!maxLength) { maxLength = true - var buckets = [] + const buckets = [] - for (var i = 0; i < RADIX; i++) { + for (let i = 0; i < RADIX; i++) { buckets.push([]) } - for (var j = 0; j < items.length; j++) { - var tmp = items[j] / placement + for (let j = 0; j < items.length; j++) { + const tmp = items[j] / placement buckets[Math.floor(tmp % RADIX)].push(items[j]) if (maxLength && tmp > 0) { maxLength = false } } - var a = 0 - for (var b = 0; b < RADIX; b++) { - var buck = buckets[b] - for (var k = 0; k < buck.length; k++) { + let a = 0 + for (let b = 0; b < RADIX; b++) { + const buck = buckets[b] + for (let k = 0; k < buck.length; k++) { items[a] = buck[k] a++ } @@ -44,7 +44,7 @@ function radixSort (items, RADIX) { // Implementation of radixSort -var ar = [5, 6, 7, 8, 1, 2, 12, 14] +const ar = [5, 6, 7, 8, 1, 2, 12, 14] // Array before Sort console.log(ar) radixSort(ar) diff --git a/Sorts/SelectionSort.test.js b/Sorts/SelectionSort.test.js index 57ad1e8ec..090ccc0a5 100644 --- a/Sorts/SelectionSort.test.js +++ b/Sorts/SelectionSort.test.js @@ -2,7 +2,7 @@ import { selectionSort } from './SelectionSort' describe('selectionSort', () => { it('expects to return the array sorted in ascending order', () => { - var toSort = [5, 6, 7, 8, 1, 2, 12, 14] + const toSort = [5, 6, 7, 8, 1, 2, 12, 14] const expected = [1, 2, 5, 6, 7, 8, 12, 14] expect(selectionSort(toSort)).toEqual(expected) diff --git a/Sorts/ShellSort.js b/Sorts/ShellSort.js index 43f29b537..e32af561c 100644 --- a/Sorts/ShellSort.js +++ b/Sorts/ShellSort.js @@ -4,16 +4,16 @@ * */ function shellSort (items) { - var interval = 1 + let interval = 1 while (interval < items.length / 3) { interval = interval * 3 + 1 } while (interval > 0) { - for (var outer = interval; outer < items.length; outer++) { - var value = items[outer] - var inner = outer + for (let outer = interval; outer < items.length; outer++) { + const value = items[outer] + let inner = outer while (inner > interval - 1 && items[inner - interval] >= value) { items[inner] = items[inner - interval] @@ -28,7 +28,7 @@ function shellSort (items) { // Implementation of shellSort -var ar = [5, 6, 7, 8, 1, 2, 12, 14] +const ar = [5, 6, 7, 8, 1, 2, 12, 14] // Array before Sort console.log(ar) shellSort(ar) diff --git a/Sorts/TopologicalSort.js b/Sorts/TopologicalSort.js index e784ad0e6..c9c5dc5e0 100644 --- a/Sorts/TopologicalSort.js +++ b/Sorts/TopologicalSort.js @@ -1,10 +1,10 @@ function TopologicalSorter () { - var graph = {} - var isVisitedNode - var finishTimeCount - var finishingTimeList - var nextNode + const graph = {} + let isVisitedNode + let finishTimeCount + let finishingTimeList + let nextNode this.addOrder = function (nodeA, nodeB) { nodeA = String(nodeA) @@ -18,7 +18,7 @@ function TopologicalSorter () { finishTimeCount = 0 finishingTimeList = [] - for (var node in graph) { + for (const node in graph) { if (Object.prototype.hasOwnProperty.call(graph, node) && !isVisitedNode[node]) { dfsTraverse(node) } @@ -34,7 +34,7 @@ function TopologicalSorter () { function dfsTraverse (node) { isVisitedNode[node] = true if (graph[node]) { - for (var i = 0; i < graph[node].length; i++) { + for (let i = 0; i < graph[node].length; i++) { nextNode = graph[node][i] if (isVisitedNode[nextNode]) continue dfsTraverse(nextNode) @@ -49,7 +49,7 @@ function TopologicalSorter () { } /* TEST */ -var topoSorter = new TopologicalSorter() +const topoSorter = new TopologicalSorter() topoSorter.addOrder(5, 2) topoSorter.addOrder(5, 0) topoSorter.addOrder(4, 0) diff --git a/Sorts/WiggleSort.js b/Sorts/WiggleSort.js index fdb2a70db..4c303c672 100644 --- a/Sorts/WiggleSort.js +++ b/Sorts/WiggleSort.js @@ -18,7 +18,7 @@ Array.prototype.wiggleSort = function () { // Implementation of wiggle sort -var arr = [3, 5, 2, 1, 6, 4] +const arr = [3, 5, 2, 1, 6, 4] // Array before Wiggle Sort console.log(arr) // [3, 5, 2, 1, 6, 4] diff --git a/String/createPurmutations.js b/String/CreatePermutations.js similarity index 91% rename from String/createPurmutations.js rename to String/CreatePermutations.js index 1b3cbb06a..6e5344f74 100644 --- a/String/createPurmutations.js +++ b/String/CreatePermutations.js @@ -33,5 +33,4 @@ const createPermutations = (str) => { } return perms } - -console.log(createPermutations('abc')) // should print ["abc", "acb", "bac", "bca", "cab", "cba"] +export { createPermutations } diff --git a/String/LevenshteinDistance.test.js b/String/LevenshteinDistance.test.js index 777884c36..e713f6d9e 100644 --- a/String/LevenshteinDistance.test.js +++ b/String/LevenshteinDistance.test.js @@ -1,4 +1,4 @@ -import levenshteinDistance from './LevenshteinDistance' +import { levenshteinDistance } from './LevenshteinDistance' describe('levenshteinDistance', () => { it('should calculate edit distance between two strings', () => { @@ -14,13 +14,13 @@ describe('levenshteinDistance', () => { // Should just substitute i with o, m with g and insert e at end expect(levenshteinDistance('firm', 'forge')).toBe(3) - // Should just substitute i with s, g with i, h with t and delete f from front - expect(levenshteinDistance('fighting', 'sitting')).toBe(4) + // Should just substitute f with s, g with t and delete h + expect(levenshteinDistance('fighting', 'sitting')).toBe(3) // Should add 4 letters b, a, s and e at the beginning. expect(levenshteinDistance('ball', 'baseball')).toBe(4) - // Should delete 4 letters b, a, s and e at the beginning. - expect(levenshteinDistance('baseball', 'foot')).toBe(4) + // Should delete 4 letters b, a, s and e at the beginning and replace the last 4 with f, o, o, t + expect(levenshteinDistance('baseball', 'foot')).toBe(8) }) }) diff --git a/String/PermutateString.js b/String/PermutateString.js index e470d7ac3..8ba4bc8a7 100644 --- a/String/PermutateString.js +++ b/String/PermutateString.js @@ -18,7 +18,7 @@ const permutate = (aString) => { const calculateCurrentCharacterPermutation = (allPermutations, currentCharacter) => { const currentPermutations = [] - allPermutations.map(permutation => { + allPermutations.forEach(permutation => { let index = 0 while (index <= permutation.length) { const tmp = [...permutation] diff --git a/String/test/CreatePermutations.test.js b/String/test/CreatePermutations.test.js new file mode 100644 index 000000000..5bb82848c --- /dev/null +++ b/String/test/CreatePermutations.test.js @@ -0,0 +1,14 @@ +import { createPermutations } from '../CreatePermutations' + +describe('createPermutations', () => { + it('expects to generate 6 different combinations', () => { + const text = 'abc' + const SUT = createPermutations(text) + expect(SUT).toStrictEqual(['abc', 'acb', 'bac', 'bca', 'cab', 'cba']) + }) + it('expects to generate 2 different combinations', () => { + const text = '12' + const SUT = createPermutations(text) + expect(SUT).toStrictEqual(['12', '21']) + }) +}) diff --git a/Trees/DepthFirstSearch.js b/Trees/DepthFirstSearch.js index ec8ca7e66..0833d9d1d 100644 --- a/Trees/DepthFirstSearch.js +++ b/Trees/DepthFirstSearch.js @@ -25,13 +25,13 @@ function traverseDFS (root) { } function searchDFS (tree, value) { - var stack = [] + const stack = [] stack.push(tree[0]) while (stack.length !== 0) { for (let i = 0; i < stack.length; i++) { - var node = stack.pop() + const node = stack.pop() if (node.value === value) { return node @@ -47,7 +47,7 @@ function searchDFS (tree, value) { return null } -var tree = [ +const tree = [ { value: 6, left: 1, right: 2 }, { value: 5, left: 3, right: 4 }, { value: 7, left: null, right: 5 }, diff --git a/package-lock.json b/package-lock.json index 3d7e04161..3080ac596 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2469,8 +2469,7 @@ "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, "aws-sign2": { "version": "0.7.0", @@ -4117,7 +4116,8 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", - "dev": true + "dev": true, + "optional": true }, "har-schema": { "version": "2.0.0", @@ -4657,6 +4657,7 @@ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, + "optional": true, "requires": { "is-docker": "^2.0.0" } @@ -7187,6 +7188,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "optional": true, "requires": { "yallist": "^4.0.0" } @@ -7380,6 +7382,7 @@ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.1.tgz", "integrity": "sha512-BvEXF+UmsnAfYfoapKM9nGxnP+Wn7P91YfXmrKnfcYCx6VBeoN5Ez5Ogck6I8Bi5k4RlpqRYaw75pAwzX9OphA==", "dev": true, + "optional": true, "requires": { "growly": "^1.3.0", "is-wsl": "^2.2.0", @@ -7394,6 +7397,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", "dev": true, + "optional": true, "requires": { "lru-cache": "^6.0.0" } @@ -7402,13 +7406,15 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true + "dev": true, + "optional": true }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "optional": true, "requires": { "isexe": "^2.0.0" } @@ -8543,7 +8549,8 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", - "dev": true + "dev": true, + "optional": true }, "signal-exit": { "version": "3.0.3", @@ -9553,7 +9560,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "optional": true }, "yargs": { "version": "15.4.1",