diff --git a/DIRECTORY.md b/DIRECTORY.md index cd8e304ee..dee2d724c 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -42,6 +42,7 @@ * [StackES6](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Stack/StackES6.js) * Tree * [BinarySearchTree](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Tree/BinarySearchTree.js) + * [Trie](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Tree/Trie.js) ## Dynamic-Programming * [CoinChange](https://github.com/TheAlgorithms/Javascript/blob/master/Dynamic-Programming/CoinChange.js) @@ -73,18 +74,22 @@ ## Maths * [Abs](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Abs.js) * [AverageMean](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/AverageMean.js) + * [digitSum](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/digitSum.js) * [Factorial](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Factorial.js) * [Fibonacci](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Fibonacci.js) * [FindHcf](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/FindHcf.js) * [FindLcm](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/FindLcm.js) * [GridGet](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/GridGet.js) + * [ModularBinaryExponentiationRecursive](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/ModularBinaryExponentiationRecursive.js) * [Palindrome](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Palindrome.js) * [PascalTriangle](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/PascalTriangle.js) * [PiApproximationMonteCarlo](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/PiApproximationMonteCarlo.js) + * [PrimeCheck](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/PrimeCheck.js) * [SieveOfEratosthenes](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/SieveOfEratosthenes.js) ## Recursive * [EucledianGCD](https://github.com/TheAlgorithms/Javascript/blob/master/Recursive/EucledianGCD.js) + * [TowerOfHanoi](https://github.com/TheAlgorithms/Javascript/blob/master/Recursive/TowerOfHanoi.js) ## Search * [BinarySearch](https://github.com/TheAlgorithms/Javascript/blob/master/Search/BinarySearch.js) diff --git a/Data-Structures/Tree/Trie.js b/Data-Structures/Tree/Trie.js new file mode 100644 index 000000000..010366286 --- /dev/null +++ b/Data-Structures/Tree/Trie.js @@ -0,0 +1,137 @@ +var TrieNode = function TrieNode (key, parent) { + this.key = key + this.count = 0 + this.children = Object.create(null) + if (parent === undefined) { + this.parent = null + } else { + this.parent = parent + } +} + +function Trie () { + // create only root with null key and parent + this.root = new TrieNode(null, null) +} + +// Recursively finds the occurence of all words in a given node +Trie.findAllWords = function (root, word, output) { + if (root === null) return + if (root.count > 0) { + if (typeof output === 'object') { output.push({ word: word, count: root.count }) } + } + var key + for (key in root.children) { + word += key + this.findAllWords(root.children[key], word, output) + word = word.slice(0, -1) + } +} + +Trie.prototype.insert = function (word) { + if (typeof word !== 'string') return + if (word === '') { + this.root.count += 1 + return + } + var node = this.root + var len = word.length + var i + for (i = 0; i < len; i++) { + if (node.children[word.charAt(i)] === undefined) { node.children[word.charAt(i)] = new TrieNode(word.charAt(i), node) } + node = node.children[word.charAt(i)] + } + node.count += 1 +} + +Trie.prototype.findPrefix = function (word) { + if (typeof word !== 'string') return null + var node = this.root + var len = word.length + var i + // After end of this loop node will be at desired prefix + for (i = 0; i < len; i++) { + if (node.children[word.charAt(i)] === undefined) return null // No such prefix exists + node = node.children[word.charAt(i)] + } + return node +} + +Trie.prototype.remove = function (word, count) { + if (typeof word !== 'string') return + if (typeof count !== 'number') count = 1 + else if (count <= 0) return + + // for empty string just delete count of root + if (word === '') { + if (this.root.count >= count) this.root.count -= count + else this.root.count = 0 + return + } + + var child = this.root + var len = word.length + var i, key + // child: node which is to be deleted + for (i = 0; i < len; i++) { + key = word.charAt(i) + if (child.children[key] === undefined) return + child = child.children[key] + } + + // Delete no of occurences specified + if (child.count >= count) child.count -= count + else child.count = 0 + + // If some occurences are left we dont delete it or else + // if the object forms some other objects prefix we dont delete it + // For checking an empty object + // https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object + if (child.count <= 0 && (Object.keys(child.children).length && child.childre.constructor === Object)) { + child.parent.children[child.key] = undefined + } +} + +Trie.prototype.findAllWords = function (prefix) { + var output = [] + // find the node with provided prefix + var node = this.findPrefix(prefix) + // No such prefix exists + if (node === null) return output + Trie.findAllWords(node, prefix, output) + return output +} + +Trie.prototype.contains = function (word) { + // find the node with given prefix + var node = this.findPrefix(word) + // No such word exists + if (node === null || node.count === 0) return false + return true +} + +Trie.prototype.findOccurences = function (word) { + // find the node with given prefix + var node = this.findPrefix(word) + // No such word exists + if (node === null) return 0 + return node.count +}; + +// To test +(function demo () { + var x = new Trie() + x.insert('sheldon') + x.insert('hello') + x.insert('anyword') + x.insert('sheldoncooper') + console.log(x.findOccurences('sheldon')) + x.remove('anything') + x.insert('sheldon') + console.log(x.findOccurences('sheldon')) + console.log(x.findAllWords('sheldon')) + x.insert('anything') + x.remove('sheldoncooper') + console.log(x.contains('sheldoncooper')) + console.log(x.findAllWords('sheldon')) +})() diff --git a/Graphs/DijkstraSmallestPath.js b/Graphs/DijkstraSmallestPath.js index 25571ed72..9e36836ff 100644 --- a/Graphs/DijkstraSmallestPath.js +++ b/Graphs/DijkstraSmallestPath.js @@ -1,23 +1,23 @@ // starting at s function solve (graph, s) { - var solutions = {} + const solutions = {} solutions[s] = [] solutions[s].dist = 0 while (true) { - var p = null - var neighbor = null - var dist = Infinity + let p = null + let neighbor = null + let dist = Infinity - for (var n in solutions) { + for (const n in solutions) { if (!solutions[n]) { continue } - var ndist = solutions[n].dist - var adj = graph[n] + const ndist = solutions[n].dist + const adj = graph[n] - for (var a in adj) { + for (const a in adj) { if (solutions[a]) { continue } - var d = adj[a] + ndist + const d = adj[a] + ndist if (d < dist) { p = solutions[n] neighbor = a @@ -40,9 +40,9 @@ function solve (graph, s) { return solutions } // create graph -var graph = {} +const graph = {} -var layout = { +const layout = { R: ['2'], 2: ['3', '4'], 3: ['4', '6', '13'], @@ -61,7 +61,7 @@ var layout = { } // convert uni-directional to bi-directional graph -// var graph = { +// let graph = { // a: {e:1, b:1, g:3}, // b: {a:1, c:1}, // c: {b:1, d:1}, @@ -72,7 +72,7 @@ var layout = { // h: {f:1} // }; -for (var id in layout) { +for (const id in layout) { if (!graph[id]) { graph[id] = {} } layout[id].forEach(function (aid) { graph[id][aid] = 1 @@ -82,13 +82,13 @@ for (var id in layout) { } // choose start node -var start = '10' +const start = '10' // get all solutions -var solutions = solve(graph, start) +const solutions = solve(graph, start) console.log("From '" + start + "' to") // display solutions -for (var s in solutions) { +for (const s in solutions) { if (!solutions[s]) continue console.log(' -> ' + s + ': [' + solutions[s].join(', ') + '] (dist:' + solutions[s].dist + ')') } diff --git a/Maths/ModularBinaryExponentiationRecursive.js b/Maths/ModularBinaryExponentiationRecursive.js new file mode 100644 index 000000000..c30ed5f2a --- /dev/null +++ b/Maths/ModularBinaryExponentiationRecursive.js @@ -0,0 +1,31 @@ +/* + Modified from: + https://github.com/TheAlgorithms/Python/blob/master/maths/binary_exp_mod.py + + Explaination: + https://en.wikipedia.org/wiki/Exponentiation_by_squaring +*/ + +const modularBinaryExponentiation = (a, n, m) => { + // input: a: int, n: int, m: int + // returns: (a^n) % m: int + if (n === 0) { + return 1 + } else if (n % 2 === 1) { + return (modularBinaryExponentiation(a, n - 1, m) * a) % m + } else { + const b = modularBinaryExponentiation(a, n / 2, m) + return (b * b) % m + } +} + +const main = () => { + // binary_exponentiation(2, 10, 17) + // > 4 + console.log(modularBinaryExponentiation(2, 10, 17)) + // binary_exponentiation(3, 9, 12) + // > 3 + console.log(modularBinaryExponentiation(3, 9, 12)) +} + +main() diff --git a/Maths/PrimeCheck.js b/Maths/PrimeCheck.js new file mode 100644 index 000000000..d46dfab4f --- /dev/null +++ b/Maths/PrimeCheck.js @@ -0,0 +1,29 @@ +/* + Modified from: + https://github.com/TheAlgorithms/Python/blob/master/maths/prime_check.py + + Complexity: + O(sqrt(n)) +*/ + +const PrimeCheck = (n) => { + // input: n: int + // output: boolean + for (let i = 2; i * i <= n; i++) { + if (n % i === 0) { + return false + } + } + return true +} + +const main = () => { + // PrimeCheck(1000003) + // > true + console.log(PrimeCheck(1000003)) + // PrimeCheck(1000001) + // > false + console.log(PrimeCheck(1000001)) +} + +main() diff --git a/Maths/digitSum.js b/Maths/digitSum.js new file mode 100644 index 000000000..3f08cf807 --- /dev/null +++ b/Maths/digitSum.js @@ -0,0 +1,18 @@ +// program to find sum of digits of a number + +// function which would calculate sum and return it +function digitSum (num) { + // sum will store sum of digits of a number + let sum = 0 + // while will run untill num become 0 + while (num) { + sum += (num % 10) + num = parseInt(num / 10) + } + + return sum +} + +// assigning number +const num = 12345 +console.log(digitSum(num)) diff --git a/Recursive/TowerOfHanoi.js b/Recursive/TowerOfHanoi.js new file mode 100644 index 000000000..0dc3ec607 --- /dev/null +++ b/Recursive/TowerOfHanoi.js @@ -0,0 +1,16 @@ +// wiki - https://en.wikipedia.org/wiki/Tower_of_Hanoi +// Recursive Javascript function to solve tower of hanoi + +function TowerOfHanoi (n, fromRod, toRod, auxRod) { + if (n === 1) { + console.log(`Move disk 1 from rod ${fromRod} to rod ${toRod}`) + return + } + TowerOfHanoi(n - 1, fromRod, auxRod, toRod) + console.log(`Move disk ${n} from rod ${fromRod} to rod ${toRod}`) + TowerOfHanoi(n - 1, auxRod, toRod, fromRod) +} +// Driver code +const n = 4 +TowerOfHanoi(n, 'A', 'C', 'B') +// A, C, B are the name of rods