From e5a04f9ad07256ef5cd86aa2fc772dc713381de3 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 30 May 2014 15:28:48 +0200 Subject: [PATCH 001/280] Replace Euclidean GCD subtraction based implementation by the division-based one --- algorithms/math/gcd.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/algorithms/math/gcd.js b/algorithms/math/gcd.js index 6e46afb..b7b6b37 100644 --- a/algorithms/math/gcd.js +++ b/algorithms/math/gcd.js @@ -30,20 +30,17 @@ * * @return Number */ -var gcd = function (a, b) { +var gcdDivisionBased = function (a, b) { var tmp = a; a = Math.max(a, b); b = Math.min(tmp, b); - if (a % b === 0) return b; - while (b !== 0) { - if (a > b) { - a -= b; - } else { - b -= a; - } + tmp = b; + b = a % b; + a = tmp; } + return a; }; -module.exports = gcd; +module.exports = gcdDivisionBased; From 64d9d9b40402697b1cda3a1ebff44b8bc688a6e4 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 30 May 2014 20:08:26 +0200 Subject: [PATCH 002/280] Closes #29 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 85f05f7..4786b07 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "algorithms.js", + "name": "algorithms", "version": "0.0.1", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { @@ -32,5 +32,5 @@ "bugs": { "url": "https://github.com/felipernb/algorithms.js/issues" }, - "homepage": "https://github.com/felipernb/algorithms.js" + "homepage": "https://github.com/felipernb/algorithms.js/wiki" } From 2ca99d34b52acb10028ca8cfde8917eacba4b999 Mon Sep 17 00:00:00 2001 From: "Matt R. Wilson" Date: Fri, 30 May 2014 18:01:10 -0400 Subject: [PATCH 003/280] Added a recursive binary implementation of the greatest common divisor. --- algorithms/math/gcd.js | 60 +++++++++++++++++++++++++++++++++++++ test/algorithms/math/gcd.js | 14 +++++++++ 2 files changed, 74 insertions(+) diff --git a/algorithms/math/gcd.js b/algorithms/math/gcd.js index b7b6b37..f921ea1 100644 --- a/algorithms/math/gcd.js +++ b/algorithms/math/gcd.js @@ -43,4 +43,64 @@ var gcdDivisionBased = function (a, b) { return a; }; +/** + * Binary GCD algorithm (Stein's Algorithm) + * + * @link https://en.wikipedia.org/wiki/Binary_GCD_algorithm + * This is basically a js version of the c implementation on Wikipedia + * + * @param Number + * @param Number + * + * @return Number + */ +var gcdBinaryIterative = function (a, b) { + + // GCD(0,b) == b; GCD(a,0) == a, GCD(0,0) == 0 + if (a === 0) { + return b; + } + + if (b === 0) { + return a; + } + + // Let shift = log(K), where K is the greatest power of 2 dividing both a and b + for (var shift = 0; ((a | b) & 1) == 0; ++shift) { + a >>= 1; + b >>= 1; + } + + // Remove all factors of 2 in a -- they are not common + // Note: a is not zero, so while will terminate + while ((a & 1) === 0) { + a >>= 1; + } + + var tmp; + + // From here on, a is always odd + do { + // Remove all factors of 2 in b -- they are not common + // Note: b is not zero, so while will terminate + while ((b & 1) === 0) { + b >>= 1; + } + + // Now a and b are both odd. Swap if necessary so a <= b, + // then set b = b - a (which is even). + if (a > b) { + tmp = b; + b = a; + a = tmp; + } + + b -= a; // Here b >= a + } while (b !== 0); + + // restore common factors of 2 + return a << shift; +}; + +gcdDivisionBased.binary = gcdBinaryIterative; module.exports = gcdDivisionBased; diff --git a/test/algorithms/math/gcd.js b/test/algorithms/math/gcd.js index 133c5bd..7c5d0c3 100644 --- a/test/algorithms/math/gcd.js +++ b/test/algorithms/math/gcd.js @@ -37,6 +37,20 @@ describe('GCD', function () { assert.equal(gcd(7, 5), 1); assert.equal(gcd(35, 49), 7); }); + + it('should calculate the correct GCD between two numbers using the binary method', function () { + var gcdb = gcd.binary; + assert.equal(gcdb(1, 0), 1); + assert.equal(gcdb(2, 2), 2); + assert.equal(gcdb(2, 4), 2); + assert.equal(gcdb(4, 2), 2); + assert.equal(gcdb(5, 2), 1); + assert.equal(gcdb(10, 100), 10); + assert.equal(gcdb(10000000, 2), 2); + assert.equal(gcdb(7, 49), 7); + assert.equal(gcdb(7, 5), 1); + assert.equal(gcdb(35, 49), 7); + }); }); From dadab1b2fa4f75ebbc52b33258f1e379e24b1744 Mon Sep 17 00:00:00 2001 From: geakstr Date: Sat, 31 May 2014 11:31:52 +0400 Subject: [PATCH 004/280] Improved efficient of Bubble Sort --- algorithms/sorting/bubble_sort.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/algorithms/sorting/bubble_sort.js b/algorithms/sorting/bubble_sort.js index 1bb146e..c436397 100644 --- a/algorithms/sorting/bubble_sort.js +++ b/algorithms/sorting/bubble_sort.js @@ -25,19 +25,24 @@ var Comparator = require('../../util/comparator'); /** * Bubble sort algorithm O(n^2) */ -var bubbleSort = function (a, comparatorFn) { - var comparator = new Comparator(comparatorFn); - for (var i = 0; i < a.length; i++) { - for (var j = i; j < a.length; j++) { - if (comparator.greaterThan(a[i], a[j])) { - var tmp = a[i]; - a[i] = a[j]; - a[j] = tmp; +var bubbleSort = function(a, comparatorFn) { + var comparator = new Comparator(comparatorFn), + n = a.length, + bound = n - 1; + for (var i = 0; i < n - 1; i++) { + var newbound = 0; + for (var j = 0; j < bound; j++) { + if (comparator.greaterThan(a[j], a[j + 1])) { + var tmp = a[j]; + a[j] = a[j + 1]; + a[j + 1] = tmp; + newbound = j; } } + bound = newbound; } return a; }; -module.exports = bubbleSort; +module.exports = bubbleSort; \ No newline at end of file From c8c77c2e3b21381eb7591b901d89c2b44d1089b1 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sat, 31 May 2014 12:54:07 +0200 Subject: [PATCH 005/280] Change build system to use good ol' make --- .travis.yml | 4 ++-- Makefile | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 Makefile diff --git a/.travis.yml b/.travis.yml index 1e86f2c..267f03a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: node_js node_js: - "0.10" -script: "npm run-script coverage" -after_success: "npm run-script coveralls" +script: "make" +after_success: "make coveralls" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6ca8ad9 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +all: jshint test coverage + +setup: + npm install + +jshint: setup + jshint algorithms data_structures test util + +test: setup + mocha -R spec --recursive test + +coverage: setup + istanbul cover ./node_modules/.bin/_mocha -- -R spec --recursive test + +coveralls: + cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js + From c6608989819a510bcd296fc57f4d38ca16bb2176 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sat, 31 May 2014 12:56:08 +0200 Subject: [PATCH 006/280] Bump version to 0.1.0 and fix linting errors --- Makefile | 2 +- algorithms/graph/dijkstra.js | 6 ++-- algorithms/math/gcd.js | 5 +-- package.json | 14 +++----- test/algorithms/math/gcd.js | 27 +++++++------- test/data_structures/priority_queue.js | 31 ++++++++-------- test/util/comparator.js | 49 +++++++++++++------------- util/comparator.js | 4 +-- 8 files changed, 71 insertions(+), 67 deletions(-) diff --git a/Makefile b/Makefile index 6ca8ad9..96ba6db 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -all: jshint test coverage +all: jshint coverage setup: npm install diff --git a/algorithms/graph/dijkstra.js b/algorithms/graph/dijkstra.js index 4377500..498b1ef 100644 --- a/algorithms/graph/dijkstra.js +++ b/algorithms/graph/dijkstra.js @@ -47,7 +47,9 @@ function dijkstra(graph, s) { var currNode; while (!q.isEmpty()) { currNode = q.extract(); - graph.neighbors(currNode).forEach(function (v) { + var neighbors = graph.neighbors(currNode); + for (var i = 0; i < neighbors.length; i++) { + var v = neighbors[i]; // relaxation var newDistance = distance[currNode] + graph.edge(currNode, v); if (newDistance < distance[v]) { @@ -55,7 +57,7 @@ function dijkstra(graph, s) { previous[v] = currNode; q.changePriority(v, distance[v]); } - }); + } } return { distance: distance, diff --git a/algorithms/math/gcd.js b/algorithms/math/gcd.js index f921ea1..e45cb2d 100644 --- a/algorithms/math/gcd.js +++ b/algorithms/math/gcd.js @@ -65,8 +65,9 @@ var gcdBinaryIterative = function (a, b) { return a; } - // Let shift = log(K), where K is the greatest power of 2 dividing both a and b - for (var shift = 0; ((a | b) & 1) == 0; ++shift) { + // Let shift = log(K), where K is the greatest power of 2 + // dividing both a and b + for (var shift = 0; ((a | b) & 1) === 0; ++shift) { a >>= 1; b >>= 1; } diff --git a/package.json b/package.json index 4786b07..327ad9b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.0.1", + "version": "0.1.0", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" @@ -8,19 +8,15 @@ "main": "main.js", "dependencies": {}, "devDependencies": { - "coveralls": "*", - "istanbul": "*", - "mocha": "*" + "coveralls": "^2.10.0", + "istanbul": "^0.2.10", + "jshint": "^2.5.1", + "mocha": "^1.20.0" }, "repository": { "type": "git", "url": "https://github.com/felipernb/algorithms.js" }, - "scripts": { - "test": "mocha -R spec --recursive test", - "coverage": "istanbul cover ./node_modules/.bin/_mocha -- -R spec --recursive test", - "coveralls": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js" - }, "keywords": [ "computer science", "cs", diff --git a/test/algorithms/math/gcd.js b/test/algorithms/math/gcd.js index 7c5d0c3..ee7a6ee 100644 --- a/test/algorithms/math/gcd.js +++ b/test/algorithms/math/gcd.js @@ -38,18 +38,21 @@ describe('GCD', function () { assert.equal(gcd(35, 49), 7); }); - it('should calculate the correct GCD between two numbers using the binary method', function () { - var gcdb = gcd.binary; - assert.equal(gcdb(1, 0), 1); - assert.equal(gcdb(2, 2), 2); - assert.equal(gcdb(2, 4), 2); - assert.equal(gcdb(4, 2), 2); - assert.equal(gcdb(5, 2), 1); - assert.equal(gcdb(10, 100), 10); - assert.equal(gcdb(10000000, 2), 2); - assert.equal(gcdb(7, 49), 7); - assert.equal(gcdb(7, 5), 1); - assert.equal(gcdb(35, 49), 7); + it('should calculate the correct GCD between two numbers using ' + + 'the binary method', function () { + var gcdb = gcd.binary; + assert.equal(gcdb(1, 0), 1); + assert.equal(gcdb(0, 1), 1); + assert.equal(gcdb(0, 0), 0); + assert.equal(gcdb(2, 2), 2); + assert.equal(gcdb(2, 4), 2); + assert.equal(gcdb(4, 2), 2); + assert.equal(gcdb(5, 2), 1); + assert.equal(gcdb(10, 100), 10); + assert.equal(gcdb(10000000, 2), 2); + assert.equal(gcdb(7, 49), 7); + assert.equal(gcdb(7, 5), 1); + assert.equal(gcdb(35, 49), 7); }); }); diff --git a/test/data_structures/priority_queue.js b/test/data_structures/priority_queue.js index 2dee806..dd107a9 100644 --- a/test/data_structures/priority_queue.js +++ b/test/data_structures/priority_queue.js @@ -56,22 +56,23 @@ describe('Min Priority Queue', function () { assert(q.isEmpty()); }); - it('can receive a dictionary with item => priority in construction', function () { - var q = new PriorityQueue({ - a: 10, - b: 2091, - c: 4, - d: 1, - e: 5 - }); + it('can receive a dictionary with item => priority in construction', + function () { + var q = new PriorityQueue({ + a: 10, + b: 2091, + c: 4, + d: 1, + e: 5 + }); - assert(!q.isEmpty()); - assert.equal(q.extract(), 'd'); - assert.equal(q.extract(), 'c'); - assert.equal(q.extract(), 'e'); - assert.equal(q.extract(), 'a'); - assert.equal(q.extract(), 'b'); - }); + assert(!q.isEmpty()); + assert.equal(q.extract(), 'd'); + assert.equal(q.extract(), 'c'); + assert.equal(q.extract(), 'e'); + assert.equal(q.extract(), 'a'); + assert.equal(q.extract(), 'b'); + }); it('should be possible to change the priority of an item', function () { var q = new PriorityQueue({ diff --git a/test/util/comparator.js b/test/util/comparator.js index 6f32c5f..4c53660 100644 --- a/test/util/comparator.js +++ b/test/util/comparator.js @@ -2,7 +2,7 @@ * Copyright (C) 2014 Felipe Ribeiro * * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to + * of this software and associated documentation files (the 'Software'), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is @@ -11,7 +11,7 @@ * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER @@ -25,28 +25,29 @@ var Comparator = require('../../util/comparator'), assert = require('assert'); describe('Comparator', function () { - it("Should use a default arithmetic comparison if no function is passed", function () { - var c = new Comparator(); - assert.equal(c.compare(1, 1), 0); - assert.equal(c.compare(1, 2), -1); - assert.equal(c.compare(1, 0), 1); - assert.equal(c.compare('a', 'b'), -1); - assert(c.lessThan(0, 1)); - assert(!c.lessThan(1, 1)); - assert(c.lessThanOrEqual(1, 1)); - assert(c.lessThanOrEqual(0, 1)); - assert(!c.lessThanOrEqual(1, 0)); - assert(c.greaterThan(1, 0)); - assert(!c.greaterThan(1, 1)); - assert(c.greaterThanOrEqual(1, 1)); - assert(c.greaterThanOrEqual(1, 0)); - assert(!c.greaterThanOrEqual(0, 1)); - assert(c.equal(0, 0)); - assert(!c.equal(0, 1)); - }); + it('Should use a default arithmetic comparison if no function is passed', + function () { + var c = new Comparator(); + assert.equal(c.compare(1, 1), 0); + assert.equal(c.compare(1, 2), -1); + assert.equal(c.compare(1, 0), 1); + assert.equal(c.compare('a', 'b'), -1); + assert(c.lessThan(0, 1)); + assert(!c.lessThan(1, 1)); + assert(c.lessThanOrEqual(1, 1)); + assert(c.lessThanOrEqual(0, 1)); + assert(!c.lessThanOrEqual(1, 0)); + assert(c.greaterThan(1, 0)); + assert(!c.greaterThan(1, 1)); + assert(c.greaterThanOrEqual(1, 1)); + assert(c.greaterThanOrEqual(1, 0)); + assert(!c.greaterThanOrEqual(0, 1)); + assert(c.equal(0, 0)); + assert(!c.equal(0, 1)); + }); - it("should allow comparison function to be defined by user", function () { - var compareFn = function (a, b) { + it('should allow comparison function to be defined by user', function () { + var compareFn = function () { return 0; }; var c = new Comparator(compareFn); @@ -68,7 +69,7 @@ describe('Comparator', function () { assert(c.equal(0, 1)); }); - it("Should allow reversing the comparisons", function () { + it('Should allow reversing the comparisons', function () { var c = new Comparator(); c.reverse(); assert.equal(c.compare(1, 1), 0); diff --git a/util/comparator.js b/util/comparator.js index 02d6b4e..037fc5e 100644 --- a/util/comparator.js +++ b/util/comparator.js @@ -60,7 +60,7 @@ Comparator.prototype.greaterThanOrEqual = function (a, b) { }; Comparator.prototype.equal = function (a, b) { - return this.compare(a, b) == 0; + return this.compare(a, b) === 0; }; /** @@ -74,6 +74,6 @@ Comparator.prototype.reverse = function () { this.compare = function (a, b) { return originalCompareFn(b, a); }; -} +}; module.exports = Comparator; From ba02bd06de977d740526905b21ed91553074049b Mon Sep 17 00:00:00 2001 From: dingshu Date: Sun, 1 Jun 2014 04:12:15 +0800 Subject: [PATCH 007/280] SPFA algorithm added --- algorithms/graph/SPFA.js | 76 +++++++++++++++++++++++++++++++++++ test/algorithms/graph/SPFA.js | 49 ++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 algorithms/graph/SPFA.js create mode 100644 test/algorithms/graph/SPFA.js diff --git a/algorithms/graph/SPFA.js b/algorithms/graph/SPFA.js new file mode 100644 index 0000000..be8c723 --- /dev/null +++ b/algorithms/graph/SPFA.js @@ -0,0 +1,76 @@ +/** + * Copyright (C) 2014 Felipe Ribeiro + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +/** + * Calculates the shortest paths in a graph to every node from the node s + * with SPFA(Shortest Path Faster Algorithm) algorithm + * + * @param {Object} graph An adjacency list representing the graph + * @param {string} start the starting node + * + */ +function SPFA(graph, s) { + var distance = {}; + var previous = {}; + var queue = {}; + var isInQue = {}; + var head = 0; + var tail = 1; + // initialize + distance[s] = 0; + queue[0] = s; + isInQue[s] = true; + graph.vertices.forEach(function (v) { + if (v !== s) { + distance[v] = Infinity; + isInQue[v] = false; + } + }); + + var currNode; + while (head != tail) { + currNode = queue[head++]; + isInQue[currNode] = false; + var neighbors = graph.neighbors(currNode); + for (var i = 0; i < neighbors.length; i++) { + var v = neighbors[i]; + // relaxation + var newDistance = distance[currNode] + graph.edge(currNode, v); + if (newDistance < distance[v]) { + distance[v] = newDistance; + previous[v] = currNode; + if (!isInQue[v]){ + queue[tail++] = v; + isInQue[v] = true; + } + } + } + } + + return { + distance: distance, + previous: previous + }; +} + +module.exports = SPFA; diff --git a/test/algorithms/graph/SPFA.js b/test/algorithms/graph/SPFA.js new file mode 100644 index 0000000..637152c --- /dev/null +++ b/test/algorithms/graph/SPFA.js @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2014 Felipe Ribeiro + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"], to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var SPFA = require('../../../algorithms/graph/SPFA'), + Graph = require('../../../data_structures/graph'), + assert = require('assert'); + +describe('SPFA Algorithm', function () { + it('should return the shortest paths to all nodes from a given origin', + function () { + var g = new Graph(); + g.addEdge('a', 'b', 5); + g.addEdge('a', 'c', 10); + g.addEdge('b', 'c', 2); + g.addEdge('b', 'd', 20); + g.addEdge('c', 'd', 1); + g.addEdge('d', 'a', 10); + + var shortestPath = SPFA(g, 'a'); + assert.equal(shortestPath.distance.b, 5); + assert.equal(shortestPath.previous.b, 'a'); + + assert.equal(shortestPath.distance.c, 7); + assert.equal(shortestPath.previous.c, 'b'); + + assert.equal(shortestPath.distance.d, 8); + assert.equal(shortestPath.previous.d, 'c'); + }); +}); From 9878882180346ceed2bb68c68e26786cb0b7755a Mon Sep 17 00:00:00 2001 From: tayllan Date: Sat, 31 May 2014 19:39:42 -0300 Subject: [PATCH 008/280] Karp-Rabin String Matching --- algorithms/string/karp_rabin.js | 131 +++++++++++++++++++++++++++ main.js | 3 +- test/algorithms/string/karp_rabin.js | 37 ++++++++ 3 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 algorithms/string/karp_rabin.js create mode 100644 test/algorithms/string/karp_rabin.js diff --git a/algorithms/string/karp_rabin.js b/algorithms/string/karp_rabin.js new file mode 100644 index 0000000..bb6673a --- /dev/null +++ b/algorithms/string/karp_rabin.js @@ -0,0 +1,131 @@ +/** + * Copyright (C) 2014 Tayllan Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +/** + * A prime number used to create + * the hash representation of a word + * + * Bigger the prime number, + * bigger the hash value + */ +var base = 997; + +/** + * Calculates String Matching between two Strings + * Returns true if String 'b' is contained in String 'a' + * + * Average and Best Case Complexity: O(a.length + b.length) + * Worst Case Complexity: O(a.length * b.length) + * + * @param String + * @param String + * @return Boolean + */ +var karpRabin = function (a, b) { + var aLength = a.length; + var bLength = b.length; + var hashValue = hashFunction(b); + var newString = []; + + for (var i = 0; i < bLength; i++) { + newString.push(a.charAt(i)); + } + + var newStringHashValue = hashFunction(newString.join('')); + + if (hashValue === newStringHashValue && checkEquality(b, newString.join(''))) { + return true; + } + else { + for (i = 1; i < aLength; i++) { + var previousCharacter = newString[0]; + var nextCharacter = a.charAt(i); + + newStringHashValue = reHash(b.length, newStringHashValue, previousCharacter, nextCharacter); + newString.shift(); + newString.push(nextCharacter); + + if (hashValue === newStringHashValue && checkEquality(b, newString.join(''))) { + return true; + } + } + + return false; + } +}; + +/** + * Checks if 'a' is equal to 'b' + * + * @param String + * @param String + * @return Boolean + */ +var checkEquality = function (a, b) { + var aLength = a.length; + + for (var i = 0; i < aLength; i++) { + if (a.charAt(i) !== b.charAt(i)) { + return false; + } + } + + return true; +}; + +/** + * Creates the hash representation of 'word' + * + * @param String + * @return Number + */ +var hashFunction = function (word) { + var hash = 0; + var wordLength = word.length; + + for (var i = 0, j = wordLength - 1; i < wordLength; i++, j--) { + hash += word.charCodeAt(i) * Math.pow(base, j); + } + + return hash; +}; + +/** + * Recalculates the hash representation of a word so that it isn't + * necessary to traverse the whole word again + * + * @param Number + * @param Number + * @param Character + * @param Character + * @return Number + */ +var reHash = function (length, hash, previousCharacter, nextCharacter) { + hash -= previousCharacter.charCodeAt(0) * Math.pow(base, length - 1); + hash *= base; + hash += nextCharacter.charCodeAt(0); + + return hash; +}; + +module.exports = karpRabin; diff --git a/main.js b/main.js index 920a4e5..d12d89b 100644 --- a/main.js +++ b/main.js @@ -42,7 +42,8 @@ var lib = { quicksort: require('./algorithms/sorting/quicksort') }, String: { - editDistance: require('./algorithms/string/edit_distance') + editDistance: require('./algorithms/string/edit_distance'), + karpRabin: require('./algorithms/string/karp_rabin') }, DataStructure: { BST: require('./data_structures/bst'), diff --git a/test/algorithms/string/karp_rabin.js b/test/algorithms/string/karp_rabin.js new file mode 100644 index 0000000..c3c6dc7 --- /dev/null +++ b/test/algorithms/string/karp_rabin.js @@ -0,0 +1,37 @@ +/** + * Copyright (C) 2014 Tayllan Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var karp_rabin = require('../../../algorithms/string/karp_rabin'), + assert = require('assert'); + +describe('Karp-Rabin', function () { + it('should verify if a string is contained in another string', + function () { + assert.equal(karp_rabin('', ''), true); + assert.equal(karp_rabin('a', 'b'), false); + assert.equal(karp_rabin('b', 'a'), false); + + // ' tes' is contained in 'super test' + assert.equal(karp_rabin('super test', ' tes'), true); + }); +}); From da646f7d049aebf325cf3bb482cd9f06a4a78bc4 Mon Sep 17 00:00:00 2001 From: tayllan Date: Sat, 31 May 2014 20:01:09 -0300 Subject: [PATCH 009/280] Indentation Correction --- algorithms/string/karp_rabin.js | 15 ++++++++++----- test/algorithms/string/karp_rabin.js | 10 +++++----- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/algorithms/string/karp_rabin.js b/algorithms/string/karp_rabin.js index bb6673a..210c3bb 100644 --- a/algorithms/string/karp_rabin.js +++ b/algorithms/string/karp_rabin.js @@ -44,16 +44,16 @@ var base = 997; var karpRabin = function (a, b) { var aLength = a.length; var bLength = b.length; - var hashValue = hashFunction(b); + var rs = hashFunction(b); var newString = []; for (var i = 0; i < bLength; i++) { newString.push(a.charAt(i)); } - var newStringHashValue = hashFunction(newString.join('')); + var rt = hashFunction(newString.join('')); - if (hashValue === newStringHashValue && checkEquality(b, newString.join(''))) { + if (rs === rt && checkEquality(b, newString.join(''))) { return true; } else { @@ -61,11 +61,16 @@ var karpRabin = function (a, b) { var previousCharacter = newString[0]; var nextCharacter = a.charAt(i); - newStringHashValue = reHash(b.length, newStringHashValue, previousCharacter, nextCharacter); + rt = reHash( + bLength, + rt, + previousCharacter, + nextCharacter + ); newString.shift(); newString.push(nextCharacter); - if (hashValue === newStringHashValue && checkEquality(b, newString.join(''))) { + if (rs === rt && checkEquality(b, newString.join(''))) { return true; } } diff --git a/test/algorithms/string/karp_rabin.js b/test/algorithms/string/karp_rabin.js index c3c6dc7..5ea8031 100644 --- a/test/algorithms/string/karp_rabin.js +++ b/test/algorithms/string/karp_rabin.js @@ -21,17 +21,17 @@ */ 'use strict'; -var karp_rabin = require('../../../algorithms/string/karp_rabin'), +var karpRabin = require('../../../algorithms/string/karp_rabin'), assert = require('assert'); describe('Karp-Rabin', function () { it('should verify if a string is contained in another string', function () { - assert.equal(karp_rabin('', ''), true); - assert.equal(karp_rabin('a', 'b'), false); - assert.equal(karp_rabin('b', 'a'), false); + assert.equal(karpRabin('', ''), true); + assert.equal(karpRabin('a', 'b'), false); + assert.equal(karpRabin('b', 'a'), false); // ' tes' is contained in 'super test' - assert.equal(karp_rabin('super test', ' tes'), true); + assert.equal(karpRabin('super test', ' tes'), true); }); }); From 4b3b8f780e3f87729dd4372321e5101364cb6c18 Mon Sep 17 00:00:00 2001 From: dingshu Date: Mon, 2 Jun 2014 07:58:15 +0800 Subject: [PATCH 010/280] small fix --- algorithms/graph/SPFA.js | 2 +- main.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/algorithms/graph/SPFA.js b/algorithms/graph/SPFA.js index be8c723..a447f9b 100644 --- a/algorithms/graph/SPFA.js +++ b/algorithms/graph/SPFA.js @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014 Felipe Ribeiro + * Copyright (C) 2014 Shu Ding * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to diff --git a/main.js b/main.js index 920a4e5..9e69e81 100644 --- a/main.js +++ b/main.js @@ -24,7 +24,8 @@ var lib = { Graph: { topologicalSort: require('./algorithms/graph/topological_sort'), - dijkstra: require('./algorithms/graph/dijkstra') + dijkstra: require('./algorithms/graph/dijkstra'), + SPFA: require('./algorithms/graph/SPFA') }, Math: { fibonacci: require('./algorithms/math/fibonacci'), From 60dae7786733ac2c8fb4cc7f0765ba3b3e8c0bed Mon Sep 17 00:00:00 2001 From: tayllan Date: Sun, 1 Jun 2014 22:06:11 -0300 Subject: [PATCH 011/280] Bellman-Ford Shortest Path --- algorithms/graph/bellman_ford.js | 91 +++++++++++++++++++++++++++ main.js | 3 +- test/algorithms/graph/bellman_ford.js | 56 +++++++++++++++++ 3 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 algorithms/graph/bellman_ford.js create mode 100644 test/algorithms/graph/bellman_ford.js diff --git a/algorithms/graph/bellman_ford.js b/algorithms/graph/bellman_ford.js new file mode 100644 index 0000000..8359fea --- /dev/null +++ b/algorithms/graph/bellman_ford.js @@ -0,0 +1,91 @@ +/** + * Copyright (C) 2014 Tayllan Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +/** + * Calculates the shortest paths in a graph to every node + * from the node 'startNode' with Bellman-Ford's algorithm + * + * Worst Case Complexity: O(|V| * |E|), where |V| is the number of + * vertices and |E| is the number of edges in the graph + * + * @param Object 'graph' An adjacency list representing the graph + * @param String 'startNode' The starting node + * @return Object the minimum distance to reach every vertice of + * the graph starting in 'startNode', or an empty object if there + * exists a Negative-Weighted Cycle in the graph + */ +var bellmanFord = function(graph, startNode) { + var minDistance = {}; + var edges = []; + var adjacencyListSize = 0; + + // Add all the edges from the graph to the 'edges' array + graph.vertices.forEach(function (s) { + graph.neighbors(s).forEach(function(t) { + edges.push({ + source: s, + target: t, + weight: graph.edge(s, t) + }); + }); + + minDistance[s] = Infinity; + ++adjacencyListSize; + }); + + minDistance[startNode] = 0; + + var edgesSize = edges.length; + var sourceDistance; + var targetDistance; + + for (var i = 0; i < adjacencyListSize - 1; i++) { + for (var j = 0; j < edgesSize; j++) { + sourceDistance = minDistance[edges[j].source] + edges[j].weight; + targetDistance = minDistance[edges[j].target]; + + if (sourceDistance < targetDistance) { + minDistance[edges[j].target] = sourceDistance; + } + } + } + + for (i = 0; i < edgesSize; i++) { + sourceDistance = minDistance[edges[i].source] + edges[i].weight; + targetDistance = minDistance[edges[i].target]; + + if (sourceDistance < targetDistance) { + + // Empty 'distance' object indicates Negative-Weighted Cycle + return { + distance: {} + }; + } + } + + return { + distance: minDistance + }; +}; + +module.exports = bellmanFord; diff --git a/main.js b/main.js index d12d89b..2b94767 100644 --- a/main.js +++ b/main.js @@ -24,7 +24,8 @@ var lib = { Graph: { topologicalSort: require('./algorithms/graph/topological_sort'), - dijkstra: require('./algorithms/graph/dijkstra') + dijkstra: require('./algorithms/graph/dijkstra'), + bellmanFord: require('./algorithms/graph/bellman_ford') }, Math: { fibonacci: require('./algorithms/math/fibonacci'), diff --git a/test/algorithms/graph/bellman_ford.js b/test/algorithms/graph/bellman_ford.js new file mode 100644 index 0000000..e00b26c --- /dev/null +++ b/test/algorithms/graph/bellman_ford.js @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2014 Tayllan Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"], to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var bellmanFord = require('../../../algorithms/graph/bellman_ford'), + Graph = require('../../../data_structures/graph'), + assert = require('assert'); + +describe('Bellman-Ford Algorithm', function () { + it('should return the shortest paths to all nodes from a given origin', + function () { + var graph = new Graph(true); + + graph.addEdge('a', 'b', -1); + graph.addEdge('a', 'c', 4); + graph.addEdge('b', 'c', 3); + graph.addEdge('b', 'd', 2); + graph.addEdge('b', 'e', 2); + graph.addEdge('d', 'b', 1); + graph.addEdge('e', 'd', -3); + graph.addEdge('d', 'c', 5); + + var shortestPaths = bellmanFord(graph, 'a'); + + assert.equal(shortestPaths.distance.a, 0); + assert.equal(shortestPaths.distance.d, -2); + assert.equal(shortestPaths.distance.e, 1); + + // It'll cause a Negative-Weighted Cycle. + graph.addEdge('c', 'a', -9); + + shortestPaths = bellmanFord(graph, 'a'); + + // The 'distance' object is empty + assert.equal(shortestPaths.distance.a, undefined); + }); +}); From b11e579a50c8a6d326353a8278f24d79e51e4c48 Mon Sep 17 00:00:00 2001 From: dingshu Date: Mon, 2 Jun 2014 14:53:31 +0800 Subject: [PATCH 012/280] Extended Euclidean algorithm --- algorithms/math/extended_euclidean.js | 62 ++++++++++++++++++++++ main.js | 3 +- test/algorithms/math/extended_euclidean.js | 41 ++++++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 algorithms/math/extended_euclidean.js create mode 100644 test/algorithms/math/extended_euclidean.js diff --git a/algorithms/math/extended_euclidean.js b/algorithms/math/extended_euclidean.js new file mode 100644 index 0000000..3be1d70 --- /dev/null +++ b/algorithms/math/extended_euclidean.js @@ -0,0 +1,62 @@ +/** + * Copyright (C) 2014 Shu Ding + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +'use strict'; + +/** + * Extended Euclidean algorithm to calculate the solve of + * ax + by = gcd(a, b) + * gcd(a, b) is the greatest common divisor of integers a and b. + * + * @param Number + * @param Number + * + * @return {Number, Number} + */ +var extEuclid = function (a, b) { + var s = 0, oldS = 1; + var t = 1, oldT = 0; + var r = b, oldR = a; + var quotient, temp; + while (r !== 0) { + quotient = Math.floor(oldR / r); + + temp = r; + r = oldR - quotient * r; + oldR = temp; + + temp = s; + s = oldS - quotient * s; + oldS = temp; + + temp = t; + t = oldT - quotient * t; + oldT = temp; + } + + return { + x: oldS, + y: oldT + }; +}; + +module.exports = extEuclid; diff --git a/main.js b/main.js index 9e69e81..a3396af 100644 --- a/main.js +++ b/main.js @@ -30,7 +30,8 @@ var lib = { Math: { fibonacci: require('./algorithms/math/fibonacci'), fisherYates: require('./algorithms/math/fisher_yates'), - gcd: require('./algorithms/math/gcd') + gcd: require('./algorithms/math/gcd'), + extendedEuclidean: require('./algorithms/math/extended_euclidean') }, Search: { bfs: require('./algorithms/searching/bfs'), diff --git a/test/algorithms/math/extended_euclidean.js b/test/algorithms/math/extended_euclidean.js new file mode 100644 index 0000000..90cf5c0 --- /dev/null +++ b/test/algorithms/math/extended_euclidean.js @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2014 Shu Ding + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var extEuclid = require('../../../algorithms/math/extended_euclidean'), + assert = require('assert'); + +describe('extEuclid', function () { + it('should calculate the solve to Bézout\'s identity', function () { + var solve = extEuclid(1, 0); + assert.equal(solve.x, 1); + assert.equal(solve.y, 0); + + solve = extEuclid(25, 35); + assert.equal(solve.x, 3); + assert.equal(solve.y, -2); + + solve = extEuclid(-55, 22); + assert.equal(solve.x, 1); + assert.equal(solve.y, 3); + }); +}); From 495b4567a1837ae31e3463179e8d1db2a5cbf889 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Mon, 2 Jun 2014 10:32:29 +0200 Subject: [PATCH 013/280] v0.2.0 Changelog and package version bump --- CHANGELOG | 46 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..cd02822 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,46 @@ +CHANGELOG +========= + +0.2.0 (2014-06-01) +* Graphs +** Shortest Path Faster Algorithm (#34) +** Bellman-Ford Shortest Path (#36) + +* Math +** Extended Euclidean Algorithm (#37) + +* Strings +** Karp-Rabin String Matching (#35) + + +0.1.0 (2014-05-30) +* Sorting +** Bubble Sort +** Quicksort +** Merge sort + +* Graphs +** Dijkstra +** Topological Sort + +* Math +** Fibonacci +** Fisher-Yates +** Euclidean GCD + +* Search +** Binary Search +** Breadth first search (for BSTs) +** Depth first search (for BSTs) + +* String +** Levenshtein edit distance + +* Data Structures +** Binary Search Tree +** Graph +** Heap +** Linked list +** Priority Queue +** Queue +** Stack diff --git a/package.json b/package.json index 327ad9b..ce63dc7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.1.0", + "version": "0.2.0", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" From 430e99ecca2fcca7e54974b13bc7267b69f11225 Mon Sep 17 00:00:00 2001 From: Iain McDonald Date: Mon, 2 Jun 2014 10:36:27 +0100 Subject: [PATCH 014/280] Add Heap Sort algorithm (using existing Heap data structure implementation). --- algorithms/sorting/heap_sort.js | 46 +++++++++++++++++++++ test/algorithms/sorting/heap_sort.js | 61 ++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 algorithms/sorting/heap_sort.js create mode 100644 test/algorithms/sorting/heap_sort.js diff --git a/algorithms/sorting/heap_sort.js b/algorithms/sorting/heap_sort.js new file mode 100644 index 0000000..2ebbdce --- /dev/null +++ b/algorithms/sorting/heap_sort.js @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2014 Iain McDonald + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; +var Comparator = require('../../util/comparator'); +var HeapStructure = require('../../data_structures/heap'); + +/** + * Heap sort first creates a valid heap data structure. Next it + * iteratively removes the smallest element of the heap until it's + * empty. The time complexity of the algorithm is O(n.lg n) + */ +var heapsortInit = function (array, comparatorFn) { + + var comparator = new Comparator(comparatorFn); + + var minHeap = new HeapStructure.MinHeap(comparatorFn); + minHeap.heapify(array); + + var result = []; + + while (!minHeap.isEmpty()) + result.push(minHeap.extract()); + + return result; +}; + +module.exports = heapsortInit; diff --git a/test/algorithms/sorting/heap_sort.js b/test/algorithms/sorting/heap_sort.js new file mode 100644 index 0000000..bd19e2f --- /dev/null +++ b/test/algorithms/sorting/heap_sort.js @@ -0,0 +1,61 @@ +/** + * Copyright (C) 2014 Felipe Ribeiro + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var heap_sort = require('../../../algorithms/sorting/heap_sort'), + assert = require('assert'); + +describe('Heap Sort', function () { + it('should sort the given array', function () { + assert.deepEqual(heap_sort([]), []); + assert.deepEqual(heap_sort([1]), [1]); + assert.deepEqual(heap_sort([2, 1]), [1, 2]); + assert.deepEqual(heap_sort([3, 1, 2]), [1, 2, 3]); + assert.deepEqual(heap_sort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual(heap_sort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual(heap_sort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), + [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); + }); + + it('should sort the array with a specific comparison function', function () { + var compare = function (a, b) { + if (a.length === b.length) return 0; + return a.length < b.length ? -1 : 1; + }; + assert.deepEqual(heap_sort([], compare), []); + assert.deepEqual(heap_sort(['apple'], compare), ['apple']); + assert.deepEqual(heap_sort(['apple', 'banana'], compare), + ['apple', 'banana']); + assert.deepEqual(heap_sort(['apple', 'banana', 'car'], compare), + ['car', 'apple', 'banana']); + assert.deepEqual(heap_sort(['apple', 'banana', 'car', 'z'], compare), + ['z', 'car', 'apple', 'banana']); + + var reverseSort = function (a, b) { + if (a == b) return 0; + return a < b ? 1: -1; + }; + assert.deepEqual(heap_sort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], + reverseSort), + [295, 20, 10, 10, 8, 6, 5, 3, 1, 0]); + }); +}); From bc8f879f11458b25818e0c13d16825d20f843464 Mon Sep 17 00:00:00 2001 From: Iain McDonald Date: Mon, 2 Jun 2014 12:07:32 +0100 Subject: [PATCH 015/280] Adding heap_sort implementation to main modules --- main.js | 1 + 1 file changed, 1 insertion(+) diff --git a/main.js b/main.js index 920a4e5..ce5f098 100644 --- a/main.js +++ b/main.js @@ -38,6 +38,7 @@ var lib = { }, Sort: { bubbleSort: require('./algorithms/sorting/bubble_sort'), + heapSort: require('./algorithms/sorting/heap_sort'), mergeSort: require('./algorithms/sorting/merge_sort'), quicksort: require('./algorithms/sorting/quicksort') }, From ca626cabd8dbf48407942e52d280cda2d52988a3 Mon Sep 17 00:00:00 2001 From: Iain McDonald Date: Mon, 2 Jun 2014 13:13:22 +0100 Subject: [PATCH 016/280] Remove unncessary Comparator object. Rename variables to Camel case. --- algorithms/sorting/heap_sort.js | 3 --- test/algorithms/sorting/heap_sort.js | 28 ++++++++++++++-------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/algorithms/sorting/heap_sort.js b/algorithms/sorting/heap_sort.js index 2ebbdce..379c2bc 100644 --- a/algorithms/sorting/heap_sort.js +++ b/algorithms/sorting/heap_sort.js @@ -20,7 +20,6 @@ * IN THE SOFTWARE. */ 'use strict'; -var Comparator = require('../../util/comparator'); var HeapStructure = require('../../data_structures/heap'); /** @@ -30,8 +29,6 @@ var HeapStructure = require('../../data_structures/heap'); */ var heapsortInit = function (array, comparatorFn) { - var comparator = new Comparator(comparatorFn); - var minHeap = new HeapStructure.MinHeap(comparatorFn); minHeap.heapify(array); diff --git a/test/algorithms/sorting/heap_sort.js b/test/algorithms/sorting/heap_sort.js index bd19e2f..f6fe511 100644 --- a/test/algorithms/sorting/heap_sort.js +++ b/test/algorithms/sorting/heap_sort.js @@ -21,18 +21,18 @@ */ 'use strict'; -var heap_sort = require('../../../algorithms/sorting/heap_sort'), +var heapSort = require('../../../algorithms/sorting/heap_sort'), assert = require('assert'); describe('Heap Sort', function () { it('should sort the given array', function () { - assert.deepEqual(heap_sort([]), []); - assert.deepEqual(heap_sort([1]), [1]); - assert.deepEqual(heap_sort([2, 1]), [1, 2]); - assert.deepEqual(heap_sort([3, 1, 2]), [1, 2, 3]); - assert.deepEqual(heap_sort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(heap_sort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(heap_sort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), + assert.deepEqual(heapSort([]), []); + assert.deepEqual(heapSort([1]), [1]); + assert.deepEqual(heapSort([2, 1]), [1, 2]); + assert.deepEqual(heapSort([3, 1, 2]), [1, 2, 3]); + assert.deepEqual(heapSort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual(heapSort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual(heapSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); }); @@ -41,20 +41,20 @@ describe('Heap Sort', function () { if (a.length === b.length) return 0; return a.length < b.length ? -1 : 1; }; - assert.deepEqual(heap_sort([], compare), []); - assert.deepEqual(heap_sort(['apple'], compare), ['apple']); - assert.deepEqual(heap_sort(['apple', 'banana'], compare), + assert.deepEqual(heapSort([], compare), []); + assert.deepEqual(heapSort(['apple'], compare), ['apple']); + assert.deepEqual(heapSort(['apple', 'banana'], compare), ['apple', 'banana']); - assert.deepEqual(heap_sort(['apple', 'banana', 'car'], compare), + assert.deepEqual(heapSort(['apple', 'banana', 'car'], compare), ['car', 'apple', 'banana']); - assert.deepEqual(heap_sort(['apple', 'banana', 'car', 'z'], compare), + assert.deepEqual(heapSort(['apple', 'banana', 'car', 'z'], compare), ['z', 'car', 'apple', 'banana']); var reverseSort = function (a, b) { if (a == b) return 0; return a < b ? 1: -1; }; - assert.deepEqual(heap_sort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], + assert.deepEqual(heapSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], reverseSort), [295, 20, 10, 10, 8, 6, 5, 3, 1, 0]); }); From cee2ab576ff9413acea2dd6419064861a75e067d Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Mon, 2 Jun 2014 16:31:09 +0200 Subject: [PATCH 017/280] Newton's method to calculate square root --- algorithms/math/newton_sqrt.js | 56 +++++++++++++++++++++++++++++ main.js | 3 +- test/algorithms/math/newton_sqrt.js | 54 ++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 algorithms/math/newton_sqrt.js create mode 100644 test/algorithms/math/newton_sqrt.js diff --git a/algorithms/math/newton_sqrt.js b/algorithms/math/newton_sqrt.js new file mode 100644 index 0000000..b722981 --- /dev/null +++ b/algorithms/math/newton_sqrt.js @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2014 Felipe Ribeiro + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +'use strict'; + +/** + * Newton's method to calculate square root + * + * @param Number n - the number which the square root should be calculated + * @param Number tolerance - The error margin accepted (Default 1e-7) + * @param Number maxIterations - The max number of iterations (Default 1e7) + */ +var sqrt = function (n, tolerance, maxIterations) { + tolerance = tolerance || 1e-7; + maxIterations = maxIterations || 1e7; + + var upperBound = n; + var lowerBound = 0; + + var i = 0; + var square, x; + do { + i++; + x = (upperBound - lowerBound) / 2 + lowerBound; + square = x * x; + if (square < n) lowerBound = x; + else upperBound = x; + } while (Math.abs(square - n) > tolerance && i < maxIterations); + + // Checks if the number is a perfect square to return the exact root + var roundX = Math.round(x); + if (roundX * roundX === n) x = roundX; + + return x; +}; + +module.exports = sqrt; diff --git a/main.js b/main.js index 925d229..376900f 100644 --- a/main.js +++ b/main.js @@ -32,7 +32,8 @@ var lib = { fibonacci: require('./algorithms/math/fibonacci'), fisherYates: require('./algorithms/math/fisher_yates'), gcd: require('./algorithms/math/gcd'), - extendedEuclidean: require('./algorithms/math/extended_euclidean') + extendedEuclidean: require('./algorithms/math/extended_euclidean'), + newtonSqrt: require('./algorithms/math/newton_sqrt') }, Search: { bfs: require('./algorithms/searching/bfs'), diff --git a/test/algorithms/math/newton_sqrt.js b/test/algorithms/math/newton_sqrt.js new file mode 100644 index 0000000..19be060 --- /dev/null +++ b/test/algorithms/math/newton_sqrt.js @@ -0,0 +1,54 @@ +/** + * Copyright (C) 2014 Felipe Ribeiro + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var newtonSqrt = require('../../../algorithms/math/newton_sqrt'), + assert = require('assert'); + +describe('Newton square root', function () { + it('should calculate the exact root of square numbers', function () { + assert.strictEqual(newtonSqrt(0), 0); + assert.strictEqual(newtonSqrt(1), 1); + assert.strictEqual(newtonSqrt(4), 2); + assert.strictEqual(newtonSqrt(9), 3); + assert.strictEqual(newtonSqrt(16), 4); + assert.strictEqual(newtonSqrt(25), 5); + assert.strictEqual(newtonSqrt(36), 6); + assert.strictEqual(newtonSqrt(49), 7); + assert.strictEqual(newtonSqrt(64), 8); + assert.strictEqual(newtonSqrt(81), 9); + assert.strictEqual(newtonSqrt(100), 10); + }); + + it('should calculate an approximated root for every number', + function () { + for (var i = 0; i < 1000; i++) { + var newton = newtonSqrt(i); + var nativeJS = Math.sqrt(i); + var difference = Math.abs(newton - nativeJS); + assert(difference < 1e-6, + 'Square root of ' + i + ' should be ' + nativeJS + + ' but got ' + newton + ' instead'); + } + }); + +}); From c0d2c8c2de7b5b52e055303ddd555e8a8ec65f29 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Mon, 2 Jun 2014 16:46:19 +0200 Subject: [PATCH 018/280] Small cleanup on heapsort --- algorithms/sorting/heap_sort.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/algorithms/sorting/heap_sort.js b/algorithms/sorting/heap_sort.js index 379c2bc..de1a11e 100644 --- a/algorithms/sorting/heap_sort.js +++ b/algorithms/sorting/heap_sort.js @@ -20,24 +20,23 @@ * IN THE SOFTWARE. */ 'use strict'; -var HeapStructure = require('../../data_structures/heap'); +var MinHeap = require('../../data_structures/heap').MinHeap; /** * Heap sort first creates a valid heap data structure. Next it * iteratively removes the smallest element of the heap until it's * empty. The time complexity of the algorithm is O(n.lg n) */ -var heapsortInit = function (array, comparatorFn) { +var heapsort = function (array, comparatorFn) { - var minHeap = new HeapStructure.MinHeap(comparatorFn); + var minHeap = new MinHeap(comparatorFn); minHeap.heapify(array); var result = []; - while (!minHeap.isEmpty()) result.push(minHeap.extract()); - + return result; }; -module.exports = heapsortInit; +module.exports = heapsort; From d21dc45018936d9068d3c4fa4d09f11bbac00417 Mon Sep 17 00:00:00 2001 From: BrunoRB Date: Tue, 3 Jun 2014 22:38:16 -0300 Subject: [PATCH 019/280] insertion sort --- algorithms/sorting/insertion_sort.js | 46 +++++++++++ test/algorithms/sorting/insertion_sort.js | 95 +++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 algorithms/sorting/insertion_sort.js create mode 100644 test/algorithms/sorting/insertion_sort.js diff --git a/algorithms/sorting/insertion_sort.js b/algorithms/sorting/insertion_sort.js new file mode 100644 index 0000000..84101fa --- /dev/null +++ b/algorithms/sorting/insertion_sort.js @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2014 Bruno Roberto Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; +var Comparator = require('../../util/comparator'); + +/** + * Insertion sort algorithm O(n + d) + */ +var insertionSort = function(vector, comparatorFn) { + var comparator = new Comparator(comparatorFn); + + for (var i=1, len=vector.length; i 0 && comparator.lessThan(aux, vector[j - 1])) { + vector[j] = vector[j - 1]; + j--; + } + + vector[j] = aux; + } + + return vector; +}; + +module.exports = insertionSort; \ No newline at end of file diff --git a/test/algorithms/sorting/insertion_sort.js b/test/algorithms/sorting/insertion_sort.js new file mode 100644 index 0000000..ac4d22c --- /dev/null +++ b/test/algorithms/sorting/insertion_sort.js @@ -0,0 +1,95 @@ +/** + * Copyright (C) 2014 Bruno Roberto Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var insertionSort = require('../../../algorithms/sorting/insertion_sort'), + assert = require('assert'); + +describe('Insertion Sort', function () { + it('should sort the given array', function () { + assert.deepEqual(insertionSort([]), []); + assert.deepEqual(insertionSort([1]), [1]); + assert.deepEqual(insertionSort([2, 1]), [1, 2]); + assert.deepEqual(insertionSort([3, 1, 2]), [1, 2, 3]); + assert.deepEqual(insertionSort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual(insertionSort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual( + insertionSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), + [0, 1, 3, 5, 6, 8, 10, 10, 20, 295] + ); + }); + + + it('should sort the array with a specific comparison function', function () { + var compare = function (a, b) { + if (a.length === b.length) { + return 0; + } + return (a.length < b.length) ? -1 : 1; + }; + assert.deepEqual(insertionSort([], compare), []); + assert.deepEqual(insertionSort(['apple'], compare), ['apple']); + assert.deepEqual( + insertionSort(['apple', 'banana'], compare), + ['apple', 'banana'] + ); + assert.deepEqual( + insertionSort(['apple', 'banana', 'car'], compare), + ['car', 'apple', 'banana'] + ); + assert.deepEqual( + insertionSort(['apple', 'banana', 'car', 'z'], compare), + ['z', 'car', 'apple', 'banana'] + ); + + var reverseSort = function (a, b) { + if (a === b) { + return 0; + } + return (a < b) ? 1 : -1; + }; + assert.deepEqual( + insertionSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], reverseSort), + [295, 20, 10, 10, 8, 6, 5, 3, 1, 0] + ); + + var Guy = function(age) { + this.age = age; + }; + + var compareAgesOfGuys = function(g1, g2) { + if (g1.age === g2.age) { + return 0; + } + return (g1.age < g2.age) ? -1 : 1; + }; + + var g1 = new Guy(30), + g2 = new Guy(80), + g3 = new Guy(15), + g4 = new Guy(20); + + assert.deepEqual( + insertionSort([g1, g2, g3, g4], compareAgesOfGuys), [g3, g4, g1, g2] + ); + }); +}); From 1fe76c02e02a11e25f06e7aba1709f5bd10b8c3b Mon Sep 17 00:00:00 2001 From: BrunoRB Date: Tue, 3 Jun 2014 22:42:37 -0300 Subject: [PATCH 020/280] typo --- test/algorithms/sorting/insertion_sort.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/algorithms/sorting/insertion_sort.js b/test/algorithms/sorting/insertion_sort.js index ac4d22c..2f1b44a 100644 --- a/test/algorithms/sorting/insertion_sort.js +++ b/test/algorithms/sorting/insertion_sort.js @@ -76,7 +76,7 @@ describe('Insertion Sort', function () { this.age = age; }; - var compareAgesOfGuys = function(g1, g2) { + var compareAgeOfGuys = function(g1, g2) { if (g1.age === g2.age) { return 0; } @@ -89,7 +89,7 @@ describe('Insertion Sort', function () { g4 = new Guy(20); assert.deepEqual( - insertionSort([g1, g2, g3, g4], compareAgesOfGuys), [g3, g4, g1, g2] + insertionSort([g1, g2, g3, g4], compareAgeOfGuys), [g3, g4, g1, g2] ); }); }); From 028963122efb611cf04fcf69bfb1d67669c06d3b Mon Sep 17 00:00:00 2001 From: tayllan Date: Wed, 4 Jun 2014 00:43:16 -0300 Subject: [PATCH 021/280] Counting Sort --- algorithms/sorting/counting_sort.js | 87 ++++++++++++++++++++++++ main.js | 1 + test/algorithms/sorting/counting_sort.js | 61 +++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 algorithms/sorting/counting_sort.js create mode 100644 test/algorithms/sorting/counting_sort.js diff --git a/algorithms/sorting/counting_sort.js b/algorithms/sorting/counting_sort.js new file mode 100644 index 0000000..223baa2 --- /dev/null +++ b/algorithms/sorting/counting_sort.js @@ -0,0 +1,87 @@ +/** + * Copyright (C) 2014 Tayllan Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +/** + * Sorts an array of objects according to their 'key' property + * Every object inside the array MUST have the 'key' property with + * a integer value. + * + * Execution Time: (3 * array.length - 1) + * Asymptotic Complexity: O(array.length + maximumKey) + * + * @param Array + * @return Array + */ +var countingSort = function(array) { + var max = maximumKey(array); + var auxiliaryArray = []; + var length = array.length; + + for (var i = 0; i < length; i++) { + var position = array[i].key; + + if (auxiliaryArray[position] === undefined) { + auxiliaryArray[position] = []; + } + + auxiliaryArray[position].push(array[i]); + } + + array = []; + var pointer = 0; + + for (i = 0; i <= max; i++) { + if (auxiliaryArray[i] !== undefined) { + var localLength = auxiliaryArray[i].length; + + for (var j = 0; j < localLength; j++) { + array[pointer++] = auxiliaryArray[i][j]; + } + } + } + + return array; +}; + +/** + * Finds the maximum key from an array of objects + * + * Asymptotic Complexity: O(array.length) + * + * @param Array + * @return Integer + */ +var maximumKey = function(array) { + var max = array[0].key; + var length = array.length; + + for (var i = 1; i < length; i++) { + if (array[i].key > max) { + max = array[i].key; + } + } + + return max; +}; + +module.exports = countingSort; diff --git a/main.js b/main.js index 376900f..987862a 100644 --- a/main.js +++ b/main.js @@ -42,6 +42,7 @@ var lib = { }, Sort: { bubbleSort: require('./algorithms/sorting/bubble_sort'), + countingSort: require('./algorithms/sorting/counting_sort'), heapSort: require('./algorithms/sorting/heap_sort'), mergeSort: require('./algorithms/sorting/merge_sort'), quicksort: require('./algorithms/sorting/quicksort') diff --git a/test/algorithms/sorting/counting_sort.js b/test/algorithms/sorting/counting_sort.js new file mode 100644 index 0000000..403ae58 --- /dev/null +++ b/test/algorithms/sorting/counting_sort.js @@ -0,0 +1,61 @@ +/** + * Copyright (C) 2014 Tayllan Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"], to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var countingSort = require('../../../algorithms/sorting/counting_sort'), + assert = require('assert'); + +var firstObject = { + someProperty: 'The', + key: 12 +}; + +var secondObject = { + someProperty: 'chosen', + key: 66 +}; + +var thirdObject = { + someProperty: 'one!', + key: 43 +}; + +var array = [ + thirdObject, + firstObject, + secondObject, + secondObject, + firstObject, + firstObject +]; + +describe('Counting Sort', function () { + it('should sort the given array', function() { + array = countingSort(array); + + // Asserts that the array is truly sorted + assert.deepEqual(array.indexOf(firstObject), 0); + assert.deepEqual(array.indexOf(secondObject), 4); + assert.deepEqual(array.indexOf(thirdObject), 3); + assert.deepEqual(array.indexOf({key: 99}), -1); + }); +}); From ba40d49404f6efe91313c85411925cf27e7e81c3 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 4 Jun 2014 10:13:39 +0200 Subject: [PATCH 022/280] Fix indentation and mixed tabs and spaces --- .jshintrc | 2 +- algorithms/graph/SPFA.js | 18 ++-- algorithms/graph/bellman_ford.js | 86 +++++++-------- algorithms/sorting/counting_sort.js | 84 +++++++-------- algorithms/sorting/insertion_sort.js | 24 ++--- algorithms/string/karp_rabin.js | 122 +++++++++++----------- test/algorithms/graph/bellman_ford.js | 52 ++++----- test/algorithms/sorting/counting_sort.js | 44 ++++---- test/algorithms/sorting/insertion_sort.js | 120 ++++++++++----------- test/algorithms/string/karp_rabin.js | 4 +- 10 files changed, 278 insertions(+), 278 deletions(-) diff --git a/.jshintrc b/.jshintrc index 4c7ac86..958f8f6 100644 --- a/.jshintrc +++ b/.jshintrc @@ -11,7 +11,7 @@ "unused": true, "strict": true, "maxlen": 80, - "white": true, + "trailing": true, "curly": false, "globals": { "describe" : false, diff --git a/algorithms/graph/SPFA.js b/algorithms/graph/SPFA.js index a447f9b..8b066e3 100644 --- a/algorithms/graph/SPFA.js +++ b/algorithms/graph/SPFA.js @@ -43,15 +43,15 @@ function SPFA(graph, s) { graph.vertices.forEach(function (v) { if (v !== s) { distance[v] = Infinity; - isInQue[v] = false; + isInQue[v] = false; } }); - + var currNode; while (head != tail) { - currNode = queue[head++]; - isInQue[currNode] = false; - var neighbors = graph.neighbors(currNode); + currNode = queue[head++]; + isInQue[currNode] = false; + var neighbors = graph.neighbors(currNode); for (var i = 0; i < neighbors.length; i++) { var v = neighbors[i]; // relaxation @@ -60,13 +60,13 @@ function SPFA(graph, s) { distance[v] = newDistance; previous[v] = currNode; if (!isInQue[v]){ - queue[tail++] = v; - isInQue[v] = true; - } + queue[tail++] = v; + isInQue[v] = true; + } } } } - + return { distance: distance, previous: previous diff --git a/algorithms/graph/bellman_ford.js b/algorithms/graph/bellman_ford.js index 8359fea..18dea14 100644 --- a/algorithms/graph/bellman_ford.js +++ b/algorithms/graph/bellman_ford.js @@ -24,68 +24,68 @@ /** * Calculates the shortest paths in a graph to every node * from the node 'startNode' with Bellman-Ford's algorithm - * + * * Worst Case Complexity: O(|V| * |E|), where |V| is the number of * vertices and |E| is the number of edges in the graph * * @param Object 'graph' An adjacency list representing the graph * @param String 'startNode' The starting node * @return Object the minimum distance to reach every vertice of - * the graph starting in 'startNode', or an empty object if there - * exists a Negative-Weighted Cycle in the graph + * the graph starting in 'startNode', or an empty object if there + * exists a Negative-Weighted Cycle in the graph */ var bellmanFord = function(graph, startNode) { var minDistance = {}; var edges = []; var adjacencyListSize = 0; - + // Add all the edges from the graph to the 'edges' array graph.vertices.forEach(function (s) { - graph.neighbors(s).forEach(function(t) { - edges.push({ - source: s, - target: t, - weight: graph.edge(s, t) - }); - }); - - minDistance[s] = Infinity; - ++adjacencyListSize; + graph.neighbors(s).forEach(function(t) { + edges.push({ + source: s, + target: t, + weight: graph.edge(s, t) + }); + }); + + minDistance[s] = Infinity; + ++adjacencyListSize; }); - + minDistance[startNode] = 0; - + var edgesSize = edges.length; var sourceDistance; var targetDistance; - + for (var i = 0; i < adjacencyListSize - 1; i++) { - for (var j = 0; j < edgesSize; j++) { - sourceDistance = minDistance[edges[j].source] + edges[j].weight; - targetDistance = minDistance[edges[j].target]; - - if (sourceDistance < targetDistance) { - minDistance[edges[j].target] = sourceDistance; - } - } - } - - for (i = 0; i < edgesSize; i++) { - sourceDistance = minDistance[edges[i].source] + edges[i].weight; - targetDistance = minDistance[edges[i].target]; - - if (sourceDistance < targetDistance) { - - // Empty 'distance' object indicates Negative-Weighted Cycle - return { - distance: {} - }; - } - } - - return { - distance: minDistance - }; + for (var j = 0; j < edgesSize; j++) { + sourceDistance = minDistance[edges[j].source] + edges[j].weight; + targetDistance = minDistance[edges[j].target]; + + if (sourceDistance < targetDistance) { + minDistance[edges[j].target] = sourceDistance; + } + } + } + + for (i = 0; i < edgesSize; i++) { + sourceDistance = minDistance[edges[i].source] + edges[i].weight; + targetDistance = minDistance[edges[i].target]; + + if (sourceDistance < targetDistance) { + + // Empty 'distance' object indicates Negative-Weighted Cycle + return { + distance: {} + }; + } + } + + return { + distance: minDistance + }; }; module.exports = bellmanFord; diff --git a/algorithms/sorting/counting_sort.js b/algorithms/sorting/counting_sort.js index 223baa2..e64bc2c 100644 --- a/algorithms/sorting/counting_sort.js +++ b/algorithms/sorting/counting_sort.js @@ -25,63 +25,63 @@ * Sorts an array of objects according to their 'key' property * Every object inside the array MUST have the 'key' property with * a integer value. - * + * * Execution Time: (3 * array.length - 1) * Asymptotic Complexity: O(array.length + maximumKey) - * + * * @param Array * @return Array */ var countingSort = function(array) { - var max = maximumKey(array); - var auxiliaryArray = []; - var length = array.length; - - for (var i = 0; i < length; i++) { - var position = array[i].key; - - if (auxiliaryArray[position] === undefined) { - auxiliaryArray[position] = []; - } - - auxiliaryArray[position].push(array[i]); - } - - array = []; - var pointer = 0; - - for (i = 0; i <= max; i++) { - if (auxiliaryArray[i] !== undefined) { - var localLength = auxiliaryArray[i].length; - - for (var j = 0; j < localLength; j++) { - array[pointer++] = auxiliaryArray[i][j]; - } - } - } - - return array; + var max = maximumKey(array); + var auxiliaryArray = []; + var length = array.length; + + for (var i = 0; i < length; i++) { + var position = array[i].key; + + if (auxiliaryArray[position] === undefined) { + auxiliaryArray[position] = []; + } + + auxiliaryArray[position].push(array[i]); + } + + array = []; + var pointer = 0; + + for (i = 0; i <= max; i++) { + if (auxiliaryArray[i] !== undefined) { + var localLength = auxiliaryArray[i].length; + + for (var j = 0; j < localLength; j++) { + array[pointer++] = auxiliaryArray[i][j]; + } + } + } + + return array; }; /** * Finds the maximum key from an array of objects - * + * * Asymptotic Complexity: O(array.length) - * + * * @param Array * @return Integer */ var maximumKey = function(array) { - var max = array[0].key; - var length = array.length; - - for (var i = 1; i < length; i++) { - if (array[i].key > max) { - max = array[i].key; - } - } - - return max; + var max = array[0].key; + var length = array.length; + + for (var i = 1; i < length; i++) { + if (array[i].key > max) { + max = array[i].key; + } + } + + return max; }; module.exports = countingSort; diff --git a/algorithms/sorting/insertion_sort.js b/algorithms/sorting/insertion_sort.js index 84101fa..7c93a32 100644 --- a/algorithms/sorting/insertion_sort.js +++ b/algorithms/sorting/insertion_sort.js @@ -26,21 +26,21 @@ var Comparator = require('../../util/comparator'); * Insertion sort algorithm O(n + d) */ var insertionSort = function(vector, comparatorFn) { - var comparator = new Comparator(comparatorFn); + var comparator = new Comparator(comparatorFn); - for (var i=1, len=vector.length; i 0 && comparator.lessThan(aux, vector[j - 1])) { - vector[j] = vector[j - 1]; - j--; - } + while (j > 0 && comparator.lessThan(aux, vector[j - 1])) { + vector[j] = vector[j - 1]; + j--; + } - vector[j] = aux; - } + vector[j] = aux; + } - return vector; + return vector; }; -module.exports = insertionSort; \ No newline at end of file +module.exports = insertionSort; diff --git a/algorithms/string/karp_rabin.js b/algorithms/string/karp_rabin.js index 210c3bb..849b0da 100644 --- a/algorithms/string/karp_rabin.js +++ b/algorithms/string/karp_rabin.js @@ -24,7 +24,7 @@ /** * A prime number used to create * the hash representation of a word - * + * * Bigger the prime number, * bigger the hash value */ @@ -42,83 +42,83 @@ var base = 997; * @return Boolean */ var karpRabin = function (a, b) { - var aLength = a.length; - var bLength = b.length; - var rs = hashFunction(b); - var newString = []; - - for (var i = 0; i < bLength; i++) { - newString.push(a.charAt(i)); - } - - var rt = hashFunction(newString.join('')); - - if (rs === rt && checkEquality(b, newString.join(''))) { - return true; - } - else { - for (i = 1; i < aLength; i++) { - var previousCharacter = newString[0]; - var nextCharacter = a.charAt(i); - - rt = reHash( - bLength, - rt, - previousCharacter, - nextCharacter - ); - newString.shift(); - newString.push(nextCharacter); - - if (rs === rt && checkEquality(b, newString.join(''))) { - return true; - } - } - - return false; - } + var aLength = a.length; + var bLength = b.length; + var rs = hashFunction(b); + var newString = []; + + for (var i = 0; i < bLength; i++) { + newString.push(a.charAt(i)); + } + + var rt = hashFunction(newString.join('')); + + if (rs === rt && checkEquality(b, newString.join(''))) { + return true; + } + else { + for (i = 1; i < aLength; i++) { + var previousCharacter = newString[0]; + var nextCharacter = a.charAt(i); + + rt = reHash( + bLength, + rt, + previousCharacter, + nextCharacter + ); + newString.shift(); + newString.push(nextCharacter); + + if (rs === rt && checkEquality(b, newString.join(''))) { + return true; + } + } + + return false; + } }; /** * Checks if 'a' is equal to 'b' - * + * * @param String * @param String * @return Boolean */ var checkEquality = function (a, b) { - var aLength = a.length; - - for (var i = 0; i < aLength; i++) { - if (a.charAt(i) !== b.charAt(i)) { - return false; - } - } - - return true; + var aLength = a.length; + + for (var i = 0; i < aLength; i++) { + if (a.charAt(i) !== b.charAt(i)) { + return false; + } + } + + return true; }; /** * Creates the hash representation of 'word' - * + * * @param String * @return Number */ var hashFunction = function (word) { - var hash = 0; - var wordLength = word.length; - - for (var i = 0, j = wordLength - 1; i < wordLength; i++, j--) { - hash += word.charCodeAt(i) * Math.pow(base, j); - } - - return hash; + var hash = 0; + var wordLength = word.length; + + for (var i = 0, j = wordLength - 1; i < wordLength; i++, j--) { + hash += word.charCodeAt(i) * Math.pow(base, j); + } + + return hash; }; /** * Recalculates the hash representation of a word so that it isn't * necessary to traverse the whole word again - * + * * @param Number * @param Number * @param Character @@ -126,11 +126,11 @@ var hashFunction = function (word) { * @return Number */ var reHash = function (length, hash, previousCharacter, nextCharacter) { - hash -= previousCharacter.charCodeAt(0) * Math.pow(base, length - 1); - hash *= base; - hash += nextCharacter.charCodeAt(0); - - return hash; + hash -= previousCharacter.charCodeAt(0) * Math.pow(base, length - 1); + hash *= base; + hash += nextCharacter.charCodeAt(0); + + return hash; }; module.exports = karpRabin; diff --git a/test/algorithms/graph/bellman_ford.js b/test/algorithms/graph/bellman_ford.js index e00b26c..3df4f8b 100644 --- a/test/algorithms/graph/bellman_ford.js +++ b/test/algorithms/graph/bellman_ford.js @@ -27,30 +27,30 @@ var bellmanFord = require('../../../algorithms/graph/bellman_ford'), describe('Bellman-Ford Algorithm', function () { it('should return the shortest paths to all nodes from a given origin', - function () { - var graph = new Graph(true); - - graph.addEdge('a', 'b', -1); - graph.addEdge('a', 'c', 4); - graph.addEdge('b', 'c', 3); - graph.addEdge('b', 'd', 2); - graph.addEdge('b', 'e', 2); - graph.addEdge('d', 'b', 1); - graph.addEdge('e', 'd', -3); - graph.addEdge('d', 'c', 5); - - var shortestPaths = bellmanFord(graph, 'a'); - - assert.equal(shortestPaths.distance.a, 0); - assert.equal(shortestPaths.distance.d, -2); - assert.equal(shortestPaths.distance.e, 1); - - // It'll cause a Negative-Weighted Cycle. - graph.addEdge('c', 'a', -9); - - shortestPaths = bellmanFord(graph, 'a'); - - // The 'distance' object is empty - assert.equal(shortestPaths.distance.a, undefined); - }); + function () { + var graph = new Graph(true); + + graph.addEdge('a', 'b', -1); + graph.addEdge('a', 'c', 4); + graph.addEdge('b', 'c', 3); + graph.addEdge('b', 'd', 2); + graph.addEdge('b', 'e', 2); + graph.addEdge('d', 'b', 1); + graph.addEdge('e', 'd', -3); + graph.addEdge('d', 'c', 5); + + var shortestPaths = bellmanFord(graph, 'a'); + + assert.equal(shortestPaths.distance.a, 0); + assert.equal(shortestPaths.distance.d, -2); + assert.equal(shortestPaths.distance.e, 1); + + // It'll cause a Negative-Weighted Cycle. + graph.addEdge('c', 'a', -9); + + shortestPaths = bellmanFord(graph, 'a'); + + // The 'distance' object is empty + assert.equal(shortestPaths.distance.a, undefined); + }); }); diff --git a/test/algorithms/sorting/counting_sort.js b/test/algorithms/sorting/counting_sort.js index 403ae58..a29e7be 100644 --- a/test/algorithms/sorting/counting_sort.js +++ b/test/algorithms/sorting/counting_sort.js @@ -23,39 +23,39 @@ var countingSort = require('../../../algorithms/sorting/counting_sort'), assert = require('assert'); - + var firstObject = { - someProperty: 'The', - key: 12 + someProperty: 'The', + key: 12 }; var secondObject = { - someProperty: 'chosen', - key: 66 + someProperty: 'chosen', + key: 66 }; var thirdObject = { - someProperty: 'one!', - key: 43 + someProperty: 'one!', + key: 43 }; - + var array = [ - thirdObject, - firstObject, - secondObject, - secondObject, - firstObject, - firstObject + thirdObject, + firstObject, + secondObject, + secondObject, + firstObject, + firstObject ]; describe('Counting Sort', function () { it('should sort the given array', function() { - array = countingSort(array); - - // Asserts that the array is truly sorted - assert.deepEqual(array.indexOf(firstObject), 0); - assert.deepEqual(array.indexOf(secondObject), 4); - assert.deepEqual(array.indexOf(thirdObject), 3); - assert.deepEqual(array.indexOf({key: 99}), -1); - }); + array = countingSort(array); + + // Asserts that the array is truly sorted + assert.deepEqual(array.indexOf(firstObject), 0); + assert.deepEqual(array.indexOf(secondObject), 4); + assert.deepEqual(array.indexOf(thirdObject), 3); + assert.deepEqual(array.indexOf({key: 99}), -1); + }); }); diff --git a/test/algorithms/sorting/insertion_sort.js b/test/algorithms/sorting/insertion_sort.js index 2f1b44a..15ec3ee 100644 --- a/test/algorithms/sorting/insertion_sort.js +++ b/test/algorithms/sorting/insertion_sort.js @@ -25,71 +25,71 @@ var insertionSort = require('../../../algorithms/sorting/insertion_sort'), assert = require('assert'); describe('Insertion Sort', function () { - it('should sort the given array', function () { - assert.deepEqual(insertionSort([]), []); - assert.deepEqual(insertionSort([1]), [1]); - assert.deepEqual(insertionSort([2, 1]), [1, 2]); - assert.deepEqual(insertionSort([3, 1, 2]), [1, 2, 3]); - assert.deepEqual(insertionSort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(insertionSort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual( - insertionSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), - [0, 1, 3, 5, 6, 8, 10, 10, 20, 295] - ); - }); + it('should sort the given array', function () { + assert.deepEqual(insertionSort([]), []); + assert.deepEqual(insertionSort([1]), [1]); + assert.deepEqual(insertionSort([2, 1]), [1, 2]); + assert.deepEqual(insertionSort([3, 1, 2]), [1, 2, 3]); + assert.deepEqual(insertionSort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual(insertionSort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual( + insertionSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), + [0, 1, 3, 5, 6, 8, 10, 10, 20, 295] + ); + }); - it('should sort the array with a specific comparison function', function () { - var compare = function (a, b) { - if (a.length === b.length) { - return 0; - } - return (a.length < b.length) ? -1 : 1; - }; - assert.deepEqual(insertionSort([], compare), []); - assert.deepEqual(insertionSort(['apple'], compare), ['apple']); - assert.deepEqual( - insertionSort(['apple', 'banana'], compare), - ['apple', 'banana'] - ); - assert.deepEqual( - insertionSort(['apple', 'banana', 'car'], compare), - ['car', 'apple', 'banana'] - ); - assert.deepEqual( - insertionSort(['apple', 'banana', 'car', 'z'], compare), - ['z', 'car', 'apple', 'banana'] - ); + it('should sort the array with a specific comparison function', function () { + var compare = function (a, b) { + if (a.length === b.length) { + return 0; + } + return (a.length < b.length) ? -1 : 1; + }; + assert.deepEqual(insertionSort([], compare), []); + assert.deepEqual(insertionSort(['apple'], compare), ['apple']); + assert.deepEqual( + insertionSort(['apple', 'banana'], compare), + ['apple', 'banana'] + ); + assert.deepEqual( + insertionSort(['apple', 'banana', 'car'], compare), + ['car', 'apple', 'banana'] + ); + assert.deepEqual( + insertionSort(['apple', 'banana', 'car', 'z'], compare), + ['z', 'car', 'apple', 'banana'] + ); - var reverseSort = function (a, b) { - if (a === b) { - return 0; - } - return (a < b) ? 1 : -1; - }; - assert.deepEqual( - insertionSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], reverseSort), - [295, 20, 10, 10, 8, 6, 5, 3, 1, 0] - ); + var reverseSort = function (a, b) { + if (a === b) { + return 0; + } + return (a < b) ? 1 : -1; + }; + assert.deepEqual( + insertionSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], reverseSort), + [295, 20, 10, 10, 8, 6, 5, 3, 1, 0] + ); - var Guy = function(age) { - this.age = age; - }; + var Guy = function(age) { + this.age = age; + }; - var compareAgeOfGuys = function(g1, g2) { - if (g1.age === g2.age) { - return 0; - } - return (g1.age < g2.age) ? -1 : 1; - }; + var compareAgeOfGuys = function(g1, g2) { + if (g1.age === g2.age) { + return 0; + } + return (g1.age < g2.age) ? -1 : 1; + }; - var g1 = new Guy(30), - g2 = new Guy(80), - g3 = new Guy(15), - g4 = new Guy(20); + var g1 = new Guy(30), + g2 = new Guy(80), + g3 = new Guy(15), + g4 = new Guy(20); - assert.deepEqual( - insertionSort([g1, g2, g3, g4], compareAgeOfGuys), [g3, g4, g1, g2] - ); - }); + assert.deepEqual( + insertionSort([g1, g2, g3, g4], compareAgeOfGuys), [g3, g4, g1, g2] + ); + }); }); diff --git a/test/algorithms/string/karp_rabin.js b/test/algorithms/string/karp_rabin.js index 5ea8031..30840be 100644 --- a/test/algorithms/string/karp_rabin.js +++ b/test/algorithms/string/karp_rabin.js @@ -22,7 +22,7 @@ 'use strict'; var karpRabin = require('../../../algorithms/string/karp_rabin'), - assert = require('assert'); + assert = require('assert'); describe('Karp-Rabin', function () { it('should verify if a string is contained in another string', @@ -30,7 +30,7 @@ describe('Karp-Rabin', function () { assert.equal(karpRabin('', ''), true); assert.equal(karpRabin('a', 'b'), false); assert.equal(karpRabin('b', 'a'), false); - + // ' tes' is contained in 'super test' assert.equal(karpRabin('super test', ' tes'), true); }); From 45e67e0341688969ece6a125bbf2b7dc5e06232a Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 4 Jun 2014 17:05:29 +0200 Subject: [PATCH 023/280] Hash table on top of native Array --- data_structures/hash_table.js | 120 ++++++++++++++++++++++++++ data_structures/linked_list.js | 5 +- test/data_structures/hash_table.js | 133 +++++++++++++++++++++++++++++ 3 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 data_structures/hash_table.js create mode 100644 test/data_structures/hash_table.js diff --git a/data_structures/hash_table.js b/data_structures/hash_table.js new file mode 100644 index 0000000..da888a2 --- /dev/null +++ b/data_structures/hash_table.js @@ -0,0 +1,120 @@ +/** + * Copyright (C) 2014 Felipe Ribeiro + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var LinkedList = require('./linked_list'); + +function HashTable(initialCapacity) { + this._table = new Array(initialCapacity || 64); + this._items = 0; + + Object.defineProperty(this, 'capacity', { + get: function () { + return this._table.length; + } + }); +} + +/** + * (Same algorithm as Java's String.hashCode) + * Returns a hash code for this string. The hash code for a String object is + * computed as: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] + * using int arithmetic, where s[i] is the ith character of the string, + * n is the length of the string, and ^ indicates exponentiation. + * (The hash value of the empty string is zero.) + */ +HashTable.prototype.hash = function (s) { + var hash = 0; + for (var i = 0; i < s.length; i++) { + hash = ((hash << 5) - hash) + s.charCodeAt(i); + hash &= hash; // Keep it a 32bit int + } + return hash; +}; + +HashTable.prototype.get = function (key) { + var i = this._position(key); + var node; + if ((node = this._findInList(this._table[i], key))) { + return node.value.v; + } +}; + +HashTable.prototype.put = function (key, value) { + var i = this._position(key); + if (!this._table[i]) { + // Hashing with chaining + this._table[i] = new LinkedList(); + } + var item = {k: key, v: value}; + + var node = this._findInList(this._table[i], key); + if (node) { + // if the key already exists in the list, replace + // by the current item + node.value = item; + } else { + this._table[i].add(item); + this._items++; + + if (this._items === this.capacity) this._increaseCapacity(); + } +}; + +HashTable.prototype.del = function (key) { + var i = this._position(key); + var node; + + if ((node = this._findInList(this._table[i], key))) { + + this._table[i].delNode(node); + this._items--; + } +}; + +HashTable.prototype._position = function (key) { + return this.hash(key) % this.capacity; +}; + +HashTable.prototype._findInList = function (list, key) { + var node = list && list.head; + while (node) { + if (node.value.k === key) return node; + node = node.next; + } +}; + +HashTable.prototype._increaseCapacity = function () { + var oldTable = this._table; + this._table = new Array(2 * this.capacity); + this._items = 0; + + for (var i = 0; i < oldTable.length; i++) { + var node = oldTable[i] && oldTable[i].head; + while (node) { + this.put(node.value.k, node.value.v); + node = node.next; + } + } +}; + +module.exports = HashTable; diff --git a/data_structures/linked_list.js b/data_structures/linked_list.js index 8e894d6..a74f3b1 100644 --- a/data_structures/linked_list.js +++ b/data_structures/linked_list.js @@ -137,8 +137,11 @@ LinkedList.prototype.del = function (index) { if (index >= this.length || index < 0) { throw new Error('Index out of bounds'); } - var node = this.getNode(index); + + this.delNode(this.getNode(index)); +}; +LinkedList.prototype.delNode = function (node) { if (node === this.tail) { // node is the last element this.tail = node.prev; diff --git a/test/data_structures/hash_table.js b/test/data_structures/hash_table.js new file mode 100644 index 0000000..56c8f22 --- /dev/null +++ b/test/data_structures/hash_table.js @@ -0,0 +1,133 @@ +/** + * Copyright (C) 2014 Felipe Ribeiro + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var HashTable = require('../../data_structures/hash_table'), + assert = require('assert'); + +describe('Hash Table', function () { + it('should calculate hashes using the same algorithm as '+ + 'Java\'s String.hashCode', function () { + var h = new HashTable(); + assert.equal(h.hash('The quick brown fox jumps over the lazy dog'), + -609428141); + assert.equal(h.hash('Testing the hashCode function'), 1538083358); + assert.equal(h.hash(''), 0); + assert.equal(h.hash('a'), 97); + var longString = + 'k"hg3q#+~/l2Eljan;DB x.P%-:iA' + + '/b/hG($8-SZcZX871&;fDEWthw.b5agzov],X00--O:mcQ$JFi-4uIo"D:(r(yvs' + + 'dj%Pq/b$sY5(O8!{^icIBwTT>,fv=$@dD(>167.xqSDXjBS#TV3oIjMGCo9)!e&hO ' + + 'I<[jlz3]r-FFFeNe#Ch4oQ,4A;i,3&3Oq*2LW(KFUW9b$}"z8,B>HRH9.D%.S~o3' + + 'L_6{wu!Kp538AmLREp*ZP`]K9}uRGEEUj37[PQq2Y>cf_{L={Ko"ADnZ8d[q0{-3' + + '@=e8UC4y)@aCefzleW[>Q8y}@Of9{WNI|?ShSF7C{62(A4ok7gRR|dd?7Pi:`0; r_wq=-F-e(iY'; + assert.equal(h.hash(longString), -998071508); + }); + + it('should initialize the table with the given capacity', + function () { + var h = new HashTable(); + assert.equal(h.capacity, 64); // default initial capacity; + + h = new HashTable(2); + assert.equal(h.capacity, 2); + }); + + it('should allow putting and getting elements from the table', function () { + var h = new HashTable(16); + var a = {a: 'foo', b: 'bar'}; + h.put('foo', a); + assert.strictEqual(h.get('foo'), a); + + var b = {a: 'bar', b: 'baz'}; + h.put('bar', b); + assert.strictEqual(h.get('bar'), b); + }); + + it('should replace items if the same key is reused', function () { + var h = new HashTable(16); + var a = {a: 'foo', b: 'bar'}; + h.put('foo', a); + assert.strictEqual(h.get('foo'), a); + + var b = {a: 'bar', b: 'baz'}; + h.put('foo', b); + assert.strictEqual(h.get('foo'), b); + }); + + it('should return undefined if there\'s no element', function () { + var h = new HashTable(8); + assert.equal(h.get('foo'), undefined); + assert.equal(h.get('bar'), undefined); + }); + + it('should handle hash conflicts', function () { + var h = new HashTable(4); + // Both keys are supposed to be pushed to the same position + assert.equal(h._position('a'), h._position('e')); + h.put('a', 'foo'); + h.put('e', 'bar'); + // the list in that position should keep both items + assert.equal(h._table[h._position('a')].length, 2); + + // and still return them properly + assert.equal(h.get('a'), 'foo'); + assert.equal(h.get('e'), 'bar'); + }); + + it('should increase capacity if needed', function () { + var h = new HashTable(2); + assert.equal(h.capacity, 2); + + h.put('foo', 'foo'); + assert.equal(h.capacity, 2); + + h.put('bar', 'bar'); + assert.equal(h.capacity, 4); + }); + + it('should allow removing items', function () { + var h = new HashTable(); + assert.equal(h.get('foo'), undefined); + + h.put('foo', 'bar'); + assert.equal(h.get('foo'), 'bar'); + + h.del('foo'); + assert.equal(h.get('foo'), undefined); + + // Deleting an unexistent item shouldn't do anything + h.del('foo'); + assert.equal(h.get('foo'), undefined); + }); +}); + From 18099e17f11da6b31a03b217ff06d92cd23d2f28 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Thu, 5 Jun 2014 00:05:36 +0200 Subject: [PATCH 024/280] Expose Hash Table in main.js --- main.js | 1 + 1 file changed, 1 insertion(+) diff --git a/main.js b/main.js index 987862a..bf0516d 100644 --- a/main.js +++ b/main.js @@ -54,6 +54,7 @@ var lib = { DataStructure: { BST: require('./data_structures/bst'), Graph: require('./data_structures/graph'), + HashTable: require('./data_structures/hash_table'), Heap: require('./data_structures/heap'), LinkedList: require('./data_structures/linked_list'), PriorityQueue: require('./data_structures/priority_queue'), From e3173942576d938e9567588d09564ff7a6a5ba49 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Thu, 5 Jun 2014 00:09:38 +0200 Subject: [PATCH 025/280] v0.3.0 Heap sort, Insertion sort, Counting Sort, Hash table, Square root --- CHANGELOG | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index cd02822..77a6ca4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,18 @@ CHANGELOG ========= +0.3.0 (2014-06-03) +* Math +** Square root by Newton's method + +* Data Structures +** Hash table + +* Sorting +** Insertion sort +** Heap sort +** Counting sort + 0.2.0 (2014-06-01) * Graphs ** Shortest Path Faster Algorithm (#34) diff --git a/package.json b/package.json index ce63dc7..c0ae88a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.2.0", + "version": "0.3.0", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" From c8eec1e05c746a5f98d967432aa1e7b6c695714e Mon Sep 17 00:00:00 2001 From: tayllan Date: Wed, 4 Jun 2014 20:20:32 -0300 Subject: [PATCH 026/280] Knuth-Morris-Pratt --- algorithms/string/knuth_morris_pratt.js | 105 +++++++++++++++++++ main.js | 3 +- test/algorithms/string/knuth_morris_pratt.js | 65 ++++++++++++ 3 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 algorithms/string/knuth_morris_pratt.js create mode 100644 test/algorithms/string/knuth_morris_pratt.js diff --git a/algorithms/string/knuth_morris_pratt.js b/algorithms/string/knuth_morris_pratt.js new file mode 100644 index 0000000..75e7328 --- /dev/null +++ b/algorithms/string/knuth_morris_pratt.js @@ -0,0 +1,105 @@ +/** + * Copyright (C) 2014 Tayllan Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +/** + * String Matching algorithm + * Tries to match the given pattern inside the given text + * If the pattern exists inside the text, it will be returned + * the index of the begining of the pattern in the text, + * otherwise it will be returned the length of the text + * + * Asymptotic Complexity: O(text.length) + * + * @param {Array} of Numbers, Strings or Characters + * or {Strig} + * @param {Array} of Numbers, Strings or Characters + * or {Strig} + * @return {Number} + */ +var knuthMorrisPratt = function(text, pattern) { + var textLength = text.length; + var patternLength = pattern.length; + var m = 0; + var i = 0; + var table = buildTable(pattern); + + while (m + i < textLength) { + if (pattern[i] === text[m + i]) { + if (i === patternLength - 1) { + return m; + } + ++i; + } + else { + if (table[i] >= 0) { + i = table[i]; + m = m + i - table[i]; + } + else { + i = 0; + ++m; + } + } + } + + return textLength; +}; + +/** + * Builds the dinamic table of the given pattern + * to record how the pattern can match it self + * + * Asymptotic Complexity: O(pattern.length) + * + * @param {Array} of Numbers, Strings or Characters + * or {Strig} + * @return {Array} of Integers + */ +var buildTable = function(pattern) { + var length = pattern.length; + var table = []; + var position = 2; + var cnd = 0; + + table[0] = -1; + table[1] = 0; + + while (position < length) { + if (pattern[position - 1] === pattern[cnd]) { + ++cnd; + table[position] = cnd; + ++position; + } + else if (cnd > 0) { + cnd = table[cnd]; + } + else { + table[position] = 0; + ++position; + } + } + + return table; +}; + +module.exports = knuthMorrisPratt; diff --git a/main.js b/main.js index bf0516d..a39ced7 100644 --- a/main.js +++ b/main.js @@ -49,7 +49,8 @@ var lib = { }, String: { editDistance: require('./algorithms/string/edit_distance'), - karpRabin: require('./algorithms/string/karp_rabin') + karpRabin: require('./algorithms/string/karp_rabin'), + knuthMorrisPratt: require('./algorithms/string/knuth_morris_pratt') }, DataStructure: { BST: require('./data_structures/bst'), diff --git a/test/algorithms/string/knuth_morris_pratt.js b/test/algorithms/string/knuth_morris_pratt.js new file mode 100644 index 0000000..d655d10 --- /dev/null +++ b/test/algorithms/string/knuth_morris_pratt.js @@ -0,0 +1,65 @@ +/** + * Copyright (C) 2014 Tayllan Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var knuthMorrisPratt = require('../../../algorithms/string/knuth_morris_pratt'), + assert = require('assert'); + +describe('Knuth-Morris-Pratt', function () { + it('should verify if a pattern is contained in some text (or array)', + function () { + var text = 'A string matching algorithm wants to find the starting' + + 'index m in string S[] that matches the search word W[].The most' + + ' straightforward algorithm is to look for a character match at ' + + 'successive values of the index m, the position in the string be' + + 'ing searched, i.e. S[m]. If the index m reaches the end of the ' + + 'string then there is no match, in which case the search is said' + + 'to "fail". At each position m the algorithm first checks for eq' + + 'uality of the first character in the searched for word, i.e. S[' + + 'm] =? W[0]. If a match is found, the algorithm tests the other ' + + 'characters in the searched for word by checking successive valu' + + 'es of the word position index, i. The algorithm retrieves the c' + + 'haracter W[i] in the searched for word and checks for equality ' + + 'of the expression S[m+i] =? W[i]. If all successive characters ' + + 'match in W at position m then a match is found at that position' + + ' in the search string. (Wikipedia, 2014): https://en.wikipedia.' + + 'org/wiki/Knuth-Morris-Pratt_algorithm'; + var pattern = 'https://en.wikipedia.org/wiki/Knuth-Morris-Pratt_al' + + 'gorithm'; + + assert.equal(knuthMorrisPratt(text, pattern), 915); + + pattern = '(https://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm'; + + assert.equal(knuthMorrisPratt(text, pattern), text.length); + + + var arrayText = [3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 4]; + var arrayPattern = [8, 9, 8]; + + assert.equal(knuthMorrisPratt(arrayText, arrayPattern), 5); + + arrayPattern = []; + + assert.equal(knuthMorrisPratt(arrayText, arrayPattern), arrayText.length); + }); +}); From ba8696ddddefde4f86bbd1dcb71dd058060ebfae Mon Sep 17 00:00:00 2001 From: tayllan Date: Thu, 5 Jun 2014 10:21:15 -0300 Subject: [PATCH 027/280] Typo --- algorithms/string/knuth_morris_pratt.js | 90 ++++++++++---------- test/algorithms/string/knuth_morris_pratt.js | 50 +++++------ 2 files changed, 70 insertions(+), 70 deletions(-) diff --git a/algorithms/string/knuth_morris_pratt.js b/algorithms/string/knuth_morris_pratt.js index 75e7328..f5623fb 100644 --- a/algorithms/string/knuth_morris_pratt.js +++ b/algorithms/string/knuth_morris_pratt.js @@ -37,32 +37,32 @@ * @return {Number} */ var knuthMorrisPratt = function(text, pattern) { - var textLength = text.length; - var patternLength = pattern.length; - var m = 0; - var i = 0; - var table = buildTable(pattern); + var textLength = text.length; + var patternLength = pattern.length; + var m = 0; + var i = 0; + var table = buildTable(pattern); - while (m + i < textLength) { - if (pattern[i] === text[m + i]) { - if (i === patternLength - 1) { - return m; - } - ++i; - } - else { - if (table[i] >= 0) { - i = table[i]; - m = m + i - table[i]; - } - else { - i = 0; - ++m; - } - } - } + while (m + i < textLength) { + if (pattern[i] === text[m + i]) { + if (i === patternLength - 1) { + return m; + } + ++i; + } + else { + if (table[i] >= 0) { + i = table[i]; + m = m + i - table[i]; + } + else { + i = 0; + ++m; + } + } + } - return textLength; + return textLength; }; /** @@ -76,30 +76,30 @@ var knuthMorrisPratt = function(text, pattern) { * @return {Array} of Integers */ var buildTable = function(pattern) { - var length = pattern.length; - var table = []; - var position = 2; - var cnd = 0; + var length = pattern.length; + var table = []; + var position = 2; + var cnd = 0; - table[0] = -1; - table[1] = 0; + table[0] = -1; + table[1] = 0; - while (position < length) { - if (pattern[position - 1] === pattern[cnd]) { - ++cnd; - table[position] = cnd; - ++position; - } - else if (cnd > 0) { - cnd = table[cnd]; - } - else { - table[position] = 0; - ++position; - } - } + while (position < length) { + if (pattern[position - 1] === pattern[cnd]) { + ++cnd; + table[position] = cnd; + ++position; + } + else if (cnd > 0) { + cnd = table[cnd]; + } + else { + table[position] = 0; + ++position; + } + } - return table; + return table; }; module.exports = knuthMorrisPratt; diff --git a/test/algorithms/string/knuth_morris_pratt.js b/test/algorithms/string/knuth_morris_pratt.js index d655d10..1ca5804 100644 --- a/test/algorithms/string/knuth_morris_pratt.js +++ b/test/algorithms/string/knuth_morris_pratt.js @@ -27,39 +27,39 @@ var knuthMorrisPratt = require('../../../algorithms/string/knuth_morris_pratt'), describe('Knuth-Morris-Pratt', function () { it('should verify if a pattern is contained in some text (or array)', function () { - var text = 'A string matching algorithm wants to find the starting' + - 'index m in string S[] that matches the search word W[].The most' + - ' straightforward algorithm is to look for a character match at ' + - 'successive values of the index m, the position in the string be' + - 'ing searched, i.e. S[m]. If the index m reaches the end of the ' + - 'string then there is no match, in which case the search is said' + - 'to "fail". At each position m the algorithm first checks for eq' + - 'uality of the first character in the searched for word, i.e. S[' + - 'm] =? W[0]. If a match is found, the algorithm tests the other ' + - 'characters in the searched for word by checking successive valu' + - 'es of the word position index, i. The algorithm retrieves the c' + - 'haracter W[i] in the searched for word and checks for equality ' + - 'of the expression S[m+i] =? W[i]. If all successive characters ' + - 'match in W at position m then a match is found at that position' + - ' in the search string. (Wikipedia, 2014): https://en.wikipedia.' + - 'org/wiki/Knuth-Morris-Pratt_algorithm'; - var pattern = 'https://en.wikipedia.org/wiki/Knuth-Morris-Pratt_al' + - 'gorithm'; + var text = 'A string matching algorithm wants to find the starting' + + 'index m in string S[] that matches the search word W[].The most' + + ' straightforward algorithm is to look for a character match at ' + + 'successive values of the index m, the position in the string be' + + 'ing searched, i.e. S[m]. If the index m reaches the end of the ' + + 'string then there is no match, in which case the search is said' + + 'to "fail". At each position m the algorithm first checks for eq' + + 'uality of the first character in the searched for word, i.e. S[' + + 'm] =? W[0]. If a match is found, the algorithm tests the other ' + + 'characters in the searched for word by checking successive valu' + + 'es of the word position index, i. The algorithm retrieves the c' + + 'haracter W[i] in the searched for word and checks for equality ' + + 'of the expression S[m+i] =? W[i]. If all successive characters ' + + 'match in W at position m then a match is found at that position' + + ' in the search string. (Wikipedia, 2014): https://en.wikipedia.' + + 'org/wiki/Knuth-Morris-Pratt_algorithm'; + var pattern = 'https://en.wikipedia.org/wiki/Knuth-Morris-Pratt_al' + + 'gorithm'; assert.equal(knuthMorrisPratt(text, pattern), 915); - + pattern = '(https://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm'; - + assert.equal(knuthMorrisPratt(text, pattern), text.length); - - + + var arrayText = [3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 4]; var arrayPattern = [8, 9, 8]; - + assert.equal(knuthMorrisPratt(arrayText, arrayPattern), 5); - + arrayPattern = []; - + assert.equal(knuthMorrisPratt(arrayText, arrayPattern), arrayText.length); }); }); From 09e6c980f5260844a78a2ed4a705c4b1be6bfe9b Mon Sep 17 00:00:00 2001 From: anaran Date: Thu, 5 Jun 2014 18:16:27 +0200 Subject: [PATCH 028/280] Add jscs to toolchain since jshint ignores indentation as of v2.5.0 --- .jscsrc | 12 ++++++++++++ Makefile | 7 ++++++- package.json | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 .jscsrc diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 0000000..0f8e8de --- /dev/null +++ b/.jscsrc @@ -0,0 +1,12 @@ +{ + "validateIndentation":2, + // "indent": 2, + "disallowMixedSpacesAndTabs":true, + // "smarttabs":false, + "maximumLineLength":80, + // "maxlen": 80, + "disallowTrailingWhitespace": true, + // "trailing": true, + "requireCurlyBraces": [] + // "curly": false, +} diff --git a/Makefile b/Makefile index 96ba6db..f405486 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ -all: jshint coverage +.PHONY: setup + +all: jshint jscs coverage setup: npm install @@ -6,6 +8,9 @@ setup: jshint: setup jshint algorithms data_structures test util +jscs: setup + jscs --reporter=inline algorithms data_structures test util + test: setup mocha -R spec --recursive test diff --git a/package.json b/package.json index c0ae88a..c423a5a 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "coveralls": "^2.10.0", "istanbul": "^0.2.10", "jshint": "^2.5.1", + "jscs": "^1.4.5", "mocha": "^1.20.0" }, "repository": { From 0d21ee35b0511945d4b20d711ae31c39837206d8 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Thu, 5 Jun 2014 19:39:37 +0200 Subject: [PATCH 029/280] Fixing code style --- algorithms/graph/SPFA.js | 10 +++++----- algorithms/graph/bellman_ford.js | 4 ++-- algorithms/math/extended_euclidean.js | 2 +- algorithms/math/newton_sqrt.js | 2 +- algorithms/sorting/bubble_sort.js | 4 ++-- algorithms/sorting/counting_sort.js | 4 ++-- algorithms/sorting/insertion_sort.js | 4 ++-- algorithms/string/knuth_morris_pratt.js | 22 +++++++++++----------- data_structures/linked_list.js | 4 ++-- test/algorithms/sorting/bubble_sort.js | 2 +- test/algorithms/sorting/counting_sort.js | 2 +- test/algorithms/sorting/heap_sort.js | 2 +- test/algorithms/sorting/insertion_sort.js | 4 ++-- test/algorithms/sorting/merge_sort.js | 2 +- test/algorithms/sorting/quicksort.js | 2 +- test/data_structures/hash_table.js | 2 +- 16 files changed, 36 insertions(+), 36 deletions(-) diff --git a/algorithms/graph/SPFA.js b/algorithms/graph/SPFA.js index 8b066e3..d60c5b1 100644 --- a/algorithms/graph/SPFA.js +++ b/algorithms/graph/SPFA.js @@ -32,10 +32,10 @@ function SPFA(graph, s) { var distance = {}; var previous = {}; - var queue = {}; - var isInQue = {}; - var head = 0; - var tail = 1; + var queue = {}; + var isInQue = {}; + var head = 0; + var tail = 1; // initialize distance[s] = 0; queue[0] = s; @@ -59,7 +59,7 @@ function SPFA(graph, s) { if (newDistance < distance[v]) { distance[v] = newDistance; previous[v] = currNode; - if (!isInQue[v]){ + if (!isInQue[v]) { queue[tail++] = v; isInQue[v] = true; } diff --git a/algorithms/graph/bellman_ford.js b/algorithms/graph/bellman_ford.js index 18dea14..a3d76a3 100644 --- a/algorithms/graph/bellman_ford.js +++ b/algorithms/graph/bellman_ford.js @@ -34,14 +34,14 @@ * the graph starting in 'startNode', or an empty object if there * exists a Negative-Weighted Cycle in the graph */ -var bellmanFord = function(graph, startNode) { +var bellmanFord = function (graph, startNode) { var minDistance = {}; var edges = []; var adjacencyListSize = 0; // Add all the edges from the graph to the 'edges' array graph.vertices.forEach(function (s) { - graph.neighbors(s).forEach(function(t) { + graph.neighbors(s).forEach(function (t) { edges.push({ source: s, target: t, diff --git a/algorithms/math/extended_euclidean.js b/algorithms/math/extended_euclidean.js index 3be1d70..b6fc25c 100644 --- a/algorithms/math/extended_euclidean.js +++ b/algorithms/math/extended_euclidean.js @@ -23,7 +23,7 @@ 'use strict'; /** - * Extended Euclidean algorithm to calculate the solve of + * Extended Euclidean algorithm to calculate the solve of * ax + by = gcd(a, b) * gcd(a, b) is the greatest common divisor of integers a and b. * diff --git a/algorithms/math/newton_sqrt.js b/algorithms/math/newton_sqrt.js index b722981..7b32208 100644 --- a/algorithms/math/newton_sqrt.js +++ b/algorithms/math/newton_sqrt.js @@ -44,7 +44,7 @@ var sqrt = function (n, tolerance, maxIterations) { square = x * x; if (square < n) lowerBound = x; else upperBound = x; - } while (Math.abs(square - n) > tolerance && i < maxIterations); + } while (Math.abs(square - n) > tolerance && i < maxIterations); // Checks if the number is a perfect square to return the exact root var roundX = Math.round(x); diff --git a/algorithms/sorting/bubble_sort.js b/algorithms/sorting/bubble_sort.js index c436397..ff851af 100644 --- a/algorithms/sorting/bubble_sort.js +++ b/algorithms/sorting/bubble_sort.js @@ -25,7 +25,7 @@ var Comparator = require('../../util/comparator'); /** * Bubble sort algorithm O(n^2) */ -var bubbleSort = function(a, comparatorFn) { +var bubbleSort = function (a, comparatorFn) { var comparator = new Comparator(comparatorFn), n = a.length, bound = n - 1; @@ -45,4 +45,4 @@ var bubbleSort = function(a, comparatorFn) { return a; }; -module.exports = bubbleSort; \ No newline at end of file +module.exports = bubbleSort; diff --git a/algorithms/sorting/counting_sort.js b/algorithms/sorting/counting_sort.js index e64bc2c..8671db8 100644 --- a/algorithms/sorting/counting_sort.js +++ b/algorithms/sorting/counting_sort.js @@ -32,7 +32,7 @@ * @param Array * @return Array */ -var countingSort = function(array) { +var countingSort = function (array) { var max = maximumKey(array); var auxiliaryArray = []; var length = array.length; @@ -71,7 +71,7 @@ var countingSort = function(array) { * @param Array * @return Integer */ -var maximumKey = function(array) { +var maximumKey = function (array) { var max = array[0].key; var length = array.length; diff --git a/algorithms/sorting/insertion_sort.js b/algorithms/sorting/insertion_sort.js index 7c93a32..08316c2 100644 --- a/algorithms/sorting/insertion_sort.js +++ b/algorithms/sorting/insertion_sort.js @@ -25,10 +25,10 @@ var Comparator = require('../../util/comparator'); /** * Insertion sort algorithm O(n + d) */ -var insertionSort = function(vector, comparatorFn) { +var insertionSort = function (vector, comparatorFn) { var comparator = new Comparator(comparatorFn); - for (var i=1, len=vector.length; i= this.length || index < 0) { throw new Error('Index out of bounds'); } - + this.delNode(this.getNode(index)); }; diff --git a/test/algorithms/sorting/bubble_sort.js b/test/algorithms/sorting/bubble_sort.js index 7948b6f..b07a51d 100644 --- a/test/algorithms/sorting/bubble_sort.js +++ b/test/algorithms/sorting/bubble_sort.js @@ -52,7 +52,7 @@ describe('Bubble Sort', function () { var reverseSort = function (a, b) { if (a == b) return 0; - return a < b ? 1: -1; + return a < b ? 1 : -1; }; assert.deepEqual(bubbleSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], reverseSort), diff --git a/test/algorithms/sorting/counting_sort.js b/test/algorithms/sorting/counting_sort.js index a29e7be..3898acb 100644 --- a/test/algorithms/sorting/counting_sort.js +++ b/test/algorithms/sorting/counting_sort.js @@ -49,7 +49,7 @@ var array = [ ]; describe('Counting Sort', function () { - it('should sort the given array', function() { + it('should sort the given array', function () { array = countingSort(array); // Asserts that the array is truly sorted diff --git a/test/algorithms/sorting/heap_sort.js b/test/algorithms/sorting/heap_sort.js index f6fe511..7aae938 100644 --- a/test/algorithms/sorting/heap_sort.js +++ b/test/algorithms/sorting/heap_sort.js @@ -52,7 +52,7 @@ describe('Heap Sort', function () { var reverseSort = function (a, b) { if (a == b) return 0; - return a < b ? 1: -1; + return a < b ? 1 : -1; }; assert.deepEqual(heapSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], reverseSort), diff --git a/test/algorithms/sorting/insertion_sort.js b/test/algorithms/sorting/insertion_sort.js index 15ec3ee..81468ac 100644 --- a/test/algorithms/sorting/insertion_sort.js +++ b/test/algorithms/sorting/insertion_sort.js @@ -72,11 +72,11 @@ describe('Insertion Sort', function () { [295, 20, 10, 10, 8, 6, 5, 3, 1, 0] ); - var Guy = function(age) { + var Guy = function (age) { this.age = age; }; - var compareAgeOfGuys = function(g1, g2) { + var compareAgeOfGuys = function (g1, g2) { if (g1.age === g2.age) { return 0; } diff --git a/test/algorithms/sorting/merge_sort.js b/test/algorithms/sorting/merge_sort.js index 55e353e..36b3e64 100644 --- a/test/algorithms/sorting/merge_sort.js +++ b/test/algorithms/sorting/merge_sort.js @@ -52,7 +52,7 @@ describe('Merge Sort', function () { var reverseSort = function (a, b) { if (a == b) return 0; - return a < b ? 1: -1; + return a < b ? 1 : -1; }; assert.deepEqual(mergeSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], reverseSort), diff --git a/test/algorithms/sorting/quicksort.js b/test/algorithms/sorting/quicksort.js index 35b19f4..f6f574f 100644 --- a/test/algorithms/sorting/quicksort.js +++ b/test/algorithms/sorting/quicksort.js @@ -52,7 +52,7 @@ describe('QuickSort', function () { var reverseSort = function (a, b) { if (a == b) return 0; - return a < b ? 1: -1; + return a < b ? 1 : -1; }; assert.deepEqual(quicksort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], reverseSort), diff --git a/test/data_structures/hash_table.js b/test/data_structures/hash_table.js index 56c8f22..fecfc17 100644 --- a/test/data_structures/hash_table.js +++ b/test/data_structures/hash_table.js @@ -25,7 +25,7 @@ var HashTable = require('../../data_structures/hash_table'), assert = require('assert'); describe('Hash Table', function () { - it('should calculate hashes using the same algorithm as '+ + it('should calculate hashes using the same algorithm as ' + 'Java\'s String.hashCode', function () { var h = new HashTable(); assert.equal(h.hash('The quick brown fox jumps over the lazy dog'), From 64de21434fc83401939526585e9925b7051efd53 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Thu, 5 Jun 2014 19:43:09 +0200 Subject: [PATCH 030/280] Downgrade to version 2.4 of jshint and fix errors --- algorithms/math/extended_euclidean.js | 40 ++++++++++++------------ algorithms/string/knuth_morris_pratt.js | 6 ++-- data_structures/hash_table.js | 7 ++--- package.json | 2 +- test/algorithms/math/gcd.js | 2 +- test/algorithms/sorting/counting_sort.js | 12 +++---- test/data_structures/hash_table.js | 4 +-- 7 files changed, 36 insertions(+), 37 deletions(-) diff --git a/algorithms/math/extended_euclidean.js b/algorithms/math/extended_euclidean.js index b6fc25c..4ada133 100644 --- a/algorithms/math/extended_euclidean.js +++ b/algorithms/math/extended_euclidean.js @@ -33,30 +33,30 @@ * @return {Number, Number} */ var extEuclid = function (a, b) { - var s = 0, oldS = 1; - var t = 1, oldT = 0; - var r = b, oldR = a; - var quotient, temp; - while (r !== 0) { - quotient = Math.floor(oldR / r); + var s = 0, oldS = 1; + var t = 1, oldT = 0; + var r = b, oldR = a; + var quotient, temp; + while (r !== 0) { + quotient = Math.floor(oldR / r); - temp = r; - r = oldR - quotient * r; - oldR = temp; + temp = r; + r = oldR - quotient * r; + oldR = temp; - temp = s; - s = oldS - quotient * s; - oldS = temp; + temp = s; + s = oldS - quotient * s; + oldS = temp; - temp = t; - t = oldT - quotient * t; - oldT = temp; - } + temp = t; + t = oldT - quotient * t; + oldT = temp; + } - return { - x: oldS, - y: oldT - }; + return { + x: oldS, + y: oldT + }; }; module.exports = extEuclid; diff --git a/algorithms/string/knuth_morris_pratt.js b/algorithms/string/knuth_morris_pratt.js index b08b5d9..b8f6f99 100644 --- a/algorithms/string/knuth_morris_pratt.js +++ b/algorithms/string/knuth_morris_pratt.js @@ -31,9 +31,9 @@ * Asymptotic Complexity: O(text.length) * * @param {Array} of Numbers, Strings or Characters - * or {Strig} + * or {String} * @param {Array} of Numbers, Strings or Characters - * or {Strig} + * or {String} * @return {Number} */ var knuthMorrisPratt = function (text, pattern) { @@ -72,7 +72,7 @@ var knuthMorrisPratt = function (text, pattern) { * Asymptotic Complexity: O(pattern.length) * * @param {Array} of Numbers, Strings or Characters - * or {Strig} + * or {String} * @return {Array} of Integers */ var buildTable = function (pattern) { diff --git a/data_structures/hash_table.js b/data_structures/hash_table.js index da888a2..5f5d66b 100644 --- a/data_structures/hash_table.js +++ b/data_structures/hash_table.js @@ -55,7 +55,7 @@ HashTable.prototype.get = function (key) { var i = this._position(key); var node; if ((node = this._findInList(this._table[i], key))) { - return node.value.v; + return node.value.v; } }; @@ -85,9 +85,8 @@ HashTable.prototype.del = function (key) { var node; if ((node = this._findInList(this._table[i], key))) { - - this._table[i].delNode(node); - this._items--; + this._table[i].delNode(node); + this._items--; } }; diff --git a/package.json b/package.json index c0ae88a..2abcea8 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "devDependencies": { "coveralls": "^2.10.0", "istanbul": "^0.2.10", - "jshint": "^2.5.1", + "jshint": "~2.4.4", "mocha": "^1.20.0" }, "repository": { diff --git a/test/algorithms/math/gcd.js b/test/algorithms/math/gcd.js index ee7a6ee..ea23823 100644 --- a/test/algorithms/math/gcd.js +++ b/test/algorithms/math/gcd.js @@ -53,7 +53,7 @@ describe('GCD', function () { assert.equal(gcdb(7, 49), 7); assert.equal(gcdb(7, 5), 1); assert.equal(gcdb(35, 49), 7); - }); + }); }); diff --git a/test/algorithms/sorting/counting_sort.js b/test/algorithms/sorting/counting_sort.js index 3898acb..f5b5b7f 100644 --- a/test/algorithms/sorting/counting_sort.js +++ b/test/algorithms/sorting/counting_sort.js @@ -50,12 +50,12 @@ var array = [ describe('Counting Sort', function () { it('should sort the given array', function () { - array = countingSort(array); + array = countingSort(array); - // Asserts that the array is truly sorted - assert.deepEqual(array.indexOf(firstObject), 0); - assert.deepEqual(array.indexOf(secondObject), 4); - assert.deepEqual(array.indexOf(thirdObject), 3); - assert.deepEqual(array.indexOf({key: 99}), -1); + // Asserts that the array is truly sorted + assert.deepEqual(array.indexOf(firstObject), 0); + assert.deepEqual(array.indexOf(secondObject), 4); + assert.deepEqual(array.indexOf(thirdObject), 3); + assert.deepEqual(array.indexOf({key: 99}), -1); }); }); diff --git a/test/data_structures/hash_table.js b/test/data_structures/hash_table.js index fecfc17..7a93168 100644 --- a/test/data_structures/hash_table.js +++ b/test/data_structures/hash_table.js @@ -51,7 +51,7 @@ describe('Hash Table', function () { 'WGD)s;Zs<8K6(K_kVko"mV82Pcl)0Rx}jfq3VBm:MOX/gLfSPvLx~%(3jHh5gG2e' + 'JaQ|nW}ekR_W5Ldv`@j^hd%Wiw6moGekrS>k7gRR|dd?7Pi:`0; r_wq=-F-e(iY'; assert.equal(h.hash(longString), -998071508); - }); + }); it('should initialize the table with the given capacity', function () { @@ -60,7 +60,7 @@ describe('Hash Table', function () { h = new HashTable(2); assert.equal(h.capacity, 2); - }); + }); it('should allow putting and getting elements from the table', function () { var h = new HashTable(16); From 06901b894d5792eb0095736e8e259d70badb5282 Mon Sep 17 00:00:00 2001 From: anaran Date: Thu, 5 Jun 2014 20:54:46 +0200 Subject: [PATCH 031/280] Fixes for indentation and trailing whitespace errors reported by jscs. --- algorithms/math/extended_euclidean.js | 42 +++--- data_structures/hash_table.js | 6 +- data_structures/linked_list.js | 2 +- test/algorithms/graph/topological_sort.js | 54 +++---- test/algorithms/math/gcd.js | 2 +- test/algorithms/sorting/counting_sort.js | 12 +- test/data_structures/bst.js | 174 +++++++++++----------- test/data_structures/hash_table.js | 4 +- 8 files changed, 148 insertions(+), 148 deletions(-) diff --git a/algorithms/math/extended_euclidean.js b/algorithms/math/extended_euclidean.js index 3be1d70..4ada133 100644 --- a/algorithms/math/extended_euclidean.js +++ b/algorithms/math/extended_euclidean.js @@ -23,7 +23,7 @@ 'use strict'; /** - * Extended Euclidean algorithm to calculate the solve of + * Extended Euclidean algorithm to calculate the solve of * ax + by = gcd(a, b) * gcd(a, b) is the greatest common divisor of integers a and b. * @@ -33,30 +33,30 @@ * @return {Number, Number} */ var extEuclid = function (a, b) { - var s = 0, oldS = 1; - var t = 1, oldT = 0; - var r = b, oldR = a; - var quotient, temp; - while (r !== 0) { - quotient = Math.floor(oldR / r); + var s = 0, oldS = 1; + var t = 1, oldT = 0; + var r = b, oldR = a; + var quotient, temp; + while (r !== 0) { + quotient = Math.floor(oldR / r); - temp = r; - r = oldR - quotient * r; - oldR = temp; + temp = r; + r = oldR - quotient * r; + oldR = temp; - temp = s; - s = oldS - quotient * s; - oldS = temp; + temp = s; + s = oldS - quotient * s; + oldS = temp; - temp = t; - t = oldT - quotient * t; - oldT = temp; - } + temp = t; + t = oldT - quotient * t; + oldT = temp; + } - return { - x: oldS, - y: oldT - }; + return { + x: oldS, + y: oldT + }; }; module.exports = extEuclid; diff --git a/data_structures/hash_table.js b/data_structures/hash_table.js index da888a2..12db22d 100644 --- a/data_structures/hash_table.js +++ b/data_structures/hash_table.js @@ -55,7 +55,7 @@ HashTable.prototype.get = function (key) { var i = this._position(key); var node; if ((node = this._findInList(this._table[i], key))) { - return node.value.v; + return node.value.v; } }; @@ -86,8 +86,8 @@ HashTable.prototype.del = function (key) { if ((node = this._findInList(this._table[i], key))) { - this._table[i].delNode(node); - this._items--; + this._table[i].delNode(node); + this._items--; } }; diff --git a/data_structures/linked_list.js b/data_structures/linked_list.js index a74f3b1..6cd00cd 100644 --- a/data_structures/linked_list.js +++ b/data_structures/linked_list.js @@ -137,7 +137,7 @@ LinkedList.prototype.del = function (index) { if (index >= this.length || index < 0) { throw new Error('Index out of bounds'); } - + this.delNode(this.getNode(index)); }; diff --git a/test/algorithms/graph/topological_sort.js b/test/algorithms/graph/topological_sort.js index 878f7da..ab7dd76 100644 --- a/test/algorithms/graph/topological_sort.js +++ b/test/algorithms/graph/topological_sort.js @@ -27,39 +27,39 @@ var topologicalSort = require('../../../algorithms/graph/topological_sort'), describe('Topological Sort', function () { it('should return a stack with the vertices ordered' + - ' considering the dependencies', function () { + ' considering the dependencies', function () { - var graph = new Graph(); - graph.addVertex('shirt'); - graph.addVertex('watch'); - graph.addVertex('socks'); - graph.addVertex('underwear'); - graph.addVertex('pants'); - graph.addVertex('belt'); - graph.addVertex('shoes'); - graph.addVertex('tie'); - graph.addVertex('jacket'); + var graph = new Graph(); + graph.addVertex('shirt'); + graph.addVertex('watch'); + graph.addVertex('socks'); + graph.addVertex('underwear'); + graph.addVertex('pants'); + graph.addVertex('belt'); + graph.addVertex('shoes'); + graph.addVertex('tie'); + graph.addVertex('jacket'); - graph.addEdge('shirt', 'belt'); - graph.addEdge('shirt', 'tie'); - graph.addEdge('shirt', 'jacket'); + graph.addEdge('shirt', 'belt'); + graph.addEdge('shirt', 'tie'); + graph.addEdge('shirt', 'jacket'); - graph.addEdge('socks', 'shoes'); + graph.addEdge('socks', 'shoes'); - graph.addEdge('underwear', 'pants'); - graph.addEdge('underwear', 'shoes'); + graph.addEdge('underwear', 'pants'); + graph.addEdge('underwear', 'shoes'); - graph.addEdge('pants', 'shoes'); - graph.addEdge('pants', 'belt'); + graph.addEdge('pants', 'shoes'); + graph.addEdge('pants', 'belt'); - graph.addEdge('belt', 'jacket'); + graph.addEdge('belt', 'jacket'); - graph.addEdge('tie', 'jacket'); + graph.addEdge('tie', 'jacket'); - var stack = topologicalSort(graph); - var a = []; - while (!stack.isEmpty()) a.push(stack.pop()); - assert.deepEqual(a, ['underwear', 'pants', 'socks', 'shoes', - 'watch', 'shirt', 'tie', 'belt', 'jacket']); - }); + var stack = topologicalSort(graph); + var a = []; + while (!stack.isEmpty()) a.push(stack.pop()); + assert.deepEqual(a, ['underwear', 'pants', 'socks', 'shoes', + 'watch', 'shirt', 'tie', 'belt', 'jacket']); + }); }); diff --git a/test/algorithms/math/gcd.js b/test/algorithms/math/gcd.js index ee7a6ee..ea23823 100644 --- a/test/algorithms/math/gcd.js +++ b/test/algorithms/math/gcd.js @@ -53,7 +53,7 @@ describe('GCD', function () { assert.equal(gcdb(7, 49), 7); assert.equal(gcdb(7, 5), 1); assert.equal(gcdb(35, 49), 7); - }); + }); }); diff --git a/test/algorithms/sorting/counting_sort.js b/test/algorithms/sorting/counting_sort.js index a29e7be..cbdf4a5 100644 --- a/test/algorithms/sorting/counting_sort.js +++ b/test/algorithms/sorting/counting_sort.js @@ -50,12 +50,12 @@ var array = [ describe('Counting Sort', function () { it('should sort the given array', function() { - array = countingSort(array); + array = countingSort(array); - // Asserts that the array is truly sorted - assert.deepEqual(array.indexOf(firstObject), 0); - assert.deepEqual(array.indexOf(secondObject), 4); - assert.deepEqual(array.indexOf(thirdObject), 3); - assert.deepEqual(array.indexOf({key: 99}), -1); + // Asserts that the array is truly sorted + assert.deepEqual(array.indexOf(firstObject), 0); + assert.deepEqual(array.indexOf(secondObject), 4); + assert.deepEqual(array.indexOf(thirdObject), 3); + assert.deepEqual(array.indexOf({key: 99}), -1); }); }); diff --git a/test/data_structures/bst.js b/test/data_structures/bst.js index ae2a12c..d55f7c7 100644 --- a/test/data_structures/bst.js +++ b/test/data_structures/bst.js @@ -88,76 +88,76 @@ describe('Binary Search Tree', function () { it('should remove a leaf without altering anything else in ' + - 'the structure of the tree', function () { + 'the structure of the tree', function () { - bst.remove(0); + bst.remove(0); /** * 4 * 2 8 * 1 3 5 10 * 2.5 100 */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 10, 2.5, 100]); - }); + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 10, 2.5, 100]); + }); it('should remove an element with just one child and substitute ' + - 'it as the root of only subtree', function () { + 'it as the root of only subtree', function () { - bst.remove(10); - /** - * 4 - * 2 8 - * 1 3 5 100 - * 2.5 - */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 100, 2.5]); - }); + bst.remove(10); + /** + * 4 + * 2 8 + * 1 3 5 100 + * 2.5 + */ + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 100, 2.5]); + }); it('should substitute an element by the leftmost child in the right ' + - 'subtree and remove it as a leaf', function () { - /** - * 4 - * 2 8 - * 1 3 5 100 - * 2.5 - */ - bst.remove(2); - /** - * 4 - * 2.5 8 - * 1 3 5 100 - * - */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [4, 2.5, 8, 1, 3, 5, 100]); + 'subtree and remove it as a leaf', function () { + /** + * 4 + * 2 8 + * 1 3 5 100 + * 2.5 + */ + bst.remove(2); + /** + * 4 + * 2.5 8 + * 1 3 5 100 + * + */ + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [4, 2.5, 8, 1, 3, 5, 100]); - bst.remove(4); - /** - * 5 - * 2.5 8 - * 1 3 100 - * - */ - a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [5, 2.5, 8, 1, 3, 100]); + bst.remove(4); + /** + * 5 + * 2.5 8 + * 1 3 100 + * + */ + a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [5, 2.5, 8, 1, 3, 100]); - bst.remove(2.5); - /** - * 5 - * 3 8 - * 1 100 - * - */ - a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [5, 3, 8, 1, 100]); - }); + bst.remove(2.5); + /** + * 5 + * 3 8 + * 1 100 + * + */ + a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [5, 3, 8, 1, 100]); + }); it('should always return the right root and size', function () { var bst = new BST(); @@ -245,42 +245,42 @@ describe('Binary Search Tree with custom comparator', function () { }); it('should remove a leaf without altering anything else in ' + - 'the structure of the tree', function () { + 'the structure of the tree', function () { - bst.remove('watermelon'); - /** - * 'banana' - * 'apple' 'pineapple' - * 'pear' - */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear']); - }); + bst.remove('watermelon'); + /** + * 'banana' + * 'apple' 'pineapple' + * 'pear' + */ + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear']); + }); it('should remove an element with just one child and substitute ' + - 'it as the root of only subtree', function () { + 'it as the root of only subtree', function () { - bst.remove('apple'); - /** - * 'banana' - * 'pear' 'pineapple' - */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, ['banana', 'pear', 'pineapple']); - }); + bst.remove('apple'); + /** + * 'banana' + * 'pear' 'pineapple' + */ + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, ['banana', 'pear', 'pineapple']); + }); it('should substitute an element by the leftmost child in the right ' + - 'subtree and remove it as a leaf', function () { + 'subtree and remove it as a leaf', function () { - bst.remove('banana'); - /** - * 'pineapple' - * 'pear' - */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, ['pineapple', 'pear']); - }); + bst.remove('banana'); + /** + * 'pineapple' + * 'pear' + */ + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, ['pineapple', 'pear']); + }); }); diff --git a/test/data_structures/hash_table.js b/test/data_structures/hash_table.js index 56c8f22..9227bd9 100644 --- a/test/data_structures/hash_table.js +++ b/test/data_structures/hash_table.js @@ -51,7 +51,7 @@ describe('Hash Table', function () { 'WGD)s;Zs<8K6(K_kVko"mV82Pcl)0Rx}jfq3VBm:MOX/gLfSPvLx~%(3jHh5gG2e' + 'JaQ|nW}ekR_W5Ldv`@j^hd%Wiw6moGekrS>k7gRR|dd?7Pi:`0; r_wq=-F-e(iY'; assert.equal(h.hash(longString), -998071508); - }); + }); it('should initialize the table with the given capacity', function () { @@ -60,7 +60,7 @@ describe('Hash Table', function () { h = new HashTable(2); assert.equal(h.capacity, 2); - }); + }); it('should allow putting and getting elements from the table', function () { var h = new HashTable(16); From 58cbd73759f8cd3d830941b3e9a4e7da98718f48 Mon Sep 17 00:00:00 2001 From: nitinsaroha Date: Fri, 6 Jun 2014 01:45:46 +0530 Subject: [PATCH 032/280] Added Selection Sort --- algorithms/sorting/selection_sort.js | 46 ++++++++++++++++++++++++++++ main.js | 3 +- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 algorithms/sorting/selection_sort.js diff --git a/algorithms/sorting/selection_sort.js b/algorithms/sorting/selection_sort.js new file mode 100644 index 0000000..a46807d --- /dev/null +++ b/algorithms/sorting/selection_sort.js @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2014 Felipe Ribeiro + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; +var Comparator = require('../../util/comparator'); +/** + * Selection sort algorithm O(n^2) + */ +var selectionSort = function(a) { + var n = a.length; + for (var i = 0; i < n - 1; i++){ + var min = i; + + for (var j = i + 1; j < n; j++){ + if(a[min] > a[j]) + min = j; + } + if (min != i){ + var tmp = a[i]; + a[i] = a[min]; + a[min] = tmp; + } + } + +return a; +}; + +module.exports = selectionSort; \ No newline at end of file diff --git a/main.js b/main.js index a39ced7..dd699c0 100644 --- a/main.js +++ b/main.js @@ -45,7 +45,8 @@ var lib = { countingSort: require('./algorithms/sorting/counting_sort'), heapSort: require('./algorithms/sorting/heap_sort'), mergeSort: require('./algorithms/sorting/merge_sort'), - quicksort: require('./algorithms/sorting/quicksort') + quicksort: require('./algorithms/sorting/quicksort'), + selectionSort: require('./algorithms/sorting/selection_sort') }, String: { editDistance: require('./algorithms/string/edit_distance'), From 975971f5d5a980012c0f30077ca6d95712160357 Mon Sep 17 00:00:00 2001 From: anaran Date: Fri, 6 Jun 2014 01:30:17 +0200 Subject: [PATCH 033/280] Fine-tune .jscsrc Fix more indentation violations guided by jscs. --- .jscsrc | 23 ++- test/algorithms/graph/topological_sort.js | 52 ++--- test/algorithms/string/knuth_morris_pratt.js | 2 +- test/data_structures/bst.js | 203 ++++++++++--------- 4 files changed, 146 insertions(+), 134 deletions(-) diff --git a/.jscsrc b/.jscsrc index 0f8e8de..e95a520 100644 --- a/.jscsrc +++ b/.jscsrc @@ -1,12 +1,23 @@ { "validateIndentation":2, - // "indent": 2, + // JSHint: "indent": 2, "disallowMixedSpacesAndTabs":true, - // "smarttabs":false, + // JSHint: "smarttabs":false, "maximumLineLength":80, - // "maxlen": 80, + // JSHint: "maxlen": 80, "disallowTrailingWhitespace": true, - // "trailing": true, - "requireCurlyBraces": [] - // "curly": false, + // JSHint: "trailing": true, + "requireCurlyBraces": [], + // JSHint: "curly": false, + "requireSpacesInConditionalExpression": true, + "requireSpacesInNamedFunctionExpression": { + "beforeOpeningCurlyBrace": true + }, + "disallowSpacesInNamedFunctionExpression": { + "beforeOpeningRoundBrace": true + }, + "requireSpacesInAnonymousFunctionExpression": { + "beforeOpeningCurlyBrace": true, + "beforeOpeningRoundBrace": true + } } diff --git a/test/algorithms/graph/topological_sort.js b/test/algorithms/graph/topological_sort.js index 878f7da..aa9a059 100644 --- a/test/algorithms/graph/topological_sort.js +++ b/test/algorithms/graph/topological_sort.js @@ -29,37 +29,37 @@ describe('Topological Sort', function () { it('should return a stack with the vertices ordered' + ' considering the dependencies', function () { - var graph = new Graph(); - graph.addVertex('shirt'); - graph.addVertex('watch'); - graph.addVertex('socks'); - graph.addVertex('underwear'); - graph.addVertex('pants'); - graph.addVertex('belt'); - graph.addVertex('shoes'); - graph.addVertex('tie'); - graph.addVertex('jacket'); + var graph = new Graph(); + graph.addVertex('shirt'); + graph.addVertex('watch'); + graph.addVertex('socks'); + graph.addVertex('underwear'); + graph.addVertex('pants'); + graph.addVertex('belt'); + graph.addVertex('shoes'); + graph.addVertex('tie'); + graph.addVertex('jacket'); - graph.addEdge('shirt', 'belt'); - graph.addEdge('shirt', 'tie'); - graph.addEdge('shirt', 'jacket'); + graph.addEdge('shirt', 'belt'); + graph.addEdge('shirt', 'tie'); + graph.addEdge('shirt', 'jacket'); - graph.addEdge('socks', 'shoes'); + graph.addEdge('socks', 'shoes'); - graph.addEdge('underwear', 'pants'); - graph.addEdge('underwear', 'shoes'); + graph.addEdge('underwear', 'pants'); + graph.addEdge('underwear', 'shoes'); - graph.addEdge('pants', 'shoes'); - graph.addEdge('pants', 'belt'); + graph.addEdge('pants', 'shoes'); + graph.addEdge('pants', 'belt'); - graph.addEdge('belt', 'jacket'); + graph.addEdge('belt', 'jacket'); - graph.addEdge('tie', 'jacket'); + graph.addEdge('tie', 'jacket'); - var stack = topologicalSort(graph); - var a = []; - while (!stack.isEmpty()) a.push(stack.pop()); - assert.deepEqual(a, ['underwear', 'pants', 'socks', 'shoes', - 'watch', 'shirt', 'tie', 'belt', 'jacket']); - }); + var stack = topologicalSort(graph); + var a = []; + while (!stack.isEmpty()) a.push(stack.pop()); + assert.deepEqual(a, ['underwear', 'pants', 'socks', 'shoes', + 'watch', 'shirt', 'tie', 'belt', 'jacket']); + }); }); diff --git a/test/algorithms/string/knuth_morris_pratt.js b/test/algorithms/string/knuth_morris_pratt.js index 1ca5804..d2dc006 100644 --- a/test/algorithms/string/knuth_morris_pratt.js +++ b/test/algorithms/string/knuth_morris_pratt.js @@ -45,7 +45,7 @@ describe('Knuth-Morris-Pratt', function () { 'org/wiki/Knuth-Morris-Pratt_algorithm'; var pattern = 'https://en.wikipedia.org/wiki/Knuth-Morris-Pratt_al' + 'gorithm'; - + assert.equal(knuthMorrisPratt(text, pattern), 915); pattern = '(https://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm'; diff --git a/test/data_structures/bst.js b/test/data_structures/bst.js index ae2a12c..e61979f 100644 --- a/test/data_structures/bst.js +++ b/test/data_structures/bst.js @@ -88,76 +88,76 @@ describe('Binary Search Tree', function () { it('should remove a leaf without altering anything else in ' + - 'the structure of the tree', function () { + 'the structure of the tree', function () { - bst.remove(0); - /** - * 4 - * 2 8 - * 1 3 5 10 - * 2.5 100 - */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 10, 2.5, 100]); - }); + bst.remove(0); + /** + * 4 + * 2 8 + * 1 3 5 10 + * 2.5 100 + */ + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 10, 2.5, 100]); + }); it('should remove an element with just one child and substitute ' + - 'it as the root of only subtree', function () { + 'it as the root of only subtree', function () { - bst.remove(10); - /** - * 4 - * 2 8 - * 1 3 5 100 - * 2.5 - */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 100, 2.5]); - }); + bst.remove(10); + /** + * 4 + * 2 8 + * 1 3 5 100 + * 2.5 + */ + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 100, 2.5]); + }); it('should substitute an element by the leftmost child in the right ' + - 'subtree and remove it as a leaf', function () { - /** - * 4 - * 2 8 - * 1 3 5 100 - * 2.5 - */ - bst.remove(2); - /** - * 4 - * 2.5 8 - * 1 3 5 100 - * - */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [4, 2.5, 8, 1, 3, 5, 100]); + 'subtree and remove it as a leaf', function () { + /** + * 4 + * 2 8 + * 1 3 5 100 + * 2.5 + */ + bst.remove(2); + /** + * 4 + * 2.5 8 + * 1 3 5 100 + * + */ + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [4, 2.5, 8, 1, 3, 5, 100]); - bst.remove(4); - /** - * 5 - * 2.5 8 - * 1 3 100 - * - */ - a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [5, 2.5, 8, 1, 3, 100]); + bst.remove(4); + /** + * 5 + * 2.5 8 + * 1 3 100 + * + */ + a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [5, 2.5, 8, 1, 3, 100]); - bst.remove(2.5); - /** - * 5 - * 3 8 - * 1 100 - * - */ - a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [5, 3, 8, 1, 100]); - }); + bst.remove(2.5); + /** + * 5 + * 3 8 + * 1 100 + * + */ + a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [5, 3, 8, 1, 100]); + }); it('should always return the right root and size', function () { var bst = new BST(); @@ -194,14 +194,15 @@ describe('Binary Search Tree with custom comparator', function () { return a.length < b.length ? -1 : 1; }; - it('should insert elements respecting the BST restrictions', function () { - var bst = new BST(strLenCompare); - bst.insert('banana'); - bst.insert('apple'); - bst.insert('pineapple'); - bst.insert('watermelon'); - assert.equal(bst.size, 4); - }); + it( + 'should insert elements respecting the BST restrictions', function () { + var bst = new BST(strLenCompare); + bst.insert('banana'); + bst.insert('apple'); + bst.insert('pineapple'); + bst.insert('watermelon'); + assert.equal(bst.size, 4); + }); it('should check if an element exists (in O(lg n))', function () { var bst = new BST(strLenCompare); @@ -245,42 +246,42 @@ describe('Binary Search Tree with custom comparator', function () { }); it('should remove a leaf without altering anything else in ' + - 'the structure of the tree', function () { + 'the structure of the tree', function () { - bst.remove('watermelon'); - /** - * 'banana' - * 'apple' 'pineapple' - * 'pear' - */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear']); - }); + bst.remove('watermelon'); + /** + * 'banana' + * 'apple' 'pineapple' + * 'pear' + */ + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear']); + }); it('should remove an element with just one child and substitute ' + - 'it as the root of only subtree', function () { + 'it as the root of only subtree', function () { - bst.remove('apple'); - /** - * 'banana' - * 'pear' 'pineapple' - */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, ['banana', 'pear', 'pineapple']); - }); + bst.remove('apple'); + /** + * 'banana' + * 'pear' 'pineapple' + */ + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, ['banana', 'pear', 'pineapple']); + }); it('should substitute an element by the leftmost child in the right ' + - 'subtree and remove it as a leaf', function () { + 'subtree and remove it as a leaf', function () { - bst.remove('banana'); - /** - * 'pineapple' - * 'pear' - */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, ['pineapple', 'pear']); - }); + bst.remove('banana'); + /** + * 'pineapple' + * 'pear' + */ + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, ['pineapple', 'pear']); + }); }); From 51e5f2bb9222a61c26aea46f19f7c7fbf3b05a53 Mon Sep 17 00:00:00 2001 From: anaran Date: Fri, 6 Jun 2014 01:34:39 +0200 Subject: [PATCH 034/280] Eliminate jscs addition from branch. --- .jscsrc | 12 ------------ Makefile | 7 +------ 2 files changed, 1 insertion(+), 18 deletions(-) delete mode 100644 .jscsrc diff --git a/.jscsrc b/.jscsrc deleted file mode 100644 index 0f8e8de..0000000 --- a/.jscsrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "validateIndentation":2, - // "indent": 2, - "disallowMixedSpacesAndTabs":true, - // "smarttabs":false, - "maximumLineLength":80, - // "maxlen": 80, - "disallowTrailingWhitespace": true, - // "trailing": true, - "requireCurlyBraces": [] - // "curly": false, -} diff --git a/Makefile b/Makefile index f405486..96ba6db 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,4 @@ -.PHONY: setup - -all: jshint jscs coverage +all: jshint coverage setup: npm install @@ -8,9 +6,6 @@ setup: jshint: setup jshint algorithms data_structures test util -jscs: setup - jscs --reporter=inline algorithms data_structures test util - test: setup mocha -R spec --recursive test From 24440c122189adbb276a7d6b925977701bee1078 Mon Sep 17 00:00:00 2001 From: eush77 Date: Fri, 6 Jun 2014 04:24:48 +0400 Subject: [PATCH 035/280] Add Euler path algorithm --- algorithms/graph/euler_path.js | 137 +++++++++++++++++++++++ main.js | 3 +- test/algorithms/graph/euler_path.js | 161 ++++++++++++++++++++++++++++ 3 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 algorithms/graph/euler_path.js create mode 100644 test/algorithms/graph/euler_path.js diff --git a/algorithms/graph/euler_path.js b/algorithms/graph/euler_path.js new file mode 100644 index 0000000..b61a0ba --- /dev/null +++ b/algorithms/graph/euler_path.js @@ -0,0 +1,137 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + + +var Graph = require('../../data_structures/graph'); + + +/** Examine a graph and compute pair of end vertices of the existing Euler path. + * Return pair of undefined values if there is no specific choice of end points. + * Return value format: {start: START, finish: FINISH}. + * + * @param {Graph} Graph, must be connected and contain at least one vertex. + * @return Object + */ +var eulerEndpoints = function(graph) { + var rank = {}; + // start -> rank = +1 + // middle points -> rank = 0 + // finish -> rank = -1 + + // Initialize ranks to be outdegrees of vertices. + graph.vertices.forEach(function(vertex) { + rank[vertex] = graph.neighbors(vertex).length; + }); + + if (graph.directed) { + // rank = outdegree - indegree + graph.vertices.forEach(function(vertex) { + graph.neighbors(vertex).forEach(function(neighbor) { + rank[neighbor] -= 1; + }); + }); + } + else { + // Compute ranks from vertex degree parity values. + var startChosen = false; + graph.vertices.forEach(function(vertex) { + rank[vertex] %= 2; + if (rank[vertex]) { + if (startChosen) { + rank[vertex] = -1; + } + startChosen = true; + } + }); + } + + var start, finish; + + graph.vertices.forEach(function(vertex) { + if (rank[vertex] == 1) { + if (start !== undefined) { + throw new Error('Duplicate start vertex.'); + } + start = vertex; + } + else if (rank[vertex] == -1) { + if (finish !== undefined) { + throw new Error('Duplicate finish vertex.'); + } + finish = vertex; + } + else if (rank[vertex]) { + throw new Error('Unexpected vertex degree for ' + vertex); + } + }); + + if (start === undefined && finish === undefined) { + start = finish = graph.vertices[0]; + } + + return {start: start, + finish: finish}; +}; + + +/** + * Compute Euler path (either walk or tour, depending on the graph). + * Euler path is a trail in a graph which visits every edge exactly once. + * The procedure works both for directed and undirected graphs, + * although the details differ a bit. + * The resulting array consists of exactly |E|+1 vertices. + * + * @param {Graph} + * @return Array + */ +var eulerPath = function(graph) { + if (!graph.vertices.length) { + return []; + } + + var endpoints = eulerEndpoints(graph); + var route = [endpoints.finish]; + + var seen = new Graph(graph.directed); + graph.vertices.forEach(seen.addVertex.bind(seen)); + + (function dfs(vertex) { + graph.neighbors(vertex).forEach(function(neighbor) { + if (!seen.edge(vertex, neighbor)) { + seen.addEdge(vertex, neighbor); + dfs(neighbor); + route.push(vertex); + } + }); + }(endpoints.start)); + + graph.vertices.forEach(function(vertex) { + if (seen.neighbors(vertex).length < graph.neighbors(vertex).length) { + throw new Error('There is no euler path for a disconnected graph.'); + } + }); + return route.reverse(); +}; + + +module.exports = eulerPath; diff --git a/main.js b/main.js index a39ced7..2dd7533 100644 --- a/main.js +++ b/main.js @@ -26,7 +26,8 @@ var lib = { topologicalSort: require('./algorithms/graph/topological_sort'), dijkstra: require('./algorithms/graph/dijkstra'), SPFA: require('./algorithms/graph/SPFA'), - bellmanFord: require('./algorithms/graph/bellman_ford') + bellmanFord: require('./algorithms/graph/bellman_ford'), + eulerPath: require('./algorithms/graph/euler_path'), }, Math: { fibonacci: require('./algorithms/math/fibonacci'), diff --git a/test/algorithms/graph/euler_path.js b/test/algorithms/graph/euler_path.js new file mode 100644 index 0000000..d9f550b --- /dev/null +++ b/test/algorithms/graph/euler_path.js @@ -0,0 +1,161 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"], to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + + +var eulerPath = require('../../../algorithms/graph/euler_path'), + Graph = require('../../../data_structures/graph'), + assert = require('assert'); + + +var verifyEulerPath = function(graph, trail) { + var visited = new Graph(graph.directed); + graph.vertices.forEach(visited.addVertex.bind(visited)); + + trail.slice(1).reduce(function(previous, current) { + assert(graph.edge(previous, current)); + assert(!visited.edge(previous, current)); + visited.addEdge(previous, current); + return current; + }, trail[0]); + + graph.vertices.forEach(function(vertex) { + assert.equal(graph.neighbors(vertex).length, + visited.neighbors(vertex).length); + }); +}; + + +var graphFromEdges = function(directed, edges) { + var graph = new Graph(directed); + edges.forEach(function(edge) { + graph.addEdge(edge[0], edge[1]); + }); + return graph; +}; + + +describe('Euler Path', function() { + it('should compute Euler tour over the undirected graph', function() { + var graph = graphFromEdges(false, [[1, 2], + [1, 5], + [1, 7], + [1, 8], + [2, 3], + [2, 4], + [2, 5], + [3, 5], + [4, 6], + [4, 9], + [4, 10], + [5, 6], + [6, 9], + [6, 10], + [7, 8]]); + var trail = eulerPath(graph); + verifyEulerPath(graph, trail); + assert.equal(trail[0], trail.slice(-1)[0]); + }); + + it('should compute Euler walk over the undirected graph', function() { + var graph = graphFromEdges(false, [[1, 2], + [1, 5], + [1, 7], + [2, 3], + [2, 4], + [2, 5], + [3, 5], + [4, 6], + [4, 9], + [4, 10], + [5, 6], + [6, 9], + [6, 10], + [7, 8]]); + var trail = eulerPath(graph); + verifyEulerPath(graph, trail); + var endpoints = [trail[0], trail.slice(-1)[0]]; + endpoints.sort(); + assert.equal(endpoints[0], 1); + assert.equal(endpoints[1], 8); + }); + + it('should compute Euler tour over the directed graph', function() { + var graph = graphFromEdges(true, [[0, 1], + [1, 2], + [2, 0], + [0, 3], + [3, 4], + [4, 0], + [4, 1], + [1, 5], + [5, 6], + [6, 4]]); + var trail = eulerPath(graph); + verifyEulerPath(graph, trail); + assert.equal(trail[0], trail.slice(-1)[0]); + }); + + it('should compute Euler walk over the directed graph', function() { + var graph = graphFromEdges(true, [[5, 0], + [0, 2], + [2, 4], + [4, 0], + [1, 5], + [3, 1], + [5, 3]]); + var trail = eulerPath(graph); + assert.deepEqual(trail, [5, 3, 1, 5, 0, 2, 4, 0]); + }); + + it('should return single-vertex-trail for an isolated vertex', function() { + var graph = new Graph(); + graph.addVertex('loner'); + var trail = eulerPath(graph); + assert.deepEqual(trail, ['loner']); + }); + + it('should return empty trail for an empty graph', function() { + var graph = new Graph(); + var trail = eulerPath(graph); + assert.deepEqual(trail, []); + }); + + it('should raise an error if there is no Euler path', function() { + var graph = graphFromEdges(false, [[0, 1], [2, 3]]); + assert.throws(eulerPath.bind(graph)); + graph = graphFromEdges(false, [[0, 1], + [0, 2], + [0, 3]]); + assert.throws(eulerPath.bind(graph)); + graph = graphFromEdges(true, [[0, 1], [0, 2]]); + assert.throws(eulerPath.bind(graph)); + graph = graphFromEdges(true, [[1, 0], [2, 0]]); + assert.throws(eulerPath.bind(graph)); + graph = graphFromEdges(true, [[0, 1], + [1, 2], + [2, 3], + [3, 0], + [3, 1]]); + assert.throws(eulerPath.bind(graph)); + }); +}); From 32efe8e0b7bc1f7eb4e0838bcfdd0334b4158491 Mon Sep 17 00:00:00 2001 From: eush77 Date: Fri, 6 Jun 2014 04:56:35 +0400 Subject: [PATCH 036/280] Fix indentation issue --- algorithms/graph/euler_path.js | 150 ++++++++--------- test/algorithms/graph/euler_path.js | 242 ++++++++++++++-------------- 2 files changed, 196 insertions(+), 196 deletions(-) diff --git a/algorithms/graph/euler_path.js b/algorithms/graph/euler_path.js index b61a0ba..b9290fc 100644 --- a/algorithms/graph/euler_path.js +++ b/algorithms/graph/euler_path.js @@ -33,64 +33,64 @@ var Graph = require('../../data_structures/graph'); * @return Object */ var eulerEndpoints = function(graph) { - var rank = {}; - // start -> rank = +1 - // middle points -> rank = 0 - // finish -> rank = -1 - - // Initialize ranks to be outdegrees of vertices. + var rank = {}; + // start -> rank = +1 + // middle points -> rank = 0 + // finish -> rank = -1 + + // Initialize ranks to be outdegrees of vertices. + graph.vertices.forEach(function(vertex) { + rank[vertex] = graph.neighbors(vertex).length; + }); + + if (graph.directed) { + // rank = outdegree - indegree graph.vertices.forEach(function(vertex) { - rank[vertex] = graph.neighbors(vertex).length; + graph.neighbors(vertex).forEach(function(neighbor) { + rank[neighbor] -= 1; + }); }); - - if (graph.directed) { - // rank = outdegree - indegree - graph.vertices.forEach(function(vertex) { - graph.neighbors(vertex).forEach(function(neighbor) { - rank[neighbor] -= 1; - }); - }); - } - else { - // Compute ranks from vertex degree parity values. - var startChosen = false; - graph.vertices.forEach(function(vertex) { - rank[vertex] %= 2; - if (rank[vertex]) { - if (startChosen) { - rank[vertex] = -1; - } - startChosen = true; - } - }); - } - - var start, finish; - + } + else { + // Compute ranks from vertex degree parity values. + var startChosen = false; graph.vertices.forEach(function(vertex) { - if (rank[vertex] == 1) { - if (start !== undefined) { - throw new Error('Duplicate start vertex.'); - } - start = vertex; - } - else if (rank[vertex] == -1) { - if (finish !== undefined) { - throw new Error('Duplicate finish vertex.'); - } - finish = vertex; - } - else if (rank[vertex]) { - throw new Error('Unexpected vertex degree for ' + vertex); + rank[vertex] %= 2; + if (rank[vertex]) { + if (startChosen) { + rank[vertex] = -1; } + startChosen = true; + } }); + } + + var start, finish; - if (start === undefined && finish === undefined) { - start = finish = graph.vertices[0]; + graph.vertices.forEach(function(vertex) { + if (rank[vertex] == 1) { + if (start !== undefined) { + throw new Error('Duplicate start vertex.'); + } + start = vertex; + } + else if (rank[vertex] == -1) { + if (finish !== undefined) { + throw new Error('Duplicate finish vertex.'); + } + finish = vertex; + } + else if (rank[vertex]) { + throw new Error('Unexpected vertex degree for ' + vertex); } + }); - return {start: start, - finish: finish}; + if (start === undefined && finish === undefined) { + start = finish = graph.vertices[0]; + } + + return {start: start, + finish: finish}; }; @@ -105,32 +105,32 @@ var eulerEndpoints = function(graph) { * @return Array */ var eulerPath = function(graph) { - if (!graph.vertices.length) { - return []; - } - - var endpoints = eulerEndpoints(graph); - var route = [endpoints.finish]; - - var seen = new Graph(graph.directed); - graph.vertices.forEach(seen.addVertex.bind(seen)); - - (function dfs(vertex) { - graph.neighbors(vertex).forEach(function(neighbor) { - if (!seen.edge(vertex, neighbor)) { - seen.addEdge(vertex, neighbor); - dfs(neighbor); - route.push(vertex); - } - }); - }(endpoints.start)); - - graph.vertices.forEach(function(vertex) { - if (seen.neighbors(vertex).length < graph.neighbors(vertex).length) { - throw new Error('There is no euler path for a disconnected graph.'); - } + if (!graph.vertices.length) { + return []; + } + + var endpoints = eulerEndpoints(graph); + var route = [endpoints.finish]; + + var seen = new Graph(graph.directed); + graph.vertices.forEach(seen.addVertex.bind(seen)); + + (function dfs(vertex) { + graph.neighbors(vertex).forEach(function(neighbor) { + if (!seen.edge(vertex, neighbor)) { + seen.addEdge(vertex, neighbor); + dfs(neighbor); + route.push(vertex); + } }); - return route.reverse(); + }(endpoints.start)); + + graph.vertices.forEach(function(vertex) { + if (seen.neighbors(vertex).length < graph.neighbors(vertex).length) { + throw new Error('There is no euler path for a disconnected graph.'); + } + }); + return route.reverse(); }; diff --git a/test/algorithms/graph/euler_path.js b/test/algorithms/graph/euler_path.js index d9f550b..a4c6240 100644 --- a/test/algorithms/graph/euler_path.js +++ b/test/algorithms/graph/euler_path.js @@ -28,134 +28,134 @@ var eulerPath = require('../../../algorithms/graph/euler_path'), var verifyEulerPath = function(graph, trail) { - var visited = new Graph(graph.directed); - graph.vertices.forEach(visited.addVertex.bind(visited)); - - trail.slice(1).reduce(function(previous, current) { - assert(graph.edge(previous, current)); - assert(!visited.edge(previous, current)); - visited.addEdge(previous, current); - return current; - }, trail[0]); - - graph.vertices.forEach(function(vertex) { - assert.equal(graph.neighbors(vertex).length, - visited.neighbors(vertex).length); - }); + var visited = new Graph(graph.directed); + graph.vertices.forEach(visited.addVertex.bind(visited)); + + trail.slice(1).reduce(function(previous, current) { + assert(graph.edge(previous, current)); + assert(!visited.edge(previous, current)); + visited.addEdge(previous, current); + return current; + }, trail[0]); + + graph.vertices.forEach(function(vertex) { + assert.equal(graph.neighbors(vertex).length, + visited.neighbors(vertex).length); + }); }; var graphFromEdges = function(directed, edges) { - var graph = new Graph(directed); - edges.forEach(function(edge) { - graph.addEdge(edge[0], edge[1]); - }); - return graph; + var graph = new Graph(directed); + edges.forEach(function(edge) { + graph.addEdge(edge[0], edge[1]); + }); + return graph; }; describe('Euler Path', function() { - it('should compute Euler tour over the undirected graph', function() { - var graph = graphFromEdges(false, [[1, 2], - [1, 5], - [1, 7], - [1, 8], - [2, 3], - [2, 4], - [2, 5], - [3, 5], - [4, 6], - [4, 9], - [4, 10], - [5, 6], - [6, 9], - [6, 10], - [7, 8]]); - var trail = eulerPath(graph); - verifyEulerPath(graph, trail); - assert.equal(trail[0], trail.slice(-1)[0]); - }); - - it('should compute Euler walk over the undirected graph', function() { - var graph = graphFromEdges(false, [[1, 2], - [1, 5], - [1, 7], - [2, 3], - [2, 4], - [2, 5], - [3, 5], - [4, 6], - [4, 9], - [4, 10], - [5, 6], - [6, 9], - [6, 10], - [7, 8]]); - var trail = eulerPath(graph); - verifyEulerPath(graph, trail); - var endpoints = [trail[0], trail.slice(-1)[0]]; - endpoints.sort(); - assert.equal(endpoints[0], 1); - assert.equal(endpoints[1], 8); - }); - - it('should compute Euler tour over the directed graph', function() { - var graph = graphFromEdges(true, [[0, 1], - [1, 2], - [2, 0], - [0, 3], - [3, 4], - [4, 0], - [4, 1], - [1, 5], - [5, 6], - [6, 4]]); - var trail = eulerPath(graph); - verifyEulerPath(graph, trail); - assert.equal(trail[0], trail.slice(-1)[0]); - }); - - it('should compute Euler walk over the directed graph', function() { - var graph = graphFromEdges(true, [[5, 0], - [0, 2], - [2, 4], - [4, 0], - [1, 5], - [3, 1], - [5, 3]]); - var trail = eulerPath(graph); - assert.deepEqual(trail, [5, 3, 1, 5, 0, 2, 4, 0]); - }); - - it('should return single-vertex-trail for an isolated vertex', function() { - var graph = new Graph(); - graph.addVertex('loner'); - var trail = eulerPath(graph); - assert.deepEqual(trail, ['loner']); - }); - - it('should return empty trail for an empty graph', function() { - var graph = new Graph(); - var trail = eulerPath(graph); - assert.deepEqual(trail, []); - }); - - it('should raise an error if there is no Euler path', function() { - var graph = graphFromEdges(false, [[0, 1], [2, 3]]); - assert.throws(eulerPath.bind(graph)); - graph = graphFromEdges(false, [[0, 1], - [0, 2], - [0, 3]]); - assert.throws(eulerPath.bind(graph)); - graph = graphFromEdges(true, [[0, 1], [0, 2]]); - assert.throws(eulerPath.bind(graph)); - graph = graphFromEdges(true, [[1, 0], [2, 0]]); - assert.throws(eulerPath.bind(graph)); - graph = graphFromEdges(true, [[0, 1], + it('should compute Euler tour over the undirected graph', function() { + var graph = graphFromEdges(false, [[1, 2], + [1, 5], + [1, 7], + [1, 8], + [2, 3], + [2, 4], + [2, 5], + [3, 5], + [4, 6], + [4, 9], + [4, 10], + [5, 6], + [6, 9], + [6, 10], + [7, 8]]); + var trail = eulerPath(graph); + verifyEulerPath(graph, trail); + assert.equal(trail[0], trail.slice(-1)[0]); + }); + + it('should compute Euler walk over the undirected graph', function() { + var graph = graphFromEdges(false, [[1, 2], + [1, 5], + [1, 7], + [2, 3], + [2, 4], + [2, 5], + [3, 5], + [4, 6], + [4, 9], + [4, 10], + [5, 6], + [6, 9], + [6, 10], + [7, 8]]); + var trail = eulerPath(graph); + verifyEulerPath(graph, trail); + var endpoints = [trail[0], trail.slice(-1)[0]]; + endpoints.sort(); + assert.equal(endpoints[0], 1); + assert.equal(endpoints[1], 8); + }); + + it('should compute Euler tour over the directed graph', function() { + var graph = graphFromEdges(true, [[0, 1], [1, 2], - [2, 3], - [3, 0], - [3, 1]]); - assert.throws(eulerPath.bind(graph)); - }); + [2, 0], + [0, 3], + [3, 4], + [4, 0], + [4, 1], + [1, 5], + [5, 6], + [6, 4]]); + var trail = eulerPath(graph); + verifyEulerPath(graph, trail); + assert.equal(trail[0], trail.slice(-1)[0]); + }); + + it('should compute Euler walk over the directed graph', function() { + var graph = graphFromEdges(true, [[5, 0], + [0, 2], + [2, 4], + [4, 0], + [1, 5], + [3, 1], + [5, 3]]); + var trail = eulerPath(graph); + assert.deepEqual(trail, [5, 3, 1, 5, 0, 2, 4, 0]); + }); + + it('should return single-vertex-trail for an isolated vertex', function() { + var graph = new Graph(); + graph.addVertex('loner'); + var trail = eulerPath(graph); + assert.deepEqual(trail, ['loner']); + }); + + it('should return empty trail for an empty graph', function() { + var graph = new Graph(); + var trail = eulerPath(graph); + assert.deepEqual(trail, []); + }); + + it('should raise an error if there is no Euler path', function() { + var graph = graphFromEdges(false, [[0, 1], [2, 3]]); + assert.throws(eulerPath.bind(graph)); + graph = graphFromEdges(false, [[0, 1], + [0, 2], + [0, 3]]); + assert.throws(eulerPath.bind(graph)); + graph = graphFromEdges(true, [[0, 1], [0, 2]]); + assert.throws(eulerPath.bind(graph)); + graph = graphFromEdges(true, [[1, 0], [2, 0]]); + assert.throws(eulerPath.bind(graph)); + graph = graphFromEdges(true, [[0, 1], + [1, 2], + [2, 3], + [3, 0], + [3, 1]]); + assert.throws(eulerPath.bind(graph)); + }); }); From bbf2b12750661aabf11c0239204097741b2e7673 Mon Sep 17 00:00:00 2001 From: nitinsaroha Date: Fri, 6 Jun 2014 13:18:25 +0530 Subject: [PATCH 037/280] Fix indentation issue --- algorithms/sorting/selection_sort.js | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/algorithms/sorting/selection_sort.js b/algorithms/sorting/selection_sort.js index a46807d..61560e1 100644 --- a/algorithms/sorting/selection_sort.js +++ b/algorithms/sorting/selection_sort.js @@ -20,27 +20,25 @@ * IN THE SOFTWARE. */ 'use strict'; -var Comparator = require('../../util/comparator'); /** * Selection sort algorithm O(n^2) */ var selectionSort = function(a) { - var n = a.length; - for (var i = 0; i < n - 1; i++){ - var min = i; - - for (var j = i + 1; j < n; j++){ - if(a[min] > a[j]) - min = j; - } - if (min != i){ - var tmp = a[i]; - a[i] = a[min]; - a[min] = tmp; - } + var n = a.length; + for (var i = 0; i < n - 1; i++){ + var min = i; + for (var j = i + 1; j < n; j++){ + if(a[min] > a[j]) + min = j; + } + if (min != i){ + var tmp = a[i]; + a[i] = a[min]; + a[min] = tmp; } + } -return a; + return a; }; module.exports = selectionSort; \ No newline at end of file From 399eb4ee8095f2474bc912fa8ff567924b8d5421 Mon Sep 17 00:00:00 2001 From: nitinsaroha Date: Fri, 6 Jun 2014 13:38:24 +0530 Subject: [PATCH 038/280] Fix indentation issue --- algorithms/sorting/selection_sort.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/algorithms/sorting/selection_sort.js b/algorithms/sorting/selection_sort.js index 61560e1..09a53a8 100644 --- a/algorithms/sorting/selection_sort.js +++ b/algorithms/sorting/selection_sort.js @@ -26,16 +26,16 @@ var selectionSort = function(a) { var n = a.length; for (var i = 0; i < n - 1; i++){ - var min = i; - for (var j = i + 1; j < n; j++){ - if(a[min] > a[j]) - min = j; - } - if (min != i){ - var tmp = a[i]; - a[i] = a[min]; - a[min] = tmp; - } + var min = i; + for (var j = i + 1; j < n; j++){ + if(a[min] > a[j]) + min = j; + } + if (min != i){ + var tmp = a[i]; + a[i] = a[min]; + a[min] = tmp; + } } return a; From a7da7c8a5a194668bd66e496e13f6b85c7d875c1 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 6 Jun 2014 11:47:22 +0200 Subject: [PATCH 039/280] More style fixes --- .jshintrc | 1 + algorithms/graph/euler_path.js | 18 +++++++++--------- data_structures/bst.js | 4 ++-- package.json | 1 + test/algorithms/graph/euler_path.js | 26 +++++++++++++------------- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/.jshintrc b/.jshintrc index 958f8f6..360f591 100644 --- a/.jshintrc +++ b/.jshintrc @@ -11,6 +11,7 @@ "unused": true, "strict": true, "maxlen": 80, + "white": true, "trailing": true, "curly": false, "globals": { diff --git a/algorithms/graph/euler_path.js b/algorithms/graph/euler_path.js index b9290fc..acd0e71 100644 --- a/algorithms/graph/euler_path.js +++ b/algorithms/graph/euler_path.js @@ -32,21 +32,21 @@ var Graph = require('../../data_structures/graph'); * @param {Graph} Graph, must be connected and contain at least one vertex. * @return Object */ -var eulerEndpoints = function(graph) { +var eulerEndpoints = function (graph) { var rank = {}; // start -> rank = +1 // middle points -> rank = 0 // finish -> rank = -1 // Initialize ranks to be outdegrees of vertices. - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(function (vertex) { rank[vertex] = graph.neighbors(vertex).length; }); if (graph.directed) { // rank = outdegree - indegree - graph.vertices.forEach(function(vertex) { - graph.neighbors(vertex).forEach(function(neighbor) { + graph.vertices.forEach(function (vertex) { + graph.neighbors(vertex).forEach(function (neighbor) { rank[neighbor] -= 1; }); }); @@ -54,7 +54,7 @@ var eulerEndpoints = function(graph) { else { // Compute ranks from vertex degree parity values. var startChosen = false; - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(function (vertex) { rank[vertex] %= 2; if (rank[vertex]) { if (startChosen) { @@ -67,7 +67,7 @@ var eulerEndpoints = function(graph) { var start, finish; - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(function (vertex) { if (rank[vertex] == 1) { if (start !== undefined) { throw new Error('Duplicate start vertex.'); @@ -104,7 +104,7 @@ var eulerEndpoints = function(graph) { * @param {Graph} * @return Array */ -var eulerPath = function(graph) { +var eulerPath = function (graph) { if (!graph.vertices.length) { return []; } @@ -116,7 +116,7 @@ var eulerPath = function(graph) { graph.vertices.forEach(seen.addVertex.bind(seen)); (function dfs(vertex) { - graph.neighbors(vertex).forEach(function(neighbor) { + graph.neighbors(vertex).forEach(function (neighbor) { if (!seen.edge(vertex, neighbor)) { seen.addEdge(vertex, neighbor); dfs(neighbor); @@ -125,7 +125,7 @@ var eulerPath = function(graph) { }); }(endpoints.start)); - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(function (vertex) { if (seen.neighbors(vertex).length < graph.neighbors(vertex).length) { throw new Error('There is no euler path for a disconnected graph.'); } diff --git a/data_structures/bst.js b/data_structures/bst.js index e14fb5e..4e4336e 100644 --- a/data_structures/bst.js +++ b/data_structures/bst.js @@ -67,9 +67,9 @@ BST.prototype.insert = function (value, parent) { } var child = this._comparator.lessThan(value, parent.value) ? 'left' : 'right'; - if (parent[child]) + if (parent[child]) { this.insert(value, parent[child]); - else { + } else { parent[child] = new Node(value, parent); this._size++; } diff --git a/package.json b/package.json index 2abcea8..0959a30 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "coveralls": "^2.10.0", "istanbul": "^0.2.10", "jshint": "~2.4.4", + "jscs": "1.4.5", "mocha": "^1.20.0" }, "repository": { diff --git a/test/algorithms/graph/euler_path.js b/test/algorithms/graph/euler_path.js index a4c6240..11e68ac 100644 --- a/test/algorithms/graph/euler_path.js +++ b/test/algorithms/graph/euler_path.js @@ -27,35 +27,35 @@ var eulerPath = require('../../../algorithms/graph/euler_path'), assert = require('assert'); -var verifyEulerPath = function(graph, trail) { +var verifyEulerPath = function (graph, trail) { var visited = new Graph(graph.directed); graph.vertices.forEach(visited.addVertex.bind(visited)); - trail.slice(1).reduce(function(previous, current) { + trail.slice(1).reduce(function (previous, current) { assert(graph.edge(previous, current)); assert(!visited.edge(previous, current)); visited.addEdge(previous, current); return current; }, trail[0]); - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(function (vertex) { assert.equal(graph.neighbors(vertex).length, visited.neighbors(vertex).length); }); }; -var graphFromEdges = function(directed, edges) { +var graphFromEdges = function (directed, edges) { var graph = new Graph(directed); - edges.forEach(function(edge) { + edges.forEach(function (edge) { graph.addEdge(edge[0], edge[1]); }); return graph; }; -describe('Euler Path', function() { - it('should compute Euler tour over the undirected graph', function() { +describe('Euler Path', function () { + it('should compute Euler tour over the undirected graph', function () { var graph = graphFromEdges(false, [[1, 2], [1, 5], [1, 7], @@ -76,7 +76,7 @@ describe('Euler Path', function() { assert.equal(trail[0], trail.slice(-1)[0]); }); - it('should compute Euler walk over the undirected graph', function() { + it('should compute Euler walk over the undirected graph', function () { var graph = graphFromEdges(false, [[1, 2], [1, 5], [1, 7], @@ -99,7 +99,7 @@ describe('Euler Path', function() { assert.equal(endpoints[1], 8); }); - it('should compute Euler tour over the directed graph', function() { + it('should compute Euler tour over the directed graph', function () { var graph = graphFromEdges(true, [[0, 1], [1, 2], [2, 0], @@ -115,7 +115,7 @@ describe('Euler Path', function() { assert.equal(trail[0], trail.slice(-1)[0]); }); - it('should compute Euler walk over the directed graph', function() { + it('should compute Euler walk over the directed graph', function () { var graph = graphFromEdges(true, [[5, 0], [0, 2], [2, 4], @@ -127,20 +127,20 @@ describe('Euler Path', function() { assert.deepEqual(trail, [5, 3, 1, 5, 0, 2, 4, 0]); }); - it('should return single-vertex-trail for an isolated vertex', function() { + it('should return single-vertex-trail for an isolated vertex', function () { var graph = new Graph(); graph.addVertex('loner'); var trail = eulerPath(graph); assert.deepEqual(trail, ['loner']); }); - it('should return empty trail for an empty graph', function() { + it('should return empty trail for an empty graph', function () { var graph = new Graph(); var trail = eulerPath(graph); assert.deepEqual(trail, []); }); - it('should raise an error if there is no Euler path', function() { + it('should raise an error if there is no Euler path', function () { var graph = graphFromEdges(false, [[0, 1], [2, 3]]); assert.throws(eulerPath.bind(graph)); graph = graphFromEdges(false, [[0, 1], From bb8367f52bd96d103d683581d58aad22dbfa797a Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 6 Jun 2014 13:29:29 +0200 Subject: [PATCH 040/280] Allow non-string keys in hash tables --- data_structures/hash_table.js | 1 + test/data_structures/hash_table.js | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/data_structures/hash_table.js b/data_structures/hash_table.js index 5f5d66b..5f5cafc 100644 --- a/data_structures/hash_table.js +++ b/data_structures/hash_table.js @@ -43,6 +43,7 @@ function HashTable(initialCapacity) { * (The hash value of the empty string is zero.) */ HashTable.prototype.hash = function (s) { + if (typeof s !== 'string') s = JSON.stringify(s); var hash = 0; for (var i = 0; i < s.length; i++) { hash = ((hash << 5) - hash) + s.charCodeAt(i); diff --git a/test/data_structures/hash_table.js b/test/data_structures/hash_table.js index 7a93168..e214bc8 100644 --- a/test/data_structures/hash_table.js +++ b/test/data_structures/hash_table.js @@ -129,5 +129,15 @@ describe('Hash Table', function () { h.del('foo'); assert.equal(h.get('foo'), undefined); }); + + it('should allow non-string keys', function () { + var h = new HashTable(); + h.put(10, 5); + assert.equal(h.get(10), 5); + + var o = {a: 'foo', b: 'bar'}; + h.put(o, 'foo'); + assert.equal(h.get(o), 'foo'); + }); }); From e23e5b374c8077b0b02134c2ce2d37b8e0f9348b Mon Sep 17 00:00:00 2001 From: nitinsaroha Date: Fri, 6 Jun 2014 22:53:10 +0530 Subject: [PATCH 041/280] Added tests --- algorithms/sorting/selection_sort.js | 2 +- test/algorithms/sorting/selection_sort.js | 43 +++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 test/algorithms/sorting/selection_sort.js diff --git a/algorithms/sorting/selection_sort.js b/algorithms/sorting/selection_sort.js index 09a53a8..afe0868 100644 --- a/algorithms/sorting/selection_sort.js +++ b/algorithms/sorting/selection_sort.js @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014 Felipe Ribeiro + * Copyright (C) 2014 Nitin Saroha * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to diff --git a/test/algorithms/sorting/selection_sort.js b/test/algorithms/sorting/selection_sort.js new file mode 100644 index 0000000..e8c1494 --- /dev/null +++ b/test/algorithms/sorting/selection_sort.js @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2014 Nitin Saroha + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var selectionSort = require('../../../algorithms/sorting/selection_sort'), + assert = require('assert'); + +describe('Selection Sort', function () { + it('should sort the given array', function () { + assert.deepEqual(selectionSort([]), []); + assert.deepEqual(selectionSort([1]), [1]); + assert.deepEqual(selectionSort([2, 1]), [1, 2]); + assert.deepEqual(selectionSort([3, 1, 2]), [1, 2, 3]); + assert.deepEqual(selectionSort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual(selectionSort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual(selectionSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), + [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); + assert.deepEqual(selectionSort(['a','A','B','c','z','Z']), ['A','B','Z','a','c','z']); + assert.deepEqual(selectionSort(['real','madrid','the','best','club','in','the','world']), + ['best','club','in','madrid','real','the','the','world']); + + }); + +}); From adc9167d1e7b63bd7cc59d48da6ae142e71617d9 Mon Sep 17 00:00:00 2001 From: nitinsaroha Date: Fri, 6 Jun 2014 23:03:51 +0530 Subject: [PATCH 042/280] Fixed space errors --- algorithms/sorting/selection_sort.js | 10 +++++----- test/algorithms/sorting/selection_sort.js | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/algorithms/sorting/selection_sort.js b/algorithms/sorting/selection_sort.js index afe0868..94772b5 100644 --- a/algorithms/sorting/selection_sort.js +++ b/algorithms/sorting/selection_sort.js @@ -23,15 +23,15 @@ /** * Selection sort algorithm O(n^2) */ -var selectionSort = function(a) { +var selectionSort = function (a) { var n = a.length; - for (var i = 0; i < n - 1; i++){ + for (var i = 0; i < n - 1; i++) { var min = i; - for (var j = i + 1; j < n; j++){ - if(a[min] > a[j]) + for (var j = i + 1; j < n; j++) { + if (a[min] > a[j]) min = j; } - if (min != i){ + if (min != i) { var tmp = a[i]; a[i] = a[min]; a[min] = tmp; diff --git a/test/algorithms/sorting/selection_sort.js b/test/algorithms/sorting/selection_sort.js index e8c1494..9ed3e17 100644 --- a/test/algorithms/sorting/selection_sort.js +++ b/test/algorithms/sorting/selection_sort.js @@ -34,9 +34,8 @@ describe('Selection Sort', function () { assert.deepEqual(selectionSort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); assert.deepEqual(selectionSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); - assert.deepEqual(selectionSort(['a','A','B','c','z','Z']), ['A','B','Z','a','c','z']); - assert.deepEqual(selectionSort(['real','madrid','the','best','club','in','the','world']), - ['best','club','in','madrid','real','the','the','world']); + assert.deepEqual(selectionSort(['a', 'A', 'b', 'Z']), ['A', 'Z', 'a', 'b']); + assert.deepEqual(selectionSort(['The', 'special', 'one']), ['one', 'special', 'the']); }); From 8eca6d8c215dd1b24faecd7874dea6e68b8fcae1 Mon Sep 17 00:00:00 2001 From: nitinsaroha Date: Fri, 6 Jun 2014 23:09:11 +0530 Subject: [PATCH 043/280] Fixed space errors --- test/algorithms/sorting/selection_sort.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/algorithms/sorting/selection_sort.js b/test/algorithms/sorting/selection_sort.js index 9ed3e17..8eacf9b 100644 --- a/test/algorithms/sorting/selection_sort.js +++ b/test/algorithms/sorting/selection_sort.js @@ -35,7 +35,7 @@ describe('Selection Sort', function () { assert.deepEqual(selectionSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); assert.deepEqual(selectionSort(['a', 'A', 'b', 'Z']), ['A', 'Z', 'a', 'b']); - assert.deepEqual(selectionSort(['The', 'special', 'one']), ['one', 'special', 'the']); + assert.deepEqual(selectionSort(['hi', 'everybody']), ['everybody', 'hi']); }); From 3405da40622d0879088a96950c5ce8968512ded6 Mon Sep 17 00:00:00 2001 From: Gaurav Mittal Date: Sat, 7 Jun 2014 00:43:36 +0530 Subject: [PATCH 044/280] Improving efficiency of bubblesort. --- algorithms/sorting/bubble_sort.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/algorithms/sorting/bubble_sort.js b/algorithms/sorting/bubble_sort.js index ff851af..5dfb9be 100644 --- a/algorithms/sorting/bubble_sort.js +++ b/algorithms/sorting/bubble_sort.js @@ -26,9 +26,10 @@ var Comparator = require('../../util/comparator'); * Bubble sort algorithm O(n^2) */ var bubbleSort = function (a, comparatorFn) { - var comparator = new Comparator(comparatorFn), - n = a.length, - bound = n - 1; + var comparator = new Comparator(comparatorFn); + var n = a.length; + var bound = n - 1; + var check = 0; for (var i = 0; i < n - 1; i++) { var newbound = 0; for (var j = 0; j < bound; j++) { @@ -37,11 +38,13 @@ var bubbleSort = function (a, comparatorFn) { a[j] = a[j + 1]; a[j + 1] = tmp; newbound = j; + check = 1; } } + if (0 === check) + return a; bound = newbound; } - return a; }; From 531aaaed207ea07299e2fa9f2a788b5ee1e62173 Mon Sep 17 00:00:00 2001 From: tayllan Date: Fri, 6 Jun 2014 12:03:24 -0300 Subject: [PATCH 045/280] Radix Sort --- algorithms/sorting/radix_sort.js | 146 ++++++++++++++++++++++++++ main.js | 3 +- test/algorithms/sorting/radix_sort.js | 70 ++++++++++++ 3 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 algorithms/sorting/radix_sort.js create mode 100644 test/algorithms/sorting/radix_sort.js diff --git a/algorithms/sorting/radix_sort.js b/algorithms/sorting/radix_sort.js new file mode 100644 index 0000000..ed9791c --- /dev/null +++ b/algorithms/sorting/radix_sort.js @@ -0,0 +1,146 @@ +/** + * Copyright (C) 2014 Tayllan Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +/** + * Sorts an array of objects according to their 'key' property + * Every object inside the array MUST have the 'key' property with + * a integer value. + * + * Asymptotic Complexity: O(array.length * d), where 'd' represents + * the amount of digits in the larger key of the array + * + * @param Array + * @return Array + */ +var radixSort = function (array) { + var max = maximumKey(array); + var digitsMax = amountOfDigits(max); + + for (var i = 0; i < digitsMax; i++) { + array = auxiliaryCountingSort(array, i); + } + + return array; +}; + +/** + * Auxiliary sorting method for RadixSort + * Sorts an array of objects according to only one digit of + * their 'key' property. The digit to be sorted is determined + * by the 'mod' variable + * Every object inside the array MUST have the 'key' property with + * a integer value. + * + * Execution Time: (2 * array.length + 10) + * Asymptotic Complexity: O(array.length) + * + * @param Array + * @return Array + */ +var auxiliaryCountingSort = function (array, mod) { + var length = array.length; + var bucket = []; + + for (var i = 0; i < 10; i++) { + bucket[i] = []; + } + + for (i = 0; i < length; i++) { + var digit = parseInt((array[i].key / Math.pow(10, mod)).toFixed(mod)) % 10; + bucket[digit].push(array[i]); + } + + var pointer = 0; + + for (i = 0; i < 10; i++) { + var localLength = bucket[i].length; + + for (var j = 0; j < localLength; j++) { + array[pointer++] = bucket[i][j]; + } + } + + return array; +}; + +/** + * Finds the maximum key from an array of objects + * + * Asymptotic Complexity: O(array.length) + * + * @param Array + * @return Integer if array non-empty + * Undefined otherwise + */ +var maximumKey = function (array) { + var length = array.length; + + if (length > 0) { + var max = array[0].key; + + for (var i = 1; i < length; i++) { + if (array[i].key > max) { + max = array[i].key; + } + } + + return max; + } + else { + return undefined; + } +}; + +/** + * Returns the amount of digits contained in a number + * + * Asymptotic Complexity: O(d), where 'd' represents the + * amount of digits in the number + * + * @param Number + * @return Number + */ +var amountOfDigits = function (number) { + if (number === 0) { + return 1; + } + else { + var counter = 0; + + // For positive numbers + while (parseInt(number) > 0) { + number /= 10; + ++counter; + } + + // For negative numbers + while (parseInt(number) < 0) { + number /= 10; + ++counter; + } + + return counter; + } +}; + +module.exports = radixSort; diff --git a/main.js b/main.js index 08eac8f..fd91238 100644 --- a/main.js +++ b/main.js @@ -47,7 +47,8 @@ var lib = { heapSort: require('./algorithms/sorting/heap_sort'), mergeSort: require('./algorithms/sorting/merge_sort'), quicksort: require('./algorithms/sorting/quicksort'), - selectionSort: require('./algorithms/sorting/selection_sort') + selectionSort: require('./algorithms/sorting/selection_sort'), + radixSort: require('./algorithms/sorting/radix_sort') }, String: { editDistance: require('./algorithms/string/edit_distance'), diff --git a/test/algorithms/sorting/radix_sort.js b/test/algorithms/sorting/radix_sort.js new file mode 100644 index 0000000..132501f --- /dev/null +++ b/test/algorithms/sorting/radix_sort.js @@ -0,0 +1,70 @@ +/** + * Copyright (C) 2014 Tayllan Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"], to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var radixSort = require('../../../algorithms/sorting/radix_sort'), + assert = require('assert'); + +var firstObject = { + someProperty: 'The', + key: 88541234132 +}; + +var secondObject = { + someProperty: 'winter', + key: 90071992540992 +}; + +var thirdObject = { + someProperty: 'is', + key: 0 +}; + +var fourthObject = { + someProperty: 'coming', + key: 65234567, + anotherProperty: '!' +}; + +var array = [ + thirdObject, + fourthObject, + firstObject, + secondObject, + secondObject, + firstObject, + firstObject, + fourthObject +]; + +describe('Radix Sort', function () { + it('should sort the given array', function () { + array = radixSort(array); + + // Asserts that the array is truly sorted + assert.deepEqual(array.indexOf(thirdObject), 0); + assert.deepEqual(array.indexOf(fourthObject), 1); + assert.deepEqual(array.indexOf(firstObject), 3); + assert.deepEqual(array.indexOf(secondObject), 6); + assert.deepEqual(array.indexOf({key: 99}), -1); + }); +}); From 1797907bdfbf5ec2cbfd7a1c74621537dfcb0b35 Mon Sep 17 00:00:00 2001 From: tayllan Date: Fri, 6 Jun 2014 17:30:22 -0300 Subject: [PATCH 046/280] Depth First Search --- algorithms/graph/depth_first_search.js | 73 +++++++++++++++++++++ main.js | 1 + test/algorithms/graph/depth_first_search.js | 64 ++++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 algorithms/graph/depth_first_search.js create mode 100644 test/algorithms/graph/depth_first_search.js diff --git a/algorithms/graph/depth_first_search.js b/algorithms/graph/depth_first_search.js new file mode 100644 index 0000000..47d96fc --- /dev/null +++ b/algorithms/graph/depth_first_search.js @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2014 Tayllan Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"], to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var time = 0, + visitedNodes = {}, + finishingTimes = {}; + +/** + * Depth First Search for all the vertices in the graph + * Worst Case Complexity: O(V * E) + * + * @param {Object} + * @return {Object} representing the order in which the + * vertices are visited + */ +var dfsAdjacencyListStart = function (graph) { + graph.vertices.forEach(function (v) { + if (visitedNodes[v] !== true) { + dfsAdjacencyList(graph, v); + } + }); + + return finishingTimes; +}; + +/** + * Depth First Search for the vertices reachable from 'startNode' + * Worst Case Complexity: O(V * E) + * + * @param {Object} + * @param {Object} + * @return {Object} + */ +var dfsAdjacencyList = function (graph, startNode) { + visitedNodes[startNode] = true; + + graph.neighbors(startNode).forEach(function (v) { + if (visitedNodes[v] !== true) { + dfsAdjacencyList(graph, v); + } + }); + + finishingTimes[startNode] = time++; + + return finishingTimes; +}; + +var depthFirstSearch = { + dfsAdjacencyList: dfsAdjacencyList, + dfsAdjacencyListStart: dfsAdjacencyListStart +}; + +module.exports = depthFirstSearch; diff --git a/main.js b/main.js index fd91238..3241a50 100644 --- a/main.js +++ b/main.js @@ -28,6 +28,7 @@ var lib = { SPFA: require('./algorithms/graph/SPFA'), bellmanFord: require('./algorithms/graph/bellman_ford'), eulerPath: require('./algorithms/graph/euler_path'), + depthFirstSearch: require('./algorithms/graph/depth_first_search') }, Math: { fibonacci: require('./algorithms/math/fibonacci'), diff --git a/test/algorithms/graph/depth_first_search.js b/test/algorithms/graph/depth_first_search.js new file mode 100644 index 0000000..a8aed0a --- /dev/null +++ b/test/algorithms/graph/depth_first_search.js @@ -0,0 +1,64 @@ +/** + * Copyright (C) 2014 Tayllan Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"], to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var depthFirstSearch = require('../../../algorithms/graph/depth_first_search'), + Graph = require('../../../data_structures/graph'), + assert = require('assert'), + graph = new Graph(true); + +graph.addEdge('one', 'three'); +graph.addEdge('one', 'four'); +graph.addEdge('four', 'two'); +graph.addEdge('two', 'one'); +graph.addEdge('three', 'one'); +graph.addEdge('five', 'six'); + +describe('Depth First Search Algorithm', function () { + it('should visit only the nodes reachable from the node {one} (inclusive)', + function () { + var finishingTimes = depthFirstSearch.dfsAdjacencyList(graph, 'one'); + + assert.equal(finishingTimes.five, undefined); + assert.equal(finishingTimes.six, undefined); + + assert.equal(finishingTimes.one, 3); + assert.equal(finishingTimes.two, 1); + assert.equal(finishingTimes.three, 0); + assert.equal(finishingTimes.four, 2); + } + ); + + it('should visit all the nodes in the graph', + function () { + var finishingTimes = depthFirstSearch.dfsAdjacencyListStart(graph); + + assert.equal(finishingTimes.one, 3); + assert.equal(finishingTimes.two, 1); + assert.equal(finishingTimes.three, 0); + assert.equal(finishingTimes.four, 2); + assert.equal(finishingTimes.five, 5); + assert.equal(finishingTimes.six, 4); + } + ); +}); + From 10fdeb440045159a59275bf413f80694de8cdec3 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 6 Jun 2014 23:50:50 +0200 Subject: [PATCH 047/280] User boolean instead of integer in bubble sort check flag --- algorithms/sorting/bubble_sort.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/algorithms/sorting/bubble_sort.js b/algorithms/sorting/bubble_sort.js index 5dfb9be..e077824 100644 --- a/algorithms/sorting/bubble_sort.js +++ b/algorithms/sorting/bubble_sort.js @@ -29,7 +29,7 @@ var bubbleSort = function (a, comparatorFn) { var comparator = new Comparator(comparatorFn); var n = a.length; var bound = n - 1; - var check = 0; + var check = false; for (var i = 0; i < n - 1; i++) { var newbound = 0; for (var j = 0; j < bound; j++) { @@ -38,10 +38,10 @@ var bubbleSort = function (a, comparatorFn) { a[j] = a[j + 1]; a[j + 1] = tmp; newbound = j; - check = 1; + check = true; } } - if (0 === check) + if (!check) return a; bound = newbound; } From 5a6129b73d57ce29ea2cf6d32a04c6beec0c298a Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 6 Jun 2014 23:54:29 +0200 Subject: [PATCH 048/280] v0.4.0 Selection Sort, Radix Sort, DFS, Euler path, Knuth-Morris-Pratt --- CHANGELOG | 67 ++++++++++++++++++++++++++++++---------------------- package.json | 2 +- 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 77a6ca4..0941e11 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,58 +1,69 @@ CHANGELOG ========= +0.4.0 (2014-06-06) +* Sorting + * Selection Sort + * Radix Sort + +* Graphs + * DFS + * Euler path + +* String + * Knuth-Morris-Pratt 0.3.0 (2014-06-03) * Math -** Square root by Newton's method + * Square root by Newton's method * Data Structures -** Hash table + * Hash table * Sorting -** Insertion sort -** Heap sort -** Counting sort + * Insertion sort + * Heap sort + * Counting sort 0.2.0 (2014-06-01) * Graphs -** Shortest Path Faster Algorithm (#34) -** Bellman-Ford Shortest Path (#36) + * Shortest Path Faster Algorithm (#34) + * Bellman-Ford Shortest Path (#36) * Math -** Extended Euclidean Algorithm (#37) + * Extended Euclidean Algorithm (#37) * Strings -** Karp-Rabin String Matching (#35) + * Karp-Rabin String Matching (#35) 0.1.0 (2014-05-30) * Sorting -** Bubble Sort -** Quicksort -** Merge sort + * Bubble Sort + * Quicksort + * Merge sort * Graphs -** Dijkstra -** Topological Sort + * Dijkstra + * Topological Sort * Math -** Fibonacci -** Fisher-Yates -** Euclidean GCD + * Fibonacci + * Fisher-Yates + * Euclidean GCD * Search -** Binary Search -** Breadth first search (for BSTs) -** Depth first search (for BSTs) + * Binary Search + * Breadth first search (for BSTs) + * Depth first search (for BSTs) * String -** Levenshtein edit distance + * Levenshtein edit distance * Data Structures -** Binary Search Tree -** Graph -** Heap -** Linked list -** Priority Queue -** Queue -** Stack + * Binary Search Tree + * Graph + * Heap + * Linked list + * Priority Queue + * Queue + * Stack diff --git a/package.json b/package.json index 0959a30..b07e4a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.3.0", + "version": "0.4.0", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" From 3621c12fc30cd702b3f9288635c981be26649b63 Mon Sep 17 00:00:00 2001 From: eush77 Date: Sat, 7 Jun 2014 04:08:03 +0400 Subject: [PATCH 049/280] Huffman encoding/decoding (close #7) --- algorithms/string/huffman.js | 232 ++++++++++++++++++++++++++++++ main.js | 3 +- test/algorithms/string/huffman.js | 103 +++++++++++++ 3 files changed, 337 insertions(+), 1 deletion(-) create mode 100644 algorithms/string/huffman.js create mode 100644 test/algorithms/string/huffman.js diff --git a/algorithms/string/huffman.js b/algorithms/string/huffman.js new file mode 100644 index 0000000..018c921 --- /dev/null +++ b/algorithms/string/huffman.js @@ -0,0 +1,232 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + + +var huffman = {}; + + +/** + * Maximum block size used by functions "compress", "decompress". + * + * @const + */ +var MAX_BLOCK_SIZE = (-1 >>> 0).toString(2).length; + + +/** + * Compress 0-1 string to int32 array. + * + * @param {string} string + * @return {number[]} + */ +var compress = function (string) { + var blocks = []; + var currentBlock = 0, currentBlockSize = 0; + + string.split('').forEach(function (char) { + if (char == '0' || char == '1') { + currentBlock = (currentBlock << 1) | char; + } + else { + throw new Error('String must be binary (only 0s and 1s allowed).'); + } + currentBlockSize += 1; + + if (currentBlockSize == MAX_BLOCK_SIZE) { + blocks.push(currentBlock); + currentBlock = currentBlockSize = 0; + } + }); + + // Append last block size to the end. + if (currentBlockSize) { + blocks.push(currentBlock, currentBlockSize); + } + else { + blocks.push(MAX_BLOCK_SIZE); + } + + return blocks; +}; + + +/** + * Decompress int32 array back to 0-1 string. + * + * @param {number[]} array + * @return {string} + */ +var decompress = function (array) { + if (!array.length) { + return ''; + } + else if (array.length == 1) { + throw new Error('Compressed array must be either empty ' + + 'or at least 2 blocks big.'); + } + + var padding = new Array(MAX_BLOCK_SIZE + 1).join(0); + + var string = array.slice(0, -2).map(function (block) { + return (padding + (block >>> 0).toString(2)).slice(-padding.length); + }).join(''); + + // Append the last block. + var lastBlockSize = array.slice(-1)[0]; + var lastBlock = array.slice(-2)[0]; + string += (padding + (lastBlock >>> 0).toString(2)).slice(-lastBlockSize); + + return string; +}; + + +/** + * Apply Huffman encoding to a string. + * + * @param {string} string + * @param {boolean} [compressed=false] - Whether compress the string to bits. + * @return {{encoding: Object., value: string|number[]}} + */ +huffman.encode = function (string, compressed) { + if (!string.length) { + return { + encoding: {}, + value: (compressed ? [] : '') + }; + } + + var counter = {}; + string.split('').forEach(function (char) { + counter[char] = (counter[char] || 0) + 1; + }); + + var letters = Object.keys(counter).map(function (char) { + return { + char: char, + count: counter[char] + }; + }); + + var compare = function (a, b) { + return a.count - b.count; + }; + var less = function (a, b) { + return a && (b && (a.count < b.count) || !b); + }; + + letters.sort(compare); + + // Each time two least letters are merged into one, the result is pushing into + // this buffer. Since the letters are pushing in ascending order of frequency, + // no more sorting is ever required. + var buffer = []; + var lettersIndex = 0, bufferIndex = 0; + + var extractMinimum = function () { + return less(letters[lettersIndex], buffer[bufferIndex]) ? + letters[lettersIndex++] : buffer[bufferIndex++]; + }; + + for (var numLetters = letters.length; numLetters > 1; --numLetters) { + var a = extractMinimum(), b = extractMinimum(); + a.code = '0'; + b.code = '1'; + var union = { + count: a.count + b.count, + parts: [a, b] + }; + buffer.push(union); + } + + // At this point there is a single letter left. + var root = extractMinimum(); + root.code = (letters.length > 1) ? '' : '0'; + + // Unroll the code recursively in reverse. + (function unroll(parent) { + if (parent.parts) { + var a = parent.parts[0], b = parent.parts[1]; + a.code += parent.code; + b.code += parent.code; + unroll(a); + unroll(b); + } + }(root)); + + var encoding = letters.reduce(function (acc, letter) { + acc[letter.char] = letter.code.split('').reverse().join(''); + return acc; + }, {}); + + // Finally, apply the encoding to the given string. + var result = string.split('').map(function (char) { + return encoding[char]; + }).join(''); + + return { + encoding: encoding, + value: (compressed ? compress(result) : result) + }; +}; + + +/** + * Decode a Huffman-encoded string or compressed number sequence. + * + * @param {Object.} encoding - Maps characters to 0-1 sequences. + * @param {string|number[]} encodedString + * @return {string} Decoded string. + */ +huffman.decode = function (encoding, encodedString) { + if (Array.isArray(encodedString)) { + encodedString = decompress(encodedString); + } + + // We can make use of the fact that encoding mapping is always one-to-one + // and rely on the power of JS hashes instead of building hand-made FSMs. + var letterByCode = Object.keys(encoding).reduce(function (acc, letter) { + acc[encoding[letter]] = letter; + return acc; + }, {}); + + var decodedLetters = []; + + var unresolved = encodedString.split('').reduce(function (code, char) { + code += char; + var letter = letterByCode[code]; + if (letter) { + decodedLetters.push(letter); + code = ''; + } + return code; + }, ''); + + if (unresolved) { + throw new Error('Invalid string to decode.'); + } + + return decodedLetters.join(''); +}; + + +module.exports = huffman; diff --git a/main.js b/main.js index 2dd7533..70359e3 100644 --- a/main.js +++ b/main.js @@ -51,7 +51,8 @@ var lib = { String: { editDistance: require('./algorithms/string/edit_distance'), karpRabin: require('./algorithms/string/karp_rabin'), - knuthMorrisPratt: require('./algorithms/string/knuth_morris_pratt') + knuthMorrisPratt: require('./algorithms/string/knuth_morris_pratt'), + huffman: require('./algorithms/string/huffman'), }, DataStructure: { BST: require('./data_structures/bst'), diff --git a/test/algorithms/string/huffman.js b/test/algorithms/string/huffman.js new file mode 100644 index 0000000..83daecd --- /dev/null +++ b/test/algorithms/string/huffman.js @@ -0,0 +1,103 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var huffman = require('../../../algorithms/string/huffman'), + assert = require('assert'); + + +describe('Huffman', function () { + var messages = ['', 'a', 'b', 'hello', 'test', 'awwawwweeeqqq', + 'The seething sea ceaseth and thus' + + ' the seething sea sufficeth us.', + 'Shep Schwab shopped at Scott\'s Schnapps shop;' + + '\nOne shot of Scott\'s Schnapps stopped Schwab\'s watch.']; + for (var randomTestIndex = 0; randomTestIndex < 15; ++randomTestIndex) { + var length = Math.floor(Math.random() * 100 + 1); + var characters = []; + for (var charIndex = 0; charIndex < length; ++charIndex) { + var charCode = Math.floor(Math.random() * 10 + 'a'.charCodeAt()); + characters.push(String.fromCharCode(charCode)); + } + messages.push(characters.join('')); + } + + it('should decode previously encoded messages correctly', function () { + messages.forEach(function (message) { + var encoded = huffman.encode(message); + var decoded = huffman.decode(encoded.encoding, encoded.value); + assert.equal(message, decoded); + var encodedCompressed = huffman.encode(message, true); + var decodedCompressed = huffman.decode(encodedCompressed.encoding, + encodedCompressed.value); + assert.equal(message, decodedCompressed); + }); + }); + + it('should raise an error if it fails to decode', function () { + var badArgs = [[{}, '0'], + [{a: '0', b: '10', c: '11'}, '001']]; + badArgs.forEach(function (args) { + assert.throws(function () { + huffman.decode.apply(null, args); + }); + }); + }); + + it('should encode sample strings in the expected manner', function () { + assert.deepEqual(huffman.encode(''), {encoding: {}, value: ''}); + assert.deepEqual(huffman.encode('a'), {encoding: {a: '0'}, value: '0'}); + assert.deepEqual(huffman.encode('aaaaa'), {encoding: {a: '0'}, + value: '00000'}); + var result = huffman.encode('aabc'); + assert.equal(result.encoding.a.length, 1); + assert.equal(result.encoding.b.length, 2); + assert.equal(result.encoding.c.length, 2); + result = huffman.encode('abcdabcdabcdabcd'); + Object.keys(result.encoding).forEach(function (char) { + assert.equal(result.encoding[char].length, 2); + }); + assert.equal(result.value.length, 32); + }); + + it('should satisfy the entropy condition (H <= cost <= H+1)', function () { + messages.forEach(function (message) { + var frequencies = message.split('').reduce(function (acc, char) { + acc[char] = (acc[char] || 0) + 1; + return acc; + }, {}); + Object.keys(frequencies).forEach(function (char) { + frequencies[char] /= message.length; + }); + var entropy = Object.keys(frequencies).reduce(function (partial, char) { + var freq = frequencies[char]; + return partial - freq * Math.log(freq); + }, 0) / Math.log(2); + var encoding = huffman.encode(message).encoding; + var cost = Object.keys(encoding).reduce(function (partial, char) { + return partial + frequencies[char] * encoding[char].length; + }, 0); + assert(entropy <= cost); + assert(cost <= entropy + 1); + }); + }); +}); From d98b7d588e58ab013ebfbf08bf0d42f701c5e5da Mon Sep 17 00:00:00 2001 From: eush77 Date: Sat, 7 Jun 2014 04:55:48 +0400 Subject: [PATCH 050/280] Explicitly convert vertices to string --- data_structures/graph.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/graph.js b/data_structures/graph.js index 9de035b..f3cedf8 100644 --- a/data_structures/graph.js +++ b/data_structures/graph.js @@ -32,7 +32,7 @@ function Graph(directed) { } Graph.prototype.addVertex = function (v) { - this.vertices.push(v); + this.vertices.push('' + v); this.adjList[v] = {}; }; From 3f7b430219d5ff7b1dc18d4bbd34861847393e7f Mon Sep 17 00:00:00 2001 From: eush77 Date: Sat, 7 Jun 2014 19:21:01 +0400 Subject: [PATCH 051/280] Add reservoir sampling (close #18) --- algorithms/math/reservoir_sampling.js | 47 ++++++++++++++++++ main.js | 3 +- test/algorithms/math/reservoir_sampling.js | 55 ++++++++++++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 algorithms/math/reservoir_sampling.js create mode 100644 test/algorithms/math/reservoir_sampling.js diff --git a/algorithms/math/reservoir_sampling.js b/algorithms/math/reservoir_sampling.js new file mode 100644 index 0000000..1950691 --- /dev/null +++ b/algorithms/math/reservoir_sampling.js @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + + +/** + * Sample random elements from the array using reservoir algorithm. + * + * @param {Array} array + * @param {number} sampleSize + * @return {Array} + */ +var reservoirSampling = function (array, sampleSize) { + if (sampleSize > array.length) { + throw new Error('Sample size exceeds the total number of elements.'); + } + var reservoir = array.slice(0, sampleSize); + for (var i = sampleSize; i < array.length; ++i) { + var j = Math.floor(Math.random() * (i + 1)); + if (j < sampleSize) { + reservoir[j] = array[i]; + } + } + return reservoir; +}; + + +module.exports = reservoirSampling; diff --git a/main.js b/main.js index 65f9c21..99dac3a 100644 --- a/main.js +++ b/main.js @@ -35,7 +35,8 @@ var lib = { fisherYates: require('./algorithms/math/fisher_yates'), gcd: require('./algorithms/math/gcd'), extendedEuclidean: require('./algorithms/math/extended_euclidean'), - newtonSqrt: require('./algorithms/math/newton_sqrt') + newtonSqrt: require('./algorithms/math/newton_sqrt'), + reservoirSampling: require('./algorithms/math/reservoir_sampling'), }, Search: { bfs: require('./algorithms/searching/bfs'), diff --git a/test/algorithms/math/reservoir_sampling.js b/test/algorithms/math/reservoir_sampling.js new file mode 100644 index 0000000..915d4e0 --- /dev/null +++ b/test/algorithms/math/reservoir_sampling.js @@ -0,0 +1,55 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + + +var reservoirSampling = require('../../../algorithms/math/reservoir_sampling'), + assert = require('assert'); + + +describe('Reservoir Sampling', function () { + var array = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + + it('should sample K distinct values from the array', function () { + var sample = reservoirSampling(array, 5); + assert.equal(sample.length, 5); + var seen = {}; + array.forEach(function (value) { + assert(!seen[value]); + assert(array.indexOf(value) >= 0); + seen[value] = true; + }); + }); + + it('should work in corner cases', function () { + assert.deepEqual(reservoirSampling(array, 0), []); + assert.deepEqual(reservoirSampling([], 0), []); + var fullSample = reservoirSampling(array, array.length); + assert.deepEqual(fullSample.sort(), array); + }); + + it('should raise an error if asked for too many elements', function () { + assert.throws(function () { + reservoirSampling(array, array.length + 1); + }); + }); +}); From bed2f94f126aa29619502f61dce685012ec1e247 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Sun, 8 Jun 2014 17:33:54 -0400 Subject: [PATCH 052/280] Iterative and recursive implementations of power set --- algorithms/math/power_set.js | 90 ++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 algorithms/math/power_set.js diff --git a/algorithms/math/power_set.js b/algorithms/math/power_set.js new file mode 100644 index 0000000..79c582c --- /dev/null +++ b/algorithms/math/power_set.js @@ -0,0 +1,90 @@ +/** + * Copyright (C) 2014 Felipe Ribeiro + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/* + * Iterative and recursive implementations of power set + * + * @author Joshua Curl + */ + +'use strict'; + +/* + * Iterative power set calculation + */ +var powerSetIterative = function (array) { + var powerSet = []; + var cache = []; + + for(var i = 0; i < array.length; i++) { + cache[i] = true; + } + + for(var i = 0; i < Math.pow(2, array.length); i++) { + + powerSet.push([]); + + for(var j = 0; j < array.length; j++) { + if(i % Math.pow(2, j) == 0) + { + cache[j] = !cache[j]; + } + } + + array.forEach(function(elem, index) { + if(cache[index]) { + powerSet[i].push(elem); + } + }); + } + + return powerSet; +}; + +/* + * Recursive power set calculation + */ +var powerSetRecursive = function (array) { + if(array.length == 1) { + return [ [], [ array[0] ] ]; + } + else { + var powerSet = []; + var firstElem = array[0]; + + array.splice(0, 1); + + powerSetRecursive(array).forEach(function(elem, index) { + powerSet.push(elem); + var withFirstElem = [ firstElem ]; + withFirstElem.push.apply(withFirstElem, elem); + powerSet.push(withFirstElem); + }); + + return powerSet; + } +}; + +// Use powerSetIterative as the default implementation +var powerSet = powerSetIterative; +powerSet.recursive = powerSetRecursive; +module.exports = powerSet; From 70323f56c49719cb0500bc8c45790498c9617648 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Sun, 8 Jun 2014 17:44:39 -0400 Subject: [PATCH 053/280] Fixed case of empty array --- algorithms/math/power_set.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/algorithms/math/power_set.js b/algorithms/math/power_set.js index 79c582c..3af361b 100644 --- a/algorithms/math/power_set.js +++ b/algorithms/math/power_set.js @@ -32,6 +32,11 @@ * Iterative power set calculation */ var powerSetIterative = function (array) { + + if(array.length == 0) { + return []; + } + var powerSet = []; var cache = []; @@ -64,7 +69,10 @@ var powerSetIterative = function (array) { * Recursive power set calculation */ var powerSetRecursive = function (array) { - if(array.length == 1) { + if(array.length == 0) { + return []; + } + else if(array.length == 1) { return [ [], [ array[0] ] ]; } else { From 713c6f65f1329a5a7a12182813c18b12ab4539b1 Mon Sep 17 00:00:00 2001 From: anaran Date: Mon, 9 Jun 2014 13:22:31 +0200 Subject: [PATCH 054/280] Indentation and jsdoc fixes driven by jscs. --- algorithms/string/knuth_morris_pratt.js | 6 +- data_structures/linked_list.js | 10 +- test/algorithms/graph/euler_path.js | 120 ++++++++++++---------- test/algorithms/graph/topological_sort.js | 6 +- util/comparator.js | 2 +- 5 files changed, 79 insertions(+), 65 deletions(-) diff --git a/algorithms/string/knuth_morris_pratt.js b/algorithms/string/knuth_morris_pratt.js index b8f6f99..91ce9a4 100644 --- a/algorithms/string/knuth_morris_pratt.js +++ b/algorithms/string/knuth_morris_pratt.js @@ -30,9 +30,9 @@ * * Asymptotic Complexity: O(text.length) * - * @param {Array} of Numbers, Strings or Characters + * @param {Array} text of Numbers, Strings or Characters * or {String} - * @param {Array} of Numbers, Strings or Characters + * @param {Array} pattern of Numbers, Strings or Characters * or {String} * @return {Number} */ @@ -71,7 +71,7 @@ var knuthMorrisPratt = function (text, pattern) { * * Asymptotic Complexity: O(pattern.length) * - * @param {Array} of Numbers, Strings or Characters + * @param {Array} pattern of Numbers, Strings or Characters * or {String} * @return {Array} of Integers */ diff --git a/data_structures/linked_list.js b/data_structures/linked_list.js index 48375b4..7130a7b 100644 --- a/data_structures/linked_list.js +++ b/data_structures/linked_list.js @@ -59,8 +59,8 @@ LinkedList.prototype.isEmpty = function () { /** * Adds the element to the end of the list or to the desired index * - * @param misc - * @param Number + * @param { Object } n + * @param { Number } index */ LinkedList.prototype.add = function (n, index) { if (index > this.length || index < 0) { @@ -102,7 +102,7 @@ LinkedList.prototype.add = function (n, index) { /** * Return the value associated to the Node on the given index * - * @param Number + * @param { Number } index * @return misc */ LinkedList.prototype.get = function (index) { @@ -112,7 +112,7 @@ LinkedList.prototype.get = function (index) { /** * O(n) get * - * @param Number + * @param { Number } index * @return Node */ LinkedList.prototype.getNode = function (index) { @@ -131,7 +131,7 @@ LinkedList.prototype.getNode = function (index) { /** * Delete the element in the indexth position * - * @param Number + * @param { Number } index */ LinkedList.prototype.del = function (index) { if (index >= this.length || index < 0) { diff --git a/test/algorithms/graph/euler_path.js b/test/algorithms/graph/euler_path.js index 11e68ac..de48f8a 100644 --- a/test/algorithms/graph/euler_path.js +++ b/test/algorithms/graph/euler_path.js @@ -56,41 +56,45 @@ var graphFromEdges = function (directed, edges) { describe('Euler Path', function () { it('should compute Euler tour over the undirected graph', function () { - var graph = graphFromEdges(false, [[1, 2], - [1, 5], - [1, 7], - [1, 8], - [2, 3], - [2, 4], - [2, 5], - [3, 5], - [4, 6], - [4, 9], - [4, 10], - [5, 6], - [6, 9], - [6, 10], - [7, 8]]); + var graph = graphFromEdges(false, [ + [1, 2], + [1, 5], + [1, 7], + [1, 8], + [2, 3], + [2, 4], + [2, 5], + [3, 5], + [4, 6], + [4, 9], + [4, 10], + [5, 6], + [6, 9], + [6, 10], + [7, 8] + ]); var trail = eulerPath(graph); verifyEulerPath(graph, trail); assert.equal(trail[0], trail.slice(-1)[0]); }); it('should compute Euler walk over the undirected graph', function () { - var graph = graphFromEdges(false, [[1, 2], - [1, 5], - [1, 7], - [2, 3], - [2, 4], - [2, 5], - [3, 5], - [4, 6], - [4, 9], - [4, 10], - [5, 6], - [6, 9], - [6, 10], - [7, 8]]); + var graph = graphFromEdges(false, [ + [1, 2], + [1, 5], + [1, 7], + [2, 3], + [2, 4], + [2, 5], + [3, 5], + [4, 6], + [4, 9], + [4, 10], + [5, 6], + [6, 9], + [6, 10], + [7, 8] + ]); var trail = eulerPath(graph); verifyEulerPath(graph, trail); var endpoints = [trail[0], trail.slice(-1)[0]]; @@ -100,29 +104,33 @@ describe('Euler Path', function () { }); it('should compute Euler tour over the directed graph', function () { - var graph = graphFromEdges(true, [[0, 1], - [1, 2], - [2, 0], - [0, 3], - [3, 4], - [4, 0], - [4, 1], - [1, 5], - [5, 6], - [6, 4]]); + var graph = graphFromEdges(true, [ + [0, 1], + [1, 2], + [2, 0], + [0, 3], + [3, 4], + [4, 0], + [4, 1], + [1, 5], + [5, 6], + [6, 4] + ]); var trail = eulerPath(graph); verifyEulerPath(graph, trail); assert.equal(trail[0], trail.slice(-1)[0]); }); it('should compute Euler walk over the directed graph', function () { - var graph = graphFromEdges(true, [[5, 0], - [0, 2], - [2, 4], - [4, 0], - [1, 5], - [3, 1], - [5, 3]]); + var graph = graphFromEdges(true, [ + [5, 0], + [0, 2], + [2, 4], + [4, 0], + [1, 5], + [3, 1], + [5, 3] + ]); var trail = eulerPath(graph); assert.deepEqual(trail, [5, 3, 1, 5, 0, 2, 4, 0]); }); @@ -143,19 +151,23 @@ describe('Euler Path', function () { it('should raise an error if there is no Euler path', function () { var graph = graphFromEdges(false, [[0, 1], [2, 3]]); assert.throws(eulerPath.bind(graph)); - graph = graphFromEdges(false, [[0, 1], - [0, 2], - [0, 3]]); + graph = graphFromEdges(false, [ + [0, 1], + [0, 2], + [0, 3] + ]); assert.throws(eulerPath.bind(graph)); graph = graphFromEdges(true, [[0, 1], [0, 2]]); assert.throws(eulerPath.bind(graph)); graph = graphFromEdges(true, [[1, 0], [2, 0]]); assert.throws(eulerPath.bind(graph)); - graph = graphFromEdges(true, [[0, 1], - [1, 2], - [2, 3], - [3, 0], - [3, 1]]); + graph = graphFromEdges(true, [ + [0, 1], + [1, 2], + [2, 3], + [3, 0], + [3, 1] + ]); assert.throws(eulerPath.bind(graph)); }); }); diff --git a/test/algorithms/graph/topological_sort.js b/test/algorithms/graph/topological_sort.js index aa9a059..6ef2a32 100644 --- a/test/algorithms/graph/topological_sort.js +++ b/test/algorithms/graph/topological_sort.js @@ -59,7 +59,9 @@ describe('Topological Sort', function () { var stack = topologicalSort(graph); var a = []; while (!stack.isEmpty()) a.push(stack.pop()); - assert.deepEqual(a, ['underwear', 'pants', 'socks', 'shoes', - 'watch', 'shirt', 'tie', 'belt', 'jacket']); + assert.deepEqual(a, [ + 'underwear', 'pants', 'socks', 'shoes', + 'watch', 'shirt', 'tie', 'belt', 'jacket' + ]); }); }); diff --git a/util/comparator.js b/util/comparator.js index 037fc5e..e7e04af 100644 --- a/util/comparator.js +++ b/util/comparator.js @@ -27,7 +27,7 @@ * If the function is not passed, it will use the default * compare signs (<, > and ==) * - * @param Function + * @param { Function } compareFn */ function Comparator(compareFn) { if (compareFn) { From 77357a8050a15fa101017c338024514459e70a04 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Tue, 10 Jun 2014 20:31:42 -0400 Subject: [PATCH 055/280] Added tests for power set --- algorithms/math/power_set.js | 21 ++--- test/algorithms/math/power_set.js | 148 ++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+), 11 deletions(-) create mode 100644 test/algorithms/math/power_set.js diff --git a/algorithms/math/power_set.js b/algorithms/math/power_set.js index 3af361b..46f928e 100644 --- a/algorithms/math/power_set.js +++ b/algorithms/math/power_set.js @@ -33,7 +33,7 @@ */ var powerSetIterative = function (array) { - if(array.length == 0) { + if(array.length === 0) { return []; } @@ -44,22 +44,21 @@ var powerSetIterative = function (array) { cache[i] = true; } - for(var i = 0; i < Math.pow(2, array.length); i++) { + for(i = 0; i < Math.pow(2, array.length); i++) { powerSet.push([]); for(var j = 0; j < array.length; j++) { - if(i % Math.pow(2, j) == 0) - { + + if(i % Math.pow(2, j) === 0) { cache[j] = !cache[j]; } - } - array.forEach(function(elem, index) { - if(cache[index]) { - powerSet[i].push(elem); + if(cache[j]) { + powerSet[i].push(array[j]); } - }); + + } } return powerSet; @@ -69,7 +68,7 @@ var powerSetIterative = function (array) { * Recursive power set calculation */ var powerSetRecursive = function (array) { - if(array.length == 0) { + if(array.length === 0) { return []; } else if(array.length == 1) { @@ -81,7 +80,7 @@ var powerSetRecursive = function (array) { array.splice(0, 1); - powerSetRecursive(array).forEach(function(elem, index) { + powerSetRecursive(array).forEach(function(elem) { powerSet.push(elem); var withFirstElem = [ firstElem ]; withFirstElem.push.apply(withFirstElem, elem); diff --git a/test/algorithms/math/power_set.js b/test/algorithms/math/power_set.js new file mode 100644 index 0000000..b8eea3b --- /dev/null +++ b/test/algorithms/math/power_set.js @@ -0,0 +1,148 @@ +/* +* Copyright (C) 2014 Felipe Ribeiro +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ +'use strict'; + +var powerSet = require('../../../algorithms/math/power_set'), + assert = require('assert'); + +function testArrayEqual(a, b) { + var arrayEqual = true; + a.forEach(function(elem, index) { + if(a[index] != b[index]) { + arrayEqual = false; + } + }); + return arrayEqual && a.length === b.length; +} + +function testArrayInArray(a, b) { + var arrayInArray = false; + b.forEach(function(array) { + if(testArrayEqual(a, array)) { + arrayInArray = true; + } + }); + return arrayInArray; +} + +describe('Power set', function () { + describe('#iterative()', function () { + it('should return the right elements of power set', function () { + var zeroElementTest = powerSet([]); + assert(zeroElementTest.length === 0); + + var oneElementTest = powerSet([0]); + assert(testArrayInArray([], oneElementTest)); + assert(testArrayInArray([0], oneElementTest)); + assert(oneElementTest.length === 2); + + var twoElementTest = powerSet([0, 1]); + assert(testArrayInArray([], twoElementTest)); + assert(testArrayInArray([0], twoElementTest)); + assert(testArrayInArray([1], twoElementTest)); + assert(testArrayInArray([0, 1], twoElementTest)); + assert(twoElementTest.length === 4); + + var threeElementTest = powerSet([0, 1, 2]); + assert(testArrayInArray([], threeElementTest)); + assert(testArrayInArray([0], threeElementTest)); + assert(testArrayInArray([1], threeElementTest)); + assert(testArrayInArray([2], threeElementTest)); + assert(testArrayInArray([0, 1], threeElementTest)); + assert(testArrayInArray([0, 2], threeElementTest)); + assert(testArrayInArray([1, 2], threeElementTest)); + assert(testArrayInArray([0, 1, 2], threeElementTest)); + assert(testArrayInArray([0, 1], threeElementTest)); + assert(threeElementTest.length === 8); + + var fourElementTest = powerSet([0, 1, 2, 3]); + assert(testArrayInArray([], fourElementTest)); + assert(testArrayInArray([0], fourElementTest)); + assert(testArrayInArray([1], fourElementTest)); + assert(testArrayInArray([2], fourElementTest)); + assert(testArrayInArray([3], fourElementTest)); + assert(testArrayInArray([0, 1], fourElementTest)); + assert(testArrayInArray([0, 2], fourElementTest)); + assert(testArrayInArray([0, 3], fourElementTest)); + assert(testArrayInArray([1, 2], fourElementTest)); + assert(testArrayInArray([1, 3], fourElementTest)); + assert(testArrayInArray([2, 3], fourElementTest)); + assert(testArrayInArray([0, 1, 2], fourElementTest)); + assert(testArrayInArray([0, 1, 3], fourElementTest)); + assert(testArrayInArray([0, 2, 3], fourElementTest)); + assert(testArrayInArray([1, 2, 3], fourElementTest)); + assert(testArrayInArray([0, 1, 2, 3], fourElementTest)); + assert(fourElementTest.length === 16); + + }); + }); + + describe('#recursive()', function () { + it('should return the right elements of power set', function () { + var zeroElementTest = powerSet.recursive([]); + assert(zeroElementTest.length === 0); + + var oneElementTest = powerSet.recursive([0]); + assert(testArrayInArray([], oneElementTest)); + assert(testArrayInArray([0], oneElementTest)); + assert(oneElementTest.length === 2); + + var twoElementTest = powerSet.recursive([0, 1]); + assert(testArrayInArray([], twoElementTest)); + assert(testArrayInArray([0], twoElementTest)); + assert(testArrayInArray([1], twoElementTest)); + assert(testArrayInArray([0, 1], twoElementTest)); + assert(twoElementTest.length === 4); + + var threeElementTest = powerSet.recursive([0, 1, 2]); + assert(testArrayInArray([], threeElementTest)); + assert(testArrayInArray([0], threeElementTest)); + assert(testArrayInArray([1], threeElementTest)); + assert(testArrayInArray([2], threeElementTest)); + assert(testArrayInArray([0, 1], threeElementTest)); + assert(testArrayInArray([0, 2], threeElementTest)); + assert(testArrayInArray([1, 2], threeElementTest)); + assert(testArrayInArray([0, 1, 2], threeElementTest)); + assert(testArrayInArray([0, 1], threeElementTest)); + assert(threeElementTest.length === 8); + + var fourElementTest = powerSet.recursive([0, 1, 2, 3]); + assert(testArrayInArray([], fourElementTest)); + assert(testArrayInArray([0], fourElementTest)); + assert(testArrayInArray([1], fourElementTest)); + assert(testArrayInArray([2], fourElementTest)); + assert(testArrayInArray([3], fourElementTest)); + assert(testArrayInArray([0, 1], fourElementTest)); + assert(testArrayInArray([0, 2], fourElementTest)); + assert(testArrayInArray([0, 3], fourElementTest)); + assert(testArrayInArray([1, 2], fourElementTest)); + assert(testArrayInArray([1, 3], fourElementTest)); + assert(testArrayInArray([2, 3], fourElementTest)); + assert(testArrayInArray([0, 1, 2], fourElementTest)); + assert(testArrayInArray([0, 1, 3], fourElementTest)); + assert(testArrayInArray([0, 2, 3], fourElementTest)); + assert(testArrayInArray([1, 2, 3], fourElementTest)); + assert(testArrayInArray([0, 1, 2, 3], fourElementTest)); + assert(fourElementTest.length === 16); + }); + }); +}); From fc85e4ae39780fedd4244282cd418689777a1bfa Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Wed, 11 Jun 2014 22:23:43 -0400 Subject: [PATCH 056/280] Least common subsequence --- algorithms/math/power_set.js | 6 +- algorithms/string/least_common_subsequence.js | 85 +++++++++++++++++++ 2 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 algorithms/string/least_common_subsequence.js diff --git a/algorithms/math/power_set.js b/algorithms/math/power_set.js index 46f928e..9e9d57d 100644 --- a/algorithms/math/power_set.js +++ b/algorithms/math/power_set.js @@ -20,7 +20,7 @@ * IN THE SOFTWARE. */ -/* +/** * Iterative and recursive implementations of power set * * @author Joshua Curl @@ -28,7 +28,7 @@ 'use strict'; -/* +/** * Iterative power set calculation */ var powerSetIterative = function (array) { @@ -64,7 +64,7 @@ var powerSetIterative = function (array) { return powerSet; }; -/* +/** * Recursive power set calculation */ var powerSetRecursive = function (array) { diff --git a/algorithms/string/least_common_subsequence.js b/algorithms/string/least_common_subsequence.js new file mode 100644 index 0000000..c009553 --- /dev/null +++ b/algorithms/string/least_common_subsequence.js @@ -0,0 +1,85 @@ +/** + * Copyright (C) 2014 Felipe Ribeiro + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * Implementation of least common subsequence + * + * @author Joshua Curl + */ + +'use strict'; + +/** + * Implementation via dynamic programming + */ +var leastCommonSubsequence = function (s1, s2) { + // Multidimensional array for dynamic programming algorithm + var cache = []; + + // First column and row are initialized with zeroes + for(var i = 0; i < s1.length + 1; i++) { + cache[i] = []; + cache[i][0] = 0; + } + for(var i = 0; i < s2.length + 1; i++) { + cache[0][i] = 0; + } + + // Fill in the cache + for(var i = 1; i < s1.length + 1; i++) { + for(var j = 1; j < s2.length + 1; j++) { + if(s1[i - 1] == s2[j - 1]) { + var new_value = cache[i - 1][j - 1] + 1; + cache[i][j] = new_value; + } + else { + cache[i][j] = Math.max(cache[i][j - 1], cache[i - 1][j]); + } + } + } + + // Build LCS from cache + i = s1.length; + j = s2.length; + var lcs = ''; + + while(cache[i][j] !== 0) { + if(s1[i - 1] === s2[j - 1]){ + lcs += s1[i - 1]; + i--; + j--; + } + else { + if(cache[i - 1][j] > cache[i][j - 1]) { + i--; + } + else { + j--; + } + } + } + + // LCS is built in reverse, return reversed string + return lcs.split('').reverse().join(''); +} + +module.exports = leastCommonSubsequence; From 308a6a64b101db398719c9e2dfccccb306373347 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Wed, 11 Jun 2014 22:31:38 -0400 Subject: [PATCH 057/280] And by that I meant longest common subsequence --- ..._common_subsequence.js => longest_common_subsequence.js} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename algorithms/string/{least_common_subsequence.js => longest_common_subsequence.js} (94%) diff --git a/algorithms/string/least_common_subsequence.js b/algorithms/string/longest_common_subsequence.js similarity index 94% rename from algorithms/string/least_common_subsequence.js rename to algorithms/string/longest_common_subsequence.js index c009553..25fc898 100644 --- a/algorithms/string/least_common_subsequence.js +++ b/algorithms/string/longest_common_subsequence.js @@ -21,7 +21,7 @@ */ /** - * Implementation of least common subsequence + * Implementation of longest common subsequence * * @author Joshua Curl */ @@ -31,7 +31,7 @@ /** * Implementation via dynamic programming */ -var leastCommonSubsequence = function (s1, s2) { +var longestCommonSubsequence = function (s1, s2) { // Multidimensional array for dynamic programming algorithm var cache = []; @@ -82,4 +82,4 @@ var leastCommonSubsequence = function (s1, s2) { return lcs.split('').reverse().join(''); } -module.exports = leastCommonSubsequence; +module.exports = longestCommonSubsequence; From e3050622239dde1e869eba6db9a33a7d151d4cc9 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Wed, 11 Jun 2014 23:05:15 -0400 Subject: [PATCH 058/280] Some basic tests for longest common subsequence --- algorithms/math/power_set.js | 2 +- .../string/longest_common_subsequence.js | 18 +++++----- test/algorithms/math/power_set.js | 2 +- .../string/longest_common_subseqence.js | 36 +++++++++++++++++++ 4 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 test/algorithms/string/longest_common_subseqence.js diff --git a/algorithms/math/power_set.js b/algorithms/math/power_set.js index 9e9d57d..d7286d1 100644 --- a/algorithms/math/power_set.js +++ b/algorithms/math/power_set.js @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014 Felipe Ribeiro + * Copyright (C) 2014 Joshua Curl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to diff --git a/algorithms/string/longest_common_subsequence.js b/algorithms/string/longest_common_subsequence.js index 25fc898..d1da646 100644 --- a/algorithms/string/longest_common_subsequence.js +++ b/algorithms/string/longest_common_subsequence.js @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014 Felipe Ribeiro + * Copyright (C) 2014 Joshua Curl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -35,21 +35,23 @@ var longestCommonSubsequence = function (s1, s2) { // Multidimensional array for dynamic programming algorithm var cache = []; + var i, j; + // First column and row are initialized with zeroes - for(var i = 0; i < s1.length + 1; i++) { + for(i = 0; i < s1.length + 1; i++) { cache[i] = []; cache[i][0] = 0; } - for(var i = 0; i < s2.length + 1; i++) { + for(i = 0; i < s2.length + 1; i++) { cache[0][i] = 0; } // Fill in the cache - for(var i = 1; i < s1.length + 1; i++) { - for(var j = 1; j < s2.length + 1; j++) { + for(i = 1; i < s1.length + 1; i++) { + for(j = 1; j < s2.length + 1; j++) { if(s1[i - 1] == s2[j - 1]) { - var new_value = cache[i - 1][j - 1] + 1; - cache[i][j] = new_value; + var newValue = cache[i - 1][j - 1] + 1; + cache[i][j] = newValue; } else { cache[i][j] = Math.max(cache[i][j - 1], cache[i - 1][j]); @@ -80,6 +82,6 @@ var longestCommonSubsequence = function (s1, s2) { // LCS is built in reverse, return reversed string return lcs.split('').reverse().join(''); -} +}; module.exports = longestCommonSubsequence; diff --git a/test/algorithms/math/power_set.js b/test/algorithms/math/power_set.js index b8eea3b..591386e 100644 --- a/test/algorithms/math/power_set.js +++ b/test/algorithms/math/power_set.js @@ -1,5 +1,5 @@ /* -* Copyright (C) 2014 Felipe Ribeiro +* Copyright (C) 2014 Joshua Curl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to diff --git a/test/algorithms/string/longest_common_subseqence.js b/test/algorithms/string/longest_common_subseqence.js new file mode 100644 index 0000000..5528328 --- /dev/null +++ b/test/algorithms/string/longest_common_subseqence.js @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2014 Joshua Curl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var directory = '../../../algorithms/string'; +var filename = '/longest_common_subsequence'; +var longestCommonSubsequence = require([directory, filename].join('')), + assert = require('assert'); + +describe('Longest common subsequence', function () { + it('should return the proper longest common subsequence', function () { + assert.equal('', longestCommonSubsequence('', '')); + assert.equal('', longestCommonSubsequence('', 'aaa')); + assert.equal('', longestCommonSubsequence('aaa', '')); + assert.equal('aaa', longestCommonSubsequence('aaa', 'aaa')); + }); +}); From a2c41177917702ac4586ed1b9a17a8139dea4f8c Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Tue, 17 Jun 2014 20:00:32 -0400 Subject: [PATCH 059/280] Added a few more tests for longest common subsequence --- test/algorithms/string/longest_common_subseqence.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/algorithms/string/longest_common_subseqence.js b/test/algorithms/string/longest_common_subseqence.js index 5528328..1704753 100644 --- a/test/algorithms/string/longest_common_subseqence.js +++ b/test/algorithms/string/longest_common_subseqence.js @@ -21,8 +21,8 @@ */ 'use strict'; -var directory = '../../../algorithms/string'; -var filename = '/longest_common_subsequence'; +var directory = '../../../algorithms/string/'; +var filename = 'longest_common_subsequence'; var longestCommonSubsequence = require([directory, filename].join('')), assert = require('assert'); @@ -32,5 +32,7 @@ describe('Longest common subsequence', function () { assert.equal('', longestCommonSubsequence('', 'aaa')); assert.equal('', longestCommonSubsequence('aaa', '')); assert.equal('aaa', longestCommonSubsequence('aaa', 'aaa')); + assert.equal('mjau', longestCommonSubsequence('xmjyauz', 'mzjawxu')); + assert.equal('hman', longestCommonSubsequence('human', 'chimpanzee')); }); }); From bb814ca004968494e38fe6fcd3be1a06b48094ed Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sun, 22 Jun 2014 17:55:48 +0200 Subject: [PATCH 060/280] Closes #61 - Binary search works as Array.prototype.indexOf --- algorithms/searching/binarysearch.js | 4 ++-- test/algorithms/searching/binarysearch.js | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/algorithms/searching/binarysearch.js b/algorithms/searching/binarysearch.js index 36e72ca..d456ace 100644 --- a/algorithms/searching/binarysearch.js +++ b/algorithms/searching/binarysearch.js @@ -37,13 +37,13 @@ var binarySearch = function (sortedArray, element) { while (end >= init) { var m = ((end - init) >> 1) + init; - if (sortedArray[m] === element) return true; + if (sortedArray[m] === element) return m; if (sortedArray[m] < element) init = m + 1; else end = m - 1; } - return false; + return -1; }; module.exports = binarySearch; diff --git a/test/algorithms/searching/binarysearch.js b/test/algorithms/searching/binarysearch.js index 07aa3c2..2071d03 100644 --- a/test/algorithms/searching/binarysearch.js +++ b/test/algorithms/searching/binarysearch.js @@ -26,14 +26,14 @@ var binarySearch = require('../../../algorithms/searching/binarysearch'), describe('Binary Search', function () { it('should find elements in the sorted array', function () { - assert(binarySearch([1, 2, 3, 4, 5], 3), '3 is in the array'); - assert(binarySearch([1, 2, 3, 4, 5], 1), '1 is in the array'); - assert(binarySearch([1, 2, 3, 4, 5], 2), '2 is in the array'); - assert(binarySearch([1, 2, 3, 4, 5], 4), '4 is in the array'); - assert(binarySearch([1, 2, 3, 4, 5], 5), '5 is in the array'); - assert(!binarySearch([1, 2, 3, 4, 5], 0), '0 is NOT in the array'); - assert(!binarySearch([1, 2, 3, 4, 5, 8], 6), '6 is NOT in the array'); - assert(!binarySearch([1, 2, 3, 4, 5], 100), '100 is NOT in the array'); + assert.equal(binarySearch([1, 2, 3, 4, 5], 3), 2); + assert.equal(binarySearch([1, 2, 3, 4, 5], 1), 0); + assert.equal(binarySearch([1, 2, 3, 4, 5], 2), 1); + assert.equal(binarySearch([1, 2, 3, 4, 5], 4), 3); + assert.equal(binarySearch([1, 2, 3, 4, 5], 5), 4); + assert.equal(binarySearch([1, 2, 3, 4, 5], 0), -1); + assert.equal(binarySearch([1, 2, 3, 4, 5, 8], 6), -1); + assert.equal(binarySearch([1, 2, 3, 4, 5], 100), -1); }); }); From 87b66449a8ae0f65b445826ceacaf94412093f33 Mon Sep 17 00:00:00 2001 From: eush77 Date: Tue, 24 Jun 2014 00:22:05 +0400 Subject: [PATCH 061/280] Add Narayana's next permutation algorithm --- algorithms/math/next_permutation.js | 72 +++++++++++++++++++ test/algorithms/math/next_permutation.js | 91 ++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 algorithms/math/next_permutation.js create mode 100644 test/algorithms/math/next_permutation.js diff --git a/algorithms/math/next_permutation.js b/algorithms/math/next_permutation.js new file mode 100644 index 0000000..b88fb55 --- /dev/null +++ b/algorithms/math/next_permutation.js @@ -0,0 +1,72 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var Comparator = require('../../util/comparator'); + + +/** + * Narayana's algorithm computes the subsequent permutation + * in lexicographical order. + * Complexity: O(n). + * + * @param {Array} array + * @param {function} [compareFn] - Custom compare function. + * @return {boolean} Boolean flag indicating whether the algorithm succeeded, + * true unless the input permutation is lexicographically the last one. + */ +var nextPermutation = function (array, compareFn) { + if (!array.length) { + return false; + } + var cmp = new Comparator(compareFn); + + // Find pivot and successor indices. + var pivot = array.length - 1; + while (pivot && cmp.greaterThanOrEqual(array[pivot - 1], array[pivot])) { + pivot -= 1; + } + if (!pivot) { + // Permutation is sorted in descending order. + return false; + } + var pivotValue = array[--pivot]; + var successor = array.length - 1; + while (cmp.lessThanOrEqual(array[successor], pivotValue)) { + successor -= 1; + } + + // Swap values. + array[pivot] = array[successor]; + array[successor] = pivotValue; + + // Reverse the descending part. + for (var left = pivot, right = array.length; ++left < --right;) { + var temp = array[left]; + array[left] = array[right]; + array[right] = temp; + } + return true; +}; + + +module.exports = nextPermutation; diff --git a/test/algorithms/math/next_permutation.js b/test/algorithms/math/next_permutation.js new file mode 100644 index 0000000..19cf453 --- /dev/null +++ b/test/algorithms/math/next_permutation.js @@ -0,0 +1,91 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var nextPermutation = require('../../../algorithms/math/next_permutation'), + Comparator = require('../../../util/comparator'), + assert = require('assert'); + + +var range = function (begin, end) { + if (end === undefined) { + end = begin; + begin = 0; + } + if (end <= begin) { + return []; + } + return new Array(end - begin + 1).join(0).split('').map(function (_, index) { + return begin + index; + }); +}; + + +var factorial = function (n) { + return range(1, n + 1).reduce(function (product, value) { + return product * value; + }, 1); +}; + + +var permutations = function (start, compareFn) { + var permutations = []; + var perm = start.slice(); + do { + permutations.push(perm.slice()); + } while (nextPermutation(perm, compareFn)); + return permutations; +}; + + +describe('Next Permutation', function () { + it('should return immediately following permutation', function () { + assert.deepEqual(permutations([1, 2]), [[1, 2], [2, 1]]); + assert.deepEqual(permutations([1, 2, 2]), + [[1, 2, 2], [2, 1, 2], [2, 2, 1]]); + assert.deepEqual(permutations([1]), [[1]]); + assert.deepEqual(permutations([]), [[]]); + }); + + it('should generate all N! permutations if the elements are distinct', + function () { + [4, 5, 6].forEach(function (size) { + var count = 0; + var perm = range(size); + do { + count += 1; + } while (nextPermutation(perm)); + assert.equal(count, factorial(size)); + }); + }); + + it('should support custom compare functions', function () { + var reverseComparator = new Comparator(); + reverseComparator.reverse(); + var reverseCompareFn = reverseComparator.compare; + + assert.deepEqual(permutations([1, 2, 3]).reverse(), + permutations([3, 2, 1], reverseCompareFn)); + assert.deepEqual(permutations([0, 0, 1]).reverse(), + permutations([1, 0, 0], reverseCompareFn)); + }); +}); From 30a8520a1f6e6c2996af00c33915ada5292fd64c Mon Sep 17 00:00:00 2001 From: eush77 Date: Tue, 24 Jun 2014 03:35:50 +0400 Subject: [PATCH 062/280] Add Disjoint Set Forest data structure --- data_structures/disjoint_set_forest.js | 130 ++++++++++++++++++++ test/data_structures/disjoint_set_forest.js | 97 +++++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 data_structures/disjoint_set_forest.js create mode 100644 test/data_structures/disjoint_set_forest.js diff --git a/data_structures/disjoint_set_forest.js b/data_structures/disjoint_set_forest.js new file mode 100644 index 0000000..2397e1b --- /dev/null +++ b/data_structures/disjoint_set_forest.js @@ -0,0 +1,130 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + + +/** + * Disjoint Set Forest data structure. + * Allows fast subset merging and querying. + * New elements lie in their own one-element subsets by default. + * + * @constructor + */ +function DisjointSetForest() { + this._parents = {}; + this._ranks = {}; + this._sizes = {}; +} + + +DisjointSetForest.prototype._introduce = function (element) { + if (!(element in this._parents)) { + this._parents[element] = element; + this._ranks[element] = 0; + this._sizes[element] = 1; + } +}; + + +/** + * Check if the elements belong to the same subset. + * Complexity: O(A^-1) (inverse Ackermann function) amortized. + * + * @param {...*} element + * @return {boolean} + */ +DisjointSetForest.prototype.sameSubset = function (element) { + this._introduce(element); + var root = this.root(element); + return [].slice.call(arguments, 1).every(function (element) { + this._introduce(element); + return this.root(element) == root; + }.bind(this)); +}; + + +/** + * Return the root element which represents the given element's subset. + * The result does not depend on the choice of the element, + * but rather on the subset itself. + * Complexity: O(A^-1) (inverse Ackermann function) amortized. + * + * @param {*} element + * @return {*} + */ +DisjointSetForest.prototype.root = function (element) { + this._introduce(element); + if (this._parents[element] != element) { + this._parents[element] = this.root(this._parents[element]); + } + return this._parents[element]; +}; + + +/** + * Return the size of the given element's subset. + * Complexity: O(A^-1) (inverse Ackermann function) amortized. + * + * @param {*} element + * @return {number} + */ +DisjointSetForest.prototype.size = function (element) { + this._introduce(element); + return this._sizes[this.root(element)]; +}; + + +/** + * Merge subsets containing two (or more) given elements into one. + * Complexity: O(A^-1) (inverse Ackermann function) amortized. + * + * @param {*} element1 + * @param {*} element2 + * @param {...*} + * @return {DisjointSetForest} + */ +DisjointSetForest.prototype.merge = function merge(element1, element2) { + if (arguments.length > 2) { + merge.apply(this, [].slice.call(arguments, 1)); + } + + this._introduce(element1); + this._introduce(element2); + var root1 = this.root(element1); + var root2 = this.root(element2); + + if (this._ranks[root1] < this._ranks[root2]) { + this._parents[root1] = root2; + this._sizes[root2] += this._sizes[root1]; + } + else if (root1 != root2) { + this._parents[root2] = root1; + this._sizes[root1] += this._sizes[root2]; + if (this._ranks[root1] == this._ranks[root2]) { + this._ranks[root1] += 1; + } + } + return this; +}; + + +module.exports = DisjointSetForest; diff --git a/test/data_structures/disjoint_set_forest.js b/test/data_structures/disjoint_set_forest.js new file mode 100644 index 0000000..a301388 --- /dev/null +++ b/test/data_structures/disjoint_set_forest.js @@ -0,0 +1,97 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var DisjointSetForest = require('../../data_structures/disjoint_set_forest'), + assert = require('assert'); + + +describe('Disjoint Set Forest', function () { + it('should decide if two elements belong to the same subset or not', + function () { + var forest = new DisjointSetForest(); + assert(!forest.sameSubset(1, 2)); + forest.merge(1, 2); + assert(forest.sameSubset(1, 2)); + forest.merge(3, 4); + assert(!forest.sameSubset(2, 4)); + forest.merge(1, 3); + assert(forest.sameSubset(1, 2, 3, 4)); + assert(!forest.sameSubset(1, 5)); + }); + + it('should maintain subset sizes', function () { + var forest = new DisjointSetForest(); + var assertSizesCorrect = function (elements, size) { + elements.forEach(function (element) { + assert.equal(forest.size(element), size); + }); + }; + assertSizesCorrect([0, 1, 2, 3, 4], 1); + forest.merge(0, 1); + assertSizesCorrect([0, 1], 2); + forest.merge(0, 2); + assertSizesCorrect([0, 1, 2], 3); + forest.merge(2, 1); + assertSizesCorrect([0, 1, 2], 3); + forest.merge(3, 4); + assertSizesCorrect([3, 4], 2); + forest.merge(0, 4); + assertSizesCorrect([0, 1, 2, 3, 4], 5); + }); + + it('should point all elements to the same root', function () { + var forest = new DisjointSetForest(); + var assertSameRoot = function (element) { + var root = forest.root(element); + [].slice.call(arguments, 1).forEach(function (element) { + assert.equal(forest.root(element), root); + }); + }; + forest.merge(0, 1); + assertSameRoot(0, 1); + forest.merge(1, 2); + assertSameRoot(0, 1, 2); + forest.merge(1, 3, 4); + assertSameRoot(0, 1, 2, 3, 4); + forest.merge(0, 5); + assertSameRoot(0, 1, 2, 3, 4, 5); + }); + + it('should not choose the root element outside the subset', function () { + var forest = new DisjointSetForest(); + var assertInside = function (value, set) { + return set.some(function (element) { + return element == value; + }); + }; + assert.equal(forest.root(0), 0); + forest.merge(0, 1); + assertInside(forest.root(0), [0, 1]); + forest.merge(2, 3); + assertInside(forest.root(2), [2, 3]); + forest.merge(4, 5, 6); + assertInside(forest.root(4), [4, 5, 6]); + forest.merge(0, 1, 2, 5, 6); + assertInside(forest.root(4), [0, 1, 2, 3, 4, 5, 6]); + }); +}); From ea951eb8b892239ede81e8cffa69cb278810fba9 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Mon, 23 Jun 2014 22:01:43 -0400 Subject: [PATCH 063/280] Fixed a few spacing issues that jshint didn't like --- algorithms/math/power_set.js | 26 +++++++++---------- .../string/longest_common_subsequence.js | 16 ++++++------ test/algorithms/math/power_set.js | 8 +++--- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/algorithms/math/power_set.js b/algorithms/math/power_set.js index d7286d1..c4eac21 100644 --- a/algorithms/math/power_set.js +++ b/algorithms/math/power_set.js @@ -33,28 +33,28 @@ */ var powerSetIterative = function (array) { - if(array.length === 0) { + if (array.length === 0) { return []; } var powerSet = []; var cache = []; - for(var i = 0; i < array.length; i++) { + for (var i = 0; i < array.length; i++) { cache[i] = true; } - for(i = 0; i < Math.pow(2, array.length); i++) { + for (i = 0; i < Math.pow(2, array.length); i++) { powerSet.push([]); - for(var j = 0; j < array.length; j++) { + for (var j = 0; j < array.length; j++) { - if(i % Math.pow(2, j) === 0) { + if (i % Math.pow(2, j) === 0) { cache[j] = !cache[j]; } - if(cache[j]) { + if (cache[j]) { powerSet[i].push(array[j]); } @@ -68,10 +68,10 @@ var powerSetIterative = function (array) { * Recursive power set calculation */ var powerSetRecursive = function (array) { - if(array.length === 0) { + if (array.length === 0) { return []; } - else if(array.length == 1) { + else if (array.length == 1) { return [ [], [ array[0] ] ]; } else { @@ -80,11 +80,11 @@ var powerSetRecursive = function (array) { array.splice(0, 1); - powerSetRecursive(array).forEach(function(elem) { - powerSet.push(elem); - var withFirstElem = [ firstElem ]; - withFirstElem.push.apply(withFirstElem, elem); - powerSet.push(withFirstElem); + powerSetRecursive(array).forEach(function (elem) { + powerSet.push(elem); + var withFirstElem = [ firstElem ]; + withFirstElem.push.apply(withFirstElem, elem); + powerSet.push(withFirstElem); }); return powerSet; diff --git a/algorithms/string/longest_common_subsequence.js b/algorithms/string/longest_common_subsequence.js index d1da646..2ee7d4f 100644 --- a/algorithms/string/longest_common_subsequence.js +++ b/algorithms/string/longest_common_subsequence.js @@ -38,18 +38,18 @@ var longestCommonSubsequence = function (s1, s2) { var i, j; // First column and row are initialized with zeroes - for(i = 0; i < s1.length + 1; i++) { + for (i = 0; i < s1.length + 1; i++) { cache[i] = []; cache[i][0] = 0; } - for(i = 0; i < s2.length + 1; i++) { + for (i = 0; i < s2.length + 1; i++) { cache[0][i] = 0; } // Fill in the cache - for(i = 1; i < s1.length + 1; i++) { - for(j = 1; j < s2.length + 1; j++) { - if(s1[i - 1] == s2[j - 1]) { + for (i = 1; i < s1.length + 1; i++) { + for (j = 1; j < s2.length + 1; j++) { + if (s1[i - 1] == s2[j - 1]) { var newValue = cache[i - 1][j - 1] + 1; cache[i][j] = newValue; } @@ -64,14 +64,14 @@ var longestCommonSubsequence = function (s1, s2) { j = s2.length; var lcs = ''; - while(cache[i][j] !== 0) { - if(s1[i - 1] === s2[j - 1]){ + while (cache[i][j] !== 0) { + if (s1[i - 1] === s2[j - 1]) { lcs += s1[i - 1]; i--; j--; } else { - if(cache[i - 1][j] > cache[i][j - 1]) { + if (cache[i - 1][j] > cache[i][j - 1]) { i--; } else { diff --git a/test/algorithms/math/power_set.js b/test/algorithms/math/power_set.js index 591386e..b3af8b9 100644 --- a/test/algorithms/math/power_set.js +++ b/test/algorithms/math/power_set.js @@ -26,8 +26,8 @@ var powerSet = require('../../../algorithms/math/power_set'), function testArrayEqual(a, b) { var arrayEqual = true; - a.forEach(function(elem, index) { - if(a[index] != b[index]) { + a.forEach(function (elem, index) { + if (a[index] != b[index]) { arrayEqual = false; } }); @@ -36,8 +36,8 @@ function testArrayEqual(a, b) { function testArrayInArray(a, b) { var arrayInArray = false; - b.forEach(function(array) { - if(testArrayEqual(a, array)) { + b.forEach(function (array) { + if (testArrayEqual(a, array)) { arrayInArray = true; } }); From eae0a44aa8f24eca39b66f6eba3c1f4e4337af6d Mon Sep 17 00:00:00 2001 From: eush77 Date: Tue, 24 Jun 2014 14:39:10 +0400 Subject: [PATCH 064/280] Add fast exponentiation algorithm (repeated squaring) --- algorithms/math/fast_power.js | 74 ++++++++++++++++++++ test/algorithms/math/fast_power.js | 104 +++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 algorithms/math/fast_power.js create mode 100644 test/algorithms/math/fast_power.js diff --git a/algorithms/math/fast_power.js b/algorithms/math/fast_power.js new file mode 100644 index 0000000..de80c37 --- /dev/null +++ b/algorithms/math/fast_power.js @@ -0,0 +1,74 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + + +var multiplicationOperator = function (a, b) { + return a * b; +}; + + +/** + * Raise value to a positive integer power by repeated squaring. + * + * @param {*} base + * @param {number} power + * @param {function} [mul] - Multiplication function, + * standard multiplication operator by default. + * @param {*} identity - Identity value, used when power == 0. + * If mul is not set, defaults to 1. + * @return {*} + */ +var fastPower = function (base, power, mul, identity) { + if (mul === undefined) { + mul = multiplicationOperator; + identity = 1; + } + if (power < 0 || Math.floor(power) != power) { + throw new Error('Power must be a positive integer or zero.'); + } + + // If the power is zero, identity value must be given (or set by default). + if (!power) { + if (identity === undefined) { + throw new Error('The power is zero, but identity value not set.'); + } + else { + return identity; + } + } + + // Iterative form of the algorithm avoids checking the same thing twice. + var result; + var multiplyBy = function (value) { + result = (result === undefined) ? value : mul(result, value); + }; + for (var factor = base; power; power >>>= 1, factor = mul(factor, factor)) { + if (power & 1) { + multiplyBy(factor); + } + } + return result; +}; + + +module.exports = fastPower; diff --git a/test/algorithms/math/fast_power.js b/test/algorithms/math/fast_power.js new file mode 100644 index 0000000..cec9da3 --- /dev/null +++ b/test/algorithms/math/fast_power.js @@ -0,0 +1,104 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var power = require('../../../algorithms/math/fast_power'), + assert = require('assert'); + + +var assertApproximatelyEqual = function (a, b, eps) { + eps = eps || 1e-12; + assert(Math.abs(a - b) < eps); +}; + + +var multiplyModulo = function (modulo) { + return function (a, b) { + return (a * b) % modulo; + }; +}; + + +/** + * This operation is isomorphic to addition in Z/3. + * + * | a | b | c | + * --------------- + * a | a | b | c | + * b | b | c | a | + * c | c | a | b | + * --------------- + */ +var abcMultiply = function (a, b) { + var table = { + a: {a: 'a', b: 'b', c: 'c'}, + b: {a: 'b', b: 'c', c: 'a'}, + c: {a: 'c', b: 'a', c: 'b'} + }; + assert(table[a] && table[b]); + return table[a][b]; +}; + + +describe('Fast Power', function () { + it('should correctly raise numbers to positive integer powers', function () { + assert.equal(power(2, 5), 32); + assert.equal(power(32, 1), 32); + assert.equal(power(3, 7), Math.pow(3, 7)); + assert.equal(power(4, 5), 1024); + assertApproximatelyEqual(power(Math.PI, 100), Math.pow(Math.PI, 100)); + assert.equal(power(-5, 2), 25); + assert.equal(power(-5, 3), -125); + assert.equal(power(1, 10000), 1); + }); + + it('should raise an error if the power is not a nonnegative integer', + function () { + // It is not clear how to handle these cases + // when custom multiplication is also supplied. + assert.throws(power.bind(null, 7, -2)); + assert.throws(power.bind(null, 5, -1)); + assert.throws(power.bind(null, Math.PI, Math.E)); + }); + + it('should accept custom multiplication functions', function () { + // Math.pow is basically useless here. + + assert.equal(power(0, 0, multiplyModulo(5), 1), 1); + assert.equal(power(2, 9, multiplyModulo(10)), 2); + assert.equal(power(31, 100, multiplyModulo(17)), 13); + assert.equal(power(5, 87654, multiplyModulo(100)), 25); + assert.equal(power(12, 12, multiplyModulo(15)), 6); + + assert.equal(power('a', 0, abcMultiply, 'a'), 'a'); + assert.equal(power('c', 2, abcMultiply, 'a'), 'b'); + assert.equal(power('a', 0xaaaa, abcMultiply), 'a'); + assert.equal(power('b', 0xbbbb, abcMultiply), 'c'); + assert.equal(power('c', 0xcccc, abcMultiply), 'a'); + }); + + it('should raise an error if the power is zero but no identity value given' + + ' (custom multiplication)', function () { + assert.throws(power.bind(null, 0, 0, multiplyModulo(5))); + assert.throws(power.bind(null, 'a', 0, abcMultiply)); + }); +}); From f6fa09e4b4516a569afad8838a740ea31ef1542f Mon Sep 17 00:00:00 2001 From: eush77 Date: Wed, 25 Jun 2014 15:24:09 +0400 Subject: [PATCH 065/280] Refactor Fibonacci test suite according to DRY principle --- test/algorithms/math/fibonacci.js | 58 ++++++++++--------------------- 1 file changed, 19 insertions(+), 39 deletions(-) diff --git a/test/algorithms/math/fibonacci.js b/test/algorithms/math/fibonacci.js index 7a79973..64e2c0c 100644 --- a/test/algorithms/math/fibonacci.js +++ b/test/algorithms/math/fibonacci.js @@ -24,58 +24,38 @@ var fib = require('../../../algorithms/math/fibonacci'), assert = require('assert'); +var testFibonacciSequence = function (fib) { + assert.equal(0, fib(0)); + assert.equal(1, fib(1)); + assert.equal(1, fib(2)); + assert.equal(2, fib(3)); + assert.equal(3, fib(4)); + assert.equal(5, fib(5)); + assert.equal(8, fib(6)); + assert.equal(13, fib(7)); + assert.equal(21, fib(8)); + assert.equal(34, fib(9)); + assert.equal(55, fib(10)); + assert.equal(89, fib(11)); + assert.equal(144, fib(12)); +}; + describe('Fibonacci', function () { describe('#exponential()', function () { it('should return the right value for fibonacci sequence', function () { - assert.equal(0, fib.exponential(0)); - assert.equal(1, fib.exponential(1)); - assert.equal(1, fib.exponential(2)); - assert.equal(2, fib.exponential(3)); - assert.equal(3, fib.exponential(4)); - assert.equal(5, fib.exponential(5)); - assert.equal(8, fib.exponential(6)); - assert.equal(13, fib.exponential(7)); - assert.equal(21, fib.exponential(8)); - assert.equal(34, fib.exponential(9)); - assert.equal(55, fib.exponential(10)); - assert.equal(89, fib.exponential(11)); - assert.equal(144, fib.exponential(12)); + testFibonacciSequence(fib.exponential); }); }); describe('#linear()', function () { it('should return the right value for fibonacci sequence', function () { - assert.equal(0, fib(0)); - assert.equal(1, fib(1)); - assert.equal(1, fib(2)); - assert.equal(2, fib(3)); - assert.equal(3, fib(4)); - assert.equal(5, fib(5)); - assert.equal(8, fib(6)); - assert.equal(13, fib(7)); - assert.equal(21, fib(8)); - assert.equal(34, fib(9)); - assert.equal(55, fib(10)); - assert.equal(89, fib(11)); - assert.equal(144, fib(12)); + testFibonacciSequence(fib); }); }); describe('#withMemoization()', function () { it('should return the right value for fibonacci sequence', function () { - assert.equal(0, fib.withMemoization(0)); - assert.equal(1, fib.withMemoization(1)); - assert.equal(1, fib.withMemoization(2)); - assert.equal(2, fib.withMemoization(3)); - assert.equal(3, fib.withMemoization(4)); - assert.equal(5, fib.withMemoization(5)); - assert.equal(8, fib.withMemoization(6)); - assert.equal(13, fib.withMemoization(7)); - assert.equal(21, fib.withMemoization(8)); - assert.equal(34, fib.withMemoization(9)); - assert.equal(55, fib.withMemoization(10)); - assert.equal(89, fib.withMemoization(11)); - assert.equal(144, fib.withMemoization(12)); + testFibonacciSequence(fib.withMemoization); }); }); }); From 0d9506d201aca7e3cfa870bb2fa9b630138f9625 Mon Sep 17 00:00:00 2001 From: eush77 Date: Sun, 29 Jun 2014 21:23:47 +0400 Subject: [PATCH 066/280] Add direct Fibonacci numbers algorithm (Binet's formula + rounding) --- algorithms/math/fibonacci.js | 14 ++++++++++++++ test/algorithms/math/fibonacci.js | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/algorithms/math/fibonacci.js b/algorithms/math/fibonacci.js index 2ebd4ca..cedf5af 100644 --- a/algorithms/math/fibonacci.js +++ b/algorithms/math/fibonacci.js @@ -78,7 +78,21 @@ var fibWithMemoization = (function () { return fib; })(); +/** + * Implementation using Binet's formula with the rounding trick. + * O(1) in time, O(1) in space + * + * @author Eugene Sharygin + * @param Number + * @return Number + */ +var fibDirect = function (number) { + var phi = (1 + Math.sqrt(5)) / 2; + return Math.floor(Math.pow(phi, number) / Math.sqrt(5) + 0.5); +}; + // Use fibLinear as the default implementation fibLinear.exponential = fibExponential; fibLinear.withMemoization = fibWithMemoization; +fibLinear.direct = fibDirect; module.exports = fibLinear; diff --git a/test/algorithms/math/fibonacci.js b/test/algorithms/math/fibonacci.js index 64e2c0c..4428096 100644 --- a/test/algorithms/math/fibonacci.js +++ b/test/algorithms/math/fibonacci.js @@ -58,5 +58,11 @@ describe('Fibonacci', function () { testFibonacciSequence(fib.withMemoization); }); }); + + describe('#direct()', function () { + it('should return the right value for fibonacci sequence', function () { + testFibonacciSequence(fib.direct); + }); + }); }); From 9d2fadd8dcc68b5b6351eaadb7ec6eabe4038fef Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Tue, 8 Jul 2014 23:15:47 -0400 Subject: [PATCH 067/280] Add hamming distance function and tests --- algorithms/string/hamming.js | 27 +++++++++++++++++++++++++++ test/algorithms/string/hamming.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 algorithms/string/hamming.js create mode 100644 test/algorithms/string/hamming.js diff --git a/algorithms/string/hamming.js b/algorithms/string/hamming.js new file mode 100644 index 0000000..5dccf95 --- /dev/null +++ b/algorithms/string/hamming.js @@ -0,0 +1,27 @@ +/** + * + * "Hamming distance between two strings of equal length is the number of + * positions at which the corresponding symbols are different. In another way, + * it measures the minimum number of substitutions required to change one string + * into the other." - https://en.wikipedia.org/wiki/Hamming_distance + * + */ +'use strict'; + +var hamming = function (a, b) { + if (a.length != b.length) { + throw new Error('Strings must be equal in length'); + } + + var dist = 0; + + for (var i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + dist++; + } + } + + return dist; +}; + +module.exports = hamming; diff --git a/test/algorithms/string/hamming.js b/test/algorithms/string/hamming.js new file mode 100644 index 0000000..3bacc46 --- /dev/null +++ b/test/algorithms/string/hamming.js @@ -0,0 +1,29 @@ +'use strict'; + +var hamming = require('../../../algorithms/string/hamming'), + assert = require('assert'); + + +describe('Hamming distance', function () { + it('should raise an error if the inputs are not equal lengths', function () { + assert.throws(function () { + hamming('abcde', '1234'); + }); + }); + + it('should return the correct the correct distances', function () { + var inputs = [ + { a: 'karolin', b: 'kathrin', expected: 3 }, + { a: 'karolin', b: 'kerstin', expected: 3 }, + { a: '1011101', b: '1001001', expected: 2 }, + { a: '2173896', b: '2233796', expected: 3 }, + { a: '1111111111', b: '0000000000', expected: 10 }, + { a: '', b: '', expected: 0} + ]; + + inputs.forEach(function (val) { + assert.equal(hamming(val.a, val.b), val.expected); + }); + }); + +}); From f3f9ad784fe82d368fd5b390d2979c92f4c5ddac Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Tue, 8 Jul 2014 23:28:36 -0400 Subject: [PATCH 068/280] Add hamming distance to main.js exports --- main.js | 1 + 1 file changed, 1 insertion(+) diff --git a/main.js b/main.js index 99dac3a..61ab6c6 100644 --- a/main.js +++ b/main.js @@ -57,6 +57,7 @@ var lib = { karpRabin: require('./algorithms/string/karp_rabin'), knuthMorrisPratt: require('./algorithms/string/knuth_morris_pratt'), huffman: require('./algorithms/string/huffman'), + hamming: require('./algorithms/string/hamming') }, DataStructure: { BST: require('./data_structures/bst'), From e1f9404a81ef200695d346ce88058f1c444531d6 Mon Sep 17 00:00:00 2001 From: eush77 Date: Wed, 9 Jul 2014 14:01:41 +0400 Subject: [PATCH 069/280] Update main.js --- main.js | 1 + 1 file changed, 1 insertion(+) diff --git a/main.js b/main.js index 99dac3a..be670a2 100644 --- a/main.js +++ b/main.js @@ -37,6 +37,7 @@ var lib = { extendedEuclidean: require('./algorithms/math/extended_euclidean'), newtonSqrt: require('./algorithms/math/newton_sqrt'), reservoirSampling: require('./algorithms/math/reservoir_sampling'), + fastPower: require('./algorithms/math/fast_power'), }, Search: { bfs: require('./algorithms/searching/bfs'), From 866e4aa14671c40137a7a66484ebca7c46e79e22 Mon Sep 17 00:00:00 2001 From: eush77 Date: Wed, 9 Jul 2014 14:05:13 +0400 Subject: [PATCH 070/280] Update main.js --- main.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main.js b/main.js index 99dac3a..7e7e8af 100644 --- a/main.js +++ b/main.js @@ -66,7 +66,8 @@ var lib = { LinkedList: require('./data_structures/linked_list'), PriorityQueue: require('./data_structures/priority_queue'), Queue: require('./data_structures/queue'), - Stack: require('./data_structures/stack') + Stack: require('./data_structures/stack'), + DisjointSetForest: require('./data_structures/disjoint_set_forest'), } }; From 22942c64dda5fb0b0e69ee9c63281796908b8c87 Mon Sep 17 00:00:00 2001 From: eush77 Date: Wed, 9 Jul 2014 14:17:46 +0400 Subject: [PATCH 071/280] Update main.js --- main.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/main.js b/main.js index 99dac3a..5220c81 100644 --- a/main.js +++ b/main.js @@ -37,6 +37,7 @@ var lib = { extendedEuclidean: require('./algorithms/math/extended_euclidean'), newtonSqrt: require('./algorithms/math/newton_sqrt'), reservoirSampling: require('./algorithms/math/reservoir_sampling'), + nextPermutation: require('./algorithms/math/next_permutation'), }, Search: { bfs: require('./algorithms/searching/bfs'), @@ -50,7 +51,8 @@ var lib = { mergeSort: require('./algorithms/sorting/merge_sort'), quicksort: require('./algorithms/sorting/quicksort'), selectionSort: require('./algorithms/sorting/selection_sort'), - radixSort: require('./algorithms/sorting/radix_sort') + radixSort: require('./algorithms/sorting/radix_sort'), + insertionSort: require('./algorithms/sorting/insertion_sort'), }, String: { editDistance: require('./algorithms/string/edit_distance'), From 0beef79a697a271719355aa1e16108bbdde65345 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 9 Jul 2014 14:49:19 +0200 Subject: [PATCH 072/280] Rename edit_distance.js to levenshtein.js --- algorithms/string/{edit_distance.js => levenshtein.js} | 0 main.js | 2 +- test/algorithms/string/{edit_distance.js => levenshtein.js} | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename algorithms/string/{edit_distance.js => levenshtein.js} (100%) rename test/algorithms/string/{edit_distance.js => levenshtein.js} (96%) diff --git a/algorithms/string/edit_distance.js b/algorithms/string/levenshtein.js similarity index 100% rename from algorithms/string/edit_distance.js rename to algorithms/string/levenshtein.js diff --git a/main.js b/main.js index be670a2..000eed6 100644 --- a/main.js +++ b/main.js @@ -54,7 +54,7 @@ var lib = { radixSort: require('./algorithms/sorting/radix_sort') }, String: { - editDistance: require('./algorithms/string/edit_distance'), + levenshtein: require('./algorithms/string/levenshtein'), karpRabin: require('./algorithms/string/karp_rabin'), knuthMorrisPratt: require('./algorithms/string/knuth_morris_pratt'), huffman: require('./algorithms/string/huffman'), diff --git a/test/algorithms/string/edit_distance.js b/test/algorithms/string/levenshtein.js similarity index 96% rename from test/algorithms/string/edit_distance.js rename to test/algorithms/string/levenshtein.js index ea53b0a..5dba227 100644 --- a/test/algorithms/string/edit_distance.js +++ b/test/algorithms/string/levenshtein.js @@ -21,7 +21,7 @@ */ 'use strict'; -var levenshtein = require('../../../algorithms/string/edit_distance'), +var levenshtein = require('../../../algorithms/string/levenshtein'), assert = require('assert'); describe('Levenshtein', function () { From 9720f07c97195f6a65a7ac2bd1e645007af7859d Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 9 Jul 2014 15:06:47 +0200 Subject: [PATCH 073/280] v0.5.0 - Fast Power - O(1) Fibonacci - Binet's formula - Subsequent permutation - Narayana's algorithm - Reservoir sampling - Hamming edit distance - Huffman encoding/decoding - Disjoint set forest --- CHANGELOG | 14 ++++++++++++++ package.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 0941e11..8419e6f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,19 @@ CHANGELOG ========= +0.5.0 (2014-07-09) +* Math + * Fast Power + * O(1) Fibonacci - Binet's formula + * Subsequent permutation - Narayana's algorithm + * Reservoir sampling + +* Data Structures + * Disjoint set forest + +* String + * Hamming edit distance + * Huffman encoding/decoding + 0.4.0 (2014-06-06) * Sorting * Selection Sort diff --git a/package.json b/package.json index b07e4a9..30d0279 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.4.0", + "version": "0.5.0", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" From 7a7516d2b02b7673876a3617a57da3d8e89a7dff Mon Sep 17 00:00:00 2001 From: "Andre P. Oliveira" Date: Wed, 4 Jun 2014 14:27:20 -0400 Subject: [PATCH 074/280] Add Set data structure --- data_structures/set.js | 115 ++++++++++++++++++++++++++++++++++++ main.js | 1 + test/data_structures/set.js | 112 +++++++++++++++++++++++++++++++++++ 3 files changed, 228 insertions(+) create mode 100644 data_structures/set.js create mode 100644 test/data_structures/set.js diff --git a/data_structures/set.js b/data_structures/set.js new file mode 100644 index 0000000..0c824ec --- /dev/null +++ b/data_structures/set.js @@ -0,0 +1,115 @@ +/** + * Copyright (C) 2014 Andre Oliveira + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"], to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +/** + * Typical representation of a mathematical set + * No restriction on element types + * i.e. set.add(1,'a', "b", { "foo" : "bar" }) + */ +var Set = function() { + this.elts = []; + + var toAdd = arguments || []; + for(var i = 0; i < toAdd.length; i++) { + this.add(toAdd[i]); + } +} + +Set.prototype.add = function() { + for(var i = 0; i < arguments.length; i++) { + if(!this.contains(arguments[i])) { + this.elts.push(arguments[i]); + } + } + return this; +} + +Set.prototype.remove = function() { + for(var i = 0; i < arguments.length; i++) { + if(this.contains(arguments[i])) + this.elts.splice(this.elts.indexOf(arguments[i]),1); + } + return this; +} + +Set.prototype.contains = function(elt) { + for(var i = 0; i < this.elts.length; i++) { + if(this.elts[i] === elt) { + return true; + } + } + return false; +} + +Set.prototype.intersect = function(other) { + var newSet = new Set(); + for(var i = 0; i < this.elts.length; i++){ + if(other.contains(this.elts[i])) + newSet.add(this.elts[i]); + } + return newSet; +} + +Set.prototype.union = function(other) { + var newSet = new Set(); + + for(var i = 0; i < this.elts.length; i++) + newSet.add(this.elts[i]); + for(var i = 0; i < other.elts.length; i++) + newSet.add(other.elts[i]); + + return newSet; +} + +Set.prototype.subset = function(other) { + for(var i = 0; i < this.elts.length; i++) { + if(!other.contains(this.elts[i])) { + return false; + } + } + return true; +} + +Set.prototype.minus = function(other) { + var newSet = new Set(); + for(var i = 0; i < this.elts.length; i++){ + if(!other.contains(this.elts[i])){ + newSet.add(this.elts[i]); + } + } + return newSet; +} + +Set.prototype.symDiff = function(other) { + return (this.minus(other)).union(other.minus(this)); +} + +Set.prototype.size = function() { + return this.elts.length; +} + +Set.prototype.equals = function(other) { + return this.subset(other) && other.subset(this); +} + +module.exports = Set; diff --git a/main.js b/main.js index bf583c9..0962ff4 100644 --- a/main.js +++ b/main.js @@ -71,6 +71,7 @@ var lib = { PriorityQueue: require('./data_structures/priority_queue'), Queue: require('./data_structures/queue'), Stack: require('./data_structures/stack'), + Set: require('./data_structures/set'), DisjointSetForest: require('./data_structures/disjoint_set_forest') } }; diff --git a/test/data_structures/set.js b/test/data_structures/set.js new file mode 100644 index 0000000..b324899 --- /dev/null +++ b/test/data_structures/set.js @@ -0,0 +1,112 @@ +/** + * Copyright (C) 2014 Andre Oliveira + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var Set = require('../../data_structures/set'), + assert = require('assert'); + +describe('Set', function () { + it('should start empty', function () { + var s = new Set(); + assert.equal(s.size(), 0); + }); + + it('should add all initial arguments', function () { + var s = new Set(1,2,3); + assert.deepEqual(s.elts, [1,2,3]); + }); + + it('should add all arguments', function () { + var s = new Set(1,2,3); + s.add(4,5,6); + assert.deepEqual(s.elts, [1,2,3,4,5,6]); + }); + + it('should remove all arguments', function() { + var s = new Set(1,2,3); + s.remove(1,3); + assert.deepEqual(s.elts, [2]); + }); + + it('should do nothing if an element that doesn\'t exist is removed', function() { + var s = new Set(1,2,3); + s.remove(4); + assert.deepEqual(s.elts, [1,2,3]); + }); + + it('should only contain its elements', function() { + var s = new Set(1,2,3); + assert.equal(s.contains(1), true); + assert.equal(s.contains(4), false); + }); + + it('should check subsets', function() { + var s = new Set(); + var t = new Set(1,2,3); + assert.equal(s.subset(s), true); + assert.equal(s.subset(t), true); + assert.equal(t.subset(s), false); + assert.equal(t.subset(t), true); + }); + + it('should union', function() { + var s = new Set(1,2,3); + var t = new Set(3,4,5); + assert.deepEqual(s.union(t).elts,[1,2,3,4,5]); + }); + + it('should intersect', function() { + var s = new Set(1,2,3); + var t = new Set(3,4,5); + assert.deepEqual(s.intersect(t).elts,[3]); + }); + + it('should subtract other sets', function() { + var s = new Set(1,2,3); + var t = new Set(3,4,5); + assert.deepEqual(s.minus(t).elts,[1,2]); + assert.deepEqual(t.minus(s).elts,[4,5]); + }); + + it('should get symmetric difference', function() { + var s = new Set(1,2,3); + var t = new Set(3,4,5); + assert.deepEqual(s.symDiff(t).elts,[1,2,4,5]); + assert.deepEqual(t.symDiff(s).elts,[4,5,1,2]); + }); + + it('should check equality', function() { + var s = new Set(); + var t = new Set(); + assert.equal(s.equals(s), true); + assert.equal(s.equals(t), true); + assert.equal(t.equals(s), true); + s.add(1,2,3); + t.add(1,2,3); + assert.equal(s.equals(s), true); + assert.equal(s.equals(t), true); + t.remove(2,3); + assert.equal(s.equals(t), false); + }); +}); + + From e30e48b47a47588bc67914053008dcf8c22d5138 Mon Sep 17 00:00:00 2001 From: "Andre P. Oliveira" Date: Thu, 5 Jun 2014 09:53:12 -0400 Subject: [PATCH 075/280] Add minor fixes to pass build --- data_structures/set.js | 30 ++++++++++++++++-------------- test/data_structures/set.js | 2 +- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/data_structures/set.js b/data_structures/set.js index 0c824ec..949f932 100644 --- a/data_structures/set.js +++ b/data_structures/set.js @@ -33,7 +33,7 @@ var Set = function() { for(var i = 0; i < toAdd.length; i++) { this.add(toAdd[i]); } -} +}; Set.prototype.add = function() { for(var i = 0; i < arguments.length; i++) { @@ -42,7 +42,7 @@ Set.prototype.add = function() { } } return this; -} +}; Set.prototype.remove = function() { for(var i = 0; i < arguments.length; i++) { @@ -50,7 +50,7 @@ Set.prototype.remove = function() { this.elts.splice(this.elts.indexOf(arguments[i]),1); } return this; -} +}; Set.prototype.contains = function(elt) { for(var i = 0; i < this.elts.length; i++) { @@ -59,7 +59,7 @@ Set.prototype.contains = function(elt) { } } return false; -} +}; Set.prototype.intersect = function(other) { var newSet = new Set(); @@ -68,18 +68,20 @@ Set.prototype.intersect = function(other) { newSet.add(this.elts[i]); } return newSet; -} +}; Set.prototype.union = function(other) { var newSet = new Set(); - for(var i = 0; i < this.elts.length; i++) + for(var i = 0; i < this.elts.length; i++) { newSet.add(this.elts[i]); - for(var i = 0; i < other.elts.length; i++) - newSet.add(other.elts[i]); + } + for(var j = 0; j < other.elts.length; j++) { + newSet.add(other.elts[j]); + } return newSet; -} +}; Set.prototype.subset = function(other) { for(var i = 0; i < this.elts.length; i++) { @@ -88,7 +90,7 @@ Set.prototype.subset = function(other) { } } return true; -} +}; Set.prototype.minus = function(other) { var newSet = new Set(); @@ -98,18 +100,18 @@ Set.prototype.minus = function(other) { } } return newSet; -} +}; Set.prototype.symDiff = function(other) { return (this.minus(other)).union(other.minus(this)); -} +}; Set.prototype.size = function() { return this.elts.length; -} +}; Set.prototype.equals = function(other) { return this.subset(other) && other.subset(this); -} +}; module.exports = Set; diff --git a/test/data_structures/set.js b/test/data_structures/set.js index b324899..60b4aa6 100644 --- a/test/data_structures/set.js +++ b/test/data_structures/set.js @@ -47,7 +47,7 @@ describe('Set', function () { assert.deepEqual(s.elts, [2]); }); - it('should do nothing if an element that doesn\'t exist is removed', function() { + it('should do nothing xist is removed', function() { var s = new Set(1,2,3); s.remove(4); assert.deepEqual(s.elts, [1,2,3]); From 86c930663ccc3d3c759fd90616bb189d2b9ef8b0 Mon Sep 17 00:00:00 2001 From: "Andre P. Oliveira" Date: Wed, 18 Jun 2014 01:11:28 -0400 Subject: [PATCH 076/280] Change Set to use HashTable as underlying structure We lose a good portion of methods this way. HashTables don't allow us to do things like subsets. This is because of how LinkedLists are implemented. --- data_structures/set.js | 74 +++++------------------------------------- 1 file changed, 9 insertions(+), 65 deletions(-) diff --git a/data_structures/set.js b/data_structures/set.js index 949f932..938212d 100644 --- a/data_structures/set.js +++ b/data_structures/set.js @@ -21,97 +21,41 @@ */ 'use strict'; +var HashTable = require("./hash_table"); + /** * Typical representation of a mathematical set * No restriction on element types * i.e. set.add(1,'a', "b", { "foo" : "bar" }) */ var Set = function() { - this.elts = []; + this.elts = new HashTable(arguments.length); - var toAdd = arguments || []; - for(var i = 0; i < toAdd.length; i++) { - this.add(toAdd[i]); + for(var i = 0; i < arguments.length; i++) { + this.add(arguments[i]); } }; Set.prototype.add = function() { for(var i = 0; i < arguments.length; i++) { - if(!this.contains(arguments[i])) { - this.elts.push(arguments[i]); - } + this.elts.put(arguments[i], {}); } return this; }; Set.prototype.remove = function() { for(var i = 0; i < arguments.length; i++) { - if(this.contains(arguments[i])) - this.elts.splice(this.elts.indexOf(arguments[i]),1); + this.elts.del(arguments[i]); } return this; }; Set.prototype.contains = function(elt) { - for(var i = 0; i < this.elts.length; i++) { - if(this.elts[i] === elt) { - return true; - } - } - return false; -}; - -Set.prototype.intersect = function(other) { - var newSet = new Set(); - for(var i = 0; i < this.elts.length; i++){ - if(other.contains(this.elts[i])) - newSet.add(this.elts[i]); - } - return newSet; -}; - -Set.prototype.union = function(other) { - var newSet = new Set(); - - for(var i = 0; i < this.elts.length; i++) { - newSet.add(this.elts[i]); - } - for(var j = 0; j < other.elts.length; j++) { - newSet.add(other.elts[j]); - } - - return newSet; -}; - -Set.prototype.subset = function(other) { - for(var i = 0; i < this.elts.length; i++) { - if(!other.contains(this.elts[i])) { - return false; - } - } - return true; -}; - -Set.prototype.minus = function(other) { - var newSet = new Set(); - for(var i = 0; i < this.elts.length; i++){ - if(!other.contains(this.elts[i])){ - newSet.add(this.elts[i]); - } - } - return newSet; -}; - -Set.prototype.symDiff = function(other) { - return (this.minus(other)).union(other.minus(this)); + return this.elts.get(elt) != undefined; }; Set.prototype.size = function() { - return this.elts.length; -}; - -Set.prototype.equals = function(other) { - return this.subset(other) && other.subset(this); + return this.elts._items; }; module.exports = Set; From ba14723374df82b2f3daafea0c575b4c4438bb8d Mon Sep 17 00:00:00 2001 From: "Andre P. Oliveira" Date: Wed, 18 Jun 2014 01:12:55 -0400 Subject: [PATCH 077/280] Update Set tests --- test/data_structures/set.js | 79 +++++++++++-------------------------- 1 file changed, 24 insertions(+), 55 deletions(-) diff --git a/test/data_structures/set.js b/test/data_structures/set.js index 60b4aa6..a69b0ba 100644 --- a/test/data_structures/set.js +++ b/test/data_structures/set.js @@ -22,6 +22,7 @@ 'use strict'; var Set = require('../../data_structures/set'), + HashTable = require("../../data_structures/hash_table"), assert = require('assert'); describe('Set', function () { @@ -32,25 +33,42 @@ describe('Set', function () { it('should add all initial arguments', function () { var s = new Set(1,2,3); - assert.deepEqual(s.elts, [1,2,3]); + var ht = new HashTable(3); + ht.put(1, {}); + ht.put(2,{}); + ht.put(3,{}); + assert.deepEqual(s.elts, ht); }); it('should add all arguments', function () { var s = new Set(1,2,3); s.add(4,5,6); - assert.deepEqual(s.elts, [1,2,3,4,5,6]); + var ht = new HashTable(3); + ht.put(1, {}); + ht.put(2, {}); + ht.put(3,{}); + ht.put(4,{}); + ht.put(5,{}); + ht.put(6,{}); + + assert.deepEqual(s.elts, ht); }); it('should remove all arguments', function() { - var s = new Set(1,2,3); - s.remove(1,3); - assert.deepEqual(s.elts, [2]); + var s = new Set(1,2,3); + s.remove(1,3); + assert.equal(s.contains(1), false); + assert.equal(s.contains(3), false); }); it('should do nothing xist is removed', function() { var s = new Set(1,2,3); s.remove(4); - assert.deepEqual(s.elts, [1,2,3]); + var ht = new HashTable(3); + ht.put(1, {}); + ht.put(2,{}); + ht.put(3,{}); + assert.deepEqual(s.elts, ht); }); it('should only contain its elements', function() { @@ -58,55 +76,6 @@ describe('Set', function () { assert.equal(s.contains(1), true); assert.equal(s.contains(4), false); }); - - it('should check subsets', function() { - var s = new Set(); - var t = new Set(1,2,3); - assert.equal(s.subset(s), true); - assert.equal(s.subset(t), true); - assert.equal(t.subset(s), false); - assert.equal(t.subset(t), true); - }); - - it('should union', function() { - var s = new Set(1,2,3); - var t = new Set(3,4,5); - assert.deepEqual(s.union(t).elts,[1,2,3,4,5]); - }); - - it('should intersect', function() { - var s = new Set(1,2,3); - var t = new Set(3,4,5); - assert.deepEqual(s.intersect(t).elts,[3]); - }); - - it('should subtract other sets', function() { - var s = new Set(1,2,3); - var t = new Set(3,4,5); - assert.deepEqual(s.minus(t).elts,[1,2]); - assert.deepEqual(t.minus(s).elts,[4,5]); - }); - - it('should get symmetric difference', function() { - var s = new Set(1,2,3); - var t = new Set(3,4,5); - assert.deepEqual(s.symDiff(t).elts,[1,2,4,5]); - assert.deepEqual(t.symDiff(s).elts,[4,5,1,2]); - }); - - it('should check equality', function() { - var s = new Set(); - var t = new Set(); - assert.equal(s.equals(s), true); - assert.equal(s.equals(t), true); - assert.equal(t.equals(s), true); - s.add(1,2,3); - t.add(1,2,3); - assert.equal(s.equals(s), true); - assert.equal(s.equals(t), true); - t.remove(2,3); - assert.equal(s.equals(t), false); - }); }); From 1e8afdb70dcbd6465fa0012bfacd2cd8831a201f Mon Sep 17 00:00:00 2001 From: "Andre P. Oliveira" Date: Wed, 18 Jun 2014 01:19:34 -0400 Subject: [PATCH 078/280] Minor fixes to pass tests --- data_structures/set.js | 4 ++-- test/data_structures/set.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data_structures/set.js b/data_structures/set.js index 938212d..640d6c0 100644 --- a/data_structures/set.js +++ b/data_structures/set.js @@ -21,7 +21,7 @@ */ 'use strict'; -var HashTable = require("./hash_table"); +var HashTable = require('./hash_table'); /** * Typical representation of a mathematical set @@ -51,7 +51,7 @@ Set.prototype.remove = function() { }; Set.prototype.contains = function(elt) { - return this.elts.get(elt) != undefined; + return this.elts.get(elt) !== undefined; }; Set.prototype.size = function() { diff --git a/test/data_structures/set.js b/test/data_structures/set.js index a69b0ba..4150135 100644 --- a/test/data_structures/set.js +++ b/test/data_structures/set.js @@ -22,7 +22,7 @@ 'use strict'; var Set = require('../../data_structures/set'), - HashTable = require("../../data_structures/hash_table"), + HashTable = require('../../data_structures/hash_table'), assert = require('assert'); describe('Set', function () { From baf8fdd734d2501623fae8cdc382d2edd6e09465 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 9 Jul 2014 15:52:57 +0200 Subject: [PATCH 079/280] Add .size to Hash Table --- data_structures/hash_table.js | 6 ++++++ test/data_structures/hash_table.js | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/data_structures/hash_table.js b/data_structures/hash_table.js index 5f5cafc..dcdeee5 100644 --- a/data_structures/hash_table.js +++ b/data_structures/hash_table.js @@ -32,6 +32,12 @@ function HashTable(initialCapacity) { return this._table.length; } }); + + Object.defineProperty(this, 'size', { + get: function () { + return this._items; + } + }); } /** diff --git a/test/data_structures/hash_table.js b/test/data_structures/hash_table.js index e214bc8..5ba5ed3 100644 --- a/test/data_structures/hash_table.js +++ b/test/data_structures/hash_table.js @@ -57,6 +57,7 @@ describe('Hash Table', function () { function () { var h = new HashTable(); assert.equal(h.capacity, 64); // default initial capacity; + assert.equal(h.size, 0); h = new HashTable(2); assert.equal(h.capacity, 2); @@ -66,10 +67,14 @@ describe('Hash Table', function () { var h = new HashTable(16); var a = {a: 'foo', b: 'bar'}; h.put('foo', a); + + assert.equal(h.size, 1); assert.strictEqual(h.get('foo'), a); var b = {a: 'bar', b: 'baz'}; h.put('bar', b); + + assert.equal(h.size, 2); assert.strictEqual(h.get('bar'), b); }); From e00ae7dc5a7e5be441535811823edcdc65ad54b8 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 9 Jul 2014 16:03:18 +0200 Subject: [PATCH 080/280] Fix code style and tests --- data_structures/set.js | 45 ++++++++++---------- test/data_structures/set.js | 82 +++++++++++++++++++------------------ 2 files changed, 64 insertions(+), 63 deletions(-) diff --git a/data_structures/set.js b/data_structures/set.js index 640d6c0..3920197 100644 --- a/data_structures/set.js +++ b/data_structures/set.js @@ -28,34 +28,33 @@ var HashTable = require('./hash_table'); * No restriction on element types * i.e. set.add(1,'a', "b", { "foo" : "bar" }) */ -var Set = function() { - this.elts = new HashTable(arguments.length); - - for(var i = 0; i < arguments.length; i++) { - this.add(arguments[i]); - } -}; - -Set.prototype.add = function() { - for(var i = 0; i < arguments.length; i++) { - this.elts.put(arguments[i], {}); - } - return this; +var HashSet = function () { + this._elements = new HashTable(arguments.length); + this.add.apply(this, arguments); + + Object.defineProperty(this, 'size', { + get: function () { + return this._elements.size; + } + }); }; -Set.prototype.remove = function() { - for(var i = 0; i < arguments.length; i++) { - this.elts.del(arguments[i]); - } - return this; +HashSet.prototype.add = function () { + for (var i = 0; i < arguments.length; i++) { + this._elements.put(arguments[i], true); + } + return this; }; -Set.prototype.contains = function(elt) { - return this.elts.get(elt) !== undefined; +HashSet.prototype.remove = function () { + for (var i = 0; i < arguments.length; i++) { + this._elements.del(arguments[i]); + } + return this; }; -Set.prototype.size = function() { - return this.elts._items; +HashSet.prototype.contains = function (e) { + return this._elements.get(e) !== undefined; }; -module.exports = Set; +module.exports = HashSet; diff --git a/test/data_structures/set.js b/test/data_structures/set.js index 4150135..1038a1b 100644 --- a/test/data_structures/set.js +++ b/test/data_structures/set.js @@ -21,60 +21,62 @@ */ 'use strict'; -var Set = require('../../data_structures/set'), - HashTable = require('../../data_structures/hash_table'), +var HashSet = require('../../data_structures/set'), assert = require('assert'); -describe('Set', function () { +describe('HashSet', function () { it('should start empty', function () { - var s = new Set(); - assert.equal(s.size(), 0); + var s = new HashSet(); + assert.equal(s.size, 0); }); it('should add all initial arguments', function () { - var s = new Set(1,2,3); - var ht = new HashTable(3); - ht.put(1, {}); - ht.put(2,{}); - ht.put(3,{}); - assert.deepEqual(s.elts, ht); + var s = new HashSet(1, 2, 3); + assert.equal(s.size, 3); + assert(s.contains(1)); + assert(s.contains(2)); + assert(s.contains(3)); + }); it('should add all arguments', function () { - var s = new Set(1,2,3); - s.add(4,5,6); - var ht = new HashTable(3); - ht.put(1, {}); - ht.put(2, {}); - ht.put(3,{}); - ht.put(4,{}); - ht.put(5,{}); - ht.put(6,{}); - - assert.deepEqual(s.elts, ht); + var s = new HashSet(1, 2, 3); + assert.equal(s.size, 3); + s.add(4, 5, 6); + assert.equal(s.size, 6); + assert(s.contains(1)); + assert(s.contains(2)); + assert(s.contains(3)); + assert(s.contains(4)); + assert(s.contains(5)); + assert(s.contains(6)); }); - it('should remove all arguments', function() { - var s = new Set(1,2,3); - s.remove(1,3); - assert.equal(s.contains(1), false); - assert.equal(s.contains(3), false); + it('should remove all arguments', function () { + var s = new HashSet(1, 2, 3); + assert.equal(s.size, 3); + s.remove(1, 3); + assert.equal(s.size, 1); + assert(!s.contains(1)); + assert(!s.contains(3)); + assert(s.contains(2)); }); - it('should do nothing xist is removed', function() { - var s = new Set(1,2,3); - s.remove(4); - var ht = new HashTable(3); - ht.put(1, {}); - ht.put(2,{}); - ht.put(3,{}); - assert.deepEqual(s.elts, ht); - }); + it('should do nothing when trying to remove an element that doesn\'t exist', + function () { + var s = new HashSet(1, 2, 3); + assert.equal(s.size, 3); + s.remove(4); + assert.equal(s.size, 3); + assert(s.contains(1)); + assert(s.contains(2)); + assert(s.contains(3)); + }); - it('should only contain its elements', function() { - var s = new Set(1,2,3); - assert.equal(s.contains(1), true); - assert.equal(s.contains(4), false); + it('should only contain its elements', function () { + var s = new HashSet(1, 2, 3); + assert(s.contains(1)); + assert(!s.contains(4)); }); }); From a98dae362879a985028c4c5f59aad83e8b42ccf9 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 9 Jul 2014 17:04:13 +0200 Subject: [PATCH 081/280] Add powerSet and longest common subsequence to main.js --- algorithms/math/power_set.js | 2 +- main.js | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/algorithms/math/power_set.js b/algorithms/math/power_set.js index c4eac21..df5f17e 100644 --- a/algorithms/math/power_set.js +++ b/algorithms/math/power_set.js @@ -60,7 +60,7 @@ var powerSetIterative = function (array) { } } - + return powerSet; }; diff --git a/main.js b/main.js index 0962ff4..0774e42 100644 --- a/main.js +++ b/main.js @@ -38,7 +38,8 @@ var lib = { newtonSqrt: require('./algorithms/math/newton_sqrt'), reservoirSampling: require('./algorithms/math/reservoir_sampling'), fastPower: require('./algorithms/math/fast_power'), - nextPermutation: require('./algorithms/math/next_permutation') + nextPermutation: require('./algorithms/math/next_permutation'), + powerSet: require('./algorithms/math/power_set') }, Search: { bfs: require('./algorithms/searching/bfs'), @@ -60,7 +61,9 @@ var lib = { karpRabin: require('./algorithms/string/karp_rabin'), knuthMorrisPratt: require('./algorithms/string/knuth_morris_pratt'), huffman: require('./algorithms/string/huffman'), - hamming: require('./algorithms/string/hamming') + hamming: require('./algorithms/string/hamming'), + longestCommonSubsequence: require( + './algorithms/string/longest_common_subsequence') }, DataStructure: { BST: require('./data_structures/bst'), From e5c19cf21b8aa4d6b792ba6d1a390a6bb02e0d24 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Thu, 10 Jul 2014 17:30:23 +0200 Subject: [PATCH 082/280] Refactor Rabin Karp and make it behave like String.prototype.indexOf --- algorithms/string/karp_rabin.js | 136 ------------------ algorithms/string/rabin_karp.js | 94 ++++++++++++ main.js | 2 +- .../string/{karp_rabin.js => rabin_karp.js} | 20 ++- 4 files changed, 109 insertions(+), 143 deletions(-) delete mode 100644 algorithms/string/karp_rabin.js create mode 100644 algorithms/string/rabin_karp.js rename test/algorithms/string/{karp_rabin.js => rabin_karp.js} (67%) diff --git a/algorithms/string/karp_rabin.js b/algorithms/string/karp_rabin.js deleted file mode 100644 index 849b0da..0000000 --- a/algorithms/string/karp_rabin.js +++ /dev/null @@ -1,136 +0,0 @@ -/** - * Copyright (C) 2014 Tayllan Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -'use strict'; - -/** - * A prime number used to create - * the hash representation of a word - * - * Bigger the prime number, - * bigger the hash value - */ -var base = 997; - -/** - * Calculates String Matching between two Strings - * Returns true if String 'b' is contained in String 'a' - * - * Average and Best Case Complexity: O(a.length + b.length) - * Worst Case Complexity: O(a.length * b.length) - * - * @param String - * @param String - * @return Boolean - */ -var karpRabin = function (a, b) { - var aLength = a.length; - var bLength = b.length; - var rs = hashFunction(b); - var newString = []; - - for (var i = 0; i < bLength; i++) { - newString.push(a.charAt(i)); - } - - var rt = hashFunction(newString.join('')); - - if (rs === rt && checkEquality(b, newString.join(''))) { - return true; - } - else { - for (i = 1; i < aLength; i++) { - var previousCharacter = newString[0]; - var nextCharacter = a.charAt(i); - - rt = reHash( - bLength, - rt, - previousCharacter, - nextCharacter - ); - newString.shift(); - newString.push(nextCharacter); - - if (rs === rt && checkEquality(b, newString.join(''))) { - return true; - } - } - - return false; - } -}; - -/** - * Checks if 'a' is equal to 'b' - * - * @param String - * @param String - * @return Boolean - */ -var checkEquality = function (a, b) { - var aLength = a.length; - - for (var i = 0; i < aLength; i++) { - if (a.charAt(i) !== b.charAt(i)) { - return false; - } - } - - return true; -}; - -/** - * Creates the hash representation of 'word' - * - * @param String - * @return Number - */ -var hashFunction = function (word) { - var hash = 0; - var wordLength = word.length; - - for (var i = 0, j = wordLength - 1; i < wordLength; i++, j--) { - hash += word.charCodeAt(i) * Math.pow(base, j); - } - - return hash; -}; - -/** - * Recalculates the hash representation of a word so that it isn't - * necessary to traverse the whole word again - * - * @param Number - * @param Number - * @param Character - * @param Character - * @return Number - */ -var reHash = function (length, hash, previousCharacter, nextCharacter) { - hash -= previousCharacter.charCodeAt(0) * Math.pow(base, length - 1); - hash *= base; - hash += nextCharacter.charCodeAt(0); - - return hash; -}; - -module.exports = karpRabin; diff --git a/algorithms/string/rabin_karp.js b/algorithms/string/rabin_karp.js new file mode 100644 index 0000000..b4097b2 --- /dev/null +++ b/algorithms/string/rabin_karp.js @@ -0,0 +1,94 @@ +/** + * Copyright (C) 2014 Tayllan Búrigo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +/** + * A prime number used to create + * the hash representation of a word + * + * Bigger the prime number, + * bigger the hash value + */ +var base = 997; + +/** + * Calculates String Matching between two Strings + * Returns true if String 'b' is contained in String 'a' + * + * Average and Best Case Complexity: O(a.length + b.length) + * Worst Case Complexity: O(a.length * b.length) + * + * @param String + * @param String + * @return Boolean + */ +var rabinKarp = function (s, pattern) { + if (pattern.length === 0) return 0; + + var hashPattern = hash(pattern); + var currentSubstring = s.substring(0, pattern.length); + var hashCurrentSubstring; + + for (var i = pattern.length; i <= s.length; i++) { + if (hashCurrentSubstring === undefined) { + hashCurrentSubstring = hash(currentSubstring); + } else { + /* + * Re-hash + * Recalculates the hash representation of a word so that it isn't + * necessary to traverse the whole word again + */ + hashCurrentSubstring -= currentSubstring.charCodeAt(0) * + Math.pow(base, pattern.length - 1); + hashCurrentSubstring *= base; + hashCurrentSubstring += s.charCodeAt(i); + + currentSubstring = currentSubstring.substring(1) + s[i]; + } + + if (hashPattern === hashCurrentSubstring && + pattern === currentSubstring) { + // Hack for the off-by-one when matching in the beginning of the string + return i === pattern.length ? 0 : i - pattern.length + 1; + } + } + + return -1; +}; + +/** + * Creates the hash representation of 'word' + * + * @param String + * @return Number + */ +var hash = function (word) { + var h = 0; + + for (var i = 0; i < word.length; i++) { + h += word.charCodeAt(i) * Math.pow(base, word.length - i - 1); + } + + return h; +}; + +module.exports = rabinKarp; diff --git a/main.js b/main.js index 0774e42..ad27ecd 100644 --- a/main.js +++ b/main.js @@ -58,7 +58,7 @@ var lib = { }, String: { levenshtein: require('./algorithms/string/levenshtein'), - karpRabin: require('./algorithms/string/karp_rabin'), + rabinKarp: require('./algorithms/string/rabin_karp'), knuthMorrisPratt: require('./algorithms/string/knuth_morris_pratt'), huffman: require('./algorithms/string/huffman'), hamming: require('./algorithms/string/hamming'), diff --git a/test/algorithms/string/karp_rabin.js b/test/algorithms/string/rabin_karp.js similarity index 67% rename from test/algorithms/string/karp_rabin.js rename to test/algorithms/string/rabin_karp.js index 30840be..5e9ddc3 100644 --- a/test/algorithms/string/karp_rabin.js +++ b/test/algorithms/string/rabin_karp.js @@ -21,17 +21,25 @@ */ 'use strict'; -var karpRabin = require('../../../algorithms/string/karp_rabin'), +var rabinKarp = require('../../../algorithms/string/rabin_karp'), assert = require('assert'); +var rabinKarpEqualsToIndexOf = function (a, b) { + assert.equal(rabinKarp(a, b), a.indexOf(b)); +}; + describe('Karp-Rabin', function () { it('should verify if a string is contained in another string', function () { - assert.equal(karpRabin('', ''), true); - assert.equal(karpRabin('a', 'b'), false); - assert.equal(karpRabin('b', 'a'), false); + rabinKarpEqualsToIndexOf('', ''); + rabinKarpEqualsToIndexOf('a', 'b'); + rabinKarpEqualsToIndexOf('b', 'a'); - // ' tes' is contained in 'super test' - assert.equal(karpRabin('super test', ' tes'), true); + rabinKarpEqualsToIndexOf('super test', 's'); + rabinKarpEqualsToIndexOf('super test', 'super'); + rabinKarpEqualsToIndexOf('super test', 'super test'); + rabinKarpEqualsToIndexOf('super test', 'test'); + rabinKarpEqualsToIndexOf('super test', ' tes'); + rabinKarpEqualsToIndexOf('super test x', 'x'); }); }); From a2981ffc5b9df61911e08a547ba67a567b4d9d4b Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Thu, 10 Jul 2014 17:33:08 +0200 Subject: [PATCH 083/280] Fix documentation in Rabin-Karp --- algorithms/string/rabin_karp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/string/rabin_karp.js b/algorithms/string/rabin_karp.js index b4097b2..7722473 100644 --- a/algorithms/string/rabin_karp.js +++ b/algorithms/string/rabin_karp.js @@ -39,7 +39,7 @@ var base = 997; * * @param String * @param String - * @return Boolean + * @return Integer */ var rabinKarp = function (s, pattern) { if (pattern.length === 0) return 0; From e56a52b16623c59c41917d4ff83b4f25a6375500 Mon Sep 17 00:00:00 2001 From: eush77 Date: Wed, 25 Jun 2014 15:45:29 +0400 Subject: [PATCH 084/280] Add logarithmic Fibonacci numbers algorithm --- algorithms/math/fibonacci.js | 36 +++++++++++++++++++++++++++++++ test/algorithms/math/fibonacci.js | 6 ++++++ 2 files changed, 42 insertions(+) diff --git a/algorithms/math/fibonacci.js b/algorithms/math/fibonacci.js index cedf5af..0c167a1 100644 --- a/algorithms/math/fibonacci.js +++ b/algorithms/math/fibonacci.js @@ -28,6 +28,8 @@ 'use strict'; +var power = require('./fast_power'); + /** * Regular fibonacci implementation following the definition: * Fib(0) = 0 @@ -91,8 +93,42 @@ var fibDirect = function (number) { return Math.floor(Math.pow(phi, number) / Math.sqrt(5) + 0.5); }; +/** + * Implementation based on matrix exponentiation. + * O(log(n)) in time, O(1) in space + * + * @author Eugene Sharygin + * @param Number + * @return Number + */ +var fibLogarithmic = function (number) { + // Transforms [f_1, f_0] to [f_2, f_1] and so on. + var nextFib = [[1, 1], [1, 0]]; + + var zeroRow = [0, 0]; + var matrixMultiply = function (matrix1, matrix2) { + return matrix1.map(function (factors) { + return matrix2.reduce(function (sum, row, i) { + return sum.map(function (a, j) { + return a + factors[i] * row[j]; + }); + }, zeroRow); + }); + }; + + var transform = power(nextFib, number, matrixMultiply, [[1, 0], [0, 1]]); + var initialState = [0, 1]; + var finalState = transform.map(function (factors) { + return factors.reduce(function (sum, factor, index) { + return sum + factor * initialState[index]; + }, 0); + }); + return finalState[0]; +}; + // Use fibLinear as the default implementation fibLinear.exponential = fibExponential; fibLinear.withMemoization = fibWithMemoization; fibLinear.direct = fibDirect; +fibLinear.logarithmic = fibLogarithmic; module.exports = fibLinear; diff --git a/test/algorithms/math/fibonacci.js b/test/algorithms/math/fibonacci.js index 4428096..020f73b 100644 --- a/test/algorithms/math/fibonacci.js +++ b/test/algorithms/math/fibonacci.js @@ -64,5 +64,11 @@ describe('Fibonacci', function () { testFibonacciSequence(fib.direct); }); }); + + describe('#logarithmic()', function () { + it('should return the right value for fibonacci sequence', function () { + testFibonacciSequence(fib.logarithmic); + }); + }); }); From cc337d2e886ab1440cfcb43deed0351dd76078c2 Mon Sep 17 00:00:00 2001 From: eush77 Date: Fri, 18 Jul 2014 22:37:47 +0400 Subject: [PATCH 085/280] Fix worst-case DFS complexity --- algorithms/graph/depth_first_search.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/algorithms/graph/depth_first_search.js b/algorithms/graph/depth_first_search.js index 47d96fc..2232925 100644 --- a/algorithms/graph/depth_first_search.js +++ b/algorithms/graph/depth_first_search.js @@ -24,11 +24,11 @@ var time = 0, visitedNodes = {}, finishingTimes = {}; - + /** * Depth First Search for all the vertices in the graph - * Worst Case Complexity: O(V * E) - * + * Worst Case Complexity: O(V + E) + * * @param {Object} * @return {Object} representing the order in which the * vertices are visited @@ -45,8 +45,8 @@ var dfsAdjacencyListStart = function (graph) { /** * Depth First Search for the vertices reachable from 'startNode' - * Worst Case Complexity: O(V * E) - * + * Worst Case Complexity: O(V + E) + * * @param {Object} * @param {Object} * @return {Object} From db400a2589ca5a0ed5c801dcf8c465e9a48544cd Mon Sep 17 00:00:00 2001 From: eush77 Date: Fri, 18 Jul 2014 23:16:41 +0400 Subject: [PATCH 086/280] Reset global state between DFS runs --- algorithms/graph/depth_first_search.js | 44 +++++++++++++-------- test/algorithms/graph/depth_first_search.js | 7 +++- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/algorithms/graph/depth_first_search.js b/algorithms/graph/depth_first_search.js index 2232925..b7d6e1f 100644 --- a/algorithms/graph/depth_first_search.js +++ b/algorithms/graph/depth_first_search.js @@ -21,9 +21,13 @@ */ 'use strict'; -var time = 0, - visitedNodes = {}, - finishingTimes = {}; +var newDfsState = function () { + return { + time: 0, + visitedNodes: {}, + finishingTimes: {} + }; +}; /** * Depth First Search for all the vertices in the graph @@ -34,13 +38,27 @@ var time = 0, * vertices are visited */ var dfsAdjacencyListStart = function (graph) { + var dfsState = newDfsState(); + graph.vertices.forEach(function (v) { - if (visitedNodes[v] !== true) { - dfsAdjacencyList(graph, v); + if (dfsState.visitedNodes[v] !== true) { + dfsInternalLoop(graph, v, dfsState); } }); - return finishingTimes; + return dfsState.finishingTimes; +}; + +var dfsInternalLoop = function (graph, startNode, dfsState) { + dfsState.visitedNodes[startNode] = true; + + graph.neighbors(startNode).forEach(function (v) { + if (dfsState.visitedNodes[v] !== true) { + dfsInternalLoop(graph, v, dfsState); + } + }); + + dfsState.finishingTimes[startNode] = dfsState.time++; }; /** @@ -52,17 +70,9 @@ var dfsAdjacencyListStart = function (graph) { * @return {Object} */ var dfsAdjacencyList = function (graph, startNode) { - visitedNodes[startNode] = true; - - graph.neighbors(startNode).forEach(function (v) { - if (visitedNodes[v] !== true) { - dfsAdjacencyList(graph, v); - } - }); - - finishingTimes[startNode] = time++; - - return finishingTimes; + var dfsState = newDfsState(); + dfsInternalLoop(graph, startNode, dfsState); + return dfsState.finishingTimes; }; var depthFirstSearch = { diff --git a/test/algorithms/graph/depth_first_search.js b/test/algorithms/graph/depth_first_search.js index a8aed0a..c29c61a 100644 --- a/test/algorithms/graph/depth_first_search.js +++ b/test/algorithms/graph/depth_first_search.js @@ -34,7 +34,7 @@ graph.addEdge('three', 'one'); graph.addEdge('five', 'six'); describe('Depth First Search Algorithm', function () { - it('should visit only the nodes reachable from the node {one} (inclusive)', + it('should visit only the nodes reachable from the start node (inclusive)', function () { var finishingTimes = depthFirstSearch.dfsAdjacencyList(graph, 'one'); @@ -45,6 +45,11 @@ describe('Depth First Search Algorithm', function () { assert.equal(finishingTimes.two, 1); assert.equal(finishingTimes.three, 0); assert.equal(finishingTimes.four, 2); + + // Finishing times for different calls shouldn't interfere. + finishingTimes = depthFirstSearch.dfsAdjacencyList(graph, 'five'); + assert.equal(finishingTimes.six, 0); + assert.equal(finishingTimes.five, 1); } ); From 5c1bc9e54f3f28a6450879e49bac18bdbda58481 Mon Sep 17 00:00:00 2001 From: eush77 Date: Sat, 19 Jul 2014 14:37:02 +0400 Subject: [PATCH 087/280] Add Kruskal's minimum spanning tree algorithm --- algorithms/graph/kruskal.js | 71 +++++++ .../algorithms/graph/minimum_spanning_tree.js | 201 ++++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 algorithms/graph/kruskal.js create mode 100644 test/algorithms/graph/minimum_spanning_tree.js diff --git a/algorithms/graph/kruskal.js b/algorithms/graph/kruskal.js new file mode 100644 index 0000000..b637aed --- /dev/null +++ b/algorithms/graph/kruskal.js @@ -0,0 +1,71 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var DisjointSetForest = require('../../data_structures/disjoint_set_forest'), + Graph = require('../../data_structures/graph'); + + +/** + * Kruskal's minimum spanning tree (forest) algorithm. + * Complexity: O(E * log(V)). + * + * @param {Graph} graph - Undirected graph. + * @return {Graph} Minimum spanning tree or forest + * (depending on whether input graph is connected itself). + */ +var kruskal = function (graph) { + if (graph.directed) { + throw new Error('Can\'t build MST of a directed graph.'); + } + + var connectedComponents = new DisjointSetForest(); + var mst = new Graph(false); + graph.vertices.forEach(mst.addVertex.bind(mst)); + + var edges = graph.vertices.reduce(function (edges, vertex) { + graph.neighbors(vertex).forEach(function (neighbor) { + // Compared as strings, loops intentionally omitted. + if (vertex < neighbor) { + edges.push({ + ends: [vertex, neighbor], + weight: graph.edge(vertex, neighbor) + }); + } + }); + return edges; + }, []); + + edges.sort(function (a, b) { + return a.weight - b.weight; + }).forEach(function (edge) { + if (!connectedComponents.sameSubset(edge.ends[0], edge.ends[1])) { + mst.addEdge(edge.ends[0], edge.ends[1], edge.weight); + connectedComponents.merge(edge.ends[0], edge.ends[1]); + } + }); + + return mst; +}; + + +module.exports = kruskal; diff --git a/test/algorithms/graph/minimum_spanning_tree.js b/test/algorithms/graph/minimum_spanning_tree.js new file mode 100644 index 0000000..8db2383 --- /dev/null +++ b/test/algorithms/graph/minimum_spanning_tree.js @@ -0,0 +1,201 @@ +/** + * Copyright (C) 2014 Eugene Sharygin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"], to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +'use strict'; + +var kruskal = require('../../../algorithms/graph/kruskal'), + Graph = require('../../../data_structures/graph'), + assert = require('assert'); + + +/** + * @param {Graph} graph - Undirected graph. + * @return {number} + */ +var numberOfConnectedComponents = function (graph) { + assert(!graph.directed); + var seen = {}; + var coverComponent = function dfs(start) { + if (!seen[start]) { + seen[start] = true; + graph.neighbors(start).forEach(dfs); + } + }; + return graph.vertices.reduce(function (count, vertex) { + if (seen[vertex]) { + return count; + } + else { + coverComponent(vertex); + return count + 1; + } + }, 0); +}; + + +/** + * Test whether graph is a valid (undirected) forest. + * In a forest #vertices = #edges + #components. + * + * @param {Graph} graph + * @param {number} connectivity + * @return {boolean} + */ +var isForest = function (graph, connectivity) { + if (graph.directed || numberOfConnectedComponents(graph) != connectivity) { + return false; + } + var numberOfEdges = graph.vertices.reduce(function (numberOfEdges, vertex) { + return numberOfEdges + graph.neighbors(vertex).filter(function (neighbor) { + return vertex <= neighbor; + }).length; + }, 0); + return graph.vertices.length == numberOfEdges + connectivity; +}; + + +/** + * Test whether two graphs share the same vertex set. + * + * @param {Graph} graph1 + * @param {Graph} graph2 + * @return {boolean} + */ +var spans = function (graph1, graph2) { + var str = function (graph) { + return JSON.stringify(graph.vertices.sort()); + }; + return str(graph1) == str(graph2); +}; + + +/** + * Sum up graph edge weights. + * + * @param {Graph} graph + * @return {?number} Null if the graph contains no edges. + */ +var graphCost = function (graph) { + var noEdges = true; + var total = graph.vertices.reduce(function (cost, vertex) { + return cost + graph.neighbors(vertex).reduce(function (cost, neighbor) { + noEdges = false; + return cost + graph.edge(vertex, neighbor); + }, 0); + }, 0); + return noEdges ? null : graph.directed ? total : total / 2; +}; + + +/** + * Test whether one graph is the minimum spanning forest of the other. + * + * @param {Graph} suspect + * @param {Graph} graph - Undirected graph. + * @param {?number} minimumCost + * @param {number} [connectivity=1] + * @return {boolean} + */ +var isMinimumSpanningForest = function (suspect, graph, + minimumCost, connectivity) { + assert(!graph.directed); + return isForest(suspect, connectivity || 1) && + spans(suspect, graph) && + graphCost(suspect) === minimumCost; +}; + + +var testMstAlgorithm = function (mst) { + it('should find a minimum spanning tree', function () { + var graph = new Graph(false); + graph.addEdge(1, 2, 1); + graph.addEdge(1, 4, 2); + graph.addEdge(1, 5, 2); + graph.addEdge(4, 2, 2); + graph.addEdge(4, 5, 1); + graph.addEdge(5, 6, 1); + graph.addEdge(6, 4, 8); + graph.addEdge(6, 3, 2); + graph.addEdge(2, 3, 3); + assert(isMinimumSpanningForest(mst(graph), graph, 7)); + + // Change (4, 5) weight to 3. + graph.addEdge(4, 5, +2); + assert(isMinimumSpanningForest(mst(graph), graph, 8)); + + // Force it go find another way to reach (6). + graph.addEdge(4, 5, +5); + graph.addEdge(6, 5, +7); + assert(isMinimumSpanningForest(mst(graph), graph, 10)); + + // It should find zero-cost MST. + var clear = function (a, b) { + graph.addEdge(a, b, -graph.edge(a, b)); + }; + clear(2, 1); + clear(1, 5); + clear(5, 6); + clear(6, 4); + clear(6, 3); + assert(isMinimumSpanningForest(mst(graph), graph, 0)); + + // But prefer a negative-cost one to it. + graph.addEdge(2, 4, -102); + assert(isMinimumSpanningForest(mst(graph), graph, -100)); + }); + + it('should find a minimum spaning forest if the graph is not connected', + function () { + var graph = new Graph(false); + graph.addVertex(1); + graph.addVertex(2); + graph.addVertex(3); + assert(isMinimumSpanningForest(mst(graph), graph, null, 3)); + + graph.addEdge(1, 2, 2); + assert(isMinimumSpanningForest(mst(graph), graph, 2, 2)); + + graph.addEdge(1, 3, 1); + graph.addEdge(2, 3, -1); + assert(isMinimumSpanningForest(mst(graph), graph, 0, 1)); + + graph.addVertex(4); + assert(isMinimumSpanningForest(mst(graph), graph, 0, 2)); + + graph.addEdge(5, 6, 1); + assert(isMinimumSpanningForest(mst(graph), graph, 1, 3)); + + graph.addEdge(5, 4, -100); + graph.addEdge(6, 4, -100); + assert(isMinimumSpanningForest(mst(graph), graph, -200, 2)); + }); + + it('should throw an error if the graph is directed', function () { + var directedGraph = new Graph(true); + directedGraph.addEdge('Rock', 'Hard Place'); + assert.throws(mst.bind(null, directedGraph)); + }); +}; + + +describe('Minimum Spanning Tree', function () { + describe('#Kruskal\'s Algorithm', testMstAlgorithm.bind(null, kruskal)); +}); From 27c3dc33f0b4630bfa98eb2616223c6c8919a9f3 Mon Sep 17 00:00:00 2001 From: eush77 Date: Tue, 22 Jul 2014 02:02:15 +0400 Subject: [PATCH 088/280] Simplify matrix operations Matrix-matrix and matrix-vector multiplication subroutines were monstrous and way too complicated for this 2x2 case. No generality is needed here. --- algorithms/math/fibonacci.js | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/algorithms/math/fibonacci.js b/algorithms/math/fibonacci.js index 0c167a1..114cbff 100644 --- a/algorithms/math/fibonacci.js +++ b/algorithms/math/fibonacci.js @@ -105,25 +105,19 @@ var fibLogarithmic = function (number) { // Transforms [f_1, f_0] to [f_2, f_1] and so on. var nextFib = [[1, 1], [1, 0]]; - var zeroRow = [0, 0]; - var matrixMultiply = function (matrix1, matrix2) { - return matrix1.map(function (factors) { - return matrix2.reduce(function (sum, row, i) { - return sum.map(function (a, j) { - return a + factors[i] * row[j]; - }); - }, zeroRow); - }); + var matrixMultiply = function (a, b) { + return [[a[0][0] * b[0][0] + a[0][1] * b[1][0], + a[0][0] * b[0][1] + a[0][1] * b[1][1]], + [a[1][0] * b[0][0] + a[1][1] * b[1][0], + a[1][0] * b[0][1] + a[1][1] * b[1][1]]]; }; var transform = power(nextFib, number, matrixMultiply, [[1, 0], [0, 1]]); - var initialState = [0, 1]; - var finalState = transform.map(function (factors) { - return factors.reduce(function (sum, factor, index) { - return sum + factor * initialState[index]; - }, 0); - }); - return finalState[0]; + + // [f_n, f_{n-1}] = Transform * [f_0, f_{-1}] = Transform * [0, 1] + // Hence the result is the first row of Transform multiplied by [0, 1], + // which is the same as transform[0][1]. + return transform[0][1]; }; // Use fibLinear as the default implementation From 259d3efb96ee14183ace35dfc680bf947945151b Mon Sep 17 00:00:00 2001 From: eush77 Date: Tue, 22 Jul 2014 13:45:06 +0400 Subject: [PATCH 089/280] Include Kruskal's algorithm in main.js --- main.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main.js b/main.js index ad27ecd..45fe369 100644 --- a/main.js +++ b/main.js @@ -28,7 +28,8 @@ var lib = { SPFA: require('./algorithms/graph/SPFA'), bellmanFord: require('./algorithms/graph/bellman_ford'), eulerPath: require('./algorithms/graph/euler_path'), - depthFirstSearch: require('./algorithms/graph/depth_first_search') + depthFirstSearch: require('./algorithms/graph/depth_first_search'), + kruskal: require('./algorithms/graph/kruskal'), }, Math: { fibonacci: require('./algorithms/math/fibonacci'), From 46df427f2c2d9b097686eee625a554fdefc23f1f Mon Sep 17 00:00:00 2001 From: eush77 Date: Wed, 23 Jul 2014 13:51:09 +0400 Subject: [PATCH 090/280] Generalize DFS, make use of it in other algorithms --- algorithms/graph/depth_first_search.js | 109 +++++++++++------- algorithms/graph/euler_path.js | 23 ++-- algorithms/graph/topological_sort.js | 32 +++-- test/algorithms/graph/depth_first_search.js | 64 ++++++---- .../algorithms/graph/minimum_spanning_tree.js | 12 +- 5 files changed, 142 insertions(+), 98 deletions(-) diff --git a/algorithms/graph/depth_first_search.js b/algorithms/graph/depth_first_search.js index b7d6e1f..64537a0 100644 --- a/algorithms/graph/depth_first_search.js +++ b/algorithms/graph/depth_first_search.js @@ -1,5 +1,6 @@ /** * Copyright (C) 2014 Tayllan Búrigo + * Copyright (C) 2014 Eugene Sharygin * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"], to @@ -21,63 +22,87 @@ */ 'use strict'; -var newDfsState = function () { - return { - time: 0, - visitedNodes: {}, - finishingTimes: {} - }; -}; /** - * Depth First Search for all the vertices in the graph - * Worst Case Complexity: O(V + E) - * - * @param {Object} - * @return {Object} representing the order in which the - * vertices are visited + * @typedef {Object} Callbacks + * @param {function(vertex: *, neighbor: *): boolean} allowTraversal - + * Determines whether DFS should traverse from the vertex to its neighbor + * (along the edge). By default prohibits visiting the same vertex again. + * @param {function(vertex: *, neighbor: *)} beforeTraversal - Called before + * recursive DFS call. + * @param {function(vertex: *, neighbor: *)} afterTraversal - Called after + * recursive DFS call. + * @param {function(vertex: *)} enterVertex - Called when DFS enters the vertex. + * @param {function(vertex: *)} leaveVertex - Called when DFS leaves the vertex. */ -var dfsAdjacencyListStart = function (graph) { - var dfsState = newDfsState(); - graph.vertices.forEach(function (v) { - if (dfsState.visitedNodes[v] !== true) { - dfsInternalLoop(graph, v, dfsState); - } - }); - return dfsState.finishingTimes; -}; +/** + * Fill in missing callbacks. + * @param {Callbacks} callbacks + * @param {Array} [seenVertices] - Vertices already discovered, + * used by default allowTraversal implementation. + * @return {Callbacks} The same object or new one (if null passed). + */ +var normalizeCallbacks = function (callbacks, seenVertices) { + callbacks = callbacks || {}; -var dfsInternalLoop = function (graph, startNode, dfsState) { - dfsState.visitedNodes[startNode] = true; + callbacks.allowTraversal = callbacks.allowTraversal || (function () { + var seen = (seenVertices || []).reduce(function (seen, vertex) { + seen[vertex] = true; + return seen; + }, {}); - graph.neighbors(startNode).forEach(function (v) { - if (dfsState.visitedNodes[v] !== true) { - dfsInternalLoop(graph, v, dfsState); - } - }); + return function (vertex, neighbor) { + // It should still be possible to redefine other callbacks, + // so we better do all at once here. - dfsState.finishingTimes[startNode] = dfsState.time++; + if (!seen[neighbor]) { + seen[neighbor] = true; + return true; + } + else { + return false; + } + }; + }()); + + var noop = function () {}; + callbacks.beforeTraversal = callbacks.beforeTraversal || noop; + callbacks.afterTraversal = callbacks.afterTraversal || noop; + callbacks.enterVertex = callbacks.enterVertex || noop; + callbacks.leaveVertex = callbacks.leaveVertex || noop; + + return callbacks; }; + /** - * Depth First Search for the vertices reachable from 'startNode' - * Worst Case Complexity: O(V + E) + * Run Depth-First Search from a start vertex. + * Worst-case complexity: O(V + E). * - * @param {Object} - * @param {Object} - * @return {Object} + * @param {Graph} graph + * @param {*} startVertex + * @param {Callbacks} [callbacks] */ -var dfsAdjacencyList = function (graph, startNode) { - var dfsState = newDfsState(); - dfsInternalLoop(graph, startNode, dfsState); - return dfsState.finishingTimes; +var depthFirstSearch = function (graph, startVertex, callbacks) { + dfsLoop(graph, startVertex, normalizeCallbacks(callbacks, [startVertex])); }; -var depthFirstSearch = { - dfsAdjacencyList: dfsAdjacencyList, - dfsAdjacencyListStart: dfsAdjacencyListStart + +var dfsLoop = function dfsLoop(graph, vertex, callbacks) { + callbacks.enterVertex(vertex); + + graph.neighbors(vertex).forEach(function (neighbor) { + if (callbacks.allowTraversal(vertex, neighbor)) { + callbacks.beforeTraversal(vertex, neighbor); + dfsLoop(graph, neighbor, callbacks); + callbacks.afterTraversal(vertex, neighbor); + } + }); + + callbacks.leaveVertex(vertex); }; + module.exports = depthFirstSearch; diff --git a/algorithms/graph/euler_path.js b/algorithms/graph/euler_path.js index acd0e71..56c4559 100644 --- a/algorithms/graph/euler_path.js +++ b/algorithms/graph/euler_path.js @@ -22,7 +22,8 @@ 'use strict'; -var Graph = require('../../data_structures/graph'); +var Graph = require('../../data_structures/graph'), + depthFirstSearch = require('../../algorithms/graph/depth_first_search'); /** Examine a graph and compute pair of end vertices of the existing Euler path. @@ -115,15 +116,17 @@ var eulerPath = function (graph) { var seen = new Graph(graph.directed); graph.vertices.forEach(seen.addVertex.bind(seen)); - (function dfs(vertex) { - graph.neighbors(vertex).forEach(function (neighbor) { - if (!seen.edge(vertex, neighbor)) { - seen.addEdge(vertex, neighbor); - dfs(neighbor); - route.push(vertex); - } - }); - }(endpoints.start)); + depthFirstSearch(graph, endpoints.start, { + allowTraversal: function (vertex, neighbor) { + return !seen.edge(vertex, neighbor); + }, + beforeTraversal: function (vertex, neighbor) { + seen.addEdge(vertex, neighbor); + }, + afterTraversal: function (vertex) { + route.push(vertex); + } + }); graph.vertices.forEach(function (vertex) { if (seen.neighbors(vertex).length < graph.neighbors(vertex).length) { diff --git a/algorithms/graph/topological_sort.js b/algorithms/graph/topological_sort.js index 8b07f85..477ed6f 100644 --- a/algorithms/graph/topological_sort.js +++ b/algorithms/graph/topological_sort.js @@ -21,7 +21,8 @@ */ 'use strict'; -var Stack = require('../../data_structures/stack'); +var Stack = require('../../data_structures/stack'), + depthFirstSearch = require('../../algorithms/graph/depth_first_search'); /** * Sorts the edges of the DAG topologically @@ -40,26 +41,21 @@ var Stack = require('../../data_structures/stack'); var topologicalSort = function (graph) { var stack = new Stack(); var firstHit = {}; - var secondHit = {}; var time = 0; - /** - * Depth first search for a directed acyclic graph (DAG) - */ - var dagDFS = function (node) { - if (firstHit[node]) return; - var neighbors = graph.neighbors(node); - firstHit[node] = ++time; - for (var i = 0; i < neighbors.length; i++) { - dagDFS(neighbors[i]); - } - secondHit[node] = ++time; - stack.push(node); - }; - graph.vertices.forEach(function (node) { - if (!secondHit[node]) { - dagDFS(node); + if (!firstHit[node]) { + depthFirstSearch(graph, node, { + allowTraversal: function (node, neighbor) { + return !firstHit[neighbor]; + }, + enterVertex: function (node) { + firstHit[node] = ++time; + }, + leaveVertex: function (node) { + stack.push(node); + } + }); } }); diff --git a/test/algorithms/graph/depth_first_search.js b/test/algorithms/graph/depth_first_search.js index c29c61a..ec03e96 100644 --- a/test/algorithms/graph/depth_first_search.js +++ b/test/algorithms/graph/depth_first_search.js @@ -36,34 +36,52 @@ graph.addEdge('five', 'six'); describe('Depth First Search Algorithm', function () { it('should visit only the nodes reachable from the start node (inclusive)', function () { - var finishingTimes = depthFirstSearch.dfsAdjacencyList(graph, 'one'); + var enter = [], leave = []; + var numEdgeTails = 0, numEdgeHeads = 0; - assert.equal(finishingTimes.five, undefined); - assert.equal(finishingTimes.six, undefined); + var dfsCallbacks = { + enterVertex: [].push.bind(enter), + leaveVertex: [].push.bind(leave), + beforeTraversal: function () { + numEdgeHeads += 1; + }, + afterTraversal: function () { + numEdgeTails += 1; + } + }; - assert.equal(finishingTimes.one, 3); - assert.equal(finishingTimes.two, 1); - assert.equal(finishingTimes.three, 0); - assert.equal(finishingTimes.four, 2); + depthFirstSearch(graph, 'one', dfsCallbacks); + assert.deepEqual(enter, ['one', 'three', 'four', 'two']); + assert.deepEqual(leave, ['three', 'two', 'four', 'one']); + assert.equal(numEdgeTails, numEdgeHeads); + assert.equal(numEdgeHeads, 3); - // Finishing times for different calls shouldn't interfere. - finishingTimes = depthFirstSearch.dfsAdjacencyList(graph, 'five'); - assert.equal(finishingTimes.six, 0); - assert.equal(finishingTimes.five, 1); + enter.splice(0, 4); + leave.splice(0, 4); + depthFirstSearch(graph, 'five', dfsCallbacks); + assert.deepEqual(enter, ['five', 'six']); + assert.deepEqual(leave, ['six', 'five']); + assert.equal(numEdgeTails, numEdgeHeads); + assert.equal(numEdgeHeads, 4); } ); - it('should visit all the nodes in the graph', - function () { - var finishingTimes = depthFirstSearch.dfsAdjacencyListStart(graph); + it('should allow user-defined allowTraversal rules', function () { + var seen = new Graph(graph.directed); + graph.vertices.forEach(seen.addVertex.bind(seen)); + var path = ['one']; - assert.equal(finishingTimes.one, 3); - assert.equal(finishingTimes.two, 1); - assert.equal(finishingTimes.three, 0); - assert.equal(finishingTimes.four, 2); - assert.equal(finishingTimes.five, 5); - assert.equal(finishingTimes.six, 4); - } - ); -}); + // Edge-centric DFS. + depthFirstSearch(graph, path[0], { + allowTraversal: function (vertex, neighbor) { + return !seen.edge(vertex, neighbor); + }, + beforeTraversal: function (vertex, neighbor) { + seen.addEdge(vertex, neighbor); + path.push(neighbor); + } + }); + assert.deepEqual(path, ['one', 'three', 'one', 'four', 'two', 'one']); + }); +}); diff --git a/test/algorithms/graph/minimum_spanning_tree.js b/test/algorithms/graph/minimum_spanning_tree.js index 8db2383..a5b0107 100644 --- a/test/algorithms/graph/minimum_spanning_tree.js +++ b/test/algorithms/graph/minimum_spanning_tree.js @@ -23,6 +23,7 @@ var kruskal = require('../../../algorithms/graph/kruskal'), Graph = require('../../../data_structures/graph'), + depthFirstSearch = require('../../../algorithms/graph/depth_first_search'), assert = require('assert'); @@ -33,11 +34,12 @@ var kruskal = require('../../../algorithms/graph/kruskal'), var numberOfConnectedComponents = function (graph) { assert(!graph.directed); var seen = {}; - var coverComponent = function dfs(start) { - if (!seen[start]) { - seen[start] = true; - graph.neighbors(start).forEach(dfs); - } + var coverComponent = function (origin) { + depthFirstSearch(graph, origin, { + enterVertex: function (vertex) { + seen[vertex] = true; + } + }); }; return graph.vertices.reduce(function (count, vertex) { if (seen[vertex]) { From 060d593adcd46c2d7af488a793910c65f737caa1 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 23 Jul 2014 15:44:18 +0200 Subject: [PATCH 091/280] Contributors list --- AUTHORS | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 AUTHORS diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..5bedf36 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,14 @@ +felipernb - Felipe Ribeiro +anaran +apoliveira - Andre P. Oliveira +BrunoRB - Bruno Roberto Búrigo +dingshu - Shu Ding +eush77 - Eugene Sharygin +gauravmittal1995 - Gaurav Mittal +geakstr - Dmitry Kharitonov +joshuacurl - Joshua Curl +liamgriffiths - Liam Griffiths +lifebeyondfife - Iain McDonald +mastermatt - Matt R. Wilson +nitinsaroha - Nitin Saroha +tayllan - Tayllan Búrigo From b3718d0971f0b9b0c71a0efdd3fb17dec73b383f Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 23 Jul 2014 17:33:18 +0200 Subject: [PATCH 092/280] Remove license text from source files --- LICENSE | 21 +++++++++++++++++ algorithms/graph/SPFA.js | 21 ----------------- algorithms/graph/bellman_ford.js | 21 ----------------- algorithms/graph/depth_first_search.js | 22 ------------------ algorithms/graph/dijkstra.js | 21 ----------------- algorithms/graph/euler_path.js | 21 ----------------- algorithms/graph/kruskal.js | 21 ----------------- algorithms/graph/topological_sort.js | 21 ----------------- algorithms/math/extended_euclidean.js | 22 ------------------ algorithms/math/fast_power.js | 21 ----------------- algorithms/math/fibonacci.js | 22 ------------------ algorithms/math/fisher_yates.js | 21 ----------------- algorithms/math/gcd.js | 22 ------------------ algorithms/math/newton_sqrt.js | 22 ------------------ algorithms/math/next_permutation.js | 21 ----------------- algorithms/math/power_set.js | 22 ------------------ algorithms/math/reservoir_sampling.js | 21 ----------------- algorithms/searching/bfs.js | 21 ----------------- algorithms/searching/binarysearch.js | 22 ------------------ algorithms/searching/dfs.js | 21 ----------------- algorithms/sorting/bubble_sort.js | 21 ----------------- algorithms/sorting/counting_sort.js | 21 ----------------- algorithms/sorting/heap_sort.js | 21 ----------------- algorithms/sorting/insertion_sort.js | 21 ----------------- algorithms/sorting/merge_sort.js | 21 ----------------- algorithms/sorting/quicksort.js | 21 ----------------- algorithms/sorting/radix_sort.js | 21 ----------------- algorithms/sorting/selection_sort.js | 23 +------------------ algorithms/string/huffman.js | 21 ----------------- algorithms/string/knuth_morris_pratt.js | 21 ----------------- algorithms/string/levenshtein.js | 21 ----------------- .../string/longest_common_subsequence.js | 22 ------------------ algorithms/string/rabin_karp.js | 21 ----------------- data_structures/bst.js | 21 ----------------- data_structures/disjoint_set_forest.js | 22 ------------------ data_structures/graph.js | 21 ----------------- data_structures/hash_table.js | 21 ----------------- data_structures/heap.js | 21 ----------------- data_structures/linked_list.js | 21 ----------------- data_structures/priority_queue.js | 21 ----------------- data_structures/queue.js | 21 ----------------- data_structures/set.js | 21 ----------------- data_structures/stack.js | 21 ----------------- main.js | 21 ----------------- test/algorithms/graph/SPFA.js | 21 ----------------- test/algorithms/graph/bellman_ford.js | 21 ----------------- test/algorithms/graph/depth_first_search.js | 21 ----------------- test/algorithms/graph/dijkstra.js | 21 ----------------- test/algorithms/graph/euler_path.js | 21 ----------------- .../algorithms/graph/minimum_spanning_tree.js | 21 ----------------- test/algorithms/graph/topological_sort.js | 21 ----------------- test/algorithms/math/extended_euclidean.js | 21 ----------------- test/algorithms/math/fast_power.js | 21 ----------------- test/algorithms/math/fibonacci.js | 21 ----------------- test/algorithms/math/fisher_yates.js | 21 ----------------- test/algorithms/math/gcd.js | 21 ----------------- test/algorithms/math/newton_sqrt.js | 21 ----------------- test/algorithms/math/next_permutation.js | 21 ----------------- test/algorithms/math/power_set.js | 21 ----------------- test/algorithms/math/reservoir_sampling.js | 21 ----------------- test/algorithms/searching/bfs.js | 21 ----------------- test/algorithms/searching/binarysearch.js | 21 ----------------- test/algorithms/searching/dfs.js | 21 ----------------- test/algorithms/sorting/bubble_sort.js | 21 ----------------- test/algorithms/sorting/counting_sort.js | 21 ----------------- test/algorithms/sorting/heap_sort.js | 21 ----------------- test/algorithms/sorting/insertion_sort.js | 21 ----------------- test/algorithms/sorting/merge_sort.js | 21 ----------------- test/algorithms/sorting/quicksort.js | 21 ----------------- test/algorithms/sorting/radix_sort.js | 21 ----------------- test/algorithms/sorting/selection_sort.js | 21 ----------------- test/algorithms/string/huffman.js | 21 ----------------- test/algorithms/string/knuth_morris_pratt.js | 21 ----------------- test/algorithms/string/levenshtein.js | 21 ----------------- .../string/longest_common_subseqence.js | 21 ----------------- test/algorithms/string/rabin_karp.js | 21 ----------------- test/data_structures/bst.js | 21 ----------------- test/data_structures/disjoint_set_forest.js | 21 ----------------- test/data_structures/graph.js | 21 ----------------- test/data_structures/hash_table.js | 21 ----------------- test/data_structures/heap.js | 21 ----------------- test/data_structures/linked_list.js | 21 ----------------- test/data_structures/priority_queue.js | 21 ----------------- test/data_structures/queue.js | 21 ----------------- test/data_structures/set.js | 21 ----------------- test/data_structures/stack.js | 21 ----------------- test/util/comparator.js | 21 ----------------- test/util/npm-debug.log | 19 --------------- util/comparator.js | 21 ----------------- 89 files changed, 22 insertions(+), 1856 deletions(-) create mode 100644 LICENSE delete mode 100644 test/util/npm-debug.log diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..af77b3e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Felipe Ribeiro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/algorithms/graph/SPFA.js b/algorithms/graph/SPFA.js index d60c5b1..89fd14d 100644 --- a/algorithms/graph/SPFA.js +++ b/algorithms/graph/SPFA.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Shu Ding - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; /** diff --git a/algorithms/graph/bellman_ford.js b/algorithms/graph/bellman_ford.js index a3d76a3..475e9b8 100644 --- a/algorithms/graph/bellman_ford.js +++ b/algorithms/graph/bellman_ford.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Tayllan Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; /** diff --git a/algorithms/graph/depth_first_search.js b/algorithms/graph/depth_first_search.js index 64537a0..657a221 100644 --- a/algorithms/graph/depth_first_search.js +++ b/algorithms/graph/depth_first_search.js @@ -1,25 +1,3 @@ -/** - * Copyright (C) 2014 Tayllan Búrigo - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"], to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; diff --git a/algorithms/graph/dijkstra.js b/algorithms/graph/dijkstra.js index 498b1ef..1c39455 100644 --- a/algorithms/graph/dijkstra.js +++ b/algorithms/graph/dijkstra.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var PriorityQueue = require('../../data_structures/priority_queue'); diff --git a/algorithms/graph/euler_path.js b/algorithms/graph/euler_path.js index 56c4559..5cf0f2d 100644 --- a/algorithms/graph/euler_path.js +++ b/algorithms/graph/euler_path.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; diff --git a/algorithms/graph/kruskal.js b/algorithms/graph/kruskal.js index b637aed..0d4d782 100644 --- a/algorithms/graph/kruskal.js +++ b/algorithms/graph/kruskal.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var DisjointSetForest = require('../../data_structures/disjoint_set_forest'), diff --git a/algorithms/graph/topological_sort.js b/algorithms/graph/topological_sort.js index 477ed6f..0d4176f 100644 --- a/algorithms/graph/topological_sort.js +++ b/algorithms/graph/topological_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Stack = require('../../data_structures/stack'), diff --git a/algorithms/math/extended_euclidean.js b/algorithms/math/extended_euclidean.js index 4ada133..4cfb5f2 100644 --- a/algorithms/math/extended_euclidean.js +++ b/algorithms/math/extended_euclidean.js @@ -1,25 +1,3 @@ -/** - * Copyright (C) 2014 Shu Ding - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - 'use strict'; /** diff --git a/algorithms/math/fast_power.js b/algorithms/math/fast_power.js index de80c37..a3d7a91 100644 --- a/algorithms/math/fast_power.js +++ b/algorithms/math/fast_power.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; diff --git a/algorithms/math/fibonacci.js b/algorithms/math/fibonacci.js index 114cbff..da4506c 100644 --- a/algorithms/math/fibonacci.js +++ b/algorithms/math/fibonacci.js @@ -1,25 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - /** * Different implementations of the Fibonacci sequence * diff --git a/algorithms/math/fisher_yates.js b/algorithms/math/fisher_yates.js index fcc5f13..dad2828 100644 --- a/algorithms/math/fisher_yates.js +++ b/algorithms/math/fisher_yates.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; /** diff --git a/algorithms/math/gcd.js b/algorithms/math/gcd.js index e45cb2d..7468778 100644 --- a/algorithms/math/gcd.js +++ b/algorithms/math/gcd.js @@ -1,25 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - 'use strict'; /** diff --git a/algorithms/math/newton_sqrt.js b/algorithms/math/newton_sqrt.js index 7b32208..4113e89 100644 --- a/algorithms/math/newton_sqrt.js +++ b/algorithms/math/newton_sqrt.js @@ -1,25 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - 'use strict'; /** diff --git a/algorithms/math/next_permutation.js b/algorithms/math/next_permutation.js index b88fb55..eacdc77 100644 --- a/algorithms/math/next_permutation.js +++ b/algorithms/math/next_permutation.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Comparator = require('../../util/comparator'); diff --git a/algorithms/math/power_set.js b/algorithms/math/power_set.js index df5f17e..3349085 100644 --- a/algorithms/math/power_set.js +++ b/algorithms/math/power_set.js @@ -1,25 +1,3 @@ -/** - * Copyright (C) 2014 Joshua Curl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - /** * Iterative and recursive implementations of power set * diff --git a/algorithms/math/reservoir_sampling.js b/algorithms/math/reservoir_sampling.js index 1950691..3d7694d 100644 --- a/algorithms/math/reservoir_sampling.js +++ b/algorithms/math/reservoir_sampling.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; diff --git a/algorithms/searching/bfs.js b/algorithms/searching/bfs.js index 6107fdd..98bcfac 100644 --- a/algorithms/searching/bfs.js +++ b/algorithms/searching/bfs.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Queue = require('../../data_structures/queue.js'); diff --git a/algorithms/searching/binarysearch.js b/algorithms/searching/binarysearch.js index d456ace..132d8bd 100644 --- a/algorithms/searching/binarysearch.js +++ b/algorithms/searching/binarysearch.js @@ -1,25 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - 'use strict'; /** diff --git a/algorithms/searching/dfs.js b/algorithms/searching/dfs.js index 06a2a94..f64fb1f 100644 --- a/algorithms/searching/dfs.js +++ b/algorithms/searching/dfs.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; /** diff --git a/algorithms/sorting/bubble_sort.js b/algorithms/sorting/bubble_sort.js index e077824..cafad17 100644 --- a/algorithms/sorting/bubble_sort.js +++ b/algorithms/sorting/bubble_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Comparator = require('../../util/comparator'); diff --git a/algorithms/sorting/counting_sort.js b/algorithms/sorting/counting_sort.js index 8671db8..0814b34 100644 --- a/algorithms/sorting/counting_sort.js +++ b/algorithms/sorting/counting_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Tayllan Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; /** diff --git a/algorithms/sorting/heap_sort.js b/algorithms/sorting/heap_sort.js index de1a11e..9d8f53e 100644 --- a/algorithms/sorting/heap_sort.js +++ b/algorithms/sorting/heap_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Iain McDonald - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var MinHeap = require('../../data_structures/heap').MinHeap; diff --git a/algorithms/sorting/insertion_sort.js b/algorithms/sorting/insertion_sort.js index 08316c2..8fef2a0 100644 --- a/algorithms/sorting/insertion_sort.js +++ b/algorithms/sorting/insertion_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Bruno Roberto Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Comparator = require('../../util/comparator'); diff --git a/algorithms/sorting/merge_sort.js b/algorithms/sorting/merge_sort.js index cba63e4..358b3e2 100644 --- a/algorithms/sorting/merge_sort.js +++ b/algorithms/sorting/merge_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Comparator = require('../../util/comparator'); diff --git a/algorithms/sorting/quicksort.js b/algorithms/sorting/quicksort.js index df6aefa..4df58bd 100644 --- a/algorithms/sorting/quicksort.js +++ b/algorithms/sorting/quicksort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Comparator = require('../../util/comparator'); diff --git a/algorithms/sorting/radix_sort.js b/algorithms/sorting/radix_sort.js index ed9791c..3324c02 100644 --- a/algorithms/sorting/radix_sort.js +++ b/algorithms/sorting/radix_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Tayllan Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; /** diff --git a/algorithms/sorting/selection_sort.js b/algorithms/sorting/selection_sort.js index 94772b5..f5e9150 100644 --- a/algorithms/sorting/selection_sort.js +++ b/algorithms/sorting/selection_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Nitin Saroha - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; /** * Selection sort algorithm O(n^2) @@ -41,4 +20,4 @@ var selectionSort = function (a) { return a; }; -module.exports = selectionSort; \ No newline at end of file +module.exports = selectionSort; diff --git a/algorithms/string/huffman.js b/algorithms/string/huffman.js index 018c921..bf8efd3 100644 --- a/algorithms/string/huffman.js +++ b/algorithms/string/huffman.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; diff --git a/algorithms/string/knuth_morris_pratt.js b/algorithms/string/knuth_morris_pratt.js index 91ce9a4..453bd4f 100644 --- a/algorithms/string/knuth_morris_pratt.js +++ b/algorithms/string/knuth_morris_pratt.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Tayllan Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; /** diff --git a/algorithms/string/levenshtein.js b/algorithms/string/levenshtein.js index 720f033..c738002 100644 --- a/algorithms/string/levenshtein.js +++ b/algorithms/string/levenshtein.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; /** diff --git a/algorithms/string/longest_common_subsequence.js b/algorithms/string/longest_common_subsequence.js index 2ee7d4f..a98a2ee 100644 --- a/algorithms/string/longest_common_subsequence.js +++ b/algorithms/string/longest_common_subsequence.js @@ -1,25 +1,3 @@ -/** - * Copyright (C) 2014 Joshua Curl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - /** * Implementation of longest common subsequence * diff --git a/algorithms/string/rabin_karp.js b/algorithms/string/rabin_karp.js index 7722473..9060e58 100644 --- a/algorithms/string/rabin_karp.js +++ b/algorithms/string/rabin_karp.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Tayllan Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; /** diff --git a/data_structures/bst.js b/data_structures/bst.js index 4e4336e..0993a19 100644 --- a/data_structures/bst.js +++ b/data_structures/bst.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Comparator = require('../util/comparator'); diff --git a/data_structures/disjoint_set_forest.js b/data_structures/disjoint_set_forest.js index 2397e1b..e9028b0 100644 --- a/data_structures/disjoint_set_forest.js +++ b/data_structures/disjoint_set_forest.js @@ -1,27 +1,5 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; - /** * Disjoint Set Forest data structure. * Allows fast subset merging and querying. diff --git a/data_structures/graph.js b/data_structures/graph.js index f3cedf8..0dd5bee 100644 --- a/data_structures/graph.js +++ b/data_structures/graph.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"], to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; /** diff --git a/data_structures/hash_table.js b/data_structures/hash_table.js index dcdeee5..bd3a3d7 100644 --- a/data_structures/hash_table.js +++ b/data_structures/hash_table.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var LinkedList = require('./linked_list'); diff --git a/data_structures/heap.js b/data_structures/heap.js index 4745946..b27cda9 100644 --- a/data_structures/heap.js +++ b/data_structures/heap.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Comparator = require('../util/comparator'); diff --git a/data_structures/linked_list.js b/data_structures/linked_list.js index 7130a7b..5ab7674 100644 --- a/data_structures/linked_list.js +++ b/data_structures/linked_list.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; /** diff --git a/data_structures/priority_queue.js b/data_structures/priority_queue.js index 633e09a..1b83d23 100644 --- a/data_structures/priority_queue.js +++ b/data_structures/priority_queue.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var MinHeap = require('./heap').MinHeap; diff --git a/data_structures/queue.js b/data_structures/queue.js index 0509778..9f71c07 100644 --- a/data_structures/queue.js +++ b/data_structures/queue.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var LinkedList = require('./linked_list'); diff --git a/data_structures/set.js b/data_structures/set.js index 3920197..74df72f 100644 --- a/data_structures/set.js +++ b/data_structures/set.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Andre Oliveira - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"], to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var HashTable = require('./hash_table'); diff --git a/data_structures/stack.js b/data_structures/stack.js index d86516e..e52b4c7 100644 --- a/data_structures/stack.js +++ b/data_structures/stack.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Queue = require('./queue'); diff --git a/main.js b/main.js index 45fe369..c91c3af 100644 --- a/main.js +++ b/main.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var lib = { diff --git a/test/algorithms/graph/SPFA.js b/test/algorithms/graph/SPFA.js index 637152c..d78fd2f 100644 --- a/test/algorithms/graph/SPFA.js +++ b/test/algorithms/graph/SPFA.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"], to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var SPFA = require('../../../algorithms/graph/SPFA'), diff --git a/test/algorithms/graph/bellman_ford.js b/test/algorithms/graph/bellman_ford.js index 3df4f8b..b2f2a2d 100644 --- a/test/algorithms/graph/bellman_ford.js +++ b/test/algorithms/graph/bellman_ford.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Tayllan Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"], to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var bellmanFord = require('../../../algorithms/graph/bellman_ford'), diff --git a/test/algorithms/graph/depth_first_search.js b/test/algorithms/graph/depth_first_search.js index ec03e96..cf8be2f 100644 --- a/test/algorithms/graph/depth_first_search.js +++ b/test/algorithms/graph/depth_first_search.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Tayllan Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"], to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var depthFirstSearch = require('../../../algorithms/graph/depth_first_search'), diff --git a/test/algorithms/graph/dijkstra.js b/test/algorithms/graph/dijkstra.js index a6d5dd7..8667868 100644 --- a/test/algorithms/graph/dijkstra.js +++ b/test/algorithms/graph/dijkstra.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"], to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var dijkstra = require('../../../algorithms/graph/dijkstra'), diff --git a/test/algorithms/graph/euler_path.js b/test/algorithms/graph/euler_path.js index de48f8a..85c4a20 100644 --- a/test/algorithms/graph/euler_path.js +++ b/test/algorithms/graph/euler_path.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"], to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; diff --git a/test/algorithms/graph/minimum_spanning_tree.js b/test/algorithms/graph/minimum_spanning_tree.js index a5b0107..aadfd4c 100644 --- a/test/algorithms/graph/minimum_spanning_tree.js +++ b/test/algorithms/graph/minimum_spanning_tree.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"], to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var kruskal = require('../../../algorithms/graph/kruskal'), diff --git a/test/algorithms/graph/topological_sort.js b/test/algorithms/graph/topological_sort.js index 6ef2a32..5d916eb 100644 --- a/test/algorithms/graph/topological_sort.js +++ b/test/algorithms/graph/topological_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"], to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var topologicalSort = require('../../../algorithms/graph/topological_sort'), diff --git a/test/algorithms/math/extended_euclidean.js b/test/algorithms/math/extended_euclidean.js index 90cf5c0..3f716de 100644 --- a/test/algorithms/math/extended_euclidean.js +++ b/test/algorithms/math/extended_euclidean.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Shu Ding - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var extEuclid = require('../../../algorithms/math/extended_euclidean'), diff --git a/test/algorithms/math/fast_power.js b/test/algorithms/math/fast_power.js index cec9da3..520da03 100644 --- a/test/algorithms/math/fast_power.js +++ b/test/algorithms/math/fast_power.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var power = require('../../../algorithms/math/fast_power'), diff --git a/test/algorithms/math/fibonacci.js b/test/algorithms/math/fibonacci.js index 020f73b..e6d1b46 100644 --- a/test/algorithms/math/fibonacci.js +++ b/test/algorithms/math/fibonacci.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var fib = require('../../../algorithms/math/fibonacci'), diff --git a/test/algorithms/math/fisher_yates.js b/test/algorithms/math/fisher_yates.js index d56f600..ee7338b 100644 --- a/test/algorithms/math/fisher_yates.js +++ b/test/algorithms/math/fisher_yates.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var fisherYates = require('../../../algorithms/math/fisher_yates'), diff --git a/test/algorithms/math/gcd.js b/test/algorithms/math/gcd.js index ea23823..6a35be2 100644 --- a/test/algorithms/math/gcd.js +++ b/test/algorithms/math/gcd.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var gcd = require('../../../algorithms/math/gcd'), diff --git a/test/algorithms/math/newton_sqrt.js b/test/algorithms/math/newton_sqrt.js index 19be060..d820cac 100644 --- a/test/algorithms/math/newton_sqrt.js +++ b/test/algorithms/math/newton_sqrt.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var newtonSqrt = require('../../../algorithms/math/newton_sqrt'), diff --git a/test/algorithms/math/next_permutation.js b/test/algorithms/math/next_permutation.js index 19cf453..1bcb9fe 100644 --- a/test/algorithms/math/next_permutation.js +++ b/test/algorithms/math/next_permutation.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var nextPermutation = require('../../../algorithms/math/next_permutation'), diff --git a/test/algorithms/math/power_set.js b/test/algorithms/math/power_set.js index b3af8b9..db31569 100644 --- a/test/algorithms/math/power_set.js +++ b/test/algorithms/math/power_set.js @@ -1,24 +1,3 @@ -/* -* Copyright (C) 2014 Joshua Curl -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to -* deal in the Software without restriction, including without limitation the -* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -* sell copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -*/ 'use strict'; var powerSet = require('../../../algorithms/math/power_set'), diff --git a/test/algorithms/math/reservoir_sampling.js b/test/algorithms/math/reservoir_sampling.js index 915d4e0..e303a0f 100644 --- a/test/algorithms/math/reservoir_sampling.js +++ b/test/algorithms/math/reservoir_sampling.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; diff --git a/test/algorithms/searching/bfs.js b/test/algorithms/searching/bfs.js index 3c2374b..c791523 100644 --- a/test/algorithms/searching/bfs.js +++ b/test/algorithms/searching/bfs.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var BST = require('../../../data_structures/bst'), bfs = require('../../../algorithms/searching/bfs'), diff --git a/test/algorithms/searching/binarysearch.js b/test/algorithms/searching/binarysearch.js index 2071d03..23a2df3 100644 --- a/test/algorithms/searching/binarysearch.js +++ b/test/algorithms/searching/binarysearch.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software'), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var binarySearch = require('../../../algorithms/searching/binarysearch'), diff --git a/test/algorithms/searching/dfs.js b/test/algorithms/searching/dfs.js index a9d07fb..cbae4e5 100644 --- a/test/algorithms/searching/dfs.js +++ b/test/algorithms/searching/dfs.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var BST = require('../../../data_structures/bst'), diff --git a/test/algorithms/sorting/bubble_sort.js b/test/algorithms/sorting/bubble_sort.js index b07a51d..b1944ba 100644 --- a/test/algorithms/sorting/bubble_sort.js +++ b/test/algorithms/sorting/bubble_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var bubbleSort = require('../../../algorithms/sorting/bubble_sort'), diff --git a/test/algorithms/sorting/counting_sort.js b/test/algorithms/sorting/counting_sort.js index f5b5b7f..577b539 100644 --- a/test/algorithms/sorting/counting_sort.js +++ b/test/algorithms/sorting/counting_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Tayllan Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"], to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var countingSort = require('../../../algorithms/sorting/counting_sort'), diff --git a/test/algorithms/sorting/heap_sort.js b/test/algorithms/sorting/heap_sort.js index 7aae938..b3d27c0 100644 --- a/test/algorithms/sorting/heap_sort.js +++ b/test/algorithms/sorting/heap_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var heapSort = require('../../../algorithms/sorting/heap_sort'), diff --git a/test/algorithms/sorting/insertion_sort.js b/test/algorithms/sorting/insertion_sort.js index 81468ac..860cc99 100644 --- a/test/algorithms/sorting/insertion_sort.js +++ b/test/algorithms/sorting/insertion_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Bruno Roberto Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var insertionSort = require('../../../algorithms/sorting/insertion_sort'), diff --git a/test/algorithms/sorting/merge_sort.js b/test/algorithms/sorting/merge_sort.js index 36b3e64..d5be06c 100644 --- a/test/algorithms/sorting/merge_sort.js +++ b/test/algorithms/sorting/merge_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var mergeSort = require('../../../algorithms/sorting/merge_sort'), diff --git a/test/algorithms/sorting/quicksort.js b/test/algorithms/sorting/quicksort.js index f6f574f..5b95fc2 100644 --- a/test/algorithms/sorting/quicksort.js +++ b/test/algorithms/sorting/quicksort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var quicksort = require('../../../algorithms/sorting/quicksort'), diff --git a/test/algorithms/sorting/radix_sort.js b/test/algorithms/sorting/radix_sort.js index 132501f..1fc442c 100644 --- a/test/algorithms/sorting/radix_sort.js +++ b/test/algorithms/sorting/radix_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Tayllan Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"], to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var radixSort = require('../../../algorithms/sorting/radix_sort'), diff --git a/test/algorithms/sorting/selection_sort.js b/test/algorithms/sorting/selection_sort.js index 8eacf9b..7194870 100644 --- a/test/algorithms/sorting/selection_sort.js +++ b/test/algorithms/sorting/selection_sort.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Nitin Saroha - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var selectionSort = require('../../../algorithms/sorting/selection_sort'), diff --git a/test/algorithms/string/huffman.js b/test/algorithms/string/huffman.js index 83daecd..c435e38 100644 --- a/test/algorithms/string/huffman.js +++ b/test/algorithms/string/huffman.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var huffman = require('../../../algorithms/string/huffman'), diff --git a/test/algorithms/string/knuth_morris_pratt.js b/test/algorithms/string/knuth_morris_pratt.js index d2dc006..1afc791 100644 --- a/test/algorithms/string/knuth_morris_pratt.js +++ b/test/algorithms/string/knuth_morris_pratt.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Tayllan Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var knuthMorrisPratt = require('../../../algorithms/string/knuth_morris_pratt'), diff --git a/test/algorithms/string/levenshtein.js b/test/algorithms/string/levenshtein.js index 5dba227..063844d 100644 --- a/test/algorithms/string/levenshtein.js +++ b/test/algorithms/string/levenshtein.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var levenshtein = require('../../../algorithms/string/levenshtein'), diff --git a/test/algorithms/string/longest_common_subseqence.js b/test/algorithms/string/longest_common_subseqence.js index 1704753..07824c8 100644 --- a/test/algorithms/string/longest_common_subseqence.js +++ b/test/algorithms/string/longest_common_subseqence.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Joshua Curl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var directory = '../../../algorithms/string/'; diff --git a/test/algorithms/string/rabin_karp.js b/test/algorithms/string/rabin_karp.js index 5e9ddc3..491b27e 100644 --- a/test/algorithms/string/rabin_karp.js +++ b/test/algorithms/string/rabin_karp.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Tayllan Búrigo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var rabinKarp = require('../../../algorithms/string/rabin_karp'), diff --git a/test/data_structures/bst.js b/test/data_structures/bst.js index e61979f..71feeb5 100644 --- a/test/data_structures/bst.js +++ b/test/data_structures/bst.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var BST = require('../../data_structures/bst'), diff --git a/test/data_structures/disjoint_set_forest.js b/test/data_structures/disjoint_set_forest.js index a301388..e77f739 100644 --- a/test/data_structures/disjoint_set_forest.js +++ b/test/data_structures/disjoint_set_forest.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Eugene Sharygin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var DisjointSetForest = require('../../data_structures/disjoint_set_forest'), diff --git a/test/data_structures/graph.js b/test/data_structures/graph.js index 235ea0e..3d1e4ef 100644 --- a/test/data_structures/graph.js +++ b/test/data_structures/graph.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"], to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Graph = require('../../data_structures/graph'), diff --git a/test/data_structures/hash_table.js b/test/data_structures/hash_table.js index 5ba5ed3..f31d2c6 100644 --- a/test/data_structures/hash_table.js +++ b/test/data_structures/hash_table.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var HashTable = require('../../data_structures/hash_table'), diff --git a/test/data_structures/heap.js b/test/data_structures/heap.js index f2a0a8f..5595994 100644 --- a/test/data_structures/heap.js +++ b/test/data_structures/heap.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var heap = require('../../data_structures/heap'), diff --git a/test/data_structures/linked_list.js b/test/data_structures/linked_list.js index eec6b0c..eb1dc55 100644 --- a/test/data_structures/linked_list.js +++ b/test/data_structures/linked_list.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var LinkedList = require('../../data_structures/linked_list'), diff --git a/test/data_structures/priority_queue.js b/test/data_structures/priority_queue.js index dd107a9..e1ff46f 100644 --- a/test/data_structures/priority_queue.js +++ b/test/data_structures/priority_queue.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var PriorityQueue = require('../../data_structures/priority_queue'), diff --git a/test/data_structures/queue.js b/test/data_structures/queue.js index 5a900c7..aca4fd5 100644 --- a/test/data_structures/queue.js +++ b/test/data_structures/queue.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Queue = require('../../data_structures/queue'), diff --git a/test/data_structures/set.js b/test/data_structures/set.js index 1038a1b..0f43a78 100644 --- a/test/data_structures/set.js +++ b/test/data_structures/set.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Andre Oliveira - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var HashSet = require('../../data_structures/set'), diff --git a/test/data_structures/stack.js b/test/data_structures/stack.js index 72e34fd..edfdc47 100644 --- a/test/data_structures/stack.js +++ b/test/data_structures/stack.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Stack = require('../../data_structures/stack'), diff --git a/test/util/comparator.js b/test/util/comparator.js index 4c53660..62bd2a6 100644 --- a/test/util/comparator.js +++ b/test/util/comparator.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the 'Software'), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; var Comparator = require('../../util/comparator'), diff --git a/test/util/npm-debug.log b/test/util/npm-debug.log deleted file mode 100644 index e1d4780..0000000 --- a/test/util/npm-debug.log +++ /dev/null @@ -1,19 +0,0 @@ -0 info it worked if it ends with ok -1 verbose cli [ '/opt/boxen/nodenv/versions/v0.10.28/bin/node', -1 verbose cli '/opt/boxen/nodenv/versions/v0.10.28/bin/npm', -1 verbose cli 'test' ] -2 info using npm@1.4.9 -3 info using node@v0.10.28 -4 error Error: ENOENT, open '/Users/felipe/Dropbox/Hacking/algorithms.js/test/util/package.json' -5 error If you need help, you may report this *entire* log, -5 error including the npm and node versions, at: -5 error -6 error System Darwin 13.1.0 -7 error command "/opt/boxen/nodenv/versions/v0.10.28/bin/node" "/opt/boxen/nodenv/versions/v0.10.28/bin/npm" "test" -8 error cwd /Users/felipe/Dropbox/Hacking/algorithms.js/test/util -9 error node -v v0.10.28 -10 error npm -v 1.4.9 -11 error path /Users/felipe/Dropbox/Hacking/algorithms.js/test/util/package.json -12 error code ENOENT -13 error errno 34 -14 verbose exit [ 34, true ] diff --git a/util/comparator.js b/util/comparator.js index e7e04af..44e268b 100644 --- a/util/comparator.js +++ b/util/comparator.js @@ -1,24 +1,3 @@ -/** - * Copyright (C) 2014 Felipe Ribeiro - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ 'use strict'; /** From 2e1aed7f85afae767b44f0f8dcc490451e85aa30 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Thu, 24 Jul 2014 12:32:10 +0200 Subject: [PATCH 093/280] Add contributors to package.json --- package.json | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 30d0279..3b3978f 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,22 @@ "algorithms", "data structures" ], - "author": "Felipe Ribeiro ", + "author": "Felipe Ribeiro (http://github.com/felipernb)", + "contributors": [ + "eush77 ", + "tayllan ", + "anaran ", + "Joshua Curl ", + "nitinsaroha ", + "Andre P. Oliveira ", + "Iain McDonald ", + "dingshu ", + "Liam Griffiths ", + "BrunoRB ", + "geakstr ", + "Matt R. Wilson ", + "Gaurav Mittal " + ], "license": "MIT", "bugs": { "url": "https://github.com/felipernb/algorithms.js/issues" From 112cee598c453eaa09ce7d307229bc32970ef87b Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Thu, 24 Jul 2014 15:53:17 +0200 Subject: [PATCH 094/280] AUTHORS extracted straight from git log: git log --format="format:%an <%ae>" | sort | uniq --- AUTHORS | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/AUTHORS b/AUTHORS index 5bedf36..fed2c19 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,14 +1,14 @@ -felipernb - Felipe Ribeiro -anaran -apoliveira - Andre P. Oliveira -BrunoRB - Bruno Roberto Búrigo -dingshu - Shu Ding -eush77 - Eugene Sharygin -gauravmittal1995 - Gaurav Mittal -geakstr - Dmitry Kharitonov -joshuacurl - Joshua Curl -liamgriffiths - Liam Griffiths -lifebeyondfife - Iain McDonald -mastermatt - Matt R. Wilson -nitinsaroha - Nitin Saroha -tayllan - Tayllan Búrigo +Felipe Ribeiro +Andre P. Oliveira +BrunoRB +Gaurav Mittal +Iain McDonald +Joshua Curl +Liam Griffiths +Matt R. Wilson +anaran +dingshu +eush77 +geakstr +nitinsaroha +tayllan From 6af19ae9ad6f75221120673c587a6df34f73bf48 Mon Sep 17 00:00:00 2001 From: eush77 Date: Sat, 26 Jul 2014 05:46:48 +0400 Subject: [PATCH 095/280] Fix DFS complexity guarantee --- algorithms/graph/depth_first_search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/graph/depth_first_search.js b/algorithms/graph/depth_first_search.js index 657a221..ed2dc41 100644 --- a/algorithms/graph/depth_first_search.js +++ b/algorithms/graph/depth_first_search.js @@ -57,7 +57,7 @@ var normalizeCallbacks = function (callbacks, seenVertices) { /** * Run Depth-First Search from a start vertex. - * Worst-case complexity: O(V + E). + * Complexity (default implementation): O(V + E). * * @param {Graph} graph * @param {*} startVertex From 658b2ed985a54ab5ac35c8c8180fc3509fa6f378 Mon Sep 17 00:00:00 2001 From: eush77 Date: Sat, 26 Jul 2014 06:27:07 +0400 Subject: [PATCH 096/280] Add Breadth-First Search --- algorithms/graph/breadth_first_search.js | 86 ++++++++++++++++++ main.js | 1 + test/algorithms/graph/breadth_first_search.js | 90 +++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 algorithms/graph/breadth_first_search.js create mode 100644 test/algorithms/graph/breadth_first_search.js diff --git a/algorithms/graph/breadth_first_search.js b/algorithms/graph/breadth_first_search.js new file mode 100644 index 0000000..6278c84 --- /dev/null +++ b/algorithms/graph/breadth_first_search.js @@ -0,0 +1,86 @@ +'use strict'; + +var Queue = require('../../data_structures/queue'); + + +/** + * @typedef {Object} Callbacks + * @param {function(vertex: *, neighbor: *): boolean} allowTraversal - + * Determines whether BFS should traverse from the vertex to its neighbor + * (along the edge). By default prohibits visiting the same vertex again. + * @param {function(vertex: *, neighbor: *)} onTraversal - Called when BFS + * follows the edge (and puts its head into the queue). + * @param {function(vertex: *)} enterVertex - Called when BFS enters the vertex. + * @param {function(vertex: *)} leaveVertex - Called when BFS leaves the vertex. + */ + + +/** + * Fill in missing callbacks. + * + * @param {Callbacks} callbacks + * @param {Array} [seenVertices] - Vertices already discovered, + * used by default allowTraversal implementation. + * @return {Callbacks} The same object or new one (if null passed). + */ +var normalizeCallbacks = function (callbacks, seenVertices) { + callbacks = callbacks || {}; + + callbacks.allowTraversal = callbacks.allowTraversal || (function () { + var seen = (seenVertices || []).reduce(function (seen, vertex) { + seen[vertex] = true; + return seen; + }, {}); + + return function (vertex, neighbor) { + if (!seen[neighbor]) { + seen[neighbor] = true; + return true; + } + else { + return false; + } + }; + }()); + + var noop = function () {}; + callbacks.onTraversal = callbacks.onTraversal || noop; + callbacks.enterVertex = callbacks.enterVertex || noop; + callbacks.leaveVertex = callbacks.leaveVertex || noop; + + return callbacks; +}; + + +/** + * Run Breadth-First Search from a start vertex. + * Complexity (default implementation): O(V + E). + * + * @param {Graph} graph + * @param {*} startVertex + * @param {Callbacks} [callbacks] + */ +var breadthFirstSearch = function (graph, startVertex, callbacks) { + var vertexQueue = new Queue(); + vertexQueue.push(startVertex); + callbacks = normalizeCallbacks(callbacks, [startVertex]); + + /* jshint loopfunc: true */ + while (!vertexQueue.isEmpty()) { + var vertex = vertexQueue.pop(); + + callbacks.enterVertex(vertex); + + graph.neighbors(vertex).forEach(function (neighbor) { + if (callbacks.allowTraversal(vertex, neighbor)) { + callbacks.onTraversal(vertex, neighbor); + vertexQueue.push(neighbor); + } + }); + + callbacks.leaveVertex(vertex); + } +}; + + +module.exports = breadthFirstSearch; diff --git a/main.js b/main.js index c91c3af..5c2a67f 100644 --- a/main.js +++ b/main.js @@ -9,6 +9,7 @@ var lib = { eulerPath: require('./algorithms/graph/euler_path'), depthFirstSearch: require('./algorithms/graph/depth_first_search'), kruskal: require('./algorithms/graph/kruskal'), + breadthFirstSearch: require('./algorithms/graph/breadth_first_search'), }, Math: { fibonacci: require('./algorithms/math/fibonacci'), diff --git a/test/algorithms/graph/breadth_first_search.js b/test/algorithms/graph/breadth_first_search.js new file mode 100644 index 0000000..6377f0a --- /dev/null +++ b/test/algorithms/graph/breadth_first_search.js @@ -0,0 +1,90 @@ +'use strict'; + +var breadthFirstSearch = + require('../../../algorithms/graph/breadth_first_search'), + Graph = require('../../../data_structures/graph'), + assert = require('assert'); + + +describe('Breadth-First Search', function () { + var graph = new Graph(); + graph.addEdge(1, 2); + graph.addEdge(1, 5); + graph.addEdge(5, 2); + graph.addEdge(2, 6); + graph.addEdge(6, 1); + graph.addEdge(6, 3); + graph.addEdge(3, 2); + graph.addEdge(2, 4); + graph.addEdge('alpha', 'omega'); + + it('should visit reachable vertices in a breadth-first manner', function () { + var enter = [], leave = []; + var lastEntered = null; + var traversed = 0; + + breadthFirstSearch(graph, 1, { + enterVertex: function (vertex) { + enter.push(vertex); + lastEntered = vertex; + }, + leaveVertex: function (vertex) { + assert.equal(lastEntered, vertex); + leave.push(vertex); + }, + onTraversal: function () { + traversed += 1; + } + }); + + assert.equal(traversed, 5); // #edges in a spanning tree. + assert.deepEqual(enter, leave); + assert.equal(enter.length, 6); + + assert.equal(enter[0], 1); + assert.deepEqual(enter.slice(1, 3).sort(), [2, 5]); + assert.deepEqual(enter.slice(3, 5).sort(), [4, 6]); + assert.equal(enter[5], 3); + }); + + it('should allow user-defined allowTraversal rules', function () { + var seen = new Graph(graph.directed); + graph.vertices.forEach(seen.addVertex.bind(seen)); + var indegrees = {1: -1}, outdegrees = {}; + + // Edge-centric BFS. + breadthFirstSearch(graph, 1, { + allowTraversal: function (vertex, neighbor) { + if (!seen.edge(vertex, neighbor)) { + seen.addEdge(vertex, neighbor); + outdegrees[vertex] = (outdegrees[vertex] || 0) + 1; + return true; + } + else { + return false; + } + }, + enterVertex: function (vertex) { + indegrees[vertex] = (indegrees[vertex] || 0) + 1; + outdegrees[vertex] = outdegrees[vertex] || 0; + } + }); + + assert.deepEqual(indegrees, { + 1: 1, + 2: 3, + 3: 1, + 4: 1, + 5: 1, + 6: 1 + }); + assert.deepEqual(outdegrees, { + 1: 2, + 2: 2, + 3: 1, + 4: 0, + 5: 1, + 6: 2 + }); + }); +}); From ae17d1b4a1c7ad20b442ae6ae85340936b08676c Mon Sep 17 00:00:00 2001 From: Eugene Sharygin Date: Sat, 26 Jul 2014 15:09:18 +0400 Subject: [PATCH 097/280] Add BFS shortest path algorithm --- algorithms/graph/bfs_shortest_path.js | 34 ++++++++++++++++ main.js | 1 + test/algorithms/graph/bfs_shortest_path.js | 45 ++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 algorithms/graph/bfs_shortest_path.js create mode 100644 test/algorithms/graph/bfs_shortest_path.js diff --git a/algorithms/graph/bfs_shortest_path.js b/algorithms/graph/bfs_shortest_path.js new file mode 100644 index 0000000..e583ebe --- /dev/null +++ b/algorithms/graph/bfs_shortest_path.js @@ -0,0 +1,34 @@ +'use strict'; + +var breadthFirstSearch = require('./breadth_first_search'); + + +/** + * Shortest-path algorithm based on Breadth-First Search. + * Works solely on graphs with equal edge weights (but works fast). + * Complexity: O(V + E). + * + * @param {Graph} graph + * @param {string} source + * @return {{distance: Object., + * previous: Object.}} + */ +var bfsShortestPath = function (graph, source) { + var distance = {}, previous = {}; + distance[source] = 0; + + breadthFirstSearch(graph, source, { + onTraversal: function (vertex, neighbor) { + distance[neighbor] = distance[vertex] + 1; + previous[neighbor] = vertex; + } + }); + + return { + distance: distance, + previous: previous + }; +}; + + +module.exports = bfsShortestPath; diff --git a/main.js b/main.js index 5c2a67f..9af2d9f 100644 --- a/main.js +++ b/main.js @@ -10,6 +10,7 @@ var lib = { depthFirstSearch: require('./algorithms/graph/depth_first_search'), kruskal: require('./algorithms/graph/kruskal'), breadthFirstSearch: require('./algorithms/graph/breadth_first_search'), + bfsShortestPath: require('./algorithms/graph/bfs_shortest_path'), }, Math: { fibonacci: require('./algorithms/math/fibonacci'), diff --git a/test/algorithms/graph/bfs_shortest_path.js b/test/algorithms/graph/bfs_shortest_path.js new file mode 100644 index 0000000..6e9258e --- /dev/null +++ b/test/algorithms/graph/bfs_shortest_path.js @@ -0,0 +1,45 @@ +'use strict'; + +var bfsShortestPath = require('../../../algorithms/graph/bfs_shortest_path'), + Graph = require('../../../data_structures/graph'), + assert = require('assert'); + + +describe('BFS Shortest Path Algorithm', function () { + it('should return the shortest paths to all nodes from a given origin', + function () { + var graph = new Graph(); + graph.addEdge(0, 1); + graph.addEdge(1, 2); + graph.addEdge(0, 2); + graph.addEdge(2, 3); + graph.addEdge(3, 6); + graph.addEdge(6, 2); + graph.addEdge(6, 0); + graph.addEdge(0, 4); + graph.addEdge(4, 6); + graph.addEdge(4, 5); + graph.addEdge(5, 0); + graph.addEdge('a', 'b'); + + var shortestPath = bfsShortestPath(graph, 0); + + assert.deepEqual(shortestPath.distance, { + 0: 0, + 1: 1, + 2: 1, + 3: 2, + 4: 1, + 5: 2, + 6: 2 + }); + assert.deepEqual(shortestPath.previous, { + 1: 0, + 2: 0, + 3: 2, + 4: 0, + 5: 4, + 6: 4 + }); + }); +}); From 5ead77ad087745b12f4fe6d02ad463c555ac016b Mon Sep 17 00:00:00 2001 From: Eugene Sharygin Date: Mon, 28 Jul 2014 04:15:11 +0400 Subject: [PATCH 098/280] Create Graph::adjList and subobjects with null prototype (fix #76) --- data_structures/graph.js | 4 ++-- test/data_structures/graph.js | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/data_structures/graph.js b/data_structures/graph.js index 0dd5bee..003ce54 100644 --- a/data_structures/graph.js +++ b/data_structures/graph.js @@ -6,13 +6,13 @@ */ function Graph(directed) { this.directed = (directed === undefined ? true : !!directed); - this.adjList = {}; + this.adjList = Object.create(null); this.vertices = []; } Graph.prototype.addVertex = function (v) { this.vertices.push('' + v); - this.adjList[v] = {}; + this.adjList[v] = Object.create(null); }; Graph.prototype.addEdge = function (a, b, w) { diff --git a/test/data_structures/graph.js b/test/data_structures/graph.js index 3d1e4ef..d3bbcd6 100644 --- a/test/data_structures/graph.js +++ b/test/data_structures/graph.js @@ -124,4 +124,12 @@ describe('Graph - Adjacency list', function () { assert.equal(g.edge('a', 'c'), 5); assert.equal(g.edge('c', 'd'), 2); }); + + it('should not "inherit" edges from Object.prototype', function () { + var g = new Graph(); + g.addEdge('a', 'b'); + + assert.ifError(g.edge('a', 'constructor')); + assert.throws(g.edge.bind(g, 'valueOf', 'call')); + }); }); From a49a48a9f5b471b51f4f8817c4daba2147e15d2d Mon Sep 17 00:00:00 2001 From: Eugene Sharygin Date: Mon, 28 Jul 2014 13:38:18 +0400 Subject: [PATCH 099/280] Return previous vertices in Bellman-Ford (as other shortest-path algorithms do) --- algorithms/graph/bellman_ford.js | 5 ++++- test/algorithms/graph/bellman_ford.js | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/algorithms/graph/bellman_ford.js b/algorithms/graph/bellman_ford.js index 475e9b8..7a468ec 100644 --- a/algorithms/graph/bellman_ford.js +++ b/algorithms/graph/bellman_ford.js @@ -15,6 +15,7 @@ */ var bellmanFord = function (graph, startNode) { var minDistance = {}; + var previousVertex = {}; var edges = []; var adjacencyListSize = 0; @@ -45,6 +46,7 @@ var bellmanFord = function (graph, startNode) { if (sourceDistance < targetDistance) { minDistance[edges[j].target] = sourceDistance; + previousVertex[edges[j].target] = edges[j].source; } } } @@ -63,7 +65,8 @@ var bellmanFord = function (graph, startNode) { } return { - distance: minDistance + distance: minDistance, + previous: previousVertex }; }; diff --git a/test/algorithms/graph/bellman_ford.js b/test/algorithms/graph/bellman_ford.js index b2f2a2d..fbc6f39 100644 --- a/test/algorithms/graph/bellman_ford.js +++ b/test/algorithms/graph/bellman_ford.js @@ -23,6 +23,8 @@ describe('Bellman-Ford Algorithm', function () { assert.equal(shortestPaths.distance.a, 0); assert.equal(shortestPaths.distance.d, -2); assert.equal(shortestPaths.distance.e, 1); + assert.equal(shortestPaths.previous.d, 'e'); + assert.equal(shortestPaths.previous.e, 'b'); // It'll cause a Negative-Weighted Cycle. graph.addEdge('c', 'a', -9); From aab7b73bb7da20095a0bcc8b5a13b30b8036e0f1 Mon Sep 17 00:00:00 2001 From: dingshu Date: Tue, 29 Jul 2014 21:31:18 +0800 Subject: [PATCH 100/280] Fixed issue #80. --- algorithms/graph/SPFA.js | 9 ++++++++ test/algorithms/graph/SPFA.js | 43 +++++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/algorithms/graph/SPFA.js b/algorithms/graph/SPFA.js index 89fd14d..657f009 100644 --- a/algorithms/graph/SPFA.js +++ b/algorithms/graph/SPFA.js @@ -13,16 +13,19 @@ function SPFA(graph, s) { var previous = {}; var queue = {}; var isInQue = {}; + var cnt = {}; var head = 0; var tail = 1; // initialize distance[s] = 0; queue[0] = s; isInQue[s] = true; + cnt[s] = 1; graph.vertices.forEach(function (v) { if (v !== s) { distance[v] = Infinity; isInQue[v] = false; + cnt[v] = 0; } }); @@ -41,6 +44,12 @@ function SPFA(graph, s) { if (!isInQue[v]) { queue[tail++] = v; isInQue[v] = true; + cnt[v]++; + if(cnt[v] > graph.vertices.length) + // indicates negative-weighted cycle + return { + distance: {} + }; } } } diff --git a/test/algorithms/graph/SPFA.js b/test/algorithms/graph/SPFA.js index d78fd2f..36326b2 100644 --- a/test/algorithms/graph/SPFA.js +++ b/test/algorithms/graph/SPFA.js @@ -7,22 +7,31 @@ var SPFA = require('../../../algorithms/graph/SPFA'), describe('SPFA Algorithm', function () { it('should return the shortest paths to all nodes from a given origin', function () { - var g = new Graph(); - g.addEdge('a', 'b', 5); - g.addEdge('a', 'c', 10); - g.addEdge('b', 'c', 2); - g.addEdge('b', 'd', 20); - g.addEdge('c', 'd', 1); - g.addEdge('d', 'a', 10); - - var shortestPath = SPFA(g, 'a'); - assert.equal(shortestPath.distance.b, 5); - assert.equal(shortestPath.previous.b, 'a'); - - assert.equal(shortestPath.distance.c, 7); - assert.equal(shortestPath.previous.c, 'b'); - - assert.equal(shortestPath.distance.d, 8); - assert.equal(shortestPath.previous.d, 'c'); + var graph = new Graph(true); + + graph.addEdge('a', 'b', -1); + graph.addEdge('a', 'c', 4); + graph.addEdge('b', 'c', 3); + graph.addEdge('b', 'd', 2); + graph.addEdge('b', 'e', 2); + graph.addEdge('d', 'b', 1); + graph.addEdge('e', 'd', -3); + graph.addEdge('d', 'c', 5); + + var shortestPaths = SPFA(graph, 'a'); + + assert.equal(shortestPaths.distance.a, 0); + assert.equal(shortestPaths.distance.d, -2); + assert.equal(shortestPaths.distance.e, 1); + assert.equal(shortestPaths.previous.d, 'e'); + assert.equal(shortestPaths.previous.e, 'b'); + + // It'll cause a Negative-Weighted Cycle. + graph.addEdge('c', 'a', -9); + + shortestPaths = SPFA(graph, 'a'); + + // The 'distance' object is empty + assert.equal(shortestPaths.distance.a, undefined); }); }); From a2d30b0b0663c0bb79743bb6c735c2a631d286ce Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 29 Jul 2014 17:08:07 +0200 Subject: [PATCH 101/280] Make the linter happy --- algorithms/graph/SPFA.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/graph/SPFA.js b/algorithms/graph/SPFA.js index 657f009..f07ee43 100644 --- a/algorithms/graph/SPFA.js +++ b/algorithms/graph/SPFA.js @@ -45,7 +45,7 @@ function SPFA(graph, s) { queue[tail++] = v; isInQue[v] = true; cnt[v]++; - if(cnt[v] > graph.vertices.length) + if (cnt[v] > graph.vertices.length) // indicates negative-weighted cycle return { distance: {} From f4d3b5cd635e52cd8fdfe705cffbf7ae47bf95ca Mon Sep 17 00:00:00 2001 From: Eugene Sharygin Date: Sat, 2 Aug 2014 18:53:23 +0400 Subject: [PATCH 102/280] Add Prim's MST algorithm --- algorithms/graph/prim.js | 55 +++++++++++++++++++ data_structures/priority_queue.js | 8 ++- .../algorithms/graph/minimum_spanning_tree.js | 2 + 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 algorithms/graph/prim.js diff --git a/algorithms/graph/prim.js b/algorithms/graph/prim.js new file mode 100644 index 0000000..b7a0e35 --- /dev/null +++ b/algorithms/graph/prim.js @@ -0,0 +1,55 @@ +'use strict'; + +var PriorityQueue = require('../../data_structures/priority_queue'), + Graph = require('../../data_structures/graph'); + + +/** + * Prim's minimum spanning tree (forest) algorithm. + * Complexity: O(E * log(V)). + * + * @param {Graph} graph - Undirected graph. + * @return {Graph} Minimum spanning tree or forest + * (depending on whether input graph is connected itself). + */ +var prim = function (graph) { + if (graph.directed) { + throw new Error('Can\'t build MST of a directed graph.'); + } + + var mst = new Graph(false); + var parent = Object.create(null); + + var q = new PriorityQueue(); + graph.vertices.forEach(function (vertex) { + q.insert(vertex, Infinity); + }); + + /* jshint loopfunc: true */ + while (!q.isEmpty()) { + var top = q.extract(true); + var vertex = top.item, + weight = top.priority; + + if (parent[vertex]) { + mst.addEdge(parent[vertex], vertex, weight); + } + else { + mst.addVertex(vertex); + } + + // Relax. + graph.neighbors(vertex).forEach(function (neighbor) { + var weight = graph.edge(vertex, neighbor); + if (weight < q.priority(neighbor)) { + q.changePriority(neighbor, weight); + parent[neighbor] = vertex; + } + }); + } + + return mst; +}; + + +module.exports = prim; diff --git a/data_structures/priority_queue.js b/data_structures/priority_queue.js index 1b83d23..18083e7 100644 --- a/data_structures/priority_queue.js +++ b/data_structures/priority_queue.js @@ -33,9 +33,13 @@ PriorityQueue.prototype.insert = function (item, priority) { MinHeap.prototype.insert.call(this, o); }; -PriorityQueue.prototype.extract = function () { +PriorityQueue.prototype.extract = function (withPriority) { var min = MinHeap.prototype.extract.call(this); - return min && min.item; + return withPriority ? min : min && min.item; +}; + +PriorityQueue.prototype.priority = function (item) { + return this._items[item].priority; }; PriorityQueue.prototype.changePriority = function (item, priority) { diff --git a/test/algorithms/graph/minimum_spanning_tree.js b/test/algorithms/graph/minimum_spanning_tree.js index aadfd4c..4903fef 100644 --- a/test/algorithms/graph/minimum_spanning_tree.js +++ b/test/algorithms/graph/minimum_spanning_tree.js @@ -1,6 +1,7 @@ 'use strict'; var kruskal = require('../../../algorithms/graph/kruskal'), + prim = require('../../../algorithms/graph/prim'), Graph = require('../../../data_structures/graph'), depthFirstSearch = require('../../../algorithms/graph/depth_first_search'), assert = require('assert'); @@ -179,4 +180,5 @@ var testMstAlgorithm = function (mst) { describe('Minimum Spanning Tree', function () { describe('#Kruskal\'s Algorithm', testMstAlgorithm.bind(null, kruskal)); + describe('#Prim\'s Algorithm', testMstAlgorithm.bind(null, prim)); }); From 7dfa0819e6eb2025549a6016ed48be5258d9bccd Mon Sep 17 00:00:00 2001 From: Eugene Sharygin Date: Sat, 2 Aug 2014 18:59:28 +0400 Subject: [PATCH 103/280] Include Prim's algorithm in main.js --- main.js | 1 + 1 file changed, 1 insertion(+) diff --git a/main.js b/main.js index 9af2d9f..644862b 100644 --- a/main.js +++ b/main.js @@ -11,6 +11,7 @@ var lib = { kruskal: require('./algorithms/graph/kruskal'), breadthFirstSearch: require('./algorithms/graph/breadth_first_search'), bfsShortestPath: require('./algorithms/graph/bfs_shortest_path'), + prim: require('./algorithms/graph/prim'), }, Math: { fibonacci: require('./algorithms/math/fibonacci'), From a3264ae06fef9e443c15d03d3690e3ada303a279 Mon Sep 17 00:00:00 2001 From: Eugene Sharygin Date: Sun, 3 Aug 2014 02:11:26 +0400 Subject: [PATCH 104/280] Stop early in Bellman-Ford This also eliminates the need for a separate extra iteration. --- algorithms/graph/bellman_ford.js | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/algorithms/graph/bellman_ford.js b/algorithms/graph/bellman_ford.js index 7a468ec..14b5e7f 100644 --- a/algorithms/graph/bellman_ford.js +++ b/algorithms/graph/bellman_ford.js @@ -39,31 +39,35 @@ var bellmanFord = function (graph, startNode) { var sourceDistance; var targetDistance; - for (var i = 0; i < adjacencyListSize - 1; i++) { + var iteration; + for (iteration = 0; iteration < adjacencyListSize; ++iteration) { + var somethingChanged = false; + for (var j = 0; j < edgesSize; j++) { sourceDistance = minDistance[edges[j].source] + edges[j].weight; targetDistance = minDistance[edges[j].target]; if (sourceDistance < targetDistance) { + somethingChanged = true; minDistance[edges[j].target] = sourceDistance; previousVertex[edges[j].target] = edges[j].source; } } - } - - for (i = 0; i < edgesSize; i++) { - sourceDistance = minDistance[edges[i].source] + edges[i].weight; - targetDistance = minDistance[edges[i].target]; - if (sourceDistance < targetDistance) { - - // Empty 'distance' object indicates Negative-Weighted Cycle - return { - distance: {} - }; + if (!somethingChanged) { + // Early stop. + break; } } + // If the loop did not break early, then there is a negative-weighted cycle. + if (iteration == adjacencyListSize) { + // Empty 'distance' object indicates Negative-Weighted Cycle + return { + distance: {} + }; + } + return { distance: minDistance, previous: previousVertex From 4b0499f2e0956146fbbfb6797dd8748b2c46b828 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sun, 3 Aug 2014 16:57:59 +0200 Subject: [PATCH 105/280] Remove function declaration from loop --- algorithms/graph/breadth_first_search.js | 21 ++++++++++----------- algorithms/graph/prim.js | 18 +++++++++--------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/algorithms/graph/breadth_first_search.js b/algorithms/graph/breadth_first_search.js index 6278c84..51ea946 100644 --- a/algorithms/graph/breadth_first_search.js +++ b/algorithms/graph/breadth_first_search.js @@ -65,19 +65,18 @@ var breadthFirstSearch = function (graph, startVertex, callbacks) { vertexQueue.push(startVertex); callbacks = normalizeCallbacks(callbacks, [startVertex]); - /* jshint loopfunc: true */ - while (!vertexQueue.isEmpty()) { - var vertex = vertexQueue.pop(); + var vertex; + var enqueue = function (neighbor) { + if (callbacks.allowTraversal(vertex, neighbor)) { + callbacks.onTraversal(vertex, neighbor); + vertexQueue.push(neighbor); + } + }; + while (!vertexQueue.isEmpty()) { + vertex = vertexQueue.pop(); callbacks.enterVertex(vertex); - - graph.neighbors(vertex).forEach(function (neighbor) { - if (callbacks.allowTraversal(vertex, neighbor)) { - callbacks.onTraversal(vertex, neighbor); - vertexQueue.push(neighbor); - } - }); - + graph.neighbors(vertex).forEach(enqueue); callbacks.leaveVertex(vertex); } }; diff --git a/algorithms/graph/prim.js b/algorithms/graph/prim.js index b7a0e35..603f490 100644 --- a/algorithms/graph/prim.js +++ b/algorithms/graph/prim.js @@ -25,7 +25,14 @@ var prim = function (graph) { q.insert(vertex, Infinity); }); - /* jshint loopfunc: true */ + var relax = function (neighbor) { + var weight = graph.edge(vertex, neighbor); + if (weight < q.priority(neighbor)) { + q.changePriority(neighbor, weight); + parent[neighbor] = vertex; + } + }; + while (!q.isEmpty()) { var top = q.extract(true); var vertex = top.item, @@ -38,14 +45,7 @@ var prim = function (graph) { mst.addVertex(vertex); } - // Relax. - graph.neighbors(vertex).forEach(function (neighbor) { - var weight = graph.edge(vertex, neighbor); - if (weight < q.priority(neighbor)) { - q.changePriority(neighbor, weight); - parent[neighbor] = vertex; - } - }); + graph.neighbors(vertex).forEach(relax); } return mst; From b877fe982f940dac566b04ce44159844151c987d Mon Sep 17 00:00:00 2001 From: Eugene Sharygin Date: Sun, 3 Aug 2014 16:07:36 +0400 Subject: [PATCH 106/280] Add Floyd-Warshall algorithm --- algorithms/graph/floyd_warshall.js | 101 ++++++++++++++++++++++++ test/algorithms/graph/floyd_warshall.js | 75 ++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 algorithms/graph/floyd_warshall.js create mode 100644 test/algorithms/graph/floyd_warshall.js diff --git a/algorithms/graph/floyd_warshall.js b/algorithms/graph/floyd_warshall.js new file mode 100644 index 0000000..e556e64 --- /dev/null +++ b/algorithms/graph/floyd_warshall.js @@ -0,0 +1,101 @@ +'use strict'; + + +/** + * Floyd-Warshall algorithm. + * Compute all-pairs shortest paths (a path for each pair of vertices). + * Complexity: O(V^3). + * + * @param {Graph} graph + * @return {{distance, path}} + */ +var floydWarshall = function (graph) { + + // Fill in the distances with initial values: + // - 0 if source == destination; + // - edge(source, destination) if there is a direct edge; + // - +inf otherwise. + var distance = graph.vertices.reduce(function (distance, source) { + distance[source] = + graph.vertices.reduce(function (distanceTo, destination) { + if (source == destination) { + distanceTo[destination] = 0; + } + else if (graph.edge(source, destination) !== undefined) { + distanceTo[destination] = graph.edge(source, destination); + } + else { + distanceTo[destination] = Infinity; + } + return distanceTo; + }, {}); + return distance; + }, {}); + + // Internal vertex with the largest index along the shortest path. + // Needed for path reconstruction. + var middleVertex = graph.vertices.reduce(function (middleVertex, vertex) { + middleVertex[vertex] = {}; + return middleVertex; + }, {}); + + graph.vertices.forEach(function (middle) { + graph.vertices.forEach(function (source) { + graph.vertices.forEach(function (destination) { + var dist = distance[source][middle] + distance[middle][destination]; + if (dist < distance[source][destination]) { + distance[source][destination] = dist; + middleVertex[source][destination] = middle; + } + }); + }); + }); + + // Check for a negative-weighted cycle. + graph.vertices.forEach(function (vertex) { + if (distance[vertex][vertex] < 0) { + // Negative-weighted cycle found. + throw new Error('The graph contains a negative-weighted cycle!'); + } + }); + + /** + * Reconstruct the shortest path for a given pair of end vertices. + * Complexity: O(L), L - length of the path (number of edges). + * + * @param {string} source + * @param {string} destination + * @return {?string[]} Null if destination is unreachable. + */ + var path = function (source, destination) { + if (!Number.isFinite(distance[source][destination])) { + // Destination unreachable. + return null; + } + + var path = [source]; + + if (source != destination) { + (function pushInOrder(source, destination) { + if (middleVertex[source][destination] === undefined) { + path.push(destination); + } + else { + var middle = middleVertex[source][destination]; + pushInOrder(source, middle); + pushInOrder(middle, destination); + } + }(source, destination)); + } + + return path; + }; + + return { + distance: distance, + path: path + }; +}; + + +module.exports = floydWarshall; diff --git a/test/algorithms/graph/floyd_warshall.js b/test/algorithms/graph/floyd_warshall.js new file mode 100644 index 0000000..5ee0ada --- /dev/null +++ b/test/algorithms/graph/floyd_warshall.js @@ -0,0 +1,75 @@ +'use strict'; + + +var floydWarshall = require('../../../algorithms/graph/floyd_warshall'), + Graph = require('../../../data_structures/graph'), + assert = require('assert'); + + +describe('Floyd-Warshall Algorithm', function () { + it('should compute all-pairs shortest paths in the graph', function () { + var graph = new Graph(); + graph.addEdge('a', 'b', -2); + graph.addEdge('b', 'c', -1); + graph.addEdge('c', 'a', 4); + graph.addEdge('c', 'x', 2); + graph.addEdge('c', 'y', -3); + graph.addEdge('z', 'x', 1); + graph.addEdge('z', 'y', -4); + + var result = floydWarshall(graph); + + assert.deepEqual(result.distance, {'a': {'a': 0, + 'b': -2, + 'c': -3, + 'x': -1, + 'y': -6, + 'z': Infinity}, + 'b': {'a': 3, + 'b': 0, + 'c': -1, + 'x': 1, + 'y': -4, + 'z': Infinity}, + 'c': {'a': 4, + 'b': 2, + 'c': 0, + 'x': 2, + 'y': -3, + 'z': Infinity}, + 'x': {'a': Infinity, + 'b': Infinity, + 'c': Infinity, + 'x': 0, + 'y': Infinity, + 'z': Infinity}, + 'y': {'a': Infinity, + 'b': Infinity, + 'c': Infinity, + 'x': Infinity, + 'y': 0, + 'z': Infinity}, + 'z': {'a': Infinity, + 'b': Infinity, + 'c': Infinity, + 'x': 1, + 'y': -4, + 'z': 0}}); + + assert.equal(result.path('x', 'y'), null); + assert.deepEqual(result.path('z', 'z'), ['z']); + assert.deepEqual(result.path('c', 'a'), ['c', 'a']); + assert.deepEqual(result.path('a', 'y'), ['a', 'b', 'c', 'y']); + }); + + it('should determine if the graph contains a negative-weighted cycle', + function () { + var graph = new Graph(); + graph.addEdge('a', 'b', -2); + graph.addEdge('b', 'c', -1); + graph.addEdge('c', 'y', -3); + graph.addEdge('c', 'a', 2); + + assert.throws(floydWarshall.bind(null, graph)); + }); +}); From ca4596539ce854259541b5f79be1e3f6468b6955 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sun, 3 Aug 2014 17:35:23 +0200 Subject: [PATCH 107/280] Refactor Radix sort --- algorithms/sorting/radix_sort.js | 56 ++++----------------------- test/algorithms/sorting/radix_sort.js | 42 ++++++++++++-------- 2 files changed, 33 insertions(+), 65 deletions(-) diff --git a/algorithms/sorting/radix_sort.js b/algorithms/sorting/radix_sort.js index 3324c02..33eef98 100644 --- a/algorithms/sorting/radix_sort.js +++ b/algorithms/sorting/radix_sort.js @@ -13,7 +13,8 @@ */ var radixSort = function (array) { var max = maximumKey(array); - var digitsMax = amountOfDigits(max); + var digitsMax = (max === 0 ? 1 : + 1 + Math.floor(Math.log(max) / Math.log(10))); // log base 10 for (var i = 0; i < digitsMax; i++) { array = auxiliaryCountingSort(array, i); @@ -71,55 +72,14 @@ var auxiliaryCountingSort = function (array, mod) { * @return Integer if array non-empty * Undefined otherwise */ -var maximumKey = function (array) { - var length = array.length; - - if (length > 0) { - var max = array[0].key; - - for (var i = 1; i < length; i++) { - if (array[i].key > max) { - max = array[i].key; - } - } - - return max; - } - else { - return undefined; - } -}; - -/** - * Returns the amount of digits contained in a number - * - * Asymptotic Complexity: O(d), where 'd' represents the - * amount of digits in the number - * - * @param Number - * @return Number - */ -var amountOfDigits = function (number) { - if (number === 0) { - return 1; - } - else { - var counter = 0; - - // For positive numbers - while (parseInt(number) > 0) { - number /= 10; - ++counter; - } - - // For negative numbers - while (parseInt(number) < 0) { - number /= 10; - ++counter; +var maximumKey = function (a) { + var max; + for (var i = 1; i < a.length; i++) { + if (max === undefined || a[i].key > max) { + max = a[i].key; } - - return counter; } + return max; }; module.exports = radixSort; diff --git a/test/algorithms/sorting/radix_sort.js b/test/algorithms/sorting/radix_sort.js index 1fc442c..dd5e42d 100644 --- a/test/algorithms/sorting/radix_sort.js +++ b/test/algorithms/sorting/radix_sort.js @@ -24,26 +24,34 @@ var fourthObject = { anotherProperty: '!' }; -var array = [ - thirdObject, - fourthObject, - firstObject, - secondObject, - secondObject, - firstObject, - firstObject, - fourthObject -]; - describe('Radix Sort', function () { it('should sort the given array', function () { - array = radixSort(array); + var sorted = radixSort([ + thirdObject, + fourthObject, + firstObject, + secondObject, + secondObject, + firstObject, + firstObject, + fourthObject + ]); // Asserts that the array is truly sorted - assert.deepEqual(array.indexOf(thirdObject), 0); - assert.deepEqual(array.indexOf(fourthObject), 1); - assert.deepEqual(array.indexOf(firstObject), 3); - assert.deepEqual(array.indexOf(secondObject), 6); - assert.deepEqual(array.indexOf({key: 99}), -1); + assert.deepEqual(sorted, [ + thirdObject, + fourthObject, + fourthObject, + firstObject, + firstObject, + firstObject, + secondObject, + secondObject + ]); + + assert.deepEqual(radixSort([thirdObject, thirdObject]), [ + thirdObject, + thirdObject + ]); }); }); From f174d3d7c7706cc4a16a0e1931a71a3b7cff1826 Mon Sep 17 00:00:00 2001 From: Eugene Sharygin Date: Sun, 3 Aug 2014 19:36:41 +0400 Subject: [PATCH 108/280] Include Floyd-Warshall in main.js --- main.js | 1 + 1 file changed, 1 insertion(+) diff --git a/main.js b/main.js index 644862b..335263d 100644 --- a/main.js +++ b/main.js @@ -12,6 +12,7 @@ var lib = { breadthFirstSearch: require('./algorithms/graph/breadth_first_search'), bfsShortestPath: require('./algorithms/graph/bfs_shortest_path'), prim: require('./algorithms/graph/prim'), + floydWarshall: require('./algorithms/graph/floyd_warshall'), }, Math: { fibonacci: require('./algorithms/math/fibonacci'), From 784992d31c20843e8f410989b55c91e61c35dfeb Mon Sep 17 00:00:00 2001 From: Eugene Sharygin Date: Mon, 4 Aug 2014 00:00:39 +0400 Subject: [PATCH 109/280] Improve coverage * Some tests fixed and some new added. * Optional parameters that can actually never be omitted became mandatory. * Exceptions that check consistency inside modules replaced with asserts. --- algorithms/graph/breadth_first_search.js | 4 ++-- algorithms/graph/depth_first_search.js | 4 ++-- algorithms/string/huffman.js | 11 ++++----- test/algorithms/graph/breadth_first_search.js | 2 ++ test/algorithms/graph/depth_first_search.js | 2 ++ test/algorithms/graph/euler_path.js | 24 ++++++++++++------- test/algorithms/string/huffman.js | 3 ++- 7 files changed, 31 insertions(+), 19 deletions(-) diff --git a/algorithms/graph/breadth_first_search.js b/algorithms/graph/breadth_first_search.js index 51ea946..b1da718 100644 --- a/algorithms/graph/breadth_first_search.js +++ b/algorithms/graph/breadth_first_search.js @@ -19,7 +19,7 @@ var Queue = require('../../data_structures/queue'); * Fill in missing callbacks. * * @param {Callbacks} callbacks - * @param {Array} [seenVertices] - Vertices already discovered, + * @param {Array} seenVertices - Vertices already discovered, * used by default allowTraversal implementation. * @return {Callbacks} The same object or new one (if null passed). */ @@ -27,7 +27,7 @@ var normalizeCallbacks = function (callbacks, seenVertices) { callbacks = callbacks || {}; callbacks.allowTraversal = callbacks.allowTraversal || (function () { - var seen = (seenVertices || []).reduce(function (seen, vertex) { + var seen = seenVertices.reduce(function (seen, vertex) { seen[vertex] = true; return seen; }, {}); diff --git a/algorithms/graph/depth_first_search.js b/algorithms/graph/depth_first_search.js index ed2dc41..d7d0f5c 100644 --- a/algorithms/graph/depth_first_search.js +++ b/algorithms/graph/depth_first_search.js @@ -18,7 +18,7 @@ /** * Fill in missing callbacks. * @param {Callbacks} callbacks - * @param {Array} [seenVertices] - Vertices already discovered, + * @param {Array} seenVertices - Vertices already discovered, * used by default allowTraversal implementation. * @return {Callbacks} The same object or new one (if null passed). */ @@ -26,7 +26,7 @@ var normalizeCallbacks = function (callbacks, seenVertices) { callbacks = callbacks || {}; callbacks.allowTraversal = callbacks.allowTraversal || (function () { - var seen = (seenVertices || []).reduce(function (seen, vertex) { + var seen = seenVertices.reduce(function (seen, vertex) { seen[vertex] = true; return seen; }, {}); diff --git a/algorithms/string/huffman.js b/algorithms/string/huffman.js index bf8efd3..3e57022 100644 --- a/algorithms/string/huffman.js +++ b/algorithms/string/huffman.js @@ -1,5 +1,7 @@ 'use strict'; +var assert = require('assert'); + var huffman = {}; @@ -23,12 +25,9 @@ var compress = function (string) { var currentBlock = 0, currentBlockSize = 0; string.split('').forEach(function (char) { - if (char == '0' || char == '1') { - currentBlock = (currentBlock << 1) | char; - } - else { - throw new Error('String must be binary (only 0s and 1s allowed).'); - } + assert(char == '0' || char == '1', + 'String must be binary (only 0s and 1s allowed).'); + currentBlock = (currentBlock << 1) | char; currentBlockSize += 1; if (currentBlockSize == MAX_BLOCK_SIZE) { diff --git a/test/algorithms/graph/breadth_first_search.js b/test/algorithms/graph/breadth_first_search.js index 6377f0a..6e7a635 100644 --- a/test/algorithms/graph/breadth_first_search.js +++ b/test/algorithms/graph/breadth_first_search.js @@ -23,6 +23,8 @@ describe('Breadth-First Search', function () { var lastEntered = null; var traversed = 0; + breadthFirstSearch(graph, 1); + breadthFirstSearch(graph, 1, { enterVertex: function (vertex) { enter.push(vertex); diff --git a/test/algorithms/graph/depth_first_search.js b/test/algorithms/graph/depth_first_search.js index cf8be2f..f1335bf 100644 --- a/test/algorithms/graph/depth_first_search.js +++ b/test/algorithms/graph/depth_first_search.js @@ -18,6 +18,8 @@ describe('Depth First Search Algorithm', function () { var enter = [], leave = []; var numEdgeTails = 0, numEdgeHeads = 0; + depthFirstSearch(graph, 'one'); + var dfsCallbacks = { enterVertex: [].push.bind(enter), leaveVertex: [].push.bind(leave), diff --git a/test/algorithms/graph/euler_path.js b/test/algorithms/graph/euler_path.js index 85c4a20..47cb995 100644 --- a/test/algorithms/graph/euler_path.js +++ b/test/algorithms/graph/euler_path.js @@ -129,24 +129,32 @@ describe('Euler Path', function () { it('should raise an error if there is no Euler path', function () { var graph = graphFromEdges(false, [[0, 1], [2, 3]]); - assert.throws(eulerPath.bind(graph)); + assert.throws(eulerPath.bind(null, graph)); + graph = graphFromEdges(false, [ [0, 1], [0, 2], [0, 3] ]); - assert.throws(eulerPath.bind(graph)); + assert.throws(eulerPath.bind(null, graph)); + graph = graphFromEdges(true, [[0, 1], [0, 2]]); - assert.throws(eulerPath.bind(graph)); + assert.throws(eulerPath.bind(null, graph)); + graph = graphFromEdges(true, [[1, 0], [2, 0]]); - assert.throws(eulerPath.bind(graph)); + assert.throws(eulerPath.bind(null, graph)); + graph = graphFromEdges(true, [ [0, 1], - [1, 2], [2, 3], - [3, 0], - [3, 1] + [3, 2] + ]); + assert.throws(eulerPath.bind(null, graph)); + + graph = graphFromEdges(true, [ + [0, 1], + [2, 3] ]); - assert.throws(eulerPath.bind(graph)); + assert.throws(eulerPath.bind(null, graph)); }); }); diff --git a/test/algorithms/string/huffman.js b/test/algorithms/string/huffman.js index c435e38..5a7e7c1 100644 --- a/test/algorithms/string/huffman.js +++ b/test/algorithms/string/huffman.js @@ -5,7 +5,7 @@ var huffman = require('../../../algorithms/string/huffman'), describe('Huffman', function () { - var messages = ['', 'a', 'b', 'hello', 'test', 'awwawwweeeqqq', + var messages = ['', 'a', 'b', 'hello', 'test', 'aaaabbbccddef', 'The seething sea ceaseth and thus' + ' the seething sea sufficeth us.', 'Shep Schwab shopped at Scott\'s Schnapps shop;' + @@ -34,6 +34,7 @@ describe('Huffman', function () { it('should raise an error if it fails to decode', function () { var badArgs = [[{}, '0'], + [{}, [0]], [{a: '0', b: '10', c: '11'}, '001']]; badArgs.forEach(function (args) { assert.throws(function () { From 1e73051e6cda4843a54ac3adbcd02ee683ae3aac Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sun, 3 Aug 2014 22:34:20 +0200 Subject: [PATCH 110/280] Refactoring in PQ and Dijkstra --- algorithms/graph/dijkstra.js | 20 +++++++++---------- data_structures/priority_queue.js | 27 +++++++++++++------------- test/data_structures/priority_queue.js | 11 ++++++++--- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/algorithms/graph/dijkstra.js b/algorithms/graph/dijkstra.js index 1c39455..da08795 100644 --- a/algorithms/graph/dijkstra.js +++ b/algorithms/graph/dijkstra.js @@ -24,19 +24,17 @@ function dijkstra(graph, s) { }); var currNode; + var relax = function (v) { + var newDistance = distance[currNode] + graph.edge(currNode, v); + if (newDistance < distance[v]) { + distance[v] = newDistance; + previous[v] = currNode; + q.changePriority(v, distance[v]); + } + }; while (!q.isEmpty()) { currNode = q.extract(); - var neighbors = graph.neighbors(currNode); - for (var i = 0; i < neighbors.length; i++) { - var v = neighbors[i]; - // relaxation - var newDistance = distance[currNode] + graph.edge(currNode, v); - if (newDistance < distance[v]) { - distance[v] = newDistance; - previous[v] = currNode; - q.changePriority(v, distance[v]); - } - } + graph.neighbors(currNode).forEach(relax); } return { distance: distance, diff --git a/data_structures/priority_queue.js b/data_structures/priority_queue.js index 18083e7..4e6f32b 100644 --- a/data_structures/priority_queue.js +++ b/data_structures/priority_queue.js @@ -8,14 +8,15 @@ var MinHeap = require('./heap').MinHeap; * and not on the element itself */ function PriorityQueue(initialItems) { + + var self = this; MinHeap.call(this, function (a, b) { - return a.priority < b.priority ? -1 : 1; + return self._priority[a] < self._priority[b] ? -1 : 1; }); - this._items = {}; + this._priority = {}; initialItems = initialItems || {}; - var self = this; Object.keys(initialItems).forEach(function (item) { self.insert(item, initialItems[item]); }); @@ -24,26 +25,26 @@ function PriorityQueue(initialItems) { PriorityQueue.prototype = new MinHeap(); PriorityQueue.prototype.insert = function (item, priority) { - var o = { - item: item, - priority: priority - }; - - this._items[item] = o; - MinHeap.prototype.insert.call(this, o); + if (this._priority[item] !== undefined) { + return this.changePriority(item, priority); + } + this._priority[item] = priority; + MinHeap.prototype.insert.call(this, item); }; PriorityQueue.prototype.extract = function (withPriority) { var min = MinHeap.prototype.extract.call(this); - return withPriority ? min : min && min.item; + return withPriority ? + min && {item: min, priority: this._priority[min]} : + min; }; PriorityQueue.prototype.priority = function (item) { - return this._items[item].priority; + return this._priority[item]; }; PriorityQueue.prototype.changePriority = function (item, priority) { - this._items[item].priority = priority; + this._priority[item] = priority; this.heapify(); }; diff --git a/test/data_structures/priority_queue.js b/test/data_structures/priority_queue.js index e1ff46f..4fa8b09 100644 --- a/test/data_structures/priority_queue.js +++ b/test/data_structures/priority_queue.js @@ -65,11 +65,16 @@ describe('Min Priority Queue', function () { assert(!q.isEmpty()); q.changePriority('b', 0); + q.changePriority('a', 1); + q.changePriority('c', 50); + q.changePriority('d', 1000); + q.changePriority('e', 2); + assert.equal(q.extract(), 'b'); - assert.equal(q.extract(), 'd'); - assert.equal(q.extract(), 'c'); - assert.equal(q.extract(), 'e'); assert.equal(q.extract(), 'a'); + assert.equal(q.extract(), 'e'); + assert.equal(q.extract(), 'c'); + assert.equal(q.extract(), 'd'); }); }); From ffa052e6d1c7dc6312cb162af2e61da391ef25cd Mon Sep 17 00:00:00 2001 From: Eugene Sharygin Date: Mon, 4 Aug 2014 00:53:39 +0400 Subject: [PATCH 111/280] Remove assertion from the code --- algorithms/string/huffman.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/algorithms/string/huffman.js b/algorithms/string/huffman.js index 3e57022..5895535 100644 --- a/algorithms/string/huffman.js +++ b/algorithms/string/huffman.js @@ -1,7 +1,5 @@ 'use strict'; -var assert = require('assert'); - var huffman = {}; @@ -25,8 +23,6 @@ var compress = function (string) { var currentBlock = 0, currentBlockSize = 0; string.split('').forEach(function (char) { - assert(char == '0' || char == '1', - 'String must be binary (only 0s and 1s allowed).'); currentBlock = (currentBlock << 1) | char; currentBlockSize += 1; From fd04111713fa0a908448824729d77bfaf35b830d Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sun, 3 Aug 2014 23:51:09 +0200 Subject: [PATCH 112/280] stop allowing repeated elements in priority queues --- data_structures/priority_queue.js | 2 +- test/data_structures/priority_queue.js | 27 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/data_structures/priority_queue.js b/data_structures/priority_queue.js index 4e6f32b..18680fb 100644 --- a/data_structures/priority_queue.js +++ b/data_structures/priority_queue.js @@ -11,7 +11,7 @@ function PriorityQueue(initialItems) { var self = this; MinHeap.call(this, function (a, b) { - return self._priority[a] < self._priority[b] ? -1 : 1; + return self.priority(a) < self.priority(b) ? -1 : 1; }); this._priority = {}; diff --git a/test/data_structures/priority_queue.js b/test/data_structures/priority_queue.js index 4fa8b09..b01a2c2 100644 --- a/test/data_structures/priority_queue.js +++ b/test/data_structures/priority_queue.js @@ -75,8 +75,35 @@ describe('Min Priority Queue', function () { assert.equal(q.extract(), 'e'); assert.equal(q.extract(), 'c'); assert.equal(q.extract(), 'd'); + assert(q.isEmpty()); + }); + + it('should just update the priority when trying to insert an element that ' + + ' already exists', function () { + var q = new PriorityQueue({ + a: 10, + b: 2091, + c: 4, + d: 1, + e: 5 + }); + assert(!q.isEmpty()); + + q.insert('b', 0); + q.insert('a', 1); + q.insert('c', 50); + q.insert('d', 1000); + q.insert('e', 2); + + assert.equal(q.extract(), 'b'); + assert.equal(q.extract(), 'a'); + assert.equal(q.extract(), 'e'); + assert.equal(q.extract(), 'c'); + assert.equal(q.extract(), 'd'); + assert(q.isEmpty()); }); + }); From 42042922312b8a6de92c0ee5a0cc1c3ca4e0d3f9 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Tue, 12 Aug 2014 12:46:04 -0400 Subject: [PATCH 113/280] Map for hash table --- data_structures/hash_table.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/data_structures/hash_table.js b/data_structures/hash_table.js index bd3a3d7..0e48939 100644 --- a/data_structures/hash_table.js +++ b/data_structures/hash_table.js @@ -102,4 +102,18 @@ HashTable.prototype._increaseCapacity = function () { } }; +HashTable.prototype.map = function (fn) { + var applyFunction = function (linkedList) { + linkedList.map( function (elem) { + fn(elem.k); + }); + }; + + for(var i = 0; i < this._table.length; i++) { + if (this._table[i]) { + applyFunction(this._table[i]); + } + } +}; + module.exports = HashTable; From 158cfa57caf76a59ade0b630984970f8eb3641a8 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Tue, 12 Aug 2014 12:46:30 -0400 Subject: [PATCH 114/280] Test for hash table map --- test/data_structures/hash_table.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/data_structures/hash_table.js b/test/data_structures/hash_table.js index f31d2c6..3bcc2f4 100644 --- a/test/data_structures/hash_table.js +++ b/test/data_structures/hash_table.js @@ -123,5 +123,19 @@ describe('Hash Table', function () { h.put(o, 'foo'); assert.equal(h.get(o), 'foo'); }); + + it('should implement map correctly', function () { + var h = new HashTable(); + h.put(1, true); + h.put(2, true); + h.put(3, true); + + var total = 0; + h.map(function (elem) { + total += elem; + }); + + assert.equal(total, 6); + }); }); From 3be516805422c7fb83fa719c3b439bd45f8d9a96 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Tue, 12 Aug 2014 14:05:28 -0400 Subject: [PATCH 115/280] Map for hash set --- data_structures/set.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data_structures/set.js b/data_structures/set.js index 74df72f..6cc0cbe 100644 --- a/data_structures/set.js +++ b/data_structures/set.js @@ -36,4 +36,8 @@ HashSet.prototype.contains = function (e) { return this._elements.get(e) !== undefined; }; +HashSet.prototype.map = function (fn) { + this._elements.map(fn); +}; + module.exports = HashSet; From 3445739974a7e66d28c765546927bf4b8ae6b36f Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Tue, 12 Aug 2014 14:05:55 -0400 Subject: [PATCH 116/280] Test for hash set map --- test/data_structures/set.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/data_structures/set.js b/test/data_structures/set.js index 0f43a78..17fc1d3 100644 --- a/test/data_structures/set.js +++ b/test/data_structures/set.js @@ -57,6 +57,18 @@ describe('HashSet', function () { assert(s.contains(1)); assert(!s.contains(4)); }); + + it('should implement map correctly', function () { + var s = new HashSet(); + s.add(1, 2, 3); + + var total = 0; + s.map(function (elem) { + total += elem; + }); + + assert.equal(total, 6); + }); }); From d1679ea840e871bcf8e144176d40febd55e8b780 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Tue, 12 Aug 2014 14:06:22 -0400 Subject: [PATCH 117/280] Map for queue --- data_structures/queue.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data_structures/queue.js b/data_structures/queue.js index 9f71c07..e10a8f3 100644 --- a/data_structures/queue.js +++ b/data_structures/queue.js @@ -46,4 +46,8 @@ Queue.prototype.peek = function () { return this._elements.get(0); }; +Queue.prototype.map = function (fn) { + this._elements.map(fn); +}; + module.exports = Queue; From e943ac5da2deb3e73588c188e57a48a1e47ef127 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Tue, 12 Aug 2014 14:06:39 -0400 Subject: [PATCH 118/280] Test for queue map --- test/data_structures/queue.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/data_structures/queue.js b/test/data_structures/queue.js index aca4fd5..5a812e3 100644 --- a/test/data_structures/queue.js +++ b/test/data_structures/queue.js @@ -35,6 +35,20 @@ describe('Queue', function () { q.pop(); assert.equal(q.peek(), 2); }); + + it('should implement map correctly', function () { + var q = new Queue(); + q.push(1); + q.push(2); + q.push(3); + + var total = 0; + q.map(function (elem) { + total += elem; + }); + + assert.equal(total, 6); + }); }); From dfb01d552b92dc9bd1b238c8b129d2828162855a Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Tue, 12 Aug 2014 14:14:35 -0400 Subject: [PATCH 119/280] Map for heap --- data_structures/heap.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data_structures/heap.js b/data_structures/heap.js index b27cda9..f80a7d2 100644 --- a/data_structures/heap.js +++ b/data_structures/heap.js @@ -89,6 +89,10 @@ MinHeap.prototype.heapify = function (a) { } }; +MinHeap.prototype.map = function (fn) { + this._elements.map(fn); +}; + /** * Max Heap, keeps the highest element always on top * From dc6c1b47692a70b9c8cadb9aaa0e358512ae2858 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Tue, 12 Aug 2014 14:14:50 -0400 Subject: [PATCH 120/280] Test for heap map --- test/data_structures/heap.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/data_structures/heap.js b/test/data_structures/heap.js index 5595994..59f9390 100644 --- a/test/data_structures/heap.js +++ b/test/data_structures/heap.js @@ -53,6 +53,18 @@ describe('Min Heap', function () { assert(h.isEmpty()); }); + + it('should implement map correctly', function () { + var h = new heap.MinHeap(); + h.heapify([1, 2, 3]); + + var total = 0; + h.map(function (elem) { + total += elem; + }); + + assert.equal(total, 6); + }); }); describe('Max Heap', function () { From d9927c58443bb3c1187402684a3506732c177fcf Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 13 Aug 2014 22:45:49 +0200 Subject: [PATCH 121/280] Add browser version (minified) --- Makefile | 4 ++++ build/algorithms.browser.min.js | 2 ++ 2 files changed, 6 insertions(+) create mode 100644 build/algorithms.browser.min.js diff --git a/Makefile b/Makefile index 96ba6db..5c56dc8 100644 --- a/Makefile +++ b/Makefile @@ -15,3 +15,7 @@ coverage: setup coveralls: cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js +VERSION := $(shell node -e "console.log(require('./package.json').version);") +browser_bundle: setup + browserify $(realpath main.js) --s algorithms | uglifyjs -c -m --screw-ie8 --wrap --preamble "/* algorithms.js v$(VERSION) | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */" > build/algorithms.browser.min.js + diff --git a/build/algorithms.browser.min.js b/build/algorithms.browser.min.js new file mode 100644 index 0000000..a8bd574 --- /dev/null +++ b/build/algorithms.browser.min.js @@ -0,0 +1,2 @@ +/* algorithms.js v0.5.0 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ +!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.length)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":45}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);ne&&r.push({ends:[e,n],weight:t.edge(e,n)})}),r},[]);return o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":39,"../../data_structures/graph":40}],10:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],18:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":49}],19:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],21:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":45}],22:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":49}],25:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],26:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":42}],27:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":49}],28:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":49}],30:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],31:[function(t,r){"use strict";var e=function(t){for(var r=t.length,e=0;r-1>e;e++){for(var n=e,i=e+1;r>i;i++)t[n]>t[i]&&(n=i);if(n!=e){var o=t[e];t[e]=t[n],t[n]=o}}return t};r.exports=e},{}],32:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],34:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],35:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],36:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;ei[e][n-1]?e--:n--;return s.split("").reverse().join("")};r.exports=e},{}],37:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":49}],43:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.map=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],44:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[48])(48)})}({},function(){return this}()); \ No newline at end of file From 5f7b84be2cbbac72e992c3db49f9dde247c457eb Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Wed, 13 Aug 2014 18:18:52 -0400 Subject: [PATCH 122/280] Fixed two syntax problems --- data_structures/hash_table.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/hash_table.js b/data_structures/hash_table.js index 0e48939..488a4f7 100644 --- a/data_structures/hash_table.js +++ b/data_structures/hash_table.js @@ -104,12 +104,12 @@ HashTable.prototype._increaseCapacity = function () { HashTable.prototype.map = function (fn) { var applyFunction = function (linkedList) { - linkedList.map( function (elem) { + linkedList.map(function (elem) { fn(elem.k); }); }; - for(var i = 0; i < this._table.length; i++) { + for (var i = 0; i < this._table.length; i++) { if (this._table[i]) { applyFunction(this._table[i]); } From 5fe80c5c7c4716300c24c44768b1d3ac4b9401d1 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Wed, 13 Aug 2014 18:43:24 -0400 Subject: [PATCH 123/280] Changed name from map to forEach --- data_structures/hash_table.js | 4 ++-- data_structures/heap.js | 4 ++-- data_structures/linked_list.js | 2 +- data_structures/queue.js | 4 ++-- data_structures/set.js | 4 ++-- test/data_structures/hash_table.js | 4 ++-- test/data_structures/heap.js | 4 ++-- test/data_structures/linked_list.js | 4 ++-- test/data_structures/queue.js | 4 ++-- test/data_structures/set.js | 4 ++-- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/data_structures/hash_table.js b/data_structures/hash_table.js index 488a4f7..f461758 100644 --- a/data_structures/hash_table.js +++ b/data_structures/hash_table.js @@ -102,9 +102,9 @@ HashTable.prototype._increaseCapacity = function () { } }; -HashTable.prototype.map = function (fn) { +HashTable.prototype.forEach = function (fn) { var applyFunction = function (linkedList) { - linkedList.map(function (elem) { + linkedList.forEach(function (elem) { fn(elem.k); }); }; diff --git a/data_structures/heap.js b/data_structures/heap.js index f80a7d2..b107c45 100644 --- a/data_structures/heap.js +++ b/data_structures/heap.js @@ -89,8 +89,8 @@ MinHeap.prototype.heapify = function (a) { } }; -MinHeap.prototype.map = function (fn) { - this._elements.map(fn); +MinHeap.prototype.forEach = function (fn) { + this._elements.forEach(fn); }; /** diff --git a/data_structures/linked_list.js b/data_structures/linked_list.js index 5ab7674..8602125 100644 --- a/data_structures/linked_list.js +++ b/data_structures/linked_list.js @@ -140,7 +140,7 @@ LinkedList.prototype.delNode = function (node) { /** * Performs the fn function with each element in the list */ -LinkedList.prototype.map = function (fn) { +LinkedList.prototype.forEach = function (fn) { var node = this.head; while (node) { fn(node.value); diff --git a/data_structures/queue.js b/data_structures/queue.js index e10a8f3..065b0d9 100644 --- a/data_structures/queue.js +++ b/data_structures/queue.js @@ -46,8 +46,8 @@ Queue.prototype.peek = function () { return this._elements.get(0); }; -Queue.prototype.map = function (fn) { - this._elements.map(fn); +Queue.prototype.forEach = function (fn) { + this._elements.forEach(fn); }; module.exports = Queue; diff --git a/data_structures/set.js b/data_structures/set.js index 6cc0cbe..e6868a3 100644 --- a/data_structures/set.js +++ b/data_structures/set.js @@ -36,8 +36,8 @@ HashSet.prototype.contains = function (e) { return this._elements.get(e) !== undefined; }; -HashSet.prototype.map = function (fn) { - this._elements.map(fn); +HashSet.prototype.forEach = function (fn) { + this._elements.forEach(fn); }; module.exports = HashSet; diff --git a/test/data_structures/hash_table.js b/test/data_structures/hash_table.js index 3bcc2f4..e58e68e 100644 --- a/test/data_structures/hash_table.js +++ b/test/data_structures/hash_table.js @@ -124,14 +124,14 @@ describe('Hash Table', function () { assert.equal(h.get(o), 'foo'); }); - it('should implement map correctly', function () { + it('should implement forEach correctly', function () { var h = new HashTable(); h.put(1, true); h.put(2, true); h.put(3, true); var total = 0; - h.map(function (elem) { + h.forEach(function (elem) { total += elem; }); diff --git a/test/data_structures/heap.js b/test/data_structures/heap.js index 59f9390..75d5404 100644 --- a/test/data_structures/heap.js +++ b/test/data_structures/heap.js @@ -54,12 +54,12 @@ describe('Min Heap', function () { assert(h.isEmpty()); }); - it('should implement map correctly', function () { + it('should implement forEach correctly', function () { var h = new heap.MinHeap(); h.heapify([1, 2, 3]); var total = 0; - h.map(function (elem) { + h.forEach(function (elem) { total += elem; }); diff --git a/test/data_structures/linked_list.js b/test/data_structures/linked_list.js index eb1dc55..9e02c44 100644 --- a/test/data_structures/linked_list.js +++ b/test/data_structures/linked_list.js @@ -133,7 +133,7 @@ describe('LinkedList', function () { assert.equal(l.length, 0); }); - it('should perform a function to all elements with map', function () { + it('should perform a function to all elements with forEach', function () { var l = new LinkedList(); l.add(5); l.add(1); @@ -142,7 +142,7 @@ describe('LinkedList', function () { l.add(1000); var a = []; - l.map(function (e) { + l.forEach(function (e) { a.push(e); }); diff --git a/test/data_structures/queue.js b/test/data_structures/queue.js index 5a812e3..488891c 100644 --- a/test/data_structures/queue.js +++ b/test/data_structures/queue.js @@ -36,14 +36,14 @@ describe('Queue', function () { assert.equal(q.peek(), 2); }); - it('should implement map correctly', function () { + it('should implement forEach correctly', function () { var q = new Queue(); q.push(1); q.push(2); q.push(3); var total = 0; - q.map(function (elem) { + q.forEach(function (elem) { total += elem; }); diff --git a/test/data_structures/set.js b/test/data_structures/set.js index 17fc1d3..9b9e322 100644 --- a/test/data_structures/set.js +++ b/test/data_structures/set.js @@ -58,12 +58,12 @@ describe('HashSet', function () { assert(!s.contains(4)); }); - it('should implement map correctly', function () { + it('should implement forEach correctly', function () { var s = new HashSet(); s.add(1, 2, 3); var total = 0; - s.map(function (elem) { + s.forEach(function (elem) { total += elem; }); From a4b8d5b1ec83a7f127c6e2ce2fcf25c0b6b002db Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Thu, 14 Aug 2014 07:54:01 +0200 Subject: [PATCH 124/280] Rename LinkedList.prototype.map -> LinkedList.prototype.forEach It should impact #88 --- data_structures/linked_list.js | 2 +- test/data_structures/linked_list.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data_structures/linked_list.js b/data_structures/linked_list.js index 5ab7674..8602125 100644 --- a/data_structures/linked_list.js +++ b/data_structures/linked_list.js @@ -140,7 +140,7 @@ LinkedList.prototype.delNode = function (node) { /** * Performs the fn function with each element in the list */ -LinkedList.prototype.map = function (fn) { +LinkedList.prototype.forEach = function (fn) { var node = this.head; while (node) { fn(node.value); diff --git a/test/data_structures/linked_list.js b/test/data_structures/linked_list.js index eb1dc55..9e02c44 100644 --- a/test/data_structures/linked_list.js +++ b/test/data_structures/linked_list.js @@ -133,7 +133,7 @@ describe('LinkedList', function () { assert.equal(l.length, 0); }); - it('should perform a function to all elements with map', function () { + it('should perform a function to all elements with forEach', function () { var l = new LinkedList(); l.add(5); l.add(1); @@ -142,7 +142,7 @@ describe('LinkedList', function () { l.add(1000); var a = []; - l.map(function (e) { + l.forEach(function (e) { a.push(e); }); From 46bb8cd094e8967af27c6a8819361011d5d245e5 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Thu, 14 Aug 2014 17:06:20 -0400 Subject: [PATCH 125/280] forEach for MinHeap iterates in order --- data_structures/heap.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/data_structures/heap.js b/data_structures/heap.js index b107c45..d5969ef 100644 --- a/data_structures/heap.js +++ b/data_structures/heap.js @@ -90,7 +90,15 @@ MinHeap.prototype.heapify = function (a) { }; MinHeap.prototype.forEach = function (fn) { - this._elements.forEach(fn); + var elementsCopy = JSON.parse(JSON.stringify(this._elements)); + + var element = this.extract(); + while (typeof element !== 'undefined') { + fn(element); + element = this.extract(); + } + + this._elements = elementsCopy; }; /** From b8475ea7580f05151ce69d1013926956add71f6e Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Thu, 14 Aug 2014 17:26:22 -0400 Subject: [PATCH 126/280] Tests for proper order in forEach for MinHeap and MaxHeap --- test/data_structures/heap.js | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/test/data_structures/heap.js b/test/data_structures/heap.js index 75d5404..891ea2e 100644 --- a/test/data_structures/heap.js +++ b/test/data_structures/heap.js @@ -54,16 +54,16 @@ describe('Min Heap', function () { assert(h.isEmpty()); }); - it('should implement forEach correctly', function () { + it('should iterate from smallest to largest', function () { var h = new heap.MinHeap(); - h.heapify([1, 2, 3]); + h.heapify([3, 10, 1000, 0, 2, 1]); - var total = 0; - h.forEach(function (elem) { - total += elem; + var output = []; + h.forEach(function (n) { + output.push(n); }); - assert.equal(total, 6); + assert.deepEqual(output, [0, 1, 2, 3, 10, 1000]); }); }); @@ -117,4 +117,16 @@ describe('Max Heap', function () { assert(h.isEmpty()); }); + + it('should iterate from largest to smallest', function () { + var h = new heap.MaxHeap(); + h.heapify([3, 10, 1000, 0, 2, 1]); + + var output = []; + h.forEach(function (n) { + output.push(n); + }); + + assert.deepEqual(output, [1000, 10, 3, 2, 1, 0]); + }); }); From 89a491ae04fe6392929b2fe27f70dd37a96705ca Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Thu, 14 Aug 2014 17:38:23 -0400 Subject: [PATCH 127/280] Better descriptions for forEach tests --- test/data_structures/hash_table.js | 2 +- test/data_structures/heap.js | 7 ++++--- test/data_structures/queue.js | 2 +- test/data_structures/set.js | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/test/data_structures/hash_table.js b/test/data_structures/hash_table.js index e58e68e..400d259 100644 --- a/test/data_structures/hash_table.js +++ b/test/data_structures/hash_table.js @@ -124,7 +124,7 @@ describe('Hash Table', function () { assert.equal(h.get(o), 'foo'); }); - it('should implement forEach correctly', function () { + it('should perform a function to all keys with forEach', function () { var h = new HashTable(); h.put(1, true); h.put(2, true); diff --git a/test/data_structures/heap.js b/test/data_structures/heap.js index 891ea2e..0d0e5d0 100644 --- a/test/data_structures/heap.js +++ b/test/data_structures/heap.js @@ -53,8 +53,8 @@ describe('Min Heap', function () { assert(h.isEmpty()); }); - - it('should iterate from smallest to largest', function () { + it('should perform a function to all elements from smallest to largest' + + ' with forEach', function () { var h = new heap.MinHeap(); h.heapify([3, 10, 1000, 0, 2, 1]); @@ -118,7 +118,8 @@ describe('Max Heap', function () { assert(h.isEmpty()); }); - it('should iterate from largest to smallest', function () { + it('should perform a function to all elements from largest to smallest' + + ' with forEach', function () { var h = new heap.MaxHeap(); h.heapify([3, 10, 1000, 0, 2, 1]); diff --git a/test/data_structures/queue.js b/test/data_structures/queue.js index 488891c..82ecd8a 100644 --- a/test/data_structures/queue.js +++ b/test/data_structures/queue.js @@ -36,7 +36,7 @@ describe('Queue', function () { assert.equal(q.peek(), 2); }); - it('should implement forEach correctly', function () { + it('should perform a function to all elements with forEach', function () { var q = new Queue(); q.push(1); q.push(2); diff --git a/test/data_structures/set.js b/test/data_structures/set.js index 9b9e322..aa8f918 100644 --- a/test/data_structures/set.js +++ b/test/data_structures/set.js @@ -58,7 +58,7 @@ describe('HashSet', function () { assert(!s.contains(4)); }); - it('should implement forEach correctly', function () { + it('should perform a function to all elements with forEach', function () { var s = new HashSet(); s.add(1, 2, 3); From eed6f4947736d06df75e8f747d2d115958796bfd Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Thu, 14 Aug 2014 17:45:02 -0400 Subject: [PATCH 128/280] Fixed syntax problems --- test/data_structures/heap.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/data_structures/heap.js b/test/data_structures/heap.js index 0d0e5d0..ac8ba9c 100644 --- a/test/data_structures/heap.js +++ b/test/data_structures/heap.js @@ -53,14 +53,15 @@ describe('Min Heap', function () { assert(h.isEmpty()); }); - it('should perform a function to all elements from smallest to largest' + + + it('should perform a function to all elements from smallest to largest' + ' with forEach', function () { var h = new heap.MinHeap(); h.heapify([3, 10, 1000, 0, 2, 1]); var output = []; h.forEach(function (n) { - output.push(n); + output.push(n); }); assert.deepEqual(output, [0, 1, 2, 3, 10, 1000]); @@ -118,14 +119,14 @@ describe('Max Heap', function () { assert(h.isEmpty()); }); - it('should perform a function to all elements from largest to smallest' + + it('should perform a function to all elements from largest to smallest' + ' with forEach', function () { var h = new heap.MaxHeap(); h.heapify([3, 10, 1000, 0, 2, 1]); var output = []; h.forEach(function (n) { - output.push(n); + output.push(n); }); assert.deepEqual(output, [1000, 10, 3, 2, 1, 0]); From f92635eceed01618636b8fcd31760f7bc40ec67e Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 15 Aug 2014 07:59:22 +0200 Subject: [PATCH 129/280] Fix Heap.forEach to just copy the array but keep the same references to the elements inside --- data_structures/heap.js | 6 +++++- test/data_structures/heap.js | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/data_structures/heap.js b/data_structures/heap.js index d5969ef..27402d0 100644 --- a/data_structures/heap.js +++ b/data_structures/heap.js @@ -90,7 +90,11 @@ MinHeap.prototype.heapify = function (a) { }; MinHeap.prototype.forEach = function (fn) { - var elementsCopy = JSON.parse(JSON.stringify(this._elements)); + var elementsCopy = []; + + for (var i = 0; i < this._elements.length; i++) { + elementsCopy.push(this._elements[i]); + } var element = this.extract(); while (typeof element !== 'undefined') { diff --git a/test/data_structures/heap.js b/test/data_structures/heap.js index ac8ba9c..fbeb175 100644 --- a/test/data_structures/heap.js +++ b/test/data_structures/heap.js @@ -65,6 +65,9 @@ describe('Min Heap', function () { }); assert.deepEqual(output, [0, 1, 2, 3, 10, 1000]); + + // Make sure nothing was really removed + assert.equal(h.n, 6); }); }); From ecfb6498c65109cb8858a63cd438a3890ea2fa96 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 15 Aug 2014 08:03:39 +0200 Subject: [PATCH 130/280] HashTable.forEach now receives key and value --- data_structures/hash_table.js | 2 +- test/data_structures/hash_table.js | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/data_structures/hash_table.js b/data_structures/hash_table.js index f461758..ecb421f 100644 --- a/data_structures/hash_table.js +++ b/data_structures/hash_table.js @@ -105,7 +105,7 @@ HashTable.prototype._increaseCapacity = function () { HashTable.prototype.forEach = function (fn) { var applyFunction = function (linkedList) { linkedList.forEach(function (elem) { - fn(elem.k); + fn(elem.k, elem.v); }); }; diff --git a/test/data_structures/hash_table.js b/test/data_structures/hash_table.js index 400d259..91d9bdf 100644 --- a/test/data_structures/hash_table.js +++ b/test/data_structures/hash_table.js @@ -126,16 +126,19 @@ describe('Hash Table', function () { it('should perform a function to all keys with forEach', function () { var h = new HashTable(); - h.put(1, true); - h.put(2, true); - h.put(3, true); - - var total = 0; - h.forEach(function (elem) { - total += elem; + h.put(1, 10); + h.put(2, 20); + h.put(3, 30); + + var totalKeys = 0; + var totalValues = 0; + h.forEach(function (k, v) { + totalKeys += k; + totalValues += v; }); - assert.equal(total, 6); + assert.equal(totalKeys, 6); + assert.equal(totalValues, 60); }); }); From 46285e3b172522862b08c1d79e384640e0bcde56 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 15 Aug 2014 11:08:10 +0200 Subject: [PATCH 131/280] Add documentation and refactor a bit MinHeap.forEach --- data_structures/heap.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/data_structures/heap.js b/data_structures/heap.js index 27402d0..2d04f2b 100644 --- a/data_structures/heap.js +++ b/data_structures/heap.js @@ -90,16 +90,18 @@ MinHeap.prototype.heapify = function (a) { }; MinHeap.prototype.forEach = function (fn) { + // A copy is necessary in order to perform extract(), + // get the items in sorted order and then restore the original + // this._elements array var elementsCopy = []; + var i; - for (var i = 0; i < this._elements.length; i++) { + for (i = 0; i < this._elements.length; i++) { elementsCopy.push(this._elements[i]); } - var element = this.extract(); - while (typeof element !== 'undefined') { - fn(element); - element = this.extract(); + for (i = this.n; i > 0; i--) { + fn(this.extract()); } this._elements = elementsCopy; From 11c8c7395b2b9824d017b18ce1f0c11cc106ad1e Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 15 Aug 2014 12:50:13 +0200 Subject: [PATCH 132/280] v0.6.0 Changelog: * Browser bundle * Data Structures * forEach in Hash Table, Set, Heap and Queue * Set * String * Longest common subsequence * Math * Logarithmic time Fibonacci * Graph * Kruskal's MST * Prim's MST * DFS * BFS * Floyd-Warshall --- CHANGELOG | 16 ++++++++++++++++ package.json | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 8419e6f..e713e1f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,21 @@ CHANGELOG ========= +0.6.0 (2014-08-15) +* Browser bundle +* Data Structures + * forEach in Hash Table, Set, Heap and Queue + * Set +* String + * Longest common subsequence +* Math + * Logarithmic time Fibonacci +* Graph + * Kruskal's MST + * Prim's MST + * DFS + * BFS + * Floyd-Warshall + 0.5.0 (2014-07-09) * Math * Fast Power diff --git a/package.json b/package.json index 3b3978f..fe2bb29 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.5.0", + "version": "0.6.0", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" From 8041cc257b711264a25c4e9444d53bdaacbcc16c Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 15 Aug 2014 12:53:26 +0200 Subject: [PATCH 133/280] Fix version number in browser bundle --- build/algorithms.browser.min.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/algorithms.browser.min.js b/build/algorithms.browser.min.js index a8bd574..fcd8c2b 100644 --- a/build/algorithms.browser.min.js +++ b/build/algorithms.browser.min.js @@ -1,2 +1,2 @@ -/* algorithms.js v0.5.0 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ -!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.length)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":45}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);ne&&r.push({ends:[e,n],weight:t.edge(e,n)})}),r},[]);return o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":39,"../../data_structures/graph":40}],10:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],18:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":49}],19:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],21:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":45}],22:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":49}],25:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],26:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":42}],27:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":49}],28:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":49}],30:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],31:[function(t,r){"use strict";var e=function(t){for(var r=t.length,e=0;r-1>e;e++){for(var n=e,i=e+1;r>i;i++)t[n]>t[i]&&(n=i);if(n!=e){var o=t[e];t[e]=t[n],t[n]=o}}return t};r.exports=e},{}],32:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],34:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],35:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],36:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;ei[e][n-1]?e--:n--;return s.split("").reverse().join("")};r.exports=e},{}],37:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":49}],43:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.map=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],44:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[48])(48)})}({},function(){return this}()); \ No newline at end of file +/* algorithms.js v0.6.0 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ +!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.length)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":45}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);ne&&r.push({ends:[e,n],weight:t.edge(e,n)})}),r},[]);return o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":39,"../../data_structures/graph":40}],10:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],18:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":49}],19:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],21:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":45}],22:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":49}],25:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],26:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":42}],27:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":49}],28:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":49}],30:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],31:[function(t,r){"use strict";var e=function(t){for(var r=t.length,e=0;r-1>e;e++){for(var n=e,i=e+1;r>i;i++)t[n]>t[i]&&(n=i);if(n!=e){var o=t[e];t[e]=t[n],t[n]=o}}return t};r.exports=e},{}],32:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],34:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],35:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],36:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;ei[e][n-1]?e--:n--;return s.split("").reverse().join("")};r.exports=e},{}],37:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":49}],43:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],44:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[48])(48)})}({},function(){return this}()); \ No newline at end of file From 9716d2f74fc11356636305dfa996905149c4965f Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 15 Aug 2014 12:55:16 +0200 Subject: [PATCH 134/280] v0.6.1 with correct browser bundle version --- build/algorithms.browser.min.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/algorithms.browser.min.js b/build/algorithms.browser.min.js index fcd8c2b..ebca4cc 100644 --- a/build/algorithms.browser.min.js +++ b/build/algorithms.browser.min.js @@ -1,2 +1,2 @@ -/* algorithms.js v0.6.0 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ +/* algorithms.js v0.6.1 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ !function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.length)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":45}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);ne&&r.push({ends:[e,n],weight:t.edge(e,n)})}),r},[]);return o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":39,"../../data_structures/graph":40}],10:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],18:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":49}],19:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],21:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":45}],22:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":49}],25:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],26:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":42}],27:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":49}],28:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":49}],30:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],31:[function(t,r){"use strict";var e=function(t){for(var r=t.length,e=0;r-1>e;e++){for(var n=e,i=e+1;r>i;i++)t[n]>t[i]&&(n=i);if(n!=e){var o=t[e];t[e]=t[n],t[n]=o}}return t};r.exports=e},{}],32:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],34:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],35:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],36:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;ei[e][n-1]?e--:n--;return s.split("").reverse().join("")};r.exports=e},{}],37:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":49}],43:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],44:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[48])(48)})}({},function(){return this}()); \ No newline at end of file diff --git a/package.json b/package.json index fe2bb29..d146692 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.6.0", + "version": "0.6.1", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" From 3958913650c4d4d2ab72d264eea9eea5a399c4b2 Mon Sep 17 00:00:00 2001 From: gyj <505324327@qq.com> Date: Sat, 9 Aug 2014 17:35:42 +0800 Subject: [PATCH 135/280] Add ShellSort --- algorithms/sorting/shell_sort.js | 29 ++++++++++++++++++ main.js | 3 +- test/algorithms/sorting/shell_sort.js | 42 +++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 algorithms/sorting/shell_sort.js create mode 100644 test/algorithms/sorting/shell_sort.js diff --git a/algorithms/sorting/shell_sort.js b/algorithms/sorting/shell_sort.js new file mode 100644 index 0000000..6530306 --- /dev/null +++ b/algorithms/sorting/shell_sort.js @@ -0,0 +1,29 @@ +'use strict'; +var Comparator = require('../../util/comparator'); +/** + * shell sort worst:O(n lg n) best:O(n) + */ +var shellSort = function (array, comparatorFn) { + var comparator = new Comparator(comparatorFn), + begin = 0, + end = array.length - 1, + gap = parseInt((end - begin + 1) / 2), + i = 0, j = 0, temp = 0; + + while (gap >= 1) { + for (i = begin + gap;i <= end;i += 1) { + temp = array[i]; + j = i - gap; + while (j >= begin && comparator.greaterThan(array[j], temp)) { + array[j + gap] = array[j]; + j = j - gap; + } + array[j + gap] = temp; + } + gap = parseInt(gap / 2); + } + + return array; +}; + +module.exports = shellSort; diff --git a/main.js b/main.js index 335263d..923ee27 100644 --- a/main.js +++ b/main.js @@ -38,7 +38,8 @@ var lib = { quicksort: require('./algorithms/sorting/quicksort'), selectionSort: require('./algorithms/sorting/selection_sort'), radixSort: require('./algorithms/sorting/radix_sort'), - insertionSort: require('./algorithms/sorting/insertion_sort') + insertionSort: require('./algorithms/sorting/insertion_sort'), + shellsort: require('./algorithms/sorting/shell_sort') }, String: { levenshtein: require('./algorithms/string/levenshtein'), diff --git a/test/algorithms/sorting/shell_sort.js b/test/algorithms/sorting/shell_sort.js new file mode 100644 index 0000000..287bb28 --- /dev/null +++ b/test/algorithms/sorting/shell_sort.js @@ -0,0 +1,42 @@ +'use strict'; + +var shellSort = require('../../../algorithms/sorting/shell_sort'), + assert = require('assert'); + +describe('ShellSort', function () { + it('should sort the given array', function () { + assert.deepEqual(shellSort([]), []); + assert.deepEqual(shellSort([1]), [1]); + assert.deepEqual(shellSort([2, 1]), [1, 2]); + assert.deepEqual(shellSort([3, 1, 2]), [1, 2, 3]); + assert.deepEqual(shellSort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual(shellSort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual(shellSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), + [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); + }); + + it('should sort the array with a specific comparison function', function () { + var compare = function (a, b) { + if (a.length === b.length) return 0; + return a.length < b.length ? -1 : 1; + }; + assert.deepEqual(shellSort([], compare), []); + assert.deepEqual(shellSort(['apple'], compare), ['apple']); + assert.deepEqual(shellSort(['apple', 'banana'], compare), + ['apple', 'banana']); + assert.deepEqual(shellSort(['apple', 'banana', 'car'], compare), + ['car', 'apple', 'banana']); + assert.deepEqual(shellSort(['apple', 'banana', 'car', 'z'], compare), + ['z', 'car', 'apple', 'banana']); + + var reverseSort = function (a, b) { + if (a == b) return 0; + return a < b ? 1 : -1; + }; + assert.deepEqual(shellSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], + reverseSort), + [295, 20, 10, 10, 8, 6, 5, 3, 1, 0]); + }); +}); + + From 2211ce9658a1874f4a91d1e038eab475a393ea3d Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 15 Aug 2014 15:31:34 +0200 Subject: [PATCH 136/280] DRY in sorting tests and make Selecion sort use the Comparator object --- algorithms/sorting/selection_sort.js | 7 +- test/algorithms/sorting/bubble_sort.js | 34 +--------- test/algorithms/sorting/heap_sort.js | 32 +-------- test/algorithms/sorting/insertion_sort.js | 65 +------------------ test/algorithms/sorting/merge_sort.js | 33 +--------- test/algorithms/sorting/quicksort.js | 32 +-------- test/algorithms/sorting/selection_sort.js | 17 ++--- test/algorithms/sorting/shell_sort.js | 32 +-------- .../sorting/sorting_tests_helper.js | 42 ++++++++++++ 9 files changed, 70 insertions(+), 224 deletions(-) create mode 100644 test/algorithms/sorting/sorting_tests_helper.js diff --git a/algorithms/sorting/selection_sort.js b/algorithms/sorting/selection_sort.js index f5e9150..f35ed12 100644 --- a/algorithms/sorting/selection_sort.js +++ b/algorithms/sorting/selection_sort.js @@ -1,14 +1,17 @@ 'use strict'; +var Comparator = require('../../util/comparator'); /** * Selection sort algorithm O(n^2) */ -var selectionSort = function (a) { +var selectionSort = function (a, comparatorFn) { + var comparator = new Comparator(comparatorFn); var n = a.length; for (var i = 0; i < n - 1; i++) { var min = i; for (var j = i + 1; j < n; j++) { - if (a[min] > a[j]) + if (comparator.greaterThan(a[min], a[j])) { min = j; + } } if (min != i) { var tmp = a[i]; diff --git a/test/algorithms/sorting/bubble_sort.js b/test/algorithms/sorting/bubble_sort.js index b1944ba..9de0405 100644 --- a/test/algorithms/sorting/bubble_sort.js +++ b/test/algorithms/sorting/bubble_sort.js @@ -1,42 +1,14 @@ 'use strict'; var bubbleSort = require('../../../algorithms/sorting/bubble_sort'), - assert = require('assert'); + sortingTestsHelper = require('./sorting_tests_helper'); describe('Bubble Sort', function () { it('should sort the given array', function () { - assert.deepEqual(bubbleSort([]), []); - assert.deepEqual(bubbleSort([1]), [1]); - assert.deepEqual(bubbleSort([2, 1]), [1, 2]); - assert.deepEqual(bubbleSort([3, 1, 2]), [1, 2, 3]); - assert.deepEqual(bubbleSort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(bubbleSort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(bubbleSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), - [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); + sortingTestsHelper.testSort(bubbleSort); }); it('should sort the array with a specific comparison function', function () { - var compare = function (a, b) { - if (a.length === b.length) return 0; - return a.length < b.length ? -1 : 1; - }; - assert.deepEqual(bubbleSort([], compare), []); - assert.deepEqual(bubbleSort(['apple'], compare), ['apple']); - assert.deepEqual(bubbleSort(['apple', 'banana'], compare), - ['apple', 'banana']); - assert.deepEqual(bubbleSort(['apple', 'banana', 'car'], compare), - ['car', 'apple', 'banana']); - assert.deepEqual(bubbleSort(['apple', 'banana', 'car', 'z'], compare), - ['z', 'car', 'apple', 'banana']); - - var reverseSort = function (a, b) { - if (a == b) return 0; - return a < b ? 1 : -1; - }; - assert.deepEqual(bubbleSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], - reverseSort), - [295, 20, 10, 10, 8, 6, 5, 3, 1, 0]); - + sortingTestsHelper.testSortWithComparisonFn(bubbleSort); }); - }); diff --git a/test/algorithms/sorting/heap_sort.js b/test/algorithms/sorting/heap_sort.js index b3d27c0..db87b24 100644 --- a/test/algorithms/sorting/heap_sort.js +++ b/test/algorithms/sorting/heap_sort.js @@ -1,40 +1,14 @@ 'use strict'; var heapSort = require('../../../algorithms/sorting/heap_sort'), - assert = require('assert'); + sortingTestsHelper = require('./sorting_tests_helper'); describe('Heap Sort', function () { it('should sort the given array', function () { - assert.deepEqual(heapSort([]), []); - assert.deepEqual(heapSort([1]), [1]); - assert.deepEqual(heapSort([2, 1]), [1, 2]); - assert.deepEqual(heapSort([3, 1, 2]), [1, 2, 3]); - assert.deepEqual(heapSort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(heapSort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(heapSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), - [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); + sortingTestsHelper.testSort(heapSort); }); it('should sort the array with a specific comparison function', function () { - var compare = function (a, b) { - if (a.length === b.length) return 0; - return a.length < b.length ? -1 : 1; - }; - assert.deepEqual(heapSort([], compare), []); - assert.deepEqual(heapSort(['apple'], compare), ['apple']); - assert.deepEqual(heapSort(['apple', 'banana'], compare), - ['apple', 'banana']); - assert.deepEqual(heapSort(['apple', 'banana', 'car'], compare), - ['car', 'apple', 'banana']); - assert.deepEqual(heapSort(['apple', 'banana', 'car', 'z'], compare), - ['z', 'car', 'apple', 'banana']); - - var reverseSort = function (a, b) { - if (a == b) return 0; - return a < b ? 1 : -1; - }; - assert.deepEqual(heapSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], - reverseSort), - [295, 20, 10, 10, 8, 6, 5, 3, 1, 0]); + sortingTestsHelper.testSortWithComparisonFn(heapSort); }); }); diff --git a/test/algorithms/sorting/insertion_sort.js b/test/algorithms/sorting/insertion_sort.js index 860cc99..fa2ca82 100644 --- a/test/algorithms/sorting/insertion_sort.js +++ b/test/algorithms/sorting/insertion_sort.js @@ -1,74 +1,15 @@ 'use strict'; var insertionSort = require('../../../algorithms/sorting/insertion_sort'), - assert = require('assert'); + sortingTestsHelper = require('./sorting_tests_helper'); describe('Insertion Sort', function () { it('should sort the given array', function () { - assert.deepEqual(insertionSort([]), []); - assert.deepEqual(insertionSort([1]), [1]); - assert.deepEqual(insertionSort([2, 1]), [1, 2]); - assert.deepEqual(insertionSort([3, 1, 2]), [1, 2, 3]); - assert.deepEqual(insertionSort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(insertionSort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual( - insertionSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), - [0, 1, 3, 5, 6, 8, 10, 10, 20, 295] - ); + sortingTestsHelper.testSort(insertionSort); }); it('should sort the array with a specific comparison function', function () { - var compare = function (a, b) { - if (a.length === b.length) { - return 0; - } - return (a.length < b.length) ? -1 : 1; - }; - assert.deepEqual(insertionSort([], compare), []); - assert.deepEqual(insertionSort(['apple'], compare), ['apple']); - assert.deepEqual( - insertionSort(['apple', 'banana'], compare), - ['apple', 'banana'] - ); - assert.deepEqual( - insertionSort(['apple', 'banana', 'car'], compare), - ['car', 'apple', 'banana'] - ); - assert.deepEqual( - insertionSort(['apple', 'banana', 'car', 'z'], compare), - ['z', 'car', 'apple', 'banana'] - ); - - var reverseSort = function (a, b) { - if (a === b) { - return 0; - } - return (a < b) ? 1 : -1; - }; - assert.deepEqual( - insertionSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], reverseSort), - [295, 20, 10, 10, 8, 6, 5, 3, 1, 0] - ); - - var Guy = function (age) { - this.age = age; - }; - - var compareAgeOfGuys = function (g1, g2) { - if (g1.age === g2.age) { - return 0; - } - return (g1.age < g2.age) ? -1 : 1; - }; - - var g1 = new Guy(30), - g2 = new Guy(80), - g3 = new Guy(15), - g4 = new Guy(20); - - assert.deepEqual( - insertionSort([g1, g2, g3, g4], compareAgeOfGuys), [g3, g4, g1, g2] - ); + sortingTestsHelper.testSortWithComparisonFn(insertionSort); }); }); diff --git a/test/algorithms/sorting/merge_sort.js b/test/algorithms/sorting/merge_sort.js index d5be06c..7c968c1 100644 --- a/test/algorithms/sorting/merge_sort.js +++ b/test/algorithms/sorting/merge_sort.js @@ -1,41 +1,14 @@ 'use strict'; var mergeSort = require('../../../algorithms/sorting/merge_sort'), - assert = require('assert'); + sortingTestsHelper = require('./sorting_tests_helper'); describe('Merge Sort', function () { it('should sort the given array', function () { - assert.deepEqual(mergeSort([]), []); - assert.deepEqual(mergeSort([1]), [1]); - assert.deepEqual(mergeSort([2, 1]), [1, 2]); - assert.deepEqual(mergeSort([3, 1, 2]), [1, 2, 3]); - assert.deepEqual(mergeSort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(mergeSort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(mergeSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), - [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); + sortingTestsHelper.testSort(mergeSort); }); it('should sort the array with a specific comparison function', function () { - var compare = function (a, b) { - if (a.length === b.length) return 0; - return a.length < b.length ? -1 : 1; - }; - assert.deepEqual(mergeSort([], compare), []); - assert.deepEqual(mergeSort(['apple'], compare), ['apple']); - assert.deepEqual(mergeSort(['banana', 'apple'], compare), - ['apple', 'banana']); - assert.deepEqual(mergeSort(['apple', 'car', 'banana'], compare), - ['car', 'apple', 'banana']); - assert.deepEqual(mergeSort(['apple', 'banana', 'car', 'z'], compare), - ['z', 'car', 'apple', 'banana']); - - var reverseSort = function (a, b) { - if (a == b) return 0; - return a < b ? 1 : -1; - }; - assert.deepEqual(mergeSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], - reverseSort), - [295, 20, 10, 10, 8, 6, 5, 3, 1, 0]); - + sortingTestsHelper.testSortWithComparisonFn(mergeSort); }); }); diff --git a/test/algorithms/sorting/quicksort.js b/test/algorithms/sorting/quicksort.js index 5b95fc2..4a4010b 100644 --- a/test/algorithms/sorting/quicksort.js +++ b/test/algorithms/sorting/quicksort.js @@ -1,40 +1,14 @@ 'use strict'; var quicksort = require('../../../algorithms/sorting/quicksort'), - assert = require('assert'); + sortingTestsHelper = require('./sorting_tests_helper'); describe('QuickSort', function () { it('should sort the given array', function () { - assert.deepEqual(quicksort([]), []); - assert.deepEqual(quicksort([1]), [1]); - assert.deepEqual(quicksort([2, 1]), [1, 2]); - assert.deepEqual(quicksort([3, 1, 2]), [1, 2, 3]); - assert.deepEqual(quicksort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(quicksort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(quicksort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), - [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); + sortingTestsHelper.testSort(quicksort); }); it('should sort the array with a specific comparison function', function () { - var compare = function (a, b) { - if (a.length === b.length) return 0; - return a.length < b.length ? -1 : 1; - }; - assert.deepEqual(quicksort([], compare), []); - assert.deepEqual(quicksort(['apple'], compare), ['apple']); - assert.deepEqual(quicksort(['apple', 'banana'], compare), - ['apple', 'banana']); - assert.deepEqual(quicksort(['apple', 'banana', 'car'], compare), - ['car', 'apple', 'banana']); - assert.deepEqual(quicksort(['apple', 'banana', 'car', 'z'], compare), - ['z', 'car', 'apple', 'banana']); - - var reverseSort = function (a, b) { - if (a == b) return 0; - return a < b ? 1 : -1; - }; - assert.deepEqual(quicksort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], - reverseSort), - [295, 20, 10, 10, 8, 6, 5, 3, 1, 0]); + sortingTestsHelper.testSortWithComparisonFn(quicksort); }); }); diff --git a/test/algorithms/sorting/selection_sort.js b/test/algorithms/sorting/selection_sort.js index 7194870..d8991ec 100644 --- a/test/algorithms/sorting/selection_sort.js +++ b/test/algorithms/sorting/selection_sort.js @@ -1,21 +1,14 @@ 'use strict'; var selectionSort = require('../../../algorithms/sorting/selection_sort'), - assert = require('assert'); + sortingTestsHelper = require('./sorting_tests_helper'); describe('Selection Sort', function () { it('should sort the given array', function () { - assert.deepEqual(selectionSort([]), []); - assert.deepEqual(selectionSort([1]), [1]); - assert.deepEqual(selectionSort([2, 1]), [1, 2]); - assert.deepEqual(selectionSort([3, 1, 2]), [1, 2, 3]); - assert.deepEqual(selectionSort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(selectionSort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(selectionSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), - [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); - assert.deepEqual(selectionSort(['a', 'A', 'b', 'Z']), ['A', 'Z', 'a', 'b']); - assert.deepEqual(selectionSort(['hi', 'everybody']), ['everybody', 'hi']); - + sortingTestsHelper.testSort(selectionSort); }); + it('should sort the array with a specific comparison function', function () { + sortingTestsHelper.testSortWithComparisonFn(selectionSort); + }); }); diff --git a/test/algorithms/sorting/shell_sort.js b/test/algorithms/sorting/shell_sort.js index 287bb28..037c0f7 100644 --- a/test/algorithms/sorting/shell_sort.js +++ b/test/algorithms/sorting/shell_sort.js @@ -1,41 +1,15 @@ 'use strict'; var shellSort = require('../../../algorithms/sorting/shell_sort'), - assert = require('assert'); + sortingTestsHelper = require('./sorting_tests_helper.js'); describe('ShellSort', function () { it('should sort the given array', function () { - assert.deepEqual(shellSort([]), []); - assert.deepEqual(shellSort([1]), [1]); - assert.deepEqual(shellSort([2, 1]), [1, 2]); - assert.deepEqual(shellSort([3, 1, 2]), [1, 2, 3]); - assert.deepEqual(shellSort([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(shellSort([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(shellSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), - [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); + sortingTestsHelper.testSort(shellSort); }); it('should sort the array with a specific comparison function', function () { - var compare = function (a, b) { - if (a.length === b.length) return 0; - return a.length < b.length ? -1 : 1; - }; - assert.deepEqual(shellSort([], compare), []); - assert.deepEqual(shellSort(['apple'], compare), ['apple']); - assert.deepEqual(shellSort(['apple', 'banana'], compare), - ['apple', 'banana']); - assert.deepEqual(shellSort(['apple', 'banana', 'car'], compare), - ['car', 'apple', 'banana']); - assert.deepEqual(shellSort(['apple', 'banana', 'car', 'z'], compare), - ['z', 'car', 'apple', 'banana']); - - var reverseSort = function (a, b) { - if (a == b) return 0; - return a < b ? 1 : -1; - }; - assert.deepEqual(shellSort([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], - reverseSort), - [295, 20, 10, 10, 8, 6, 5, 3, 1, 0]); + sortingTestsHelper.testSortWithComparisonFn(shellSort); }); }); diff --git a/test/algorithms/sorting/sorting_tests_helper.js b/test/algorithms/sorting/sorting_tests_helper.js new file mode 100644 index 0000000..e01f43f --- /dev/null +++ b/test/algorithms/sorting/sorting_tests_helper.js @@ -0,0 +1,42 @@ +'use strict'; + +var assert = require('assert'); + +module.exports = { + testSort: function (sortFn) { + assert.deepEqual(sortFn([]), []); + assert.deepEqual(sortFn([1]), [1]); + assert.deepEqual(sortFn([2, 1]), [1, 2]); + assert.deepEqual(sortFn([3, 1, 2]), [1, 2, 3]); + assert.deepEqual(sortFn([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual(sortFn([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); + assert.deepEqual(sortFn([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), + [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); + assert.deepEqual(sortFn(['a', 'b', 'abc']), ['a', 'abc', 'b']); + }, + + testSortWithComparisonFn: function (sortFn) { + var compare = function (a, b) { + if (a.length === b.length) return 0; + return a.length < b.length ? -1 : 1; + }; + assert.deepEqual(sortFn([], compare), []); + assert.deepEqual(sortFn(['apple'], compare), ['apple']); + assert.deepEqual(sortFn(['apple', 'banana'], compare), + ['apple', 'banana']); + assert.deepEqual(sortFn(['apple', 'banana', 'car'], compare), + ['car', 'apple', 'banana']); + assert.deepEqual(sortFn(['apple', 'banana', 'car', 'z'], compare), + ['z', 'car', 'apple', 'banana']); + + var reverseSort = function (a, b) { + if (a == b) return 0; + return a < b ? 1 : -1; + }; + assert.deepEqual(sortFn([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], + reverseSort), + [295, 20, 10, 10, 8, 6, 5, 3, 1, 0]); + } +}; + + From d80cc5adb603c02bda9c763f5e686d08dcc3b8df Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Mon, 1 Sep 2014 13:53:23 -0400 Subject: [PATCH 137/280] Implemented longest common substring --- algorithms/string/longest_common_substring.js | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 algorithms/string/longest_common_substring.js diff --git a/algorithms/string/longest_common_substring.js b/algorithms/string/longest_common_substring.js new file mode 100644 index 0000000..9511213 --- /dev/null +++ b/algorithms/string/longest_common_substring.js @@ -0,0 +1,68 @@ +/** + * Implementation of longest common substring + * + * @author Joshua Curl + */ + +'use strict'; + +/** + * Implementation via dynamic programming + */ +var longestCommonSubstring = function (s1, s2) { + // Multidimensional array for dynamic programming algorithm + var cache = []; + + var i, j; + + // First column and row are initialized with zeroes + for (i = 0; i < s1.length + 1; i++) { + cache[i] = []; + cache[i][0] = 0; + } + for (i = 0; i < s2.length + 1; i++) { + cache[0][i] = 0; + } + + var lcsPosition = {}; + var commonSubstringFound = false; + + // Fill in the cache + for (i = 1; i < s1.length + 1; i++) { + for (j = 1; j < s2.length + 1; j++) { + if (s1[i - 1] == s2[j - 1]) { + cache[i][j] = cache[i - 1][j - 1] + 1; + if (commonSubstringFound) { + if (cache[i][j] > cache[lcsPosition.i][lcsPosition.j]) { + lcsPosition.i = i; + lcsPosition.j = j; + commonSubstringFound = true; + } + } + else { + lcsPosition.i = i; + lcsPosition.j = j; + } + } + else { + cache[i][j] = 0; + } + } + } + + // Build LCS from cache + i = lcsPosition.i; + j = lcsPosition.j; + var lcs = ''; + + while (cache[i][j] !== 0) { + lcs += s1[i - 1]; + i--; + j--; + } + + // LCS is built in reverse, return reversed string + return lcs.split('').reverse().join(''); +}; + +module.exports = longestCommonSubstring; From 7b257ce0d10f083d0f8850d6f1008403183b550e Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Mon, 1 Sep 2014 13:55:56 -0400 Subject: [PATCH 138/280] Fixed error when there wasn't a longest common substring --- algorithms/string/longest_common_substring.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/algorithms/string/longest_common_substring.js b/algorithms/string/longest_common_substring.js index 9511213..63738df 100644 --- a/algorithms/string/longest_common_substring.js +++ b/algorithms/string/longest_common_substring.js @@ -50,6 +50,10 @@ var longestCommonSubstring = function (s1, s2) { } } + if (!commonSubstringFound) { + return ''; + } + // Build LCS from cache i = lcsPosition.i; j = lcsPosition.j; From a0b6d2ad01f5ece237a85189a7c3ba0d0c61d457 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Mon, 1 Sep 2014 14:03:40 -0400 Subject: [PATCH 139/280] Fixed another error --- algorithms/string/longest_common_substring.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/string/longest_common_substring.js b/algorithms/string/longest_common_substring.js index 63738df..92b158b 100644 --- a/algorithms/string/longest_common_substring.js +++ b/algorithms/string/longest_common_substring.js @@ -36,12 +36,12 @@ var longestCommonSubstring = function (s1, s2) { if (cache[i][j] > cache[lcsPosition.i][lcsPosition.j]) { lcsPosition.i = i; lcsPosition.j = j; - commonSubstringFound = true; } } else { lcsPosition.i = i; lcsPosition.j = j; + commonSubstringFound = true; } } else { From cd97a17642459283aee0189546ef6bea8d4fe94b Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Mon, 1 Sep 2014 14:10:16 -0400 Subject: [PATCH 140/280] Tests for longest common substring --- .../string/longest_common_subseqence.js | 5 +++-- .../string/longest_common_substring.js | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 test/algorithms/string/longest_common_substring.js diff --git a/test/algorithms/string/longest_common_subseqence.js b/test/algorithms/string/longest_common_subseqence.js index 07824c8..bcf023a 100644 --- a/test/algorithms/string/longest_common_subseqence.js +++ b/test/algorithms/string/longest_common_subseqence.js @@ -2,11 +2,12 @@ var directory = '../../../algorithms/string/'; var filename = 'longest_common_subsequence'; -var longestCommonSubsequence = require([directory, filename].join('')), +var longestCommonSubsequence = require(directory + filename), assert = require('assert'); describe('Longest common subsequence', function () { - it('should return the proper longest common subsequence', function () { + it('should return the longest common subsequence of ' + + 'two strings', function () { assert.equal('', longestCommonSubsequence('', '')); assert.equal('', longestCommonSubsequence('', 'aaa')); assert.equal('', longestCommonSubsequence('aaa', '')); diff --git a/test/algorithms/string/longest_common_substring.js b/test/algorithms/string/longest_common_substring.js new file mode 100644 index 0000000..2c910dc --- /dev/null +++ b/test/algorithms/string/longest_common_substring.js @@ -0,0 +1,18 @@ +'use strict'; + +var directory = '../../../algorithms/string/'; +var filename = 'longest_common_substring'; +var longestCommonSubstring = require(directory + filename), + assert = require('assert'); + +describe('Longest common substring', function () { + it('should return the longest common substring of two strings', function () { + assert.equal('', longestCommonSubstring('', '')); + assert.equal('', longestCommonSubstring('', 'aaa')); + assert.equal('', longestCommonSubstring('aaa', '')); + assert.equal('aaa', longestCommonSubstring('aaa', 'aaa')); + assert.equal('xun', longestCommonSubstring('xunmjyauz', 'mzjawxun')); + assert.equal('xun', longestCommonSubstring('jyaxunmuz', 'mzjawxun')); + assert.equal('xun', longestCommonSubstring('jyamuzxun', 'mzjawxun')); + }); +}); From efb23c65d91a7bd788e064d3ffa973a5d1935b18 Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Mon, 1 Sep 2014 14:13:39 -0400 Subject: [PATCH 141/280] Removed an unnecessary variable --- algorithms/string/longest_common_subsequence.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/algorithms/string/longest_common_subsequence.js b/algorithms/string/longest_common_subsequence.js index a98a2ee..99569c9 100644 --- a/algorithms/string/longest_common_subsequence.js +++ b/algorithms/string/longest_common_subsequence.js @@ -28,8 +28,7 @@ var longestCommonSubsequence = function (s1, s2) { for (i = 1; i < s1.length + 1; i++) { for (j = 1; j < s2.length + 1; j++) { if (s1[i - 1] == s2[j - 1]) { - var newValue = cache[i - 1][j - 1] + 1; - cache[i][j] = newValue; + cache[i][j] = cache[i - 1][j - 1] + 1; } else { cache[i][j] = Math.max(cache[i][j - 1], cache[i - 1][j]); From b1ea461f5fed5a3aeb5fd0a486a78bfdd9552b6f Mon Sep 17 00:00:00 2001 From: Joshua Curl Date: Mon, 1 Sep 2014 14:29:02 -0400 Subject: [PATCH 142/280] Strings aren't built in reverse anymore --- algorithms/string/longest_common_subsequence.js | 5 ++--- algorithms/string/longest_common_substring.js | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/algorithms/string/longest_common_subsequence.js b/algorithms/string/longest_common_subsequence.js index 99569c9..b6992a2 100644 --- a/algorithms/string/longest_common_subsequence.js +++ b/algorithms/string/longest_common_subsequence.js @@ -43,7 +43,7 @@ var longestCommonSubsequence = function (s1, s2) { while (cache[i][j] !== 0) { if (s1[i - 1] === s2[j - 1]) { - lcs += s1[i - 1]; + lcs = s1[i - 1] + lcs; i--; j--; } @@ -57,8 +57,7 @@ var longestCommonSubsequence = function (s1, s2) { } } - // LCS is built in reverse, return reversed string - return lcs.split('').reverse().join(''); + return lcs; }; module.exports = longestCommonSubsequence; diff --git a/algorithms/string/longest_common_substring.js b/algorithms/string/longest_common_substring.js index 92b158b..c973f6b 100644 --- a/algorithms/string/longest_common_substring.js +++ b/algorithms/string/longest_common_substring.js @@ -60,13 +60,12 @@ var longestCommonSubstring = function (s1, s2) { var lcs = ''; while (cache[i][j] !== 0) { - lcs += s1[i - 1]; + lcs = s1[i - 1] + lcs; i--; j--; } - // LCS is built in reverse, return reversed string - return lcs.split('').reverse().join(''); + return lcs; }; module.exports = longestCommonSubstring; From 3c62a5bab00714b69eae020942b68ed7deb561ef Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 10 Oct 2014 21:25:27 +0200 Subject: [PATCH 143/280] Reorganize files --- Makefile | 8 +- algorithms/graph/floyd_warshall.js | 101 --------- build/algorithms.browser.min.js | 2 +- main.js | 67 ------ package.json | 3 +- {algorithms => src/algorithms}/graph/SPFA.js | 2 +- .../algorithms}/graph/bellman_ford.js | 0 .../algorithms}/graph/bfs_shortest_path.js | 0 .../algorithms}/graph/breadth_first_search.js | 0 .../algorithms}/graph/depth_first_search.js | 10 +- .../algorithms}/graph/dijkstra.js | 0 .../algorithms}/graph/euler_path.js | 20 +- src/algorithms/graph/floyd_warshall.js | 97 +++++++++ src/algorithms/graph/index.js | 16 ++ .../algorithms}/graph/kruskal.js | 6 +- {algorithms => src/algorithms}/graph/prim.js | 0 .../algorithms}/graph/topological_sort.js | 0 .../algorithms}/math/extended_euclidean.js | 0 .../algorithms}/math/fast_power.js | 0 .../algorithms}/math/fibonacci.js | 6 +- .../algorithms}/math/fisher_yates.js | 0 {algorithms => src/algorithms}/math/gcd.js | 0 src/algorithms/math/index.js | 14 ++ .../algorithms}/math/newton_sqrt.js | 0 .../algorithms}/math/next_permutation.js | 0 .../algorithms}/math/power_set.js | 0 .../algorithms}/math/reservoir_sampling.js | 0 .../algorithms}/searching/bfs.js | 0 .../algorithms}/searching/binarysearch.js | 0 .../algorithms}/searching/dfs.js | 0 src/algorithms/searching/index.js | 8 + .../algorithms}/sorting/bubble_sort.js | 0 .../algorithms}/sorting/counting_sort.js | 0 .../algorithms}/sorting/heap_sort.js | 0 src/algorithms/sorting/index.js | 14 ++ .../algorithms}/sorting/insertion_sort.js | 0 .../algorithms}/sorting/merge_sort.js | 0 .../algorithms}/sorting/quicksort.js | 0 .../algorithms}/sorting/radix_sort.js | 0 .../algorithms}/sorting/selection_sort.js | 0 .../algorithms}/sorting/shell_sort.js | 0 .../algorithms}/string/hamming.js | 0 .../algorithms}/string/huffman.js | 0 src/algorithms/string/index.js | 12 ++ .../algorithms}/string/knuth_morris_pratt.js | 0 .../algorithms}/string/levenshtein.js | 0 .../string/longest_common_subsequence.js | 0 .../algorithms}/string/rabin_karp.js | 0 .../data_structures}/bst.js | 0 .../data_structures}/disjoint_set_forest.js | 0 .../data_structures}/graph.js | 21 +- .../data_structures}/hash_table.js | 2 +- .../data_structures}/heap.js | 0 src/data_structures/index.js | 15 ++ .../data_structures}/linked_list.js | 0 .../data_structures}/priority_queue.js | 0 .../data_structures}/queue.js | 0 .../data_structures}/set.js | 0 .../data_structures}/stack.js | 0 src/index.js | 12 ++ {test => src/test}/algorithms/graph/SPFA.js | 5 +- .../test}/algorithms/graph/bellman_ford.js | 5 +- .../algorithms/graph/bfs_shortest_path.js | 5 +- .../algorithms/graph/breadth_first_search.js | 30 +-- .../algorithms/graph/depth_first_search.js | 27 ++- .../test}/algorithms/graph/dijkstra.js | 5 +- .../test}/algorithms/graph/euler_path.js | 57 +++-- .../test}/algorithms/graph/floyd_warshall.js | 6 +- .../algorithms/graph/minimum_spanning_tree.js | 199 ++++++++++++++++++ .../algorithms/graph/topological_sort.js | 17 +- .../algorithms/math/extended_euclidean.js | 3 +- .../test}/algorithms/math/fast_power.js | 3 +- .../test}/algorithms/math/fibonacci.js | 3 +- .../test}/algorithms/math/fisher_yates.js | 3 +- {test => src/test}/algorithms/math/gcd.js | 3 +- .../test}/algorithms/math/newton_sqrt.js | 3 +- .../test}/algorithms/math/next_permutation.js | 3 +- .../test}/algorithms/math/power_set.js | 3 +- .../algorithms/math/reservoir_sampling.js | 4 +- .../test}/algorithms/searching/bfs.js | 6 +- .../algorithms/searching/binarysearch.js | 2 +- .../test}/algorithms/searching/dfs.js | 5 +- .../test}/algorithms/sorting/bubble_sort.js | 2 +- .../test}/algorithms/sorting/counting_sort.js | 2 +- .../test}/algorithms/sorting/heap_sort.js | 2 +- .../algorithms/sorting/insertion_sort.js | 2 +- .../test}/algorithms/sorting/merge_sort.js | 2 +- .../test}/algorithms/sorting/quicksort.js | 2 +- .../test}/algorithms/sorting/radix_sort.js | 2 +- .../algorithms/sorting/selection_sort.js | 2 +- .../test}/algorithms/sorting/shell_sort.js | 2 +- .../sorting/sorting_tests_helper.js | 0 .../test}/algorithms/string/hamming.js | 2 +- .../test}/algorithms/string/huffman.js | 2 +- .../algorithms/string/knuth_morris_pratt.js | 2 +- .../test}/algorithms/string/levenshtein.js | 2 +- .../string/longest_common_subseqence.js | 15 ++ .../test}/algorithms/string/rabin_karp.js | 2 +- {test => src/test}/data_structures/bst.js | 5 +- .../data_structures/disjoint_set_forest.js | 2 +- {test => src/test}/data_structures/graph.js | 23 +- .../test}/data_structures/hash_table.js | 2 +- {test => src/test}/data_structures/heap.js | 2 +- .../test}/data_structures/linked_list.js | 2 +- .../test}/data_structures/priority_queue.js | 2 +- {test => src/test}/data_structures/queue.js | 2 +- {test => src/test}/data_structures/set.js | 2 +- {test => src/test}/data_structures/stack.js | 2 +- {test => src/test}/util/comparator.js | 0 {util => src/util}/comparator.js | 0 .../algorithms/graph/minimum_spanning_tree.js | 184 ---------------- .../string/longest_common_subseqence.js | 17 -- 112 files changed, 599 insertions(+), 522 deletions(-) delete mode 100644 algorithms/graph/floyd_warshall.js delete mode 100644 main.js rename {algorithms => src/algorithms}/graph/SPFA.js (96%) rename {algorithms => src/algorithms}/graph/bellman_ford.js (100%) rename {algorithms => src/algorithms}/graph/bfs_shortest_path.js (100%) rename {algorithms => src/algorithms}/graph/breadth_first_search.js (100%) rename {algorithms => src/algorithms}/graph/depth_first_search.js (94%) rename {algorithms => src/algorithms}/graph/dijkstra.js (100%) rename {algorithms => src/algorithms}/graph/euler_path.js (90%) create mode 100644 src/algorithms/graph/floyd_warshall.js create mode 100644 src/algorithms/graph/index.js rename {algorithms => src/algorithms}/graph/kruskal.js (93%) rename {algorithms => src/algorithms}/graph/prim.js (100%) rename {algorithms => src/algorithms}/graph/topological_sort.js (100%) rename {algorithms => src/algorithms}/math/extended_euclidean.js (100%) rename {algorithms => src/algorithms}/math/fast_power.js (100%) rename {algorithms => src/algorithms}/math/fibonacci.js (97%) rename {algorithms => src/algorithms}/math/fisher_yates.js (100%) rename {algorithms => src/algorithms}/math/gcd.js (100%) create mode 100644 src/algorithms/math/index.js rename {algorithms => src/algorithms}/math/newton_sqrt.js (100%) rename {algorithms => src/algorithms}/math/next_permutation.js (100%) rename {algorithms => src/algorithms}/math/power_set.js (100%) rename {algorithms => src/algorithms}/math/reservoir_sampling.js (100%) rename {algorithms => src/algorithms}/searching/bfs.js (100%) rename {algorithms => src/algorithms}/searching/binarysearch.js (100%) rename {algorithms => src/algorithms}/searching/dfs.js (100%) create mode 100644 src/algorithms/searching/index.js rename {algorithms => src/algorithms}/sorting/bubble_sort.js (100%) rename {algorithms => src/algorithms}/sorting/counting_sort.js (100%) rename {algorithms => src/algorithms}/sorting/heap_sort.js (100%) create mode 100644 src/algorithms/sorting/index.js rename {algorithms => src/algorithms}/sorting/insertion_sort.js (100%) rename {algorithms => src/algorithms}/sorting/merge_sort.js (100%) rename {algorithms => src/algorithms}/sorting/quicksort.js (100%) rename {algorithms => src/algorithms}/sorting/radix_sort.js (100%) rename {algorithms => src/algorithms}/sorting/selection_sort.js (100%) rename {algorithms => src/algorithms}/sorting/shell_sort.js (100%) rename {algorithms => src/algorithms}/string/hamming.js (100%) rename {algorithms => src/algorithms}/string/huffman.js (100%) create mode 100644 src/algorithms/string/index.js rename {algorithms => src/algorithms}/string/knuth_morris_pratt.js (100%) rename {algorithms => src/algorithms}/string/levenshtein.js (100%) rename {algorithms => src/algorithms}/string/longest_common_subsequence.js (100%) rename {algorithms => src/algorithms}/string/rabin_karp.js (100%) rename {data_structures => src/data_structures}/bst.js (100%) rename {data_structures => src/data_structures}/disjoint_set_forest.js (100%) rename {data_structures => src/data_structures}/graph.js (71%) rename {data_structures => src/data_structures}/hash_table.js (98%) rename {data_structures => src/data_structures}/heap.js (100%) create mode 100644 src/data_structures/index.js rename {data_structures => src/data_structures}/linked_list.js (100%) rename {data_structures => src/data_structures}/priority_queue.js (100%) rename {data_structures => src/data_structures}/queue.js (100%) rename {data_structures => src/data_structures}/set.js (100%) rename {data_structures => src/data_structures}/stack.js (100%) create mode 100644 src/index.js rename {test => src/test}/algorithms/graph/SPFA.js (90%) rename {test => src/test}/algorithms/graph/bellman_ford.js (88%) rename {test => src/test}/algorithms/graph/bfs_shortest_path.js (88%) rename {test => src/test}/algorithms/graph/breadth_first_search.js (81%) rename {test => src/test}/algorithms/graph/depth_first_search.js (81%) rename {test => src/test}/algorithms/graph/dijkstra.js (86%) rename {test => src/test}/algorithms/graph/euler_path.js (77%) rename {test => src/test}/algorithms/graph/floyd_warshall.js (95%) create mode 100644 src/test/algorithms/graph/minimum_spanning_tree.js rename {test => src/test}/algorithms/graph/topological_sort.js (82%) rename {test => src/test}/algorithms/math/extended_euclidean.js (85%) rename {test => src/test}/algorithms/math/fast_power.js (97%) rename {test => src/test}/algorithms/math/fibonacci.js (95%) rename {test => src/test}/algorithms/math/fisher_yates.js (88%) rename {test => src/test}/algorithms/math/gcd.js (94%) rename {test => src/test}/algorithms/math/newton_sqrt.js (93%) rename {test => src/test}/algorithms/math/next_permutation.js (95%) rename {test => src/test}/algorithms/math/power_set.js (98%) rename {test => src/test}/algorithms/math/reservoir_sampling.js (91%) rename {test => src/test}/algorithms/searching/bfs.js (86%) rename {test => src/test}/algorithms/searching/binarysearch.js (89%) rename {test => src/test}/algorithms/searching/dfs.js (90%) rename {test => src/test}/algorithms/sorting/bubble_sort.js (84%) rename {test => src/test}/algorithms/sorting/counting_sort.js (90%) rename {test => src/test}/algorithms/sorting/heap_sort.js (84%) rename {test => src/test}/algorithms/sorting/insertion_sort.js (83%) rename {test => src/test}/algorithms/sorting/merge_sort.js (84%) rename {test => src/test}/algorithms/sorting/quicksort.js (84%) rename {test => src/test}/algorithms/sorting/radix_sort.js (93%) rename {test => src/test}/algorithms/sorting/selection_sort.js (83%) rename {test => src/test}/algorithms/sorting/shell_sort.js (84%) rename {test => src/test}/algorithms/sorting/sorting_tests_helper.js (100%) rename {test => src/test}/algorithms/string/hamming.js (92%) rename {test => src/test}/algorithms/string/huffman.js (98%) rename {test => src/test}/algorithms/string/knuth_morris_pratt.js (96%) rename {test => src/test}/algorithms/string/levenshtein.js (91%) create mode 100644 src/test/algorithms/string/longest_common_subseqence.js rename {test => src/test}/algorithms/string/rabin_karp.js (91%) rename {test => src/test}/data_structures/bst.js (98%) rename {test => src/test}/data_structures/disjoint_set_forest.js (96%) rename {test => src/test}/data_structures/graph.js (86%) rename {test => src/test}/data_structures/hash_table.js (98%) rename {test => src/test}/data_structures/heap.js (98%) rename {test => src/test}/data_structures/linked_list.js (98%) rename {test => src/test}/data_structures/priority_queue.js (97%) rename {test => src/test}/data_structures/queue.js (95%) rename {test => src/test}/data_structures/set.js (96%) rename {test => src/test}/data_structures/stack.js (94%) rename {test => src/test}/util/comparator.js (100%) rename {util => src/util}/comparator.js (100%) delete mode 100644 test/algorithms/graph/minimum_spanning_tree.js delete mode 100644 test/algorithms/string/longest_common_subseqence.js diff --git a/Makefile b/Makefile index 5c56dc8..cfc6f5c 100644 --- a/Makefile +++ b/Makefile @@ -4,18 +4,18 @@ setup: npm install jshint: setup - jshint algorithms data_structures test util + jshint src test: setup - mocha -R spec --recursive test + mocha -R spec --recursive src/test coverage: setup - istanbul cover ./node_modules/.bin/_mocha -- -R spec --recursive test + istanbul cover ./node_modules/.bin/_mocha -- -R spec --recursive src/test coveralls: cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js VERSION := $(shell node -e "console.log(require('./package.json').version);") browser_bundle: setup - browserify $(realpath main.js) --s algorithms | uglifyjs -c -m --screw-ie8 --wrap --preamble "/* algorithms.js v$(VERSION) | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */" > build/algorithms.browser.min.js + browserify $(realpath src/index.js) --s algorithms | uglifyjs -c -m --screw-ie8 --wrap --preamble "/* algorithms.js v$(VERSION) | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */" > build/algorithms.browser.min.js diff --git a/algorithms/graph/floyd_warshall.js b/algorithms/graph/floyd_warshall.js deleted file mode 100644 index e556e64..0000000 --- a/algorithms/graph/floyd_warshall.js +++ /dev/null @@ -1,101 +0,0 @@ -'use strict'; - - -/** - * Floyd-Warshall algorithm. - * Compute all-pairs shortest paths (a path for each pair of vertices). - * Complexity: O(V^3). - * - * @param {Graph} graph - * @return {{distance, path}} - */ -var floydWarshall = function (graph) { - - // Fill in the distances with initial values: - // - 0 if source == destination; - // - edge(source, destination) if there is a direct edge; - // - +inf otherwise. - var distance = graph.vertices.reduce(function (distance, source) { - distance[source] = - graph.vertices.reduce(function (distanceTo, destination) { - if (source == destination) { - distanceTo[destination] = 0; - } - else if (graph.edge(source, destination) !== undefined) { - distanceTo[destination] = graph.edge(source, destination); - } - else { - distanceTo[destination] = Infinity; - } - return distanceTo; - }, {}); - return distance; - }, {}); - - // Internal vertex with the largest index along the shortest path. - // Needed for path reconstruction. - var middleVertex = graph.vertices.reduce(function (middleVertex, vertex) { - middleVertex[vertex] = {}; - return middleVertex; - }, {}); - - graph.vertices.forEach(function (middle) { - graph.vertices.forEach(function (source) { - graph.vertices.forEach(function (destination) { - var dist = distance[source][middle] + distance[middle][destination]; - if (dist < distance[source][destination]) { - distance[source][destination] = dist; - middleVertex[source][destination] = middle; - } - }); - }); - }); - - // Check for a negative-weighted cycle. - graph.vertices.forEach(function (vertex) { - if (distance[vertex][vertex] < 0) { - // Negative-weighted cycle found. - throw new Error('The graph contains a negative-weighted cycle!'); - } - }); - - /** - * Reconstruct the shortest path for a given pair of end vertices. - * Complexity: O(L), L - length of the path (number of edges). - * - * @param {string} source - * @param {string} destination - * @return {?string[]} Null if destination is unreachable. - */ - var path = function (source, destination) { - if (!Number.isFinite(distance[source][destination])) { - // Destination unreachable. - return null; - } - - var path = [source]; - - if (source != destination) { - (function pushInOrder(source, destination) { - if (middleVertex[source][destination] === undefined) { - path.push(destination); - } - else { - var middle = middleVertex[source][destination]; - pushInOrder(source, middle); - pushInOrder(middle, destination); - } - }(source, destination)); - } - - return path; - }; - - return { - distance: distance, - path: path - }; -}; - - -module.exports = floydWarshall; diff --git a/build/algorithms.browser.min.js b/build/algorithms.browser.min.js index ebca4cc..ee02aaa 100644 --- a/build/algorithms.browser.min.js +++ b/build/algorithms.browser.min.js @@ -1,2 +1,2 @@ /* algorithms.js v0.6.1 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ -!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.length)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":45}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);ne&&r.push({ends:[e,n],weight:t.edge(e,n)})}),r},[]);return o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":39,"../../data_structures/graph":40}],10:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],18:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":49}],19:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],21:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":45}],22:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":49}],25:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],26:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":42}],27:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":49}],28:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":49}],30:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],31:[function(t,r){"use strict";var e=function(t){for(var r=t.length,e=0;r-1>e;e++){for(var n=e,i=e+1;r>i;i++)t[n]>t[i]&&(n=i);if(n!=e){var o=t[e];t[e]=t[n],t[n]=o}}return t};r.exports=e},{}],32:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],34:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],35:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],36:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;ei[e][n-1]?e--:n--;return s.split("").reverse().join("")};r.exports=e},{}],37:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":49}],43:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],44:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[48])(48)})}({},function(){return this}()); \ No newline at end of file +!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":52}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":45,"../../data_structures/graph":46}],11:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],15:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":14}],16:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],17:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],20:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":56}],21:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],23:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":52}],24:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":56}],28:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],29:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":48}],30:[function(t,r){"use strict";r.exports={bubbleSort:t("./bubble_sort"),countingSort:t("./counting_sort"),heapSort:t("./heap_sort"),mergeSort:t("./merge_sort"),quicksort:t("./quicksort"),selectionSort:t("./selection_sort"),radixSort:t("./radix_sort"),insertionSort:t("./insertion_sort"),shellSort:t("./shell_sort")}},{"./bubble_sort":27,"./counting_sort":28,"./heap_sort":29,"./insertion_sort":31,"./merge_sort":32,"./quicksort":33,"./radix_sort":34,"./selection_sort":35,"./shell_sort":36}],31:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":56}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":56}],34:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],35:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":56}],36:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":56}],37:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var v={count:l.count+p.count,parts:[l,p]};a.push(v)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var g=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return g[t]}).join("");return{encoding:g,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],39:[function(t,r){"use strict";r.exports={levenshtein:t("./levenshtein"),rabinKarp:t("./rabin_karp"),knuthMorrisPratt:t("./knuth_morris_pratt"),huffman:t("./huffman"),hamming:t("./hamming"),longestCommonSubsequence:t("./longest_common_subsequence")}},{"./hamming":37,"./huffman":38,"./knuth_morris_pratt":40,"./levenshtein":41,"./longest_common_subsequence":42,"./rabin_karp":43}],40:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],41:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],42:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;ei[e][n-1]?e--:n--;return s.split("").reverse().join("")};r.exports=e},{}],43:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":56}],49:[function(t,r){"use strict";r.exports={BST:t("./bst"),Graph:t("./graph"),HashTable:t("./hash_table"),Heap:t("./heap"),LinkedList:t("./linked_list"),PriorityQueue:t("./priority_queue"),Queue:t("./queue"),Stack:t("./stack"),Set:t("./set"),DisjointSetForest:t("./disjoint_set_forest")}},{"./bst":44,"./disjoint_set_forest":45,"./graph":46,"./hash_table":47,"./heap":48,"./linked_list":50,"./priority_queue":51,"./queue":52,"./set":53,"./stack":54}],50:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],51:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[55])(55)})}({},function(){return this}()); \ No newline at end of file diff --git a/main.js b/main.js deleted file mode 100644 index 923ee27..0000000 --- a/main.js +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; - -var lib = { - Graph: { - topologicalSort: require('./algorithms/graph/topological_sort'), - dijkstra: require('./algorithms/graph/dijkstra'), - SPFA: require('./algorithms/graph/SPFA'), - bellmanFord: require('./algorithms/graph/bellman_ford'), - eulerPath: require('./algorithms/graph/euler_path'), - depthFirstSearch: require('./algorithms/graph/depth_first_search'), - kruskal: require('./algorithms/graph/kruskal'), - breadthFirstSearch: require('./algorithms/graph/breadth_first_search'), - bfsShortestPath: require('./algorithms/graph/bfs_shortest_path'), - prim: require('./algorithms/graph/prim'), - floydWarshall: require('./algorithms/graph/floyd_warshall'), - }, - Math: { - fibonacci: require('./algorithms/math/fibonacci'), - fisherYates: require('./algorithms/math/fisher_yates'), - gcd: require('./algorithms/math/gcd'), - extendedEuclidean: require('./algorithms/math/extended_euclidean'), - newtonSqrt: require('./algorithms/math/newton_sqrt'), - reservoirSampling: require('./algorithms/math/reservoir_sampling'), - fastPower: require('./algorithms/math/fast_power'), - nextPermutation: require('./algorithms/math/next_permutation'), - powerSet: require('./algorithms/math/power_set') - }, - Search: { - bfs: require('./algorithms/searching/bfs'), - binarySearch: require('./algorithms/searching/binarysearch'), - dfs: require('./algorithms/searching/dfs') - }, - Sort: { - bubbleSort: require('./algorithms/sorting/bubble_sort'), - countingSort: require('./algorithms/sorting/counting_sort'), - heapSort: require('./algorithms/sorting/heap_sort'), - mergeSort: require('./algorithms/sorting/merge_sort'), - quicksort: require('./algorithms/sorting/quicksort'), - selectionSort: require('./algorithms/sorting/selection_sort'), - radixSort: require('./algorithms/sorting/radix_sort'), - insertionSort: require('./algorithms/sorting/insertion_sort'), - shellsort: require('./algorithms/sorting/shell_sort') - }, - String: { - levenshtein: require('./algorithms/string/levenshtein'), - rabinKarp: require('./algorithms/string/rabin_karp'), - knuthMorrisPratt: require('./algorithms/string/knuth_morris_pratt'), - huffman: require('./algorithms/string/huffman'), - hamming: require('./algorithms/string/hamming'), - longestCommonSubsequence: require( - './algorithms/string/longest_common_subsequence') - }, - DataStructure: { - BST: require('./data_structures/bst'), - Graph: require('./data_structures/graph'), - HashTable: require('./data_structures/hash_table'), - Heap: require('./data_structures/heap'), - LinkedList: require('./data_structures/linked_list'), - PriorityQueue: require('./data_structures/priority_queue'), - Queue: require('./data_structures/queue'), - Stack: require('./data_structures/stack'), - Set: require('./data_structures/set'), - DisjointSetForest: require('./data_structures/disjoint_set_forest') - } -}; - -module.exports = lib; diff --git a/package.json b/package.json index d146692..80e1131 100644 --- a/package.json +++ b/package.json @@ -5,13 +5,12 @@ "directories": { "test": "test" }, - "main": "main.js", + "main": "src/index.js", "dependencies": {}, "devDependencies": { "coveralls": "^2.10.0", "istanbul": "^0.2.10", "jshint": "~2.4.4", - "jscs": "1.4.5", "mocha": "^1.20.0" }, "repository": { diff --git a/algorithms/graph/SPFA.js b/src/algorithms/graph/SPFA.js similarity index 96% rename from algorithms/graph/SPFA.js rename to src/algorithms/graph/SPFA.js index f07ee43..23d1000 100644 --- a/algorithms/graph/SPFA.js +++ b/src/algorithms/graph/SPFA.js @@ -45,7 +45,7 @@ function SPFA(graph, s) { queue[tail++] = v; isInQue[v] = true; cnt[v]++; - if (cnt[v] > graph.vertices.length) + if (cnt[v] > graph.vertices.size) // indicates negative-weighted cycle return { distance: {} diff --git a/algorithms/graph/bellman_ford.js b/src/algorithms/graph/bellman_ford.js similarity index 100% rename from algorithms/graph/bellman_ford.js rename to src/algorithms/graph/bellman_ford.js diff --git a/algorithms/graph/bfs_shortest_path.js b/src/algorithms/graph/bfs_shortest_path.js similarity index 100% rename from algorithms/graph/bfs_shortest_path.js rename to src/algorithms/graph/bfs_shortest_path.js diff --git a/algorithms/graph/breadth_first_search.js b/src/algorithms/graph/breadth_first_search.js similarity index 100% rename from algorithms/graph/breadth_first_search.js rename to src/algorithms/graph/breadth_first_search.js diff --git a/algorithms/graph/depth_first_search.js b/src/algorithms/graph/depth_first_search.js similarity index 94% rename from algorithms/graph/depth_first_search.js rename to src/algorithms/graph/depth_first_search.js index d7d0f5c..739e72c 100644 --- a/algorithms/graph/depth_first_search.js +++ b/src/algorithms/graph/depth_first_search.js @@ -26,10 +26,10 @@ var normalizeCallbacks = function (callbacks, seenVertices) { callbacks = callbacks || {}; callbacks.allowTraversal = callbacks.allowTraversal || (function () { - var seen = seenVertices.reduce(function (seen, vertex) { + var seen = {}; + seenVertices.forEach(function (vertex) { seen[vertex] = true; - return seen; - }, {}); + }); return function (vertex, neighbor) { // It should still be possible to redefine other callbacks, @@ -39,9 +39,7 @@ var normalizeCallbacks = function (callbacks, seenVertices) { seen[neighbor] = true; return true; } - else { - return false; - } + return false; }; }()); diff --git a/algorithms/graph/dijkstra.js b/src/algorithms/graph/dijkstra.js similarity index 100% rename from algorithms/graph/dijkstra.js rename to src/algorithms/graph/dijkstra.js diff --git a/algorithms/graph/euler_path.js b/src/algorithms/graph/euler_path.js similarity index 90% rename from algorithms/graph/euler_path.js rename to src/algorithms/graph/euler_path.js index 5cf0f2d..c63c765 100644 --- a/algorithms/graph/euler_path.js +++ b/src/algorithms/graph/euler_path.js @@ -45,28 +45,28 @@ var eulerEndpoints = function (graph) { }); } - var start, finish; + var start, finish, v; graph.vertices.forEach(function (vertex) { if (rank[vertex] == 1) { - if (start !== undefined) { + if (start) { throw new Error('Duplicate start vertex.'); } start = vertex; - } - else if (rank[vertex] == -1) { - if (finish !== undefined) { + } else if (rank[vertex] == -1) { + if (finish) { throw new Error('Duplicate finish vertex.'); } finish = vertex; - } - else if (rank[vertex]) { + } else if (rank[vertex]) { throw new Error('Unexpected vertex degree for ' + vertex); + } else if (!v) { + v = vertex; } }); - if (start === undefined && finish === undefined) { - start = finish = graph.vertices[0]; + if (!start && !finish) { + start = finish = v; } return {start: start, @@ -85,7 +85,7 @@ var eulerEndpoints = function (graph) { * @return Array */ var eulerPath = function (graph) { - if (!graph.vertices.length) { + if (!graph.vertices.size) { return []; } diff --git a/src/algorithms/graph/floyd_warshall.js b/src/algorithms/graph/floyd_warshall.js new file mode 100644 index 0000000..a064bf8 --- /dev/null +++ b/src/algorithms/graph/floyd_warshall.js @@ -0,0 +1,97 @@ +'use strict'; + + +/** + * Floyd-Warshall algorithm. + * Compute all-pairs shortest paths (a path for each pair of vertices). + * Complexity: O(V^3). + * + * @param {Graph} graph + * @return {{distance, path}} + */ +var floydWarshall = function (graph) { + + // Fill in the distances with initial values: + // - 0 if source == destination; + // - edge(source, destination) if there is a direct edge; + // - +inf otherwise. + var distance = Object.create(null); + graph.vertices.forEach(function (src) { + distance[src] = Object.create(null); + graph.vertices.forEach(function (dest) { + if (src === dest) { + distance[src][dest] = 0; + } else if (graph.edge(src, dest) !== undefined) { + distance[src][dest] = graph.edge(src, dest); + } else { + distance[src][dest] = Infinity; + } + }); + }); + + // Internal vertex with the largest index along the shortest path. + // Needed for path reconstruction. + var middleVertex = Object.create(null); + graph.vertices.forEach(function (vertex) { + middleVertex[vertex] = Object.create(null); + }); + + graph.vertices.forEach(function (middle) { + graph.vertices.forEach(function (src) { + graph.vertices.forEach(function (dest) { + var dist = distance[src][middle] + distance[middle][dest]; + if (dist < distance[src][dest]) { + distance[src][dest] = dist; + middleVertex[src][dest] = middle; + } + }); + }); + }); + + // Check for a negative-weighted cycle. + graph.vertices.forEach(function (vertex) { + if (distance[vertex][vertex] < 0) { + // Negative-weighted cycle found. + throw new Error('The graph contains a negative-weighted cycle!'); + } + }); + + /** + * Reconstruct the shortest path for a given pair of end vertices. + * Complexity: O(L), L - length of the path (number of edges). + * + * @param {string} srce + * @param {string} dest + * @return {?string[]} Null if destination is unreachable. + */ + var path = function (src, dest) { + if (!Number.isFinite(distance[src][dest])) { + // dest unreachable. + return null; + } + + var path = [src]; + + if (src != dest) { + (function pushInOrder(src, dest) { + if (middleVertex[src][dest] === undefined) { + path.push(dest); + } else { + var middle = middleVertex[src][dest]; + pushInOrder(src, middle); + pushInOrder(middle, dest); + } + }(src, dest)); + } + + return path; + }; + + return { + distance: distance, + path: path + }; +}; + + +module.exports = floydWarshall; diff --git a/src/algorithms/graph/index.js b/src/algorithms/graph/index.js new file mode 100644 index 0000000..4b338e4 --- /dev/null +++ b/src/algorithms/graph/index.js @@ -0,0 +1,16 @@ +'use strict'; + +// Graph algorithms +module.exports = { + topologicalSort: require('./topological_sort'), + dijkstra: require('./dijkstra'), + SPFA: require('./SPFA'), + bellmanFord: require('./bellman_ford'), + eulerPath: require('./euler_path'), + depthFirstSearch: require('./depth_first_search'), + kruskal: require('./kruskal'), + breadthFirstSearch: require('./breadth_first_search'), + bfsShortestPath: require('./bfs_shortest_path'), + prim: require('./prim'), + floydWarshall: require('./floyd_warshall') +}; diff --git a/algorithms/graph/kruskal.js b/src/algorithms/graph/kruskal.js similarity index 93% rename from algorithms/graph/kruskal.js rename to src/algorithms/graph/kruskal.js index 0d4d782..436effb 100644 --- a/algorithms/graph/kruskal.js +++ b/src/algorithms/graph/kruskal.js @@ -21,7 +21,8 @@ var kruskal = function (graph) { var mst = new Graph(false); graph.vertices.forEach(mst.addVertex.bind(mst)); - var edges = graph.vertices.reduce(function (edges, vertex) { + var edges = []; + graph.vertices.forEach(function (vertex) { graph.neighbors(vertex).forEach(function (neighbor) { // Compared as strings, loops intentionally omitted. if (vertex < neighbor) { @@ -31,8 +32,7 @@ var kruskal = function (graph) { }); } }); - return edges; - }, []); + }); edges.sort(function (a, b) { return a.weight - b.weight; diff --git a/algorithms/graph/prim.js b/src/algorithms/graph/prim.js similarity index 100% rename from algorithms/graph/prim.js rename to src/algorithms/graph/prim.js diff --git a/algorithms/graph/topological_sort.js b/src/algorithms/graph/topological_sort.js similarity index 100% rename from algorithms/graph/topological_sort.js rename to src/algorithms/graph/topological_sort.js diff --git a/algorithms/math/extended_euclidean.js b/src/algorithms/math/extended_euclidean.js similarity index 100% rename from algorithms/math/extended_euclidean.js rename to src/algorithms/math/extended_euclidean.js diff --git a/algorithms/math/fast_power.js b/src/algorithms/math/fast_power.js similarity index 100% rename from algorithms/math/fast_power.js rename to src/algorithms/math/fast_power.js diff --git a/algorithms/math/fibonacci.js b/src/algorithms/math/fibonacci.js similarity index 97% rename from algorithms/math/fibonacci.js rename to src/algorithms/math/fibonacci.js index da4506c..f41f6c7 100644 --- a/algorithms/math/fibonacci.js +++ b/src/algorithms/math/fibonacci.js @@ -1,11 +1,9 @@ +'use strict'; + /** * Different implementations of the Fibonacci sequence - * - * @author Felipe Ribeiro */ -'use strict'; - var power = require('./fast_power'); /** diff --git a/algorithms/math/fisher_yates.js b/src/algorithms/math/fisher_yates.js similarity index 100% rename from algorithms/math/fisher_yates.js rename to src/algorithms/math/fisher_yates.js diff --git a/algorithms/math/gcd.js b/src/algorithms/math/gcd.js similarity index 100% rename from algorithms/math/gcd.js rename to src/algorithms/math/gcd.js diff --git a/src/algorithms/math/index.js b/src/algorithms/math/index.js new file mode 100644 index 0000000..b2829b4 --- /dev/null +++ b/src/algorithms/math/index.js @@ -0,0 +1,14 @@ +'use strict'; + +// Math algorithms +module.exports = { + fibonacci: require('./fibonacci'), + fisherYates: require('./fisher_yates'), + gcd: require('./gcd'), + extendedEuclidean: require('./extended_euclidean'), + newtonSqrt: require('./newton_sqrt'), + reservoirSampling: require('./reservoir_sampling'), + fastPower: require('./fast_power'), + nextPermutation: require('./next_permutation'), + powerSet: require('./power_set') +}; diff --git a/algorithms/math/newton_sqrt.js b/src/algorithms/math/newton_sqrt.js similarity index 100% rename from algorithms/math/newton_sqrt.js rename to src/algorithms/math/newton_sqrt.js diff --git a/algorithms/math/next_permutation.js b/src/algorithms/math/next_permutation.js similarity index 100% rename from algorithms/math/next_permutation.js rename to src/algorithms/math/next_permutation.js diff --git a/algorithms/math/power_set.js b/src/algorithms/math/power_set.js similarity index 100% rename from algorithms/math/power_set.js rename to src/algorithms/math/power_set.js diff --git a/algorithms/math/reservoir_sampling.js b/src/algorithms/math/reservoir_sampling.js similarity index 100% rename from algorithms/math/reservoir_sampling.js rename to src/algorithms/math/reservoir_sampling.js diff --git a/algorithms/searching/bfs.js b/src/algorithms/searching/bfs.js similarity index 100% rename from algorithms/searching/bfs.js rename to src/algorithms/searching/bfs.js diff --git a/algorithms/searching/binarysearch.js b/src/algorithms/searching/binarysearch.js similarity index 100% rename from algorithms/searching/binarysearch.js rename to src/algorithms/searching/binarysearch.js diff --git a/algorithms/searching/dfs.js b/src/algorithms/searching/dfs.js similarity index 100% rename from algorithms/searching/dfs.js rename to src/algorithms/searching/dfs.js diff --git a/src/algorithms/searching/index.js b/src/algorithms/searching/index.js new file mode 100644 index 0000000..311c6e2 --- /dev/null +++ b/src/algorithms/searching/index.js @@ -0,0 +1,8 @@ +'use strict'; + +// Search algorithms +module.exports = { + bfs: require('./bfs'), + binarySearch: require('./binarysearch'), + dfs: require('./dfs') +}; diff --git a/algorithms/sorting/bubble_sort.js b/src/algorithms/sorting/bubble_sort.js similarity index 100% rename from algorithms/sorting/bubble_sort.js rename to src/algorithms/sorting/bubble_sort.js diff --git a/algorithms/sorting/counting_sort.js b/src/algorithms/sorting/counting_sort.js similarity index 100% rename from algorithms/sorting/counting_sort.js rename to src/algorithms/sorting/counting_sort.js diff --git a/algorithms/sorting/heap_sort.js b/src/algorithms/sorting/heap_sort.js similarity index 100% rename from algorithms/sorting/heap_sort.js rename to src/algorithms/sorting/heap_sort.js diff --git a/src/algorithms/sorting/index.js b/src/algorithms/sorting/index.js new file mode 100644 index 0000000..f77b6c6 --- /dev/null +++ b/src/algorithms/sorting/index.js @@ -0,0 +1,14 @@ +'use strict'; + +// Sorting algorithms +module.exports = { + bubbleSort: require('./bubble_sort'), + countingSort: require('./counting_sort'), + heapSort: require('./heap_sort'), + mergeSort: require('./merge_sort'), + quicksort: require('./quicksort'), + selectionSort: require('./selection_sort'), + radixSort: require('./radix_sort'), + insertionSort: require('./insertion_sort'), + shellSort: require('./shell_sort') +}; diff --git a/algorithms/sorting/insertion_sort.js b/src/algorithms/sorting/insertion_sort.js similarity index 100% rename from algorithms/sorting/insertion_sort.js rename to src/algorithms/sorting/insertion_sort.js diff --git a/algorithms/sorting/merge_sort.js b/src/algorithms/sorting/merge_sort.js similarity index 100% rename from algorithms/sorting/merge_sort.js rename to src/algorithms/sorting/merge_sort.js diff --git a/algorithms/sorting/quicksort.js b/src/algorithms/sorting/quicksort.js similarity index 100% rename from algorithms/sorting/quicksort.js rename to src/algorithms/sorting/quicksort.js diff --git a/algorithms/sorting/radix_sort.js b/src/algorithms/sorting/radix_sort.js similarity index 100% rename from algorithms/sorting/radix_sort.js rename to src/algorithms/sorting/radix_sort.js diff --git a/algorithms/sorting/selection_sort.js b/src/algorithms/sorting/selection_sort.js similarity index 100% rename from algorithms/sorting/selection_sort.js rename to src/algorithms/sorting/selection_sort.js diff --git a/algorithms/sorting/shell_sort.js b/src/algorithms/sorting/shell_sort.js similarity index 100% rename from algorithms/sorting/shell_sort.js rename to src/algorithms/sorting/shell_sort.js diff --git a/algorithms/string/hamming.js b/src/algorithms/string/hamming.js similarity index 100% rename from algorithms/string/hamming.js rename to src/algorithms/string/hamming.js diff --git a/algorithms/string/huffman.js b/src/algorithms/string/huffman.js similarity index 100% rename from algorithms/string/huffman.js rename to src/algorithms/string/huffman.js diff --git a/src/algorithms/string/index.js b/src/algorithms/string/index.js new file mode 100644 index 0000000..3fd19e5 --- /dev/null +++ b/src/algorithms/string/index.js @@ -0,0 +1,12 @@ +'use strict'; + +// String algorithms +module.exports = { + levenshtein: require('./levenshtein'), + rabinKarp: require('./rabin_karp'), + knuthMorrisPratt: require('./knuth_morris_pratt'), + huffman: require('./huffman'), + hamming: require('./hamming'), + longestCommonSubsequence: require( + './longest_common_subsequence') +}; diff --git a/algorithms/string/knuth_morris_pratt.js b/src/algorithms/string/knuth_morris_pratt.js similarity index 100% rename from algorithms/string/knuth_morris_pratt.js rename to src/algorithms/string/knuth_morris_pratt.js diff --git a/algorithms/string/levenshtein.js b/src/algorithms/string/levenshtein.js similarity index 100% rename from algorithms/string/levenshtein.js rename to src/algorithms/string/levenshtein.js diff --git a/algorithms/string/longest_common_subsequence.js b/src/algorithms/string/longest_common_subsequence.js similarity index 100% rename from algorithms/string/longest_common_subsequence.js rename to src/algorithms/string/longest_common_subsequence.js diff --git a/algorithms/string/rabin_karp.js b/src/algorithms/string/rabin_karp.js similarity index 100% rename from algorithms/string/rabin_karp.js rename to src/algorithms/string/rabin_karp.js diff --git a/data_structures/bst.js b/src/data_structures/bst.js similarity index 100% rename from data_structures/bst.js rename to src/data_structures/bst.js diff --git a/data_structures/disjoint_set_forest.js b/src/data_structures/disjoint_set_forest.js similarity index 100% rename from data_structures/disjoint_set_forest.js rename to src/data_structures/disjoint_set_forest.js diff --git a/data_structures/graph.js b/src/data_structures/graph.js similarity index 71% rename from data_structures/graph.js rename to src/data_structures/graph.js index 003ce54..082ff95 100644 --- a/data_structures/graph.js +++ b/src/data_structures/graph.js @@ -1,5 +1,7 @@ 'use strict'; +var HashSet = require('./set'); + /** * Adjacency list representation of a graph * @param {bool} directed @@ -7,15 +9,26 @@ function Graph(directed) { this.directed = (directed === undefined ? true : !!directed); this.adjList = Object.create(null); - this.vertices = []; + this.vertices = new HashSet(); } +// Normalize vertex labels as strings +var _ = function (v) { + return '' + v; +}; + Graph.prototype.addVertex = function (v) { - this.vertices.push('' + v); + v = _(v); + if (this.vertices.contains(v)) { + throw new Error('Vertex "' + v + '" has already been added'); + } + this.vertices.add(v); this.adjList[v] = Object.create(null); }; Graph.prototype.addEdge = function (a, b, w) { + a = _(a); + b = _(b); // If no weight is assigned to the edge, 1 is the default w = (w === undefined ? 1 : w); @@ -33,11 +46,11 @@ Graph.prototype.addEdge = function (a, b, w) { }; Graph.prototype.neighbors = function (v) { - return Object.keys(this.adjList[v]); + return Object.keys(this.adjList[_(v)]); }; Graph.prototype.edge = function (a, b) { - return this.adjList[a][b]; + return this.adjList[_(a)][_(b)]; }; module.exports = Graph; diff --git a/data_structures/hash_table.js b/src/data_structures/hash_table.js similarity index 98% rename from data_structures/hash_table.js rename to src/data_structures/hash_table.js index ecb421f..60402ee 100644 --- a/data_structures/hash_table.js +++ b/src/data_structures/hash_table.js @@ -77,7 +77,7 @@ HashTable.prototype.del = function (key) { }; HashTable.prototype._position = function (key) { - return this.hash(key) % this.capacity; + return Math.abs(this.hash(key)) % this.capacity; }; HashTable.prototype._findInList = function (list, key) { diff --git a/data_structures/heap.js b/src/data_structures/heap.js similarity index 100% rename from data_structures/heap.js rename to src/data_structures/heap.js diff --git a/src/data_structures/index.js b/src/data_structures/index.js new file mode 100644 index 0000000..4f1765d --- /dev/null +++ b/src/data_structures/index.js @@ -0,0 +1,15 @@ +'use strict'; + +// Data Structures +module.exports = { + BST: require('./bst'), + Graph: require('./graph'), + HashTable: require('./hash_table'), + Heap: require('./heap'), + LinkedList: require('./linked_list'), + PriorityQueue: require('./priority_queue'), + Queue: require('./queue'), + Stack: require('./stack'), + Set: require('./set'), + DisjointSetForest: require('./disjoint_set_forest') +}; diff --git a/data_structures/linked_list.js b/src/data_structures/linked_list.js similarity index 100% rename from data_structures/linked_list.js rename to src/data_structures/linked_list.js diff --git a/data_structures/priority_queue.js b/src/data_structures/priority_queue.js similarity index 100% rename from data_structures/priority_queue.js rename to src/data_structures/priority_queue.js diff --git a/data_structures/queue.js b/src/data_structures/queue.js similarity index 100% rename from data_structures/queue.js rename to src/data_structures/queue.js diff --git a/data_structures/set.js b/src/data_structures/set.js similarity index 100% rename from data_structures/set.js rename to src/data_structures/set.js diff --git a/data_structures/stack.js b/src/data_structures/stack.js similarity index 100% rename from data_structures/stack.js rename to src/data_structures/stack.js diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..cf6380e --- /dev/null +++ b/src/index.js @@ -0,0 +1,12 @@ +'use strict'; + +var lib = { + DataStructure: require('./data_structures'), + Graph: require('./algorithms/graph'), + Math: require('./algorithms/math'), + Search: require('./algorithms/searching'), + Sorting: require('./algorithms/sorting'), + String: require('./algorithms/string') +}; + +module.exports = lib; diff --git a/test/algorithms/graph/SPFA.js b/src/test/algorithms/graph/SPFA.js similarity index 90% rename from test/algorithms/graph/SPFA.js rename to src/test/algorithms/graph/SPFA.js index 36326b2..dcf3e6d 100644 --- a/test/algorithms/graph/SPFA.js +++ b/src/test/algorithms/graph/SPFA.js @@ -1,7 +1,8 @@ 'use strict'; -var SPFA = require('../../../algorithms/graph/SPFA'), - Graph = require('../../../data_structures/graph'), +var root = require('../../../'), + SPFA = root.Graph.SPFA, + Graph = root.DataStructure.Graph, assert = require('assert'); describe('SPFA Algorithm', function () { diff --git a/test/algorithms/graph/bellman_ford.js b/src/test/algorithms/graph/bellman_ford.js similarity index 88% rename from test/algorithms/graph/bellman_ford.js rename to src/test/algorithms/graph/bellman_ford.js index fbc6f39..d4ec90b 100644 --- a/test/algorithms/graph/bellman_ford.js +++ b/src/test/algorithms/graph/bellman_ford.js @@ -1,7 +1,8 @@ 'use strict'; -var bellmanFord = require('../../../algorithms/graph/bellman_ford'), - Graph = require('../../../data_structures/graph'), +var root = require('../../../'), + bellmanFord = root.Graph.bellmanFord, + Graph = root.DataStructure.Graph, assert = require('assert'); describe('Bellman-Ford Algorithm', function () { diff --git a/test/algorithms/graph/bfs_shortest_path.js b/src/test/algorithms/graph/bfs_shortest_path.js similarity index 88% rename from test/algorithms/graph/bfs_shortest_path.js rename to src/test/algorithms/graph/bfs_shortest_path.js index 6e9258e..5300f88 100644 --- a/test/algorithms/graph/bfs_shortest_path.js +++ b/src/test/algorithms/graph/bfs_shortest_path.js @@ -1,7 +1,8 @@ 'use strict'; -var bfsShortestPath = require('../../../algorithms/graph/bfs_shortest_path'), - Graph = require('../../../data_structures/graph'), +var root = require('../../../'), + bfsShortestPath = root.Graph.bfsShortestPath, + Graph = root.DataStructure.Graph, assert = require('assert'); diff --git a/test/algorithms/graph/breadth_first_search.js b/src/test/algorithms/graph/breadth_first_search.js similarity index 81% rename from test/algorithms/graph/breadth_first_search.js rename to src/test/algorithms/graph/breadth_first_search.js index 6e7a635..457da6f 100644 --- a/test/algorithms/graph/breadth_first_search.js +++ b/src/test/algorithms/graph/breadth_first_search.js @@ -1,22 +1,26 @@ 'use strict'; -var breadthFirstSearch = - require('../../../algorithms/graph/breadth_first_search'), - Graph = require('../../../data_structures/graph'), +var root = require('../../../'), + breadthFirstSearch = root.Graph.breadthFirstSearch, + Graph = root.DataStructure.Graph, assert = require('assert'); describe('Breadth-First Search', function () { - var graph = new Graph(); - graph.addEdge(1, 2); - graph.addEdge(1, 5); - graph.addEdge(5, 2); - graph.addEdge(2, 6); - graph.addEdge(6, 1); - graph.addEdge(6, 3); - graph.addEdge(3, 2); - graph.addEdge(2, 4); - graph.addEdge('alpha', 'omega'); + var graph; + + before(function () { + graph = new Graph(); + graph.addEdge(1, 2); + graph.addEdge(1, 5); + graph.addEdge(5, 2); + graph.addEdge(2, 6); + graph.addEdge(6, 1); + graph.addEdge(6, 3); + graph.addEdge(3, 2); + graph.addEdge(2, 4); + graph.addEdge('alpha', 'omega'); + }); it('should visit reachable vertices in a breadth-first manner', function () { var enter = [], leave = []; diff --git a/test/algorithms/graph/depth_first_search.js b/src/test/algorithms/graph/depth_first_search.js similarity index 81% rename from test/algorithms/graph/depth_first_search.js rename to src/test/algorithms/graph/depth_first_search.js index f1335bf..fb9382e 100644 --- a/test/algorithms/graph/depth_first_search.js +++ b/src/test/algorithms/graph/depth_first_search.js @@ -1,18 +1,23 @@ 'use strict'; -var depthFirstSearch = require('../../../algorithms/graph/depth_first_search'), - Graph = require('../../../data_structures/graph'), - assert = require('assert'), - graph = new Graph(true); - -graph.addEdge('one', 'three'); -graph.addEdge('one', 'four'); -graph.addEdge('four', 'two'); -graph.addEdge('two', 'one'); -graph.addEdge('three', 'one'); -graph.addEdge('five', 'six'); +var root = require('../../../'), + depthFirstSearch = root.Graph.depthFirstSearch, + Graph = root.DataStructure.Graph, + assert = require('assert'); describe('Depth First Search Algorithm', function () { + + var graph; + before(function () { + graph = new Graph(true); + graph.addEdge('one', 'three'); + graph.addEdge('one', 'four'); + graph.addEdge('four', 'two'); + graph.addEdge('two', 'one'); + graph.addEdge('three', 'one'); + graph.addEdge('five', 'six'); + }); + it('should visit only the nodes reachable from the start node (inclusive)', function () { var enter = [], leave = []; diff --git a/test/algorithms/graph/dijkstra.js b/src/test/algorithms/graph/dijkstra.js similarity index 86% rename from test/algorithms/graph/dijkstra.js rename to src/test/algorithms/graph/dijkstra.js index 8667868..edf2300 100644 --- a/test/algorithms/graph/dijkstra.js +++ b/src/test/algorithms/graph/dijkstra.js @@ -1,7 +1,8 @@ 'use strict'; -var dijkstra = require('../../../algorithms/graph/dijkstra'), - Graph = require('../../../data_structures/graph'), +var root = require('../../../'), + dijkstra = root.Graph.dijkstra, + Graph = root.DataStructure.Graph, assert = require('assert'); describe('Dijkstra Algorithm', function () { diff --git a/test/algorithms/graph/euler_path.js b/src/test/algorithms/graph/euler_path.js similarity index 77% rename from test/algorithms/graph/euler_path.js rename to src/test/algorithms/graph/euler_path.js index 47cb995..6bf384c 100644 --- a/test/algorithms/graph/euler_path.js +++ b/src/test/algorithms/graph/euler_path.js @@ -1,39 +1,38 @@ 'use strict'; -var eulerPath = require('../../../algorithms/graph/euler_path'), - Graph = require('../../../data_structures/graph'), +var root = require('../../../'), + eulerPath = root.Graph.eulerPath, + Graph = root.DataStructure.Graph, assert = require('assert'); -var verifyEulerPath = function (graph, trail) { - var visited = new Graph(graph.directed); - graph.vertices.forEach(visited.addVertex.bind(visited)); - - trail.slice(1).reduce(function (previous, current) { - assert(graph.edge(previous, current)); - assert(!visited.edge(previous, current)); - visited.addEdge(previous, current); - return current; - }, trail[0]); - - graph.vertices.forEach(function (vertex) { - assert.equal(graph.neighbors(vertex).length, - visited.neighbors(vertex).length); - }); -}; - - -var graphFromEdges = function (directed, edges) { - var graph = new Graph(directed); - edges.forEach(function (edge) { - graph.addEdge(edge[0], edge[1]); - }); - return graph; -}; - - describe('Euler Path', function () { + var verifyEulerPath = function (graph, trail) { + var visited = new Graph(graph.directed); + graph.vertices.forEach(visited.addVertex.bind(visited)); + + trail.slice(1).reduce(function (previous, current) { + assert(graph.edge(previous, current)); + assert(!visited.edge(previous, current)); + visited.addEdge(previous, current); + return current; + }, trail[0]); + + graph.vertices.forEach(function (vertex) { + assert.equal(graph.neighbors(vertex).length, + visited.neighbors(vertex).length); + }); + }; + + var graphFromEdges = function (directed, edges) { + var graph = new Graph(directed); + edges.forEach(function (edge) { + graph.addEdge(edge[0], edge[1]); + }); + return graph; + }; + it('should compute Euler tour over the undirected graph', function () { var graph = graphFromEdges(false, [ [1, 2], diff --git a/test/algorithms/graph/floyd_warshall.js b/src/test/algorithms/graph/floyd_warshall.js similarity index 95% rename from test/algorithms/graph/floyd_warshall.js rename to src/test/algorithms/graph/floyd_warshall.js index 5ee0ada..3cab6d3 100644 --- a/test/algorithms/graph/floyd_warshall.js +++ b/src/test/algorithms/graph/floyd_warshall.js @@ -1,8 +1,8 @@ 'use strict'; - -var floydWarshall = require('../../../algorithms/graph/floyd_warshall'), - Graph = require('../../../data_structures/graph'), +var root = require('../../../'), + floydWarshall = root.Graph.floydWarshall, + Graph = root.DataStructure.Graph, assert = require('assert'); diff --git a/src/test/algorithms/graph/minimum_spanning_tree.js b/src/test/algorithms/graph/minimum_spanning_tree.js new file mode 100644 index 0000000..d72e314 --- /dev/null +++ b/src/test/algorithms/graph/minimum_spanning_tree.js @@ -0,0 +1,199 @@ +'use strict'; + +var root = require('../../../'), + kruskal = root.Graph.kruskal, + prim = root.Graph.prim, + depthFirstSearch = root.Graph.depthFirstSearch, + Graph = root.DataStructure.Graph, + assert = require('assert'); + + +describe('Minimum Spanning Tree', function () { + + /** + * @param {Graph} graph - Undirected graph. + * @return {number} + */ + var numberOfConnectedComponents = function (graph) { + assert(!graph.directed); + var seen = {}; + var coverComponent = function (origin) { + depthFirstSearch(graph, origin, { + enterVertex: function (vertex) { + seen[vertex] = true; + } + }); + }; + + var count = 0; + graph.vertices.forEach(function (vertex) { + if (!seen[vertex]) { + coverComponent(vertex); + count++; + } + }); + return count; + }; + + + /** + * Test whether graph is a valid (undirected) forest. + * In a forest #vertices = #edges + #components. + * + * @param {Graph} graph + * @param {number} connectivity + * @return {boolean} + */ + var isForest = function (graph, connectivity) { + if (graph.directed || numberOfConnectedComponents(graph) != connectivity) { + return false; + } + var numberOfEdges = 0; + graph.vertices.forEach(function (vertex) { + graph.neighbors(vertex).filter( + function (neighbor) { + if (vertex <= neighbor) { + numberOfEdges++; + } + }); + }); + return graph.vertices.size == numberOfEdges + connectivity; + }; + + + /** + * Test whether two graphs share the same vertex set. + * + * @param {Graph} graph1 + * @param {Graph} graph2 + * @return {boolean} + */ + var spans = function (graph1, graph2) { + var span; + if (graph1.vertices.size === graph2.vertices.size) { + span = true; + graph1.vertices.forEach(function (v) { + if (!graph2.vertices.contains(v)) { + span = false; + } + }); + } else { + span = false; + } + return span; + }; + + + /** + * Sum up graph edge weights. + * + * @param {Graph} graph + * @return {?number} Null if the graph contains no edges. + */ + var graphCost = function (graph) { + var noEdges = true; + var total = 0; + graph.vertices.forEach(function (vertex) { + graph.neighbors(vertex).forEach(function (neighbor) { + noEdges = false; + total += graph.edge(vertex, neighbor); + }); + }); + return noEdges ? null : graph.directed ? total : total / 2; + }; + + + /** + * Test whether one graph is the minimum spanning forest of the other. + * + * @param {Graph} suspect + * @param {Graph} graph - Undirected graph. + * @param {?number} minimumCost + * @param {number} [connectivity=1] + * @return {boolean} + */ + var isMinimumSpanningForest = function (suspect, graph, + minimumCost, connectivity) { + assert(!graph.directed); + return isForest(suspect, connectivity || 1) && + spans(suspect, graph) && + graphCost(suspect) === minimumCost; + }; + + + var testMstAlgorithm = function (mst) { + it('should find a minimum spanning tree', function () { + var graph = new Graph(false); + graph.addEdge(1, 2, 1); + graph.addEdge(1, 4, 2); + graph.addEdge(1, 5, 2); + graph.addEdge(4, 2, 2); + graph.addEdge(4, 5, 1); + graph.addEdge(5, 6, 1); + graph.addEdge(6, 4, 8); + graph.addEdge(6, 3, 2); + graph.addEdge(2, 3, 3); + assert(isMinimumSpanningForest(mst(graph), graph, 7)); + + // Change (4, 5) weight to 3. + graph.addEdge(4, 5, +2); + assert(isMinimumSpanningForest(mst(graph), graph, 8)); + + // Force it go find another way to reach (6). + graph.addEdge(4, 5, +5); + graph.addEdge(6, 5, +7); + assert(isMinimumSpanningForest(mst(graph), graph, 10)); + + // It should find zero-cost MST. + var clear = function (a, b) { + graph.addEdge(a, b, -graph.edge(a, b)); + }; + clear(2, 1); + clear(1, 5); + clear(5, 6); + clear(6, 4); + clear(6, 3); + assert(isMinimumSpanningForest(mst(graph), graph, 0)); + + // But prefer a negative-cost one to it. + graph.addEdge(2, 4, -102); + assert(isMinimumSpanningForest(mst(graph), graph, -100)); + }); + + it('should find a minimum spaning forest if the graph is not connected', + function () { + var graph = new Graph(false); + graph.addVertex(1); + graph.addVertex(2); + graph.addVertex(3); + assert(isMinimumSpanningForest(mst(graph), graph, null, 3)); + + graph.addEdge(1, 2, 2); + assert(isMinimumSpanningForest(mst(graph), graph, 2, 2)); + + graph.addEdge(1, 3, 1); + graph.addEdge(2, 3, -1); + assert(isMinimumSpanningForest(mst(graph), graph, 0, 1)); + + graph.addVertex(4); + assert(isMinimumSpanningForest(mst(graph), graph, 0, 2)); + + graph.addEdge(5, 6, 1); + assert(isMinimumSpanningForest(mst(graph), graph, 1, 3)); + + graph.addEdge(5, 4, -100); + graph.addEdge(6, 4, -100); + assert(isMinimumSpanningForest(mst(graph), graph, -200, 2)); + }); + + it('should throw an error if the graph is directed', function () { + var directedGraph = new Graph(true); + directedGraph.addEdge('Rock', 'Hard Place'); + assert.throws(mst.bind(null, directedGraph)); + }); + }; + + + describe('#Kruskal\'s Algorithm', testMstAlgorithm.bind(null, kruskal)); + describe('#Prim\'s Algorithm', testMstAlgorithm.bind(null, prim)); +}); diff --git a/test/algorithms/graph/topological_sort.js b/src/test/algorithms/graph/topological_sort.js similarity index 82% rename from test/algorithms/graph/topological_sort.js rename to src/test/algorithms/graph/topological_sort.js index 5d916eb..0ec4133 100644 --- a/test/algorithms/graph/topological_sort.js +++ b/src/test/algorithms/graph/topological_sort.js @@ -1,7 +1,8 @@ 'use strict'; -var topologicalSort = require('../../../algorithms/graph/topological_sort'), - Graph = require('../../../data_structures/graph'), +var root = require('../../../'), + topologicalSort = root.Graph.topologicalSort, + Graph = root.DataStructure.Graph, assert = require('assert'); describe('Topological Sort', function () { @@ -9,16 +10,16 @@ describe('Topological Sort', function () { ' considering the dependencies', function () { var graph = new Graph(); - graph.addVertex('shirt'); + graph.addVertex('shoes'); graph.addVertex('watch'); - graph.addVertex('socks'); graph.addVertex('underwear'); + graph.addVertex('socks'); + graph.addVertex('shirt'); graph.addVertex('pants'); graph.addVertex('belt'); - graph.addVertex('shoes'); graph.addVertex('tie'); graph.addVertex('jacket'); - + graph.addEdge('shirt', 'belt'); graph.addEdge('shirt', 'tie'); graph.addEdge('shirt', 'jacket'); @@ -39,8 +40,8 @@ describe('Topological Sort', function () { var a = []; while (!stack.isEmpty()) a.push(stack.pop()); assert.deepEqual(a, [ - 'underwear', 'pants', 'socks', 'shoes', - 'watch', 'shirt', 'tie', 'belt', 'jacket' + 'shirt', 'socks', 'underwear', 'pants', 'shoes', + 'tie', 'watch', 'belt', 'jacket' ]); }); }); diff --git a/test/algorithms/math/extended_euclidean.js b/src/test/algorithms/math/extended_euclidean.js similarity index 85% rename from test/algorithms/math/extended_euclidean.js rename to src/test/algorithms/math/extended_euclidean.js index 3f716de..ecd9de3 100644 --- a/test/algorithms/math/extended_euclidean.js +++ b/src/test/algorithms/math/extended_euclidean.js @@ -1,6 +1,7 @@ 'use strict'; -var extEuclid = require('../../../algorithms/math/extended_euclidean'), +var math = require('../../..').Math, + extEuclid = math.extendedEuclidean, assert = require('assert'); describe('extEuclid', function () { diff --git a/test/algorithms/math/fast_power.js b/src/test/algorithms/math/fast_power.js similarity index 97% rename from test/algorithms/math/fast_power.js rename to src/test/algorithms/math/fast_power.js index 520da03..bcad8fe 100644 --- a/test/algorithms/math/fast_power.js +++ b/src/test/algorithms/math/fast_power.js @@ -1,6 +1,7 @@ 'use strict'; -var power = require('../../../algorithms/math/fast_power'), +var math = require('../../..').Math, + power = math.fastPower, assert = require('assert'); diff --git a/test/algorithms/math/fibonacci.js b/src/test/algorithms/math/fibonacci.js similarity index 95% rename from test/algorithms/math/fibonacci.js rename to src/test/algorithms/math/fibonacci.js index e6d1b46..78043c5 100644 --- a/test/algorithms/math/fibonacci.js +++ b/src/test/algorithms/math/fibonacci.js @@ -1,6 +1,7 @@ 'use strict'; -var fib = require('../../../algorithms/math/fibonacci'), +var math = require('../../..').Math, + fib = math.fibonacci, assert = require('assert'); var testFibonacciSequence = function (fib) { diff --git a/test/algorithms/math/fisher_yates.js b/src/test/algorithms/math/fisher_yates.js similarity index 88% rename from test/algorithms/math/fisher_yates.js rename to src/test/algorithms/math/fisher_yates.js index ee7338b..8142dc2 100644 --- a/test/algorithms/math/fisher_yates.js +++ b/src/test/algorithms/math/fisher_yates.js @@ -1,6 +1,7 @@ 'use strict'; -var fisherYates = require('../../../algorithms/math/fisher_yates'), +var math = require('../../..').Math, + fisherYates = math.fisherYates, assert = require('assert'); describe('Fisher-Yates', function () { diff --git a/test/algorithms/math/gcd.js b/src/test/algorithms/math/gcd.js similarity index 94% rename from test/algorithms/math/gcd.js rename to src/test/algorithms/math/gcd.js index 6a35be2..1fa476c 100644 --- a/test/algorithms/math/gcd.js +++ b/src/test/algorithms/math/gcd.js @@ -1,6 +1,7 @@ 'use strict'; -var gcd = require('../../../algorithms/math/gcd'), +var root = require('../../..'), + gcd = root.Math.gcd, assert = require('assert'); describe('GCD', function () { diff --git a/test/algorithms/math/newton_sqrt.js b/src/test/algorithms/math/newton_sqrt.js similarity index 93% rename from test/algorithms/math/newton_sqrt.js rename to src/test/algorithms/math/newton_sqrt.js index d820cac..c74ba25 100644 --- a/test/algorithms/math/newton_sqrt.js +++ b/src/test/algorithms/math/newton_sqrt.js @@ -1,6 +1,7 @@ 'use strict'; -var newtonSqrt = require('../../../algorithms/math/newton_sqrt'), +var math = require('../../..').Math, + newtonSqrt = math.newtonSqrt, assert = require('assert'); describe('Newton square root', function () { diff --git a/test/algorithms/math/next_permutation.js b/src/test/algorithms/math/next_permutation.js similarity index 95% rename from test/algorithms/math/next_permutation.js rename to src/test/algorithms/math/next_permutation.js index 1bcb9fe..7d351ad 100644 --- a/test/algorithms/math/next_permutation.js +++ b/src/test/algorithms/math/next_permutation.js @@ -1,6 +1,7 @@ 'use strict'; -var nextPermutation = require('../../../algorithms/math/next_permutation'), +var math = require('../../..').Math, + nextPermutation = math.nextPermutation, Comparator = require('../../../util/comparator'), assert = require('assert'); diff --git a/test/algorithms/math/power_set.js b/src/test/algorithms/math/power_set.js similarity index 98% rename from test/algorithms/math/power_set.js rename to src/test/algorithms/math/power_set.js index db31569..aba6ea6 100644 --- a/test/algorithms/math/power_set.js +++ b/src/test/algorithms/math/power_set.js @@ -1,6 +1,7 @@ 'use strict'; -var powerSet = require('../../../algorithms/math/power_set'), +var math = require('../../..').Math, + powerSet = math.powerSet, assert = require('assert'); function testArrayEqual(a, b) { diff --git a/test/algorithms/math/reservoir_sampling.js b/src/test/algorithms/math/reservoir_sampling.js similarity index 91% rename from test/algorithms/math/reservoir_sampling.js rename to src/test/algorithms/math/reservoir_sampling.js index e303a0f..16bc8d0 100644 --- a/test/algorithms/math/reservoir_sampling.js +++ b/src/test/algorithms/math/reservoir_sampling.js @@ -1,7 +1,7 @@ 'use strict'; - -var reservoirSampling = require('../../../algorithms/math/reservoir_sampling'), +var math = require('../../..').Math, + reservoirSampling = math.reservoirSampling, assert = require('assert'); diff --git a/test/algorithms/searching/bfs.js b/src/test/algorithms/searching/bfs.js similarity index 86% rename from test/algorithms/searching/bfs.js rename to src/test/algorithms/searching/bfs.js index c791523..14f79a7 100644 --- a/test/algorithms/searching/bfs.js +++ b/src/test/algorithms/searching/bfs.js @@ -1,6 +1,8 @@ 'use strict'; -var BST = require('../../../data_structures/bst'), - bfs = require('../../../algorithms/searching/bfs'), + +var root = require('../../..'), + BST = root.DataStructure.BST, + bfs = root.Search.bfs, assert = require('assert'); describe('Breadth First Search', function () { diff --git a/test/algorithms/searching/binarysearch.js b/src/test/algorithms/searching/binarysearch.js similarity index 89% rename from test/algorithms/searching/binarysearch.js rename to src/test/algorithms/searching/binarysearch.js index 23a2df3..f2e5169 100644 --- a/test/algorithms/searching/binarysearch.js +++ b/src/test/algorithms/searching/binarysearch.js @@ -1,6 +1,6 @@ 'use strict'; -var binarySearch = require('../../../algorithms/searching/binarysearch'), +var binarySearch = require('../../..').Search.binarySearch, assert = require('assert'); describe('Binary Search', function () { diff --git a/test/algorithms/searching/dfs.js b/src/test/algorithms/searching/dfs.js similarity index 90% rename from test/algorithms/searching/dfs.js rename to src/test/algorithms/searching/dfs.js index cbae4e5..3e53ca9 100644 --- a/test/algorithms/searching/dfs.js +++ b/src/test/algorithms/searching/dfs.js @@ -1,7 +1,8 @@ 'use strict'; -var BST = require('../../../data_structures/bst'), - dfs = require('../../../algorithms/searching/dfs'), +var root = require('../../..'), + BST = root.DataStructure.BST, + dfs = root.Search.dfs, assert = require('assert'); describe('Depth First Search', function () { diff --git a/test/algorithms/sorting/bubble_sort.js b/src/test/algorithms/sorting/bubble_sort.js similarity index 84% rename from test/algorithms/sorting/bubble_sort.js rename to src/test/algorithms/sorting/bubble_sort.js index 9de0405..329c977 100644 --- a/test/algorithms/sorting/bubble_sort.js +++ b/src/test/algorithms/sorting/bubble_sort.js @@ -1,6 +1,6 @@ 'use strict'; -var bubbleSort = require('../../../algorithms/sorting/bubble_sort'), +var bubbleSort = require('../../..').Sorting.bubbleSort, sortingTestsHelper = require('./sorting_tests_helper'); describe('Bubble Sort', function () { diff --git a/test/algorithms/sorting/counting_sort.js b/src/test/algorithms/sorting/counting_sort.js similarity index 90% rename from test/algorithms/sorting/counting_sort.js rename to src/test/algorithms/sorting/counting_sort.js index 577b539..e47d5b0 100644 --- a/test/algorithms/sorting/counting_sort.js +++ b/src/test/algorithms/sorting/counting_sort.js @@ -1,6 +1,6 @@ 'use strict'; -var countingSort = require('../../../algorithms/sorting/counting_sort'), +var countingSort = require('../../..').Sorting.countingSort, assert = require('assert'); var firstObject = { diff --git a/test/algorithms/sorting/heap_sort.js b/src/test/algorithms/sorting/heap_sort.js similarity index 84% rename from test/algorithms/sorting/heap_sort.js rename to src/test/algorithms/sorting/heap_sort.js index db87b24..5d95edc 100644 --- a/test/algorithms/sorting/heap_sort.js +++ b/src/test/algorithms/sorting/heap_sort.js @@ -1,6 +1,6 @@ 'use strict'; -var heapSort = require('../../../algorithms/sorting/heap_sort'), +var heapSort = require('../../..').Sorting.heapSort, sortingTestsHelper = require('./sorting_tests_helper'); describe('Heap Sort', function () { diff --git a/test/algorithms/sorting/insertion_sort.js b/src/test/algorithms/sorting/insertion_sort.js similarity index 83% rename from test/algorithms/sorting/insertion_sort.js rename to src/test/algorithms/sorting/insertion_sort.js index fa2ca82..97ab7f3 100644 --- a/test/algorithms/sorting/insertion_sort.js +++ b/src/test/algorithms/sorting/insertion_sort.js @@ -1,6 +1,6 @@ 'use strict'; -var insertionSort = require('../../../algorithms/sorting/insertion_sort'), +var insertionSort = require('../../..').Sorting.insertionSort, sortingTestsHelper = require('./sorting_tests_helper'); describe('Insertion Sort', function () { diff --git a/test/algorithms/sorting/merge_sort.js b/src/test/algorithms/sorting/merge_sort.js similarity index 84% rename from test/algorithms/sorting/merge_sort.js rename to src/test/algorithms/sorting/merge_sort.js index 7c968c1..acb43b3 100644 --- a/test/algorithms/sorting/merge_sort.js +++ b/src/test/algorithms/sorting/merge_sort.js @@ -1,6 +1,6 @@ 'use strict'; -var mergeSort = require('../../../algorithms/sorting/merge_sort'), +var mergeSort = require('../../..').Sorting.mergeSort, sortingTestsHelper = require('./sorting_tests_helper'); describe('Merge Sort', function () { diff --git a/test/algorithms/sorting/quicksort.js b/src/test/algorithms/sorting/quicksort.js similarity index 84% rename from test/algorithms/sorting/quicksort.js rename to src/test/algorithms/sorting/quicksort.js index 4a4010b..c970567 100644 --- a/test/algorithms/sorting/quicksort.js +++ b/src/test/algorithms/sorting/quicksort.js @@ -1,6 +1,6 @@ 'use strict'; -var quicksort = require('../../../algorithms/sorting/quicksort'), +var quicksort = require('../../..').Sorting.quicksort, sortingTestsHelper = require('./sorting_tests_helper'); describe('QuickSort', function () { diff --git a/test/algorithms/sorting/radix_sort.js b/src/test/algorithms/sorting/radix_sort.js similarity index 93% rename from test/algorithms/sorting/radix_sort.js rename to src/test/algorithms/sorting/radix_sort.js index dd5e42d..358ce93 100644 --- a/test/algorithms/sorting/radix_sort.js +++ b/src/test/algorithms/sorting/radix_sort.js @@ -1,6 +1,6 @@ 'use strict'; -var radixSort = require('../../../algorithms/sorting/radix_sort'), +var radixSort = require('../../..').Sorting.radixSort, assert = require('assert'); var firstObject = { diff --git a/test/algorithms/sorting/selection_sort.js b/src/test/algorithms/sorting/selection_sort.js similarity index 83% rename from test/algorithms/sorting/selection_sort.js rename to src/test/algorithms/sorting/selection_sort.js index d8991ec..0cc85cd 100644 --- a/test/algorithms/sorting/selection_sort.js +++ b/src/test/algorithms/sorting/selection_sort.js @@ -1,6 +1,6 @@ 'use strict'; -var selectionSort = require('../../../algorithms/sorting/selection_sort'), +var selectionSort = require('../../..').Sorting.selectionSort, sortingTestsHelper = require('./sorting_tests_helper'); describe('Selection Sort', function () { diff --git a/test/algorithms/sorting/shell_sort.js b/src/test/algorithms/sorting/shell_sort.js similarity index 84% rename from test/algorithms/sorting/shell_sort.js rename to src/test/algorithms/sorting/shell_sort.js index 037c0f7..97f6bc1 100644 --- a/test/algorithms/sorting/shell_sort.js +++ b/src/test/algorithms/sorting/shell_sort.js @@ -1,6 +1,6 @@ 'use strict'; -var shellSort = require('../../../algorithms/sorting/shell_sort'), +var shellSort = require('../../..').Sorting.shellSort, sortingTestsHelper = require('./sorting_tests_helper.js'); describe('ShellSort', function () { diff --git a/test/algorithms/sorting/sorting_tests_helper.js b/src/test/algorithms/sorting/sorting_tests_helper.js similarity index 100% rename from test/algorithms/sorting/sorting_tests_helper.js rename to src/test/algorithms/sorting/sorting_tests_helper.js diff --git a/test/algorithms/string/hamming.js b/src/test/algorithms/string/hamming.js similarity index 92% rename from test/algorithms/string/hamming.js rename to src/test/algorithms/string/hamming.js index 3bacc46..cce683d 100644 --- a/test/algorithms/string/hamming.js +++ b/src/test/algorithms/string/hamming.js @@ -1,6 +1,6 @@ 'use strict'; -var hamming = require('../../../algorithms/string/hamming'), +var hamming = require('../../..').String.hamming, assert = require('assert'); diff --git a/test/algorithms/string/huffman.js b/src/test/algorithms/string/huffman.js similarity index 98% rename from test/algorithms/string/huffman.js rename to src/test/algorithms/string/huffman.js index 5a7e7c1..d0b7cf4 100644 --- a/test/algorithms/string/huffman.js +++ b/src/test/algorithms/string/huffman.js @@ -1,6 +1,6 @@ 'use strict'; -var huffman = require('../../../algorithms/string/huffman'), +var huffman = require('../../..').String.huffman, assert = require('assert'); diff --git a/test/algorithms/string/knuth_morris_pratt.js b/src/test/algorithms/string/knuth_morris_pratt.js similarity index 96% rename from test/algorithms/string/knuth_morris_pratt.js rename to src/test/algorithms/string/knuth_morris_pratt.js index 1afc791..6cb5e34 100644 --- a/test/algorithms/string/knuth_morris_pratt.js +++ b/src/test/algorithms/string/knuth_morris_pratt.js @@ -1,6 +1,6 @@ 'use strict'; -var knuthMorrisPratt = require('../../../algorithms/string/knuth_morris_pratt'), +var knuthMorrisPratt = require('../../..').String.knuthMorrisPratt, assert = require('assert'); describe('Knuth-Morris-Pratt', function () { diff --git a/test/algorithms/string/levenshtein.js b/src/test/algorithms/string/levenshtein.js similarity index 91% rename from test/algorithms/string/levenshtein.js rename to src/test/algorithms/string/levenshtein.js index 063844d..cc94f7c 100644 --- a/test/algorithms/string/levenshtein.js +++ b/src/test/algorithms/string/levenshtein.js @@ -1,6 +1,6 @@ 'use strict'; -var levenshtein = require('../../../algorithms/string/levenshtein'), +var levenshtein = require('../../..').String.levenshtein, assert = require('assert'); describe('Levenshtein', function () { diff --git a/src/test/algorithms/string/longest_common_subseqence.js b/src/test/algorithms/string/longest_common_subseqence.js new file mode 100644 index 0000000..40bd604 --- /dev/null +++ b/src/test/algorithms/string/longest_common_subseqence.js @@ -0,0 +1,15 @@ +'use strict'; + +var lcs = require('../../..').String.longestCommonSubsequence, + assert = require('assert'); + +describe('Longest common subsequence', function () { + it('should return the proper longest common subsequence', function () { + assert.equal('', lcs('', '')); + assert.equal('', lcs('', 'aaa')); + assert.equal('', lcs('aaa', '')); + assert.equal('aaa', lcs('aaa', 'aaa')); + assert.equal('mjau', lcs('xmjyauz', 'mzjawxu')); + assert.equal('hman', lcs('human', 'chimpanzee')); + }); +}); diff --git a/test/algorithms/string/rabin_karp.js b/src/test/algorithms/string/rabin_karp.js similarity index 91% rename from test/algorithms/string/rabin_karp.js rename to src/test/algorithms/string/rabin_karp.js index 491b27e..1789b1f 100644 --- a/test/algorithms/string/rabin_karp.js +++ b/src/test/algorithms/string/rabin_karp.js @@ -1,6 +1,6 @@ 'use strict'; -var rabinKarp = require('../../../algorithms/string/rabin_karp'), +var rabinKarp = require('../../..').String.rabinKarp, assert = require('assert'); var rabinKarpEqualsToIndexOf = function (a, b) { diff --git a/test/data_structures/bst.js b/src/test/data_structures/bst.js similarity index 98% rename from test/data_structures/bst.js rename to src/test/data_structures/bst.js index 71feeb5..72b194c 100644 --- a/test/data_structures/bst.js +++ b/src/test/data_structures/bst.js @@ -1,7 +1,8 @@ 'use strict'; -var BST = require('../../data_structures/bst'), - bfs = require('../../algorithms/searching/bfs'), +var root = require('../..'), + BST = root.DataStructure.BST, + bfs = root.Search.bfs, assert = require('assert'); describe('Binary Search Tree', function () { diff --git a/test/data_structures/disjoint_set_forest.js b/src/test/data_structures/disjoint_set_forest.js similarity index 96% rename from test/data_structures/disjoint_set_forest.js rename to src/test/data_structures/disjoint_set_forest.js index e77f739..6e75c03 100644 --- a/test/data_structures/disjoint_set_forest.js +++ b/src/test/data_structures/disjoint_set_forest.js @@ -1,6 +1,6 @@ 'use strict'; -var DisjointSetForest = require('../../data_structures/disjoint_set_forest'), +var DisjointSetForest = require('../..').DataStructure.DisjointSetForest, assert = require('assert'); diff --git a/test/data_structures/graph.js b/src/test/data_structures/graph.js similarity index 86% rename from test/data_structures/graph.js rename to src/test/data_structures/graph.js index d3bbcd6..709edf2 100644 --- a/test/data_structures/graph.js +++ b/src/test/data_structures/graph.js @@ -1,6 +1,6 @@ 'use strict'; -var Graph = require('../../data_structures/graph'), +var Graph = require('../..').DataStructure.Graph, assert = require('assert'); describe('Graph - Adjacency list', function () { @@ -27,9 +27,9 @@ describe('Graph - Adjacency list', function () { function () { var g = new Graph(); g.addEdge('a', 'b'); - assert.equal(g.vertices.length, 2); - assert.notEqual(g.vertices.indexOf('a'), -1); - assert.notEqual(g.vertices.indexOf('b'), -1); + assert.equal(g.vertices.size, 2); + assert(g.vertices.contains('a')); + assert(g.vertices.contains('b')); }); it('should sum multiple edges between the same vertices', function () { @@ -88,11 +88,22 @@ describe('Graph - Adjacency list', function () { it('should have a list of vertices', function () { var g = new Graph(); - assert.deepEqual(g.vertices, []); + assert.equal(g.vertices.size, 0); g.addVertex('a'); g.addVertex('b'); g.addVertex('c'); - assert.deepEqual(g.vertices, ['a', 'b', 'c']); + assert.equal(g.vertices.size, 3); + assert(g.vertices.contains('a')); + assert(g.vertices.contains('b')); + assert(g.vertices.contains('c')); + }); + + it('should not allow repeated vertices', function () { + var g = new Graph(); + g.addVertex('a'); + assert.throws(function () { + g.addVertex('a'); + }); }); it('should return a list of neighbors of a vertex', function () { diff --git a/test/data_structures/hash_table.js b/src/test/data_structures/hash_table.js similarity index 98% rename from test/data_structures/hash_table.js rename to src/test/data_structures/hash_table.js index 91d9bdf..c9a8370 100644 --- a/test/data_structures/hash_table.js +++ b/src/test/data_structures/hash_table.js @@ -1,6 +1,6 @@ 'use strict'; -var HashTable = require('../../data_structures/hash_table'), +var HashTable = require('../..').DataStructure.HashTable, assert = require('assert'); describe('Hash Table', function () { diff --git a/test/data_structures/heap.js b/src/test/data_structures/heap.js similarity index 98% rename from test/data_structures/heap.js rename to src/test/data_structures/heap.js index fbeb175..1bf4585 100644 --- a/test/data_structures/heap.js +++ b/src/test/data_structures/heap.js @@ -1,6 +1,6 @@ 'use strict'; -var heap = require('../../data_structures/heap'), +var heap = require('../..').DataStructure.Heap, assert = require('assert'); describe('Min Heap', function () { diff --git a/test/data_structures/linked_list.js b/src/test/data_structures/linked_list.js similarity index 98% rename from test/data_structures/linked_list.js rename to src/test/data_structures/linked_list.js index 9e02c44..66636da 100644 --- a/test/data_structures/linked_list.js +++ b/src/test/data_structures/linked_list.js @@ -1,6 +1,6 @@ 'use strict'; -var LinkedList = require('../../data_structures/linked_list'), +var LinkedList = require('../..').DataStructure.LinkedList, assert = require('assert'); describe('LinkedList', function () { diff --git a/test/data_structures/priority_queue.js b/src/test/data_structures/priority_queue.js similarity index 97% rename from test/data_structures/priority_queue.js rename to src/test/data_structures/priority_queue.js index b01a2c2..e2b5f06 100644 --- a/test/data_structures/priority_queue.js +++ b/src/test/data_structures/priority_queue.js @@ -1,6 +1,6 @@ 'use strict'; -var PriorityQueue = require('../../data_structures/priority_queue'), +var PriorityQueue = require('../..').DataStructure.PriorityQueue, assert = require('assert'); describe('Min Priority Queue', function () { diff --git a/test/data_structures/queue.js b/src/test/data_structures/queue.js similarity index 95% rename from test/data_structures/queue.js rename to src/test/data_structures/queue.js index 82ecd8a..8ede8f9 100644 --- a/test/data_structures/queue.js +++ b/src/test/data_structures/queue.js @@ -1,6 +1,6 @@ 'use strict'; -var Queue = require('../../data_structures/queue'), +var Queue = require('../..').DataStructure.Queue, assert = require('assert'); describe('Queue', function () { diff --git a/test/data_structures/set.js b/src/test/data_structures/set.js similarity index 96% rename from test/data_structures/set.js rename to src/test/data_structures/set.js index aa8f918..c31b2cd 100644 --- a/test/data_structures/set.js +++ b/src/test/data_structures/set.js @@ -1,6 +1,6 @@ 'use strict'; -var HashSet = require('../../data_structures/set'), +var HashSet = require('../..').DataStructure.Set, assert = require('assert'); describe('HashSet', function () { diff --git a/test/data_structures/stack.js b/src/test/data_structures/stack.js similarity index 94% rename from test/data_structures/stack.js rename to src/test/data_structures/stack.js index edfdc47..6790745 100644 --- a/test/data_structures/stack.js +++ b/src/test/data_structures/stack.js @@ -1,6 +1,6 @@ 'use strict'; -var Stack = require('../../data_structures/stack'), +var Stack = require('../..').DataStructure.Stack, assert = require('assert'); describe('Stack', function () { diff --git a/test/util/comparator.js b/src/test/util/comparator.js similarity index 100% rename from test/util/comparator.js rename to src/test/util/comparator.js diff --git a/util/comparator.js b/src/util/comparator.js similarity index 100% rename from util/comparator.js rename to src/util/comparator.js diff --git a/test/algorithms/graph/minimum_spanning_tree.js b/test/algorithms/graph/minimum_spanning_tree.js deleted file mode 100644 index 4903fef..0000000 --- a/test/algorithms/graph/minimum_spanning_tree.js +++ /dev/null @@ -1,184 +0,0 @@ -'use strict'; - -var kruskal = require('../../../algorithms/graph/kruskal'), - prim = require('../../../algorithms/graph/prim'), - Graph = require('../../../data_structures/graph'), - depthFirstSearch = require('../../../algorithms/graph/depth_first_search'), - assert = require('assert'); - - -/** - * @param {Graph} graph - Undirected graph. - * @return {number} - */ -var numberOfConnectedComponents = function (graph) { - assert(!graph.directed); - var seen = {}; - var coverComponent = function (origin) { - depthFirstSearch(graph, origin, { - enterVertex: function (vertex) { - seen[vertex] = true; - } - }); - }; - return graph.vertices.reduce(function (count, vertex) { - if (seen[vertex]) { - return count; - } - else { - coverComponent(vertex); - return count + 1; - } - }, 0); -}; - - -/** - * Test whether graph is a valid (undirected) forest. - * In a forest #vertices = #edges + #components. - * - * @param {Graph} graph - * @param {number} connectivity - * @return {boolean} - */ -var isForest = function (graph, connectivity) { - if (graph.directed || numberOfConnectedComponents(graph) != connectivity) { - return false; - } - var numberOfEdges = graph.vertices.reduce(function (numberOfEdges, vertex) { - return numberOfEdges + graph.neighbors(vertex).filter(function (neighbor) { - return vertex <= neighbor; - }).length; - }, 0); - return graph.vertices.length == numberOfEdges + connectivity; -}; - - -/** - * Test whether two graphs share the same vertex set. - * - * @param {Graph} graph1 - * @param {Graph} graph2 - * @return {boolean} - */ -var spans = function (graph1, graph2) { - var str = function (graph) { - return JSON.stringify(graph.vertices.sort()); - }; - return str(graph1) == str(graph2); -}; - - -/** - * Sum up graph edge weights. - * - * @param {Graph} graph - * @return {?number} Null if the graph contains no edges. - */ -var graphCost = function (graph) { - var noEdges = true; - var total = graph.vertices.reduce(function (cost, vertex) { - return cost + graph.neighbors(vertex).reduce(function (cost, neighbor) { - noEdges = false; - return cost + graph.edge(vertex, neighbor); - }, 0); - }, 0); - return noEdges ? null : graph.directed ? total : total / 2; -}; - - -/** - * Test whether one graph is the minimum spanning forest of the other. - * - * @param {Graph} suspect - * @param {Graph} graph - Undirected graph. - * @param {?number} minimumCost - * @param {number} [connectivity=1] - * @return {boolean} - */ -var isMinimumSpanningForest = function (suspect, graph, - minimumCost, connectivity) { - assert(!graph.directed); - return isForest(suspect, connectivity || 1) && - spans(suspect, graph) && - graphCost(suspect) === minimumCost; -}; - - -var testMstAlgorithm = function (mst) { - it('should find a minimum spanning tree', function () { - var graph = new Graph(false); - graph.addEdge(1, 2, 1); - graph.addEdge(1, 4, 2); - graph.addEdge(1, 5, 2); - graph.addEdge(4, 2, 2); - graph.addEdge(4, 5, 1); - graph.addEdge(5, 6, 1); - graph.addEdge(6, 4, 8); - graph.addEdge(6, 3, 2); - graph.addEdge(2, 3, 3); - assert(isMinimumSpanningForest(mst(graph), graph, 7)); - - // Change (4, 5) weight to 3. - graph.addEdge(4, 5, +2); - assert(isMinimumSpanningForest(mst(graph), graph, 8)); - - // Force it go find another way to reach (6). - graph.addEdge(4, 5, +5); - graph.addEdge(6, 5, +7); - assert(isMinimumSpanningForest(mst(graph), graph, 10)); - - // It should find zero-cost MST. - var clear = function (a, b) { - graph.addEdge(a, b, -graph.edge(a, b)); - }; - clear(2, 1); - clear(1, 5); - clear(5, 6); - clear(6, 4); - clear(6, 3); - assert(isMinimumSpanningForest(mst(graph), graph, 0)); - - // But prefer a negative-cost one to it. - graph.addEdge(2, 4, -102); - assert(isMinimumSpanningForest(mst(graph), graph, -100)); - }); - - it('should find a minimum spaning forest if the graph is not connected', - function () { - var graph = new Graph(false); - graph.addVertex(1); - graph.addVertex(2); - graph.addVertex(3); - assert(isMinimumSpanningForest(mst(graph), graph, null, 3)); - - graph.addEdge(1, 2, 2); - assert(isMinimumSpanningForest(mst(graph), graph, 2, 2)); - - graph.addEdge(1, 3, 1); - graph.addEdge(2, 3, -1); - assert(isMinimumSpanningForest(mst(graph), graph, 0, 1)); - - graph.addVertex(4); - assert(isMinimumSpanningForest(mst(graph), graph, 0, 2)); - - graph.addEdge(5, 6, 1); - assert(isMinimumSpanningForest(mst(graph), graph, 1, 3)); - - graph.addEdge(5, 4, -100); - graph.addEdge(6, 4, -100); - assert(isMinimumSpanningForest(mst(graph), graph, -200, 2)); - }); - - it('should throw an error if the graph is directed', function () { - var directedGraph = new Graph(true); - directedGraph.addEdge('Rock', 'Hard Place'); - assert.throws(mst.bind(null, directedGraph)); - }); -}; - - -describe('Minimum Spanning Tree', function () { - describe('#Kruskal\'s Algorithm', testMstAlgorithm.bind(null, kruskal)); - describe('#Prim\'s Algorithm', testMstAlgorithm.bind(null, prim)); -}); diff --git a/test/algorithms/string/longest_common_subseqence.js b/test/algorithms/string/longest_common_subseqence.js deleted file mode 100644 index 07824c8..0000000 --- a/test/algorithms/string/longest_common_subseqence.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -var directory = '../../../algorithms/string/'; -var filename = 'longest_common_subsequence'; -var longestCommonSubsequence = require([directory, filename].join('')), - assert = require('assert'); - -describe('Longest common subsequence', function () { - it('should return the proper longest common subsequence', function () { - assert.equal('', longestCommonSubsequence('', '')); - assert.equal('', longestCommonSubsequence('', 'aaa')); - assert.equal('', longestCommonSubsequence('aaa', '')); - assert.equal('aaa', longestCommonSubsequence('aaa', 'aaa')); - assert.equal('mjau', longestCommonSubsequence('xmjyauz', 'mzjawxu')); - assert.equal('hman', longestCommonSubsequence('human', 'chimpanzee')); - }); -}); From 625789698fd28c36f94d81a52111bda7c1f7f42f Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sun, 12 Oct 2014 00:34:28 +0200 Subject: [PATCH 144/280] Bump version --- build/algorithms.browser.min.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/algorithms.browser.min.js b/build/algorithms.browser.min.js index ee02aaa..9ff8036 100644 --- a/build/algorithms.browser.min.js +++ b/build/algorithms.browser.min.js @@ -1,2 +1,2 @@ -/* algorithms.js v0.6.1 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ +/* algorithms.js v0.7.0 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ !function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":52}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":45,"../../data_structures/graph":46}],11:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],15:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":14}],16:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],17:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],20:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":56}],21:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],23:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":52}],24:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":56}],28:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],29:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":48}],30:[function(t,r){"use strict";r.exports={bubbleSort:t("./bubble_sort"),countingSort:t("./counting_sort"),heapSort:t("./heap_sort"),mergeSort:t("./merge_sort"),quicksort:t("./quicksort"),selectionSort:t("./selection_sort"),radixSort:t("./radix_sort"),insertionSort:t("./insertion_sort"),shellSort:t("./shell_sort")}},{"./bubble_sort":27,"./counting_sort":28,"./heap_sort":29,"./insertion_sort":31,"./merge_sort":32,"./quicksort":33,"./radix_sort":34,"./selection_sort":35,"./shell_sort":36}],31:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":56}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":56}],34:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],35:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":56}],36:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":56}],37:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var v={count:l.count+p.count,parts:[l,p]};a.push(v)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var g=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return g[t]}).join("");return{encoding:g,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],39:[function(t,r){"use strict";r.exports={levenshtein:t("./levenshtein"),rabinKarp:t("./rabin_karp"),knuthMorrisPratt:t("./knuth_morris_pratt"),huffman:t("./huffman"),hamming:t("./hamming"),longestCommonSubsequence:t("./longest_common_subsequence")}},{"./hamming":37,"./huffman":38,"./knuth_morris_pratt":40,"./levenshtein":41,"./longest_common_subsequence":42,"./rabin_karp":43}],40:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],41:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],42:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;ei[e][n-1]?e--:n--;return s.split("").reverse().join("")};r.exports=e},{}],43:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":56}],49:[function(t,r){"use strict";r.exports={BST:t("./bst"),Graph:t("./graph"),HashTable:t("./hash_table"),Heap:t("./heap"),LinkedList:t("./linked_list"),PriorityQueue:t("./priority_queue"),Queue:t("./queue"),Stack:t("./stack"),Set:t("./set"),DisjointSetForest:t("./disjoint_set_forest")}},{"./bst":44,"./disjoint_set_forest":45,"./graph":46,"./hash_table":47,"./heap":48,"./linked_list":50,"./priority_queue":51,"./queue":52,"./set":53,"./stack":54}],50:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],51:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[55])(55)})}({},function(){return this}()); \ No newline at end of file diff --git a/package.json b/package.json index 80e1131..059a156 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.6.1", + "version": "0.7.0", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" From 97a3ec3d7ad19722da53e22ed382b82aa7c271fd Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sun, 12 Oct 2014 00:40:29 +0200 Subject: [PATCH 145/280] Changelog and Readme updates --- CHANGELOG | 4 ++++ README.md | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index e713e1f..215184d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ CHANGELOG ========= +0.7.0 (2014-10-12) +* Module Sort is now "Sorting" +* And some backward compatible refactoring + 0.6.0 (2014-08-15) * Browser bundle * Data Structures diff --git a/README.md b/README.md index 3072499..ac8cd89 100644 --- a/README.md +++ b/README.md @@ -10,5 +10,11 @@ Classic algorithms and data structures implemented in JavaScript, you know... FOR SCIENCE. +### Installing +``` +npm install --save algorithms +``` + ### [Documentation](https://github.com/felipernb/algorithms.js/wiki) + From 63605df77a8a5f38fbb99df73961d038e615cef4 Mon Sep 17 00:00:00 2001 From: Liam Griffiths Date: Fri, 17 Oct 2014 00:50:01 -0400 Subject: [PATCH 146/280] Add shannon entropy, test --- algorithms/math/shannon_entropy.js | 27 +++++++++++++++++++++++++ test/algorithms/math/shannon_entropy.js | 13 ++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 algorithms/math/shannon_entropy.js create mode 100644 test/algorithms/math/shannon_entropy.js diff --git a/algorithms/math/shannon_entropy.js b/algorithms/math/shannon_entropy.js new file mode 100644 index 0000000..0039731 --- /dev/null +++ b/algorithms/math/shannon_entropy.js @@ -0,0 +1,27 @@ +'use strict'; + +/** + * Calculate Shannon Entropy of an array + * + * @param {Array} arr - An array of values. + * @return Number + */ +var shannonEntropy = function (arr) { + // find the frequency of each value + var freqs = arr.reduce(function (acc, item) { + acc[item] = acc[item] + 1 || 1; + return acc; + }, {}); + + // find the probability of each value + var probs = Object.keys(freqs).map(function (key) { + return freqs[key] / arr.length; + }); + + // calulate the shannon entropy of the array + return probs.reduce(function (e, p) { + return e - p * Math.log(p) + }, 0) * Math.LOG2E; +}; + +module.exports = shannonEntropy; diff --git a/test/algorithms/math/shannon_entropy.js b/test/algorithms/math/shannon_entropy.js new file mode 100644 index 0000000..b6411cc --- /dev/null +++ b/test/algorithms/math/shannon_entropy.js @@ -0,0 +1,13 @@ +'use strict'; + +var shannonEntropy = require('../../../algorithms/math/shannon_entropy'); +var assert = require('assert'); + +describe('Shannon Entropy', function () { + it('calculates shannon entropy', function () { + assert.equal(shannonEntropy([]), 0); + assert.equal(shannonEntropy([1]), 0); + assert.equal(shannonEntropy([1, 0]), 1); + assert.equal(shannonEntropy(['a', 'b', 'c', 'd']), 2); + }); +}); From 562bf070f9452be19dbaefb588875ddd4691914e Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sat, 18 Oct 2014 12:55:26 +0200 Subject: [PATCH 147/280] Move Shannon entropy to new path --- {algorithms => src/algorithms}/math/shannon_entropy.js | 0 {test => src/test}/algorithms/math/shannon_entropy.js | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {algorithms => src/algorithms}/math/shannon_entropy.js (100%) rename {test => src/test}/algorithms/math/shannon_entropy.js (100%) diff --git a/algorithms/math/shannon_entropy.js b/src/algorithms/math/shannon_entropy.js similarity index 100% rename from algorithms/math/shannon_entropy.js rename to src/algorithms/math/shannon_entropy.js diff --git a/test/algorithms/math/shannon_entropy.js b/src/test/algorithms/math/shannon_entropy.js similarity index 100% rename from test/algorithms/math/shannon_entropy.js rename to src/test/algorithms/math/shannon_entropy.js From 2fbd76196abe92bac564c8ea19bc2d6f4a610c67 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sat, 18 Oct 2014 13:00:17 +0200 Subject: [PATCH 148/280] Add shannonEntropy to Math namespace --- src/algorithms/math/index.js | 3 ++- src/test/algorithms/math/shannon_entropy.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/algorithms/math/index.js b/src/algorithms/math/index.js index b2829b4..db0269a 100644 --- a/src/algorithms/math/index.js +++ b/src/algorithms/math/index.js @@ -10,5 +10,6 @@ module.exports = { reservoirSampling: require('./reservoir_sampling'), fastPower: require('./fast_power'), nextPermutation: require('./next_permutation'), - powerSet: require('./power_set') + powerSet: require('./power_set'), + shannonEntropy: require('./shannon_entropy') }; diff --git a/src/test/algorithms/math/shannon_entropy.js b/src/test/algorithms/math/shannon_entropy.js index b6411cc..8dcb56b 100644 --- a/src/test/algorithms/math/shannon_entropy.js +++ b/src/test/algorithms/math/shannon_entropy.js @@ -1,6 +1,6 @@ 'use strict'; -var shannonEntropy = require('../../../algorithms/math/shannon_entropy'); +var shannonEntropy = require('../../../').Math.shannonEntropy; var assert = require('assert'); describe('Shannon Entropy', function () { From 9b1c0d8e7e9bc1d481fbc4a8564af40e09a96c2f Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sat, 18 Oct 2014 13:09:21 +0200 Subject: [PATCH 149/280] Fix linting errors in shannon entropy --- Makefile | 2 +- src/algorithms/math/shannon_entropy.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index cfc6f5c..c7b7d6b 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ setup: jshint: setup jshint src -test: setup +test: jshint mocha -R spec --recursive src/test coverage: setup diff --git a/src/algorithms/math/shannon_entropy.js b/src/algorithms/math/shannon_entropy.js index 0039731..5c42c30 100644 --- a/src/algorithms/math/shannon_entropy.js +++ b/src/algorithms/math/shannon_entropy.js @@ -4,7 +4,7 @@ * Calculate Shannon Entropy of an array * * @param {Array} arr - An array of values. - * @return Number + * @return Number */ var shannonEntropy = function (arr) { // find the frequency of each value @@ -14,13 +14,13 @@ var shannonEntropy = function (arr) { }, {}); // find the probability of each value - var probs = Object.keys(freqs).map(function (key) { - return freqs[key] / arr.length; + var probs = Object.keys(freqs).map(function (key) { + return freqs[key] / arr.length; }); // calulate the shannon entropy of the array return probs.reduce(function (e, p) { - return e - p * Math.log(p) + return e - p * Math.log(p); }, 0) * Math.LOG2E; }; From 4fc2fb4dc2d7f77b349d716ce48487abef73a1d6 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sat, 18 Oct 2014 13:03:56 +0200 Subject: [PATCH 150/280] 0.7.1 --- CHANGELOG | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 215184d..8ee26eb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ CHANGELOG ========= +0.7.1 (2014-10-18) +* Added Shannon Entropy to Math namespace + 0.7.0 (2014-10-12) * Module Sort is now "Sorting" * And some backward compatible refactoring diff --git a/package.json b/package.json index 059a156..ea35ea2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.7.0", + "version": "0.7.1", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" From 64ace307dd9784afd12fee13c695050441070540 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sat, 18 Oct 2014 13:25:41 +0200 Subject: [PATCH 151/280] Add browser_bundle to the make all task --- Makefile | 2 +- build/algorithms.browser.min.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index c7b7d6b..414e6bd 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -all: jshint coverage +all: jshint browser_bundle coverage setup: npm install diff --git a/build/algorithms.browser.min.js b/build/algorithms.browser.min.js index 9ff8036..efc2fbf 100644 --- a/build/algorithms.browser.min.js +++ b/build/algorithms.browser.min.js @@ -1,2 +1,2 @@ -/* algorithms.js v0.7.0 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ -!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":52}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":45,"../../data_structures/graph":46}],11:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],15:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":14}],16:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],17:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],20:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":56}],21:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],23:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":52}],24:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":56}],28:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],29:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":48}],30:[function(t,r){"use strict";r.exports={bubbleSort:t("./bubble_sort"),countingSort:t("./counting_sort"),heapSort:t("./heap_sort"),mergeSort:t("./merge_sort"),quicksort:t("./quicksort"),selectionSort:t("./selection_sort"),radixSort:t("./radix_sort"),insertionSort:t("./insertion_sort"),shellSort:t("./shell_sort")}},{"./bubble_sort":27,"./counting_sort":28,"./heap_sort":29,"./insertion_sort":31,"./merge_sort":32,"./quicksort":33,"./radix_sort":34,"./selection_sort":35,"./shell_sort":36}],31:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":56}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":56}],34:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],35:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":56}],36:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":56}],37:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var v={count:l.count+p.count,parts:[l,p]};a.push(v)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var g=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return g[t]}).join("");return{encoding:g,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],39:[function(t,r){"use strict";r.exports={levenshtein:t("./levenshtein"),rabinKarp:t("./rabin_karp"),knuthMorrisPratt:t("./knuth_morris_pratt"),huffman:t("./huffman"),hamming:t("./hamming"),longestCommonSubsequence:t("./longest_common_subsequence")}},{"./hamming":37,"./huffman":38,"./knuth_morris_pratt":40,"./levenshtein":41,"./longest_common_subsequence":42,"./rabin_karp":43}],40:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],41:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],42:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;ei[e][n-1]?e--:n--;return s.split("").reverse().join("")};r.exports=e},{}],43:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":56}],49:[function(t,r){"use strict";r.exports={BST:t("./bst"),Graph:t("./graph"),HashTable:t("./hash_table"),Heap:t("./heap"),LinkedList:t("./linked_list"),PriorityQueue:t("./priority_queue"),Queue:t("./queue"),Stack:t("./stack"),Set:t("./set"),DisjointSetForest:t("./disjoint_set_forest")}},{"./bst":44,"./disjoint_set_forest":45,"./graph":46,"./hash_table":47,"./heap":48,"./linked_list":50,"./priority_queue":51,"./queue":52,"./set":53,"./stack":54}],50:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],51:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[55])(55)})}({},function(){return this}()); \ No newline at end of file +/* algorithms.js v0.7.1 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ +!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":53}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":46,"../../data_structures/graph":47}],11:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],15:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":14}],16:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],17:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],20:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":57}],21:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],23:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],24:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":53}],25:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":57}],29:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],30:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":49}],31:[function(t,r){"use strict";r.exports={bubbleSort:t("./bubble_sort"),countingSort:t("./counting_sort"),heapSort:t("./heap_sort"),mergeSort:t("./merge_sort"),quicksort:t("./quicksort"),selectionSort:t("./selection_sort"),radixSort:t("./radix_sort"),insertionSort:t("./insertion_sort"),shellSort:t("./shell_sort")}},{"./bubble_sort":28,"./counting_sort":29,"./heap_sort":30,"./insertion_sort":32,"./merge_sort":33,"./quicksort":34,"./radix_sort":35,"./selection_sort":36,"./shell_sort":37}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":57}],33:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":57}],35:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],36:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":57}],37:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":57}],38:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var v={count:l.count+p.count,parts:[l,p]};a.push(v)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var g=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return g[t]}).join("");return{encoding:g,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],40:[function(t,r){"use strict";r.exports={levenshtein:t("./levenshtein"),rabinKarp:t("./rabin_karp"),knuthMorrisPratt:t("./knuth_morris_pratt"),huffman:t("./huffman"),hamming:t("./hamming"),longestCommonSubsequence:t("./longest_common_subsequence")}},{"./hamming":38,"./huffman":39,"./knuth_morris_pratt":41,"./levenshtein":42,"./longest_common_subsequence":43,"./rabin_karp":44}],41:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],42:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],43:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;ei[e][n-1]?e--:n--;return s.split("").reverse().join("")};r.exports=e},{}],44:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":57}],50:[function(t,r){"use strict";r.exports={BST:t("./bst"),Graph:t("./graph"),HashTable:t("./hash_table"),Heap:t("./heap"),LinkedList:t("./linked_list"),PriorityQueue:t("./priority_queue"),Queue:t("./queue"),Stack:t("./stack"),Set:t("./set"),DisjointSetForest:t("./disjoint_set_forest")}},{"./bst":45,"./disjoint_set_forest":46,"./graph":47,"./hash_table":48,"./heap":49,"./linked_list":51,"./priority_queue":52,"./queue":53,"./set":54,"./stack":55}],51:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],52:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[56])(56)})}({},function(){return this}()); \ No newline at end of file From 99c0ff378b2a11045b5640b658a2f8d80c3a90f0 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sat, 18 Oct 2014 13:48:33 +0200 Subject: [PATCH 152/280] Remove browser_bundle from 'make all' --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 414e6bd..c7b7d6b 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -all: jshint browser_bundle coverage +all: jshint coverage setup: npm install From 22def453cf3841dc5b232e37a0c496610cfcdfe8 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 29 Oct 2014 14:48:48 +0100 Subject: [PATCH 153/280] Move location of browser bundle --- {build => bundle}/algorithms.browser.min.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {build => bundle}/algorithms.browser.min.js (100%) diff --git a/build/algorithms.browser.min.js b/bundle/algorithms.browser.min.js similarity index 100% rename from build/algorithms.browser.min.js rename to bundle/algorithms.browser.min.js From 1d4ff2d2b8df869dc828bf323d1971b3a6208e7d Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 29 Oct 2014 14:49:44 +0100 Subject: [PATCH 154/280] Build step to create a cleaner package to be imported --- .gitignore | 1 + Makefile | 13 +++++++++++++ package.json | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ba2a97b..ccc2d8b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules coverage +_build diff --git a/Makefile b/Makefile index c7b7d6b..9a8aa9c 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,19 @@ all: jshint coverage setup: npm install +dist: all + rm -rf _build + mkdir _build + cp -r src/* _build + cp package.json _build + cp LICENSE _build + cp AUTHORS _build + cp README.md _build + cp CHANGELOG _build + +release: dist + cd _build; npm publish + jshint: setup jshint src diff --git a/package.json b/package.json index ea35ea2..3c65550 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "directories": { "test": "test" }, - "main": "src/index.js", + "main": "./index.js", "dependencies": {}, "devDependencies": { "coveralls": "^2.10.0", From 8630855d1f9d911b5af3b3fdb38826b06a19d29b Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 29 Oct 2014 14:51:28 +0100 Subject: [PATCH 155/280] Cleaner dist package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3c65550..f0449ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.7.1", + "version": "0.7.2", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" From 53e78ef3060a2cf5ef7c350d83609208d16ee0a9 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 29 Oct 2014 14:54:23 +0100 Subject: [PATCH 156/280] Fix browser bundle --- Makefile | 2 +- bundle/algorithms.browser.min.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 9a8aa9c..76283f3 100644 --- a/Makefile +++ b/Makefile @@ -30,5 +30,5 @@ coveralls: VERSION := $(shell node -e "console.log(require('./package.json').version);") browser_bundle: setup - browserify $(realpath src/index.js) --s algorithms | uglifyjs -c -m --screw-ie8 --wrap --preamble "/* algorithms.js v$(VERSION) | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */" > build/algorithms.browser.min.js + browserify $(realpath src/index.js) --s algorithms | uglifyjs -c -m --screw-ie8 --wrap --preamble "/* algorithms.js v$(VERSION) | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */" > bundle/algorithms.browser.min.js diff --git a/bundle/algorithms.browser.min.js b/bundle/algorithms.browser.min.js index efc2fbf..ee3f20e 100644 --- a/bundle/algorithms.browser.min.js +++ b/bundle/algorithms.browser.min.js @@ -1,2 +1,2 @@ -/* algorithms.js v0.7.1 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ +/* algorithms.js v0.7.2 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ !function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":53}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":46,"../../data_structures/graph":47}],11:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],15:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":14}],16:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],17:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],20:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":57}],21:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],23:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],24:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":53}],25:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":57}],29:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],30:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":49}],31:[function(t,r){"use strict";r.exports={bubbleSort:t("./bubble_sort"),countingSort:t("./counting_sort"),heapSort:t("./heap_sort"),mergeSort:t("./merge_sort"),quicksort:t("./quicksort"),selectionSort:t("./selection_sort"),radixSort:t("./radix_sort"),insertionSort:t("./insertion_sort"),shellSort:t("./shell_sort")}},{"./bubble_sort":28,"./counting_sort":29,"./heap_sort":30,"./insertion_sort":32,"./merge_sort":33,"./quicksort":34,"./radix_sort":35,"./selection_sort":36,"./shell_sort":37}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":57}],33:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":57}],35:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],36:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":57}],37:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":57}],38:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var v={count:l.count+p.count,parts:[l,p]};a.push(v)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var g=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return g[t]}).join("");return{encoding:g,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],40:[function(t,r){"use strict";r.exports={levenshtein:t("./levenshtein"),rabinKarp:t("./rabin_karp"),knuthMorrisPratt:t("./knuth_morris_pratt"),huffman:t("./huffman"),hamming:t("./hamming"),longestCommonSubsequence:t("./longest_common_subsequence")}},{"./hamming":38,"./huffman":39,"./knuth_morris_pratt":41,"./levenshtein":42,"./longest_common_subsequence":43,"./rabin_karp":44}],41:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],42:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],43:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;ei[e][n-1]?e--:n--;return s.split("").reverse().join("")};r.exports=e},{}],44:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":57}],50:[function(t,r){"use strict";r.exports={BST:t("./bst"),Graph:t("./graph"),HashTable:t("./hash_table"),Heap:t("./heap"),LinkedList:t("./linked_list"),PriorityQueue:t("./priority_queue"),Queue:t("./queue"),Stack:t("./stack"),Set:t("./set"),DisjointSetForest:t("./disjoint_set_forest")}},{"./bst":45,"./disjoint_set_forest":46,"./graph":47,"./hash_table":48,"./heap":49,"./linked_list":51,"./priority_queue":52,"./queue":53,"./set":54,"./stack":55}],51:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],52:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[56])(56)})}({},function(){return this}()); \ No newline at end of file From 3cb9dcc03e539313bd2b3f6a4f4356a55657dbf7 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 29 Oct 2014 15:13:43 +0100 Subject: [PATCH 157/280] Modularize --- CHANGELOG | 4 ++++ src/algorithms/graph/index.js | 16 ---------------- src/algorithms/math/index.js | 15 --------------- src/algorithms/searching/index.js | 8 -------- src/algorithms/sorting/index.js | 14 -------------- src/algorithms/string/index.js | 12 ------------ src/data_structures.js | 15 +++++++++++++++ src/data_structures/index.js | 15 --------------- src/graph.js | 16 ++++++++++++++++ src/index.js | 10 +++++----- src/math.js | 15 +++++++++++++++ src/searching.js | 8 ++++++++ src/sorting.js | 14 ++++++++++++++ src/string.js | 12 ++++++++++++ 14 files changed, 89 insertions(+), 85 deletions(-) delete mode 100644 src/algorithms/graph/index.js delete mode 100644 src/algorithms/math/index.js delete mode 100644 src/algorithms/searching/index.js delete mode 100644 src/algorithms/sorting/index.js delete mode 100644 src/algorithms/string/index.js create mode 100644 src/data_structures.js delete mode 100644 src/data_structures/index.js create mode 100644 src/graph.js create mode 100644 src/math.js create mode 100644 src/searching.js create mode 100644 src/sorting.js create mode 100644 src/string.js diff --git a/CHANGELOG b/CHANGELOG index 8ee26eb..0c0ac70 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ CHANGELOG ========= +0.7.2 (2014-10-29) +* Modular package, lets you require just specific modules, i.e +require('algorithms/data_structures'), or require('algorithms/sorting') + 0.7.1 (2014-10-18) * Added Shannon Entropy to Math namespace diff --git a/src/algorithms/graph/index.js b/src/algorithms/graph/index.js deleted file mode 100644 index 4b338e4..0000000 --- a/src/algorithms/graph/index.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -// Graph algorithms -module.exports = { - topologicalSort: require('./topological_sort'), - dijkstra: require('./dijkstra'), - SPFA: require('./SPFA'), - bellmanFord: require('./bellman_ford'), - eulerPath: require('./euler_path'), - depthFirstSearch: require('./depth_first_search'), - kruskal: require('./kruskal'), - breadthFirstSearch: require('./breadth_first_search'), - bfsShortestPath: require('./bfs_shortest_path'), - prim: require('./prim'), - floydWarshall: require('./floyd_warshall') -}; diff --git a/src/algorithms/math/index.js b/src/algorithms/math/index.js deleted file mode 100644 index db0269a..0000000 --- a/src/algorithms/math/index.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -// Math algorithms -module.exports = { - fibonacci: require('./fibonacci'), - fisherYates: require('./fisher_yates'), - gcd: require('./gcd'), - extendedEuclidean: require('./extended_euclidean'), - newtonSqrt: require('./newton_sqrt'), - reservoirSampling: require('./reservoir_sampling'), - fastPower: require('./fast_power'), - nextPermutation: require('./next_permutation'), - powerSet: require('./power_set'), - shannonEntropy: require('./shannon_entropy') -}; diff --git a/src/algorithms/searching/index.js b/src/algorithms/searching/index.js deleted file mode 100644 index 311c6e2..0000000 --- a/src/algorithms/searching/index.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; - -// Search algorithms -module.exports = { - bfs: require('./bfs'), - binarySearch: require('./binarysearch'), - dfs: require('./dfs') -}; diff --git a/src/algorithms/sorting/index.js b/src/algorithms/sorting/index.js deleted file mode 100644 index f77b6c6..0000000 --- a/src/algorithms/sorting/index.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -// Sorting algorithms -module.exports = { - bubbleSort: require('./bubble_sort'), - countingSort: require('./counting_sort'), - heapSort: require('./heap_sort'), - mergeSort: require('./merge_sort'), - quicksort: require('./quicksort'), - selectionSort: require('./selection_sort'), - radixSort: require('./radix_sort'), - insertionSort: require('./insertion_sort'), - shellSort: require('./shell_sort') -}; diff --git a/src/algorithms/string/index.js b/src/algorithms/string/index.js deleted file mode 100644 index 3fd19e5..0000000 --- a/src/algorithms/string/index.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -// String algorithms -module.exports = { - levenshtein: require('./levenshtein'), - rabinKarp: require('./rabin_karp'), - knuthMorrisPratt: require('./knuth_morris_pratt'), - huffman: require('./huffman'), - hamming: require('./hamming'), - longestCommonSubsequence: require( - './longest_common_subsequence') -}; diff --git a/src/data_structures.js b/src/data_structures.js new file mode 100644 index 0000000..005ac04 --- /dev/null +++ b/src/data_structures.js @@ -0,0 +1,15 @@ +'use strict'; + +// Data Structures +module.exports = { + BST: require('./data_structures/bst'), + Graph: require('./data_structures/graph'), + HashTable: require('./data_structures/hash_table'), + Heap: require('./data_structures/heap'), + LinkedList: require('./data_structures/linked_list'), + PriorityQueue: require('./data_structures/priority_queue'), + Queue: require('./data_structures/queue'), + Stack: require('./data_structures/stack'), + Set: require('./data_structures/set'), + DisjointSetForest: require('./data_structures/disjoint_set_forest') +}; diff --git a/src/data_structures/index.js b/src/data_structures/index.js deleted file mode 100644 index 4f1765d..0000000 --- a/src/data_structures/index.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -// Data Structures -module.exports = { - BST: require('./bst'), - Graph: require('./graph'), - HashTable: require('./hash_table'), - Heap: require('./heap'), - LinkedList: require('./linked_list'), - PriorityQueue: require('./priority_queue'), - Queue: require('./queue'), - Stack: require('./stack'), - Set: require('./set'), - DisjointSetForest: require('./disjoint_set_forest') -}; diff --git a/src/graph.js b/src/graph.js new file mode 100644 index 0000000..2fbbde5 --- /dev/null +++ b/src/graph.js @@ -0,0 +1,16 @@ +'use strict'; + +// Graph algorithms +module.exports = { + topologicalSort: require('./algorithms/graph/topological_sort'), + dijkstra: require('./algorithms/graph/dijkstra'), + SPFA: require('./algorithms/graph/SPFA'), + bellmanFord: require('./algorithms/graph/bellman_ford'), + eulerPath: require('./algorithms/graph/euler_path'), + depthFirstSearch: require('./algorithms/graph/depth_first_search'), + kruskal: require('./algorithms/graph/kruskal'), + breadthFirstSearch: require('./algorithms/graph/breadth_first_search'), + bfsShortestPath: require('./algorithms/graph/bfs_shortest_path'), + prim: require('./algorithms/graph/prim'), + floydWarshall: require('./algorithms/graph/floyd_warshall') +}; diff --git a/src/index.js b/src/index.js index cf6380e..183cb15 100644 --- a/src/index.js +++ b/src/index.js @@ -2,11 +2,11 @@ var lib = { DataStructure: require('./data_structures'), - Graph: require('./algorithms/graph'), - Math: require('./algorithms/math'), - Search: require('./algorithms/searching'), - Sorting: require('./algorithms/sorting'), - String: require('./algorithms/string') + Graph: require('./graph'), + Math: require('./math'), + Search: require('./searching'), + Sorting: require('./sorting'), + String: require('./string') }; module.exports = lib; diff --git a/src/math.js b/src/math.js new file mode 100644 index 0000000..b439a83 --- /dev/null +++ b/src/math.js @@ -0,0 +1,15 @@ +'use strict'; + +// Math algorithms +module.exports = { + fibonacci: require('./algorithms/math/fibonacci'), + fisherYates: require('./algorithms/math/fisher_yates'), + gcd: require('./algorithms/math/gcd'), + extendedEuclidean: require('./algorithms/math/extended_euclidean'), + newtonSqrt: require('./algorithms/math/newton_sqrt'), + reservoirSampling: require('./algorithms/math/reservoir_sampling'), + fastPower: require('./algorithms/math/fast_power'), + nextPermutation: require('./algorithms/math/next_permutation'), + powerSet: require('./algorithms/math/power_set'), + shannonEntropy: require('./algorithms/math/shannon_entropy') +}; diff --git a/src/searching.js b/src/searching.js new file mode 100644 index 0000000..49a7ff9 --- /dev/null +++ b/src/searching.js @@ -0,0 +1,8 @@ +'use strict'; + +// Search algorithms +module.exports = { + bfs: require('./algorithms/searching/bfs'), + binarySearch: require('./algorithms/searching/binarysearch'), + dfs: require('./algorithms/searching/dfs') +}; diff --git a/src/sorting.js b/src/sorting.js new file mode 100644 index 0000000..6499d73 --- /dev/null +++ b/src/sorting.js @@ -0,0 +1,14 @@ +'use strict'; + +// Sorting algorithms +module.exports = { + bubbleSort: require('./algorithms/sorting/bubble_sort'), + countingSort: require('./algorithms/sorting/counting_sort'), + heapSort: require('./algorithms/sorting/heap_sort'), + mergeSort: require('./algorithms/sorting/merge_sort'), + quicksort: require('./algorithms/sorting/quicksort'), + selectionSort: require('./algorithms/sorting/selection_sort'), + radixSort: require('./algorithms/sorting/radix_sort'), + insertionSort: require('./algorithms/sorting/insertion_sort'), + shellSort: require('./algorithms/sorting/shell_sort') +}; diff --git a/src/string.js b/src/string.js new file mode 100644 index 0000000..58eb41e --- /dev/null +++ b/src/string.js @@ -0,0 +1,12 @@ +'use strict'; + +// String algorithms +module.exports = { + levenshtein: require('./algorithms/string/levenshtein'), + rabinKarp: require('./algorithms/string/rabin_karp'), + knuthMorrisPratt: require('./algorithms/string/knuth_morris_pratt'), + huffman: require('./algorithms/string/huffman'), + hamming: require('./algorithms/string/hamming'), + longestCommonSubsequence: require( + './algorithms/string/longest_common_subsequence') +}; From 16df722acbeb349081b4f5f7dbdf118895f142f5 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 29 Oct 2014 15:15:06 +0100 Subject: [PATCH 158/280] Searching -> Search --- CHANGELOG | 11 ++++++++--- src/algorithms/{searching => search}/bfs.js | 0 src/algorithms/{searching => search}/binarysearch.js | 0 src/algorithms/{searching => search}/dfs.js | 0 src/index.js | 2 +- src/search.js | 8 ++++++++ src/searching.js | 8 -------- 7 files changed, 17 insertions(+), 12 deletions(-) rename src/algorithms/{searching => search}/bfs.js (100%) rename src/algorithms/{searching => search}/binarysearch.js (100%) rename src/algorithms/{searching => search}/dfs.js (100%) create mode 100644 src/search.js delete mode 100644 src/searching.js diff --git a/CHANGELOG b/CHANGELOG index 0c0ac70..e18567a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,8 +1,13 @@ CHANGELOG ========= -0.7.2 (2014-10-29) -* Modular package, lets you require just specific modules, i.e -require('algorithms/data_structures'), or require('algorithms/sorting') +0.8.0 (2014-10-29) +* Modular package, lets you require specific modules: + * require('algorithms/data_structures') + * require('algorithms/sorting') + * require('algorithms/search') + * require('algorithms/graph') + * require('algorithms/math') + * require('algorithms/string') 0.7.1 (2014-10-18) * Added Shannon Entropy to Math namespace diff --git a/src/algorithms/searching/bfs.js b/src/algorithms/search/bfs.js similarity index 100% rename from src/algorithms/searching/bfs.js rename to src/algorithms/search/bfs.js diff --git a/src/algorithms/searching/binarysearch.js b/src/algorithms/search/binarysearch.js similarity index 100% rename from src/algorithms/searching/binarysearch.js rename to src/algorithms/search/binarysearch.js diff --git a/src/algorithms/searching/dfs.js b/src/algorithms/search/dfs.js similarity index 100% rename from src/algorithms/searching/dfs.js rename to src/algorithms/search/dfs.js diff --git a/src/index.js b/src/index.js index 183cb15..d5373b5 100644 --- a/src/index.js +++ b/src/index.js @@ -4,7 +4,7 @@ var lib = { DataStructure: require('./data_structures'), Graph: require('./graph'), Math: require('./math'), - Search: require('./searching'), + Search: require('./search'), Sorting: require('./sorting'), String: require('./string') }; diff --git a/src/search.js b/src/search.js new file mode 100644 index 0000000..b78f914 --- /dev/null +++ b/src/search.js @@ -0,0 +1,8 @@ +'use strict'; + +// Search algorithms +module.exports = { + bfs: require('./algorithms/search/bfs'), + binarySearch: require('./algorithms/search/binarysearch'), + dfs: require('./algorithms/search/dfs') +}; diff --git a/src/searching.js b/src/searching.js deleted file mode 100644 index 49a7ff9..0000000 --- a/src/searching.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; - -// Search algorithms -module.exports = { - bfs: require('./algorithms/searching/bfs'), - binarySearch: require('./algorithms/searching/binarysearch'), - dfs: require('./algorithms/searching/dfs') -}; From 88da827c3564110673a9e0f9ed66f878ba372d26 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 29 Oct 2014 15:17:59 +0100 Subject: [PATCH 159/280] 0.8.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f0449ec..5ce06d3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.7.2", + "version": "0.8.0", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" From d5ffb232e8760bd025c430bc54b9c553d2e31bd1 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 29 Oct 2014 15:18:30 +0100 Subject: [PATCH 160/280] bundle/ Update browser bundle --- bundle/algorithms.browser.min.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bundle/algorithms.browser.min.js b/bundle/algorithms.browser.min.js index ee3f20e..1207571 100644 --- a/bundle/algorithms.browser.min.js +++ b/bundle/algorithms.browser.min.js @@ -1,2 +1,3 @@ -/* algorithms.js v0.7.2 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ -!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":53}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":46,"../../data_structures/graph":47}],11:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],15:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":14}],16:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],17:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],20:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":57}],21:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],23:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],24:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":53}],25:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":57}],29:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],30:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":49}],31:[function(t,r){"use strict";r.exports={bubbleSort:t("./bubble_sort"),countingSort:t("./counting_sort"),heapSort:t("./heap_sort"),mergeSort:t("./merge_sort"),quicksort:t("./quicksort"),selectionSort:t("./selection_sort"),radixSort:t("./radix_sort"),insertionSort:t("./insertion_sort"),shellSort:t("./shell_sort")}},{"./bubble_sort":28,"./counting_sort":29,"./heap_sort":30,"./insertion_sort":32,"./merge_sort":33,"./quicksort":34,"./radix_sort":35,"./selection_sort":36,"./shell_sort":37}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":57}],33:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":57}],35:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],36:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":57}],37:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":57}],38:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var v={count:l.count+p.count,parts:[l,p]};a.push(v)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var g=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return g[t]}).join("");return{encoding:g,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],40:[function(t,r){"use strict";r.exports={levenshtein:t("./levenshtein"),rabinKarp:t("./rabin_karp"),knuthMorrisPratt:t("./knuth_morris_pratt"),huffman:t("./huffman"),hamming:t("./hamming"),longestCommonSubsequence:t("./longest_common_subsequence")}},{"./hamming":38,"./huffman":39,"./knuth_morris_pratt":41,"./levenshtein":42,"./longest_common_subsequence":43,"./rabin_karp":44}],41:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],42:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],43:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;ei[e][n-1]?e--:n--;return s.split("").reverse().join("")};r.exports=e},{}],44:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":57}],50:[function(t,r){"use strict";r.exports={BST:t("./bst"),Graph:t("./graph"),HashTable:t("./hash_table"),Heap:t("./heap"),LinkedList:t("./linked_list"),PriorityQueue:t("./priority_queue"),Queue:t("./queue"),Stack:t("./stack"),Set:t("./set"),DisjointSetForest:t("./disjoint_set_forest")}},{"./bst":45,"./disjoint_set_forest":46,"./graph":47,"./hash_table":48,"./heap":49,"./linked_list":51,"./priority_queue":52,"./queue":53,"./set":54,"./stack":55}],51:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],52:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[56])(56)})}({},function(){return this}()); \ No newline at end of file +/* algorithms.js v0.8.0 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ +!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":48}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":42,"../../data_structures/graph":43}],10:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],18:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":57}],19:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],21:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],22:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":48}],23:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":57}],26:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],27:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":45}],28:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":57}],29:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":57}],31:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":57}],33:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":57}],34:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],36:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],37:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],38:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;ei[e][n-1]?e--:n--;return s.split("").reverse().join("")};r.exports=e},{}],39:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":57}],46:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],47:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r) +},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[52])(52)})}({},function(){return this}()); \ No newline at end of file From bc1f0d663ea17629a35f80d30c540a07aebd017f Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Thu, 30 Oct 2014 11:09:37 +0100 Subject: [PATCH 161/280] List contents in README --- README.md | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ac8cd89..24d9c54 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,119 @@ Classic algorithms and data structures implemented in JavaScript, you know... FO npm install --save algorithms ``` -### [Documentation](https://github.com/felipernb/algorithms.js/wiki) +### Contents + +#### Data Structures + +```javascript +require('algorithms/data_structures'); +// or +require('algorithms').DataStructure; +``` + +* BST +* Graph +* HashTable +* Heap + * MinHeap + * MaxHeap +* LinkedList +* PriorityQueue +* Queue +* Stack +* Set (HashSet) +* DisjointSetForest + +#### Graph algorithms + +```javascript +require('algorithms/graph'); +// or +require('algorithms').Graph; +``` + +* topologicalSort +* eulerPath +* depthFirstSearch +* breadthFirstSearch +* bfsShortestPath + +##### Shortest path +* dijkstra +* SPFA (Shortest Path Faster Algorithm) +* bellmanFord +* floydWarshall + +##### Minimum spanning tree +* prim +* kruskal + +#### Math algorithms + +```javascript +require('algorithms/math'); +// or +require('algorithms').Math; +``` + +* fibonacci +* fisherYates +* gcd (Greatest common divisor) +* extendedEuclidean +* newtonSqrt +* reservoirSampling +* fastPower +* nextPermutation +* powerSet +* shannonEntropy + +#### Search algorithms + +```javascript +require('algorithms/search'); +// or +require('algorithms').Search; +``` + +* bfs (breadth-first search for binary trees) +* binarySearch +* dfs (depth-first search for binary trees) + * inOrder (default) + * preOrder + * postOrder + +#### Sorting algorithms + +```javascript +require('algorithms/sorting'); +// or +require('algorithms').Sorting; +``` + +* bubbleSort +* countingSort +* heapSort +* quicksort +* selectionSort +* radixSort +* insertionSort +* shellSort + +#### String algorithms + +```javascript +require('algorithms/string'); +// or +require('algorithms').String; +``` + +* levenshtein +* rabinKarp +* knuthMorrisPratt +* huffman + * encode + * decode +* hamming +* longestCommonSubsequence From 5f0c23c4aea561ef0d028f7d759b53aee4a8d8a3 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Thu, 30 Oct 2014 11:16:46 +0100 Subject: [PATCH 162/280] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 24d9c54..e868d2a 100644 --- a/README.md +++ b/README.md @@ -50,9 +50,9 @@ require('algorithms').Graph; * eulerPath * depthFirstSearch * breadthFirstSearch -* bfsShortestPath ##### Shortest path +* bfsShortestPath * dijkstra * SPFA (Shortest Path Faster Algorithm) * bellmanFord From 4f33f91a9d5eeb0eaa1b1da38b58fb33242bbb4c Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 14 Nov 2014 13:02:37 +0100 Subject: [PATCH 163/280] Style changes in Longest Common Substring and Longest Common Subsequence --- README.md | 1 + .../string/longest_common_subsequence.js | 30 +++++-------- .../string/longest_common_substring.js | 44 +++++-------------- src/string.js | 4 +- 4 files changed, 25 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index e868d2a..1f6b0f6 100644 --- a/README.md +++ b/README.md @@ -129,5 +129,6 @@ require('algorithms').String; * decode * hamming * longestCommonSubsequence +* longestCommonSubstring diff --git a/src/algorithms/string/longest_common_subsequence.js b/src/algorithms/string/longest_common_subsequence.js index b6992a2..1824fd0 100644 --- a/src/algorithms/string/longest_common_subsequence.js +++ b/src/algorithms/string/longest_common_subsequence.js @@ -11,26 +11,20 @@ */ var longestCommonSubsequence = function (s1, s2) { // Multidimensional array for dynamic programming algorithm - var cache = []; + var cache = new Array(s1.length + 1); var i, j; - // First column and row are initialized with zeroes - for (i = 0; i < s1.length + 1; i++) { - cache[i] = []; - cache[i][0] = 0; - } - for (i = 0; i < s2.length + 1; i++) { - cache[0][i] = 0; + for (i = 0; i <= s1.length; i++) { + cache[i] = new Int32Array(s2.length + 1); } // Fill in the cache - for (i = 1; i < s1.length + 1; i++) { - for (j = 1; j < s2.length + 1; j++) { + for (i = 1; i <= s1.length; i++) { + for (j = 1; j <= s2.length; j++) { if (s1[i - 1] == s2[j - 1]) { cache[i][j] = cache[i - 1][j - 1] + 1; - } - else { + } else { cache[i][j] = Math.max(cache[i][j - 1], cache[i - 1][j]); } } @@ -46,14 +40,10 @@ var longestCommonSubsequence = function (s1, s2) { lcs = s1[i - 1] + lcs; i--; j--; - } - else { - if (cache[i - 1][j] > cache[i][j - 1]) { - i--; - } - else { - j--; - } + } else if (cache[i - 1][j] > cache[i][j - 1]) { + i--; + } else { + j--; } } diff --git a/src/algorithms/string/longest_common_substring.js b/src/algorithms/string/longest_common_substring.js index c973f6b..43c7255 100644 --- a/src/algorithms/string/longest_common_substring.js +++ b/src/algorithms/string/longest_common_substring.js @@ -11,58 +11,36 @@ */ var longestCommonSubstring = function (s1, s2) { // Multidimensional array for dynamic programming algorithm - var cache = []; + var cache = new Array(s1.length + 1); var i, j; - // First column and row are initialized with zeroes - for (i = 0; i < s1.length + 1; i++) { - cache[i] = []; - cache[i][0] = 0; - } - for (i = 0; i < s2.length + 1; i++) { - cache[0][i] = 0; + for (i = 0; i <= s1.length + 1; i++) { + cache[i] = new Int32Array(s2.length + 1); } var lcsPosition = {}; - var commonSubstringFound = false; + var lcsLength = 0; // Fill in the cache - for (i = 1; i < s1.length + 1; i++) { - for (j = 1; j < s2.length + 1; j++) { + for (i = 1; i <= s1.length; i++) { + for (j = 1; j <= s2.length; j++) { if (s1[i - 1] == s2[j - 1]) { cache[i][j] = cache[i - 1][j - 1] + 1; - if (commonSubstringFound) { - if (cache[i][j] > cache[lcsPosition.i][lcsPosition.j]) { - lcsPosition.i = i; - lcsPosition.j = j; - } - } - else { + if (cache[i][j] > lcsLength) { lcsPosition.i = i; lcsPosition.j = j; - commonSubstringFound = true; + lcsLength = cache[i][j]; } - } - else { + } else { cache[i][j] = 0; } } } - if (!commonSubstringFound) { - return ''; - } - - // Build LCS from cache - i = lcsPosition.i; - j = lcsPosition.j; var lcs = ''; - - while (cache[i][j] !== 0) { - lcs = s1[i - 1] + lcs; - i--; - j--; + if (lcsLength) { + lcs = s1.substring(lcsPosition.i - lcsLength, lcsPosition.i); } return lcs; diff --git a/src/string.js b/src/string.js index 58eb41e..2001a23 100644 --- a/src/string.js +++ b/src/string.js @@ -8,5 +8,7 @@ module.exports = { huffman: require('./algorithms/string/huffman'), hamming: require('./algorithms/string/hamming'), longestCommonSubsequence: require( - './algorithms/string/longest_common_subsequence') + './algorithms/string/longest_common_subsequence'), + longestCommonSubstring: require( + './algorithms/string/longest_common_substring') }; From 274de407d339253a5a9b8c58451119e93eb167f1 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 14 Nov 2014 13:05:19 +0100 Subject: [PATCH 164/280] Remove @author comments, since we already have the AUTHORS file --- src/algorithms/math/fibonacci.js | 2 -- src/algorithms/math/power_set.js | 2 -- src/algorithms/string/longest_common_subsequence.js | 2 -- src/algorithms/string/longest_common_substring.js | 2 -- 4 files changed, 8 deletions(-) diff --git a/src/algorithms/math/fibonacci.js b/src/algorithms/math/fibonacci.js index f41f6c7..fe7abf1 100644 --- a/src/algorithms/math/fibonacci.js +++ b/src/algorithms/math/fibonacci.js @@ -60,7 +60,6 @@ var fibWithMemoization = (function () { * Implementation using Binet's formula with the rounding trick. * O(1) in time, O(1) in space * - * @author Eugene Sharygin * @param Number * @return Number */ @@ -73,7 +72,6 @@ var fibDirect = function (number) { * Implementation based on matrix exponentiation. * O(log(n)) in time, O(1) in space * - * @author Eugene Sharygin * @param Number * @return Number */ diff --git a/src/algorithms/math/power_set.js b/src/algorithms/math/power_set.js index 3349085..585342c 100644 --- a/src/algorithms/math/power_set.js +++ b/src/algorithms/math/power_set.js @@ -1,7 +1,5 @@ /** * Iterative and recursive implementations of power set - * - * @author Joshua Curl */ 'use strict'; diff --git a/src/algorithms/string/longest_common_subsequence.js b/src/algorithms/string/longest_common_subsequence.js index 1824fd0..c698ba7 100644 --- a/src/algorithms/string/longest_common_subsequence.js +++ b/src/algorithms/string/longest_common_subsequence.js @@ -1,7 +1,5 @@ /** * Implementation of longest common subsequence - * - * @author Joshua Curl */ 'use strict'; diff --git a/src/algorithms/string/longest_common_substring.js b/src/algorithms/string/longest_common_substring.js index 43c7255..8a349f9 100644 --- a/src/algorithms/string/longest_common_substring.js +++ b/src/algorithms/string/longest_common_substring.js @@ -1,7 +1,5 @@ /** * Implementation of longest common substring - * - * @author Joshua Curl */ 'use strict'; From ad22e1ac40c9e27879f7ba489280325873f47908 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 14 Nov 2014 13:18:08 +0100 Subject: [PATCH 165/280] Rename files --- src/data_structure.js | 15 +++++++++++++++ src/{data_structures => data_structure}/bst.js | 0 .../disjoint_set_forest.js | 0 src/{data_structures => data_structure}/graph.js | 0 .../hash_table.js | 0 src/{data_structures => data_structure}/heap.js | 0 .../linked_list.js | 0 .../priority_queue.js | 0 src/{data_structures => data_structure}/queue.js | 0 src/{data_structures => data_structure}/set.js | 0 src/{data_structures => data_structure}/stack.js | 0 src/data_structures.js | 15 --------------- src/index.js | 2 +- 13 files changed, 16 insertions(+), 16 deletions(-) create mode 100644 src/data_structure.js rename src/{data_structures => data_structure}/bst.js (100%) rename src/{data_structures => data_structure}/disjoint_set_forest.js (100%) rename src/{data_structures => data_structure}/graph.js (100%) rename src/{data_structures => data_structure}/hash_table.js (100%) rename src/{data_structures => data_structure}/heap.js (100%) rename src/{data_structures => data_structure}/linked_list.js (100%) rename src/{data_structures => data_structure}/priority_queue.js (100%) rename src/{data_structures => data_structure}/queue.js (100%) rename src/{data_structures => data_structure}/set.js (100%) rename src/{data_structures => data_structure}/stack.js (100%) delete mode 100644 src/data_structures.js diff --git a/src/data_structure.js b/src/data_structure.js new file mode 100644 index 0000000..df774ed --- /dev/null +++ b/src/data_structure.js @@ -0,0 +1,15 @@ +'use strict'; + +// Data Structures +module.exports = { + BST: require('./data_structure/bst'), + Graph: require('./data_structure/graph'), + HashTable: require('./data_structure/hash_table'), + Heap: require('./data_structure/heap'), + LinkedList: require('./data_structure/linked_list'), + PriorityQueue: require('./data_structure/priority_queue'), + Queue: require('./data_structure/queue'), + Stack: require('./data_structure/stack'), + Set: require('./data_structure/set'), + DisjointSetForest: require('./data_structure/disjoint_set_forest') +}; diff --git a/src/data_structures/bst.js b/src/data_structure/bst.js similarity index 100% rename from src/data_structures/bst.js rename to src/data_structure/bst.js diff --git a/src/data_structures/disjoint_set_forest.js b/src/data_structure/disjoint_set_forest.js similarity index 100% rename from src/data_structures/disjoint_set_forest.js rename to src/data_structure/disjoint_set_forest.js diff --git a/src/data_structures/graph.js b/src/data_structure/graph.js similarity index 100% rename from src/data_structures/graph.js rename to src/data_structure/graph.js diff --git a/src/data_structures/hash_table.js b/src/data_structure/hash_table.js similarity index 100% rename from src/data_structures/hash_table.js rename to src/data_structure/hash_table.js diff --git a/src/data_structures/heap.js b/src/data_structure/heap.js similarity index 100% rename from src/data_structures/heap.js rename to src/data_structure/heap.js diff --git a/src/data_structures/linked_list.js b/src/data_structure/linked_list.js similarity index 100% rename from src/data_structures/linked_list.js rename to src/data_structure/linked_list.js diff --git a/src/data_structures/priority_queue.js b/src/data_structure/priority_queue.js similarity index 100% rename from src/data_structures/priority_queue.js rename to src/data_structure/priority_queue.js diff --git a/src/data_structures/queue.js b/src/data_structure/queue.js similarity index 100% rename from src/data_structures/queue.js rename to src/data_structure/queue.js diff --git a/src/data_structures/set.js b/src/data_structure/set.js similarity index 100% rename from src/data_structures/set.js rename to src/data_structure/set.js diff --git a/src/data_structures/stack.js b/src/data_structure/stack.js similarity index 100% rename from src/data_structures/stack.js rename to src/data_structure/stack.js diff --git a/src/data_structures.js b/src/data_structures.js deleted file mode 100644 index 005ac04..0000000 --- a/src/data_structures.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -// Data Structures -module.exports = { - BST: require('./data_structures/bst'), - Graph: require('./data_structures/graph'), - HashTable: require('./data_structures/hash_table'), - Heap: require('./data_structures/heap'), - LinkedList: require('./data_structures/linked_list'), - PriorityQueue: require('./data_structures/priority_queue'), - Queue: require('./data_structures/queue'), - Stack: require('./data_structures/stack'), - Set: require('./data_structures/set'), - DisjointSetForest: require('./data_structures/disjoint_set_forest') -}; diff --git a/src/index.js b/src/index.js index d5373b5..b94900f 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ 'use strict'; var lib = { - DataStructure: require('./data_structures'), + DataStructure: require('./data_structure'), Graph: require('./graph'), Math: require('./math'), Search: require('./search'), From f88e60ea73dac3fb0d5bdc82a3041403c543612b Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 14 Nov 2014 13:23:34 +0100 Subject: [PATCH 166/280] Fix references to data_structures --- README.md | 2 +- src/algorithms/graph/breadth_first_search.js | 2 +- src/algorithms/graph/dijkstra.js | 2 +- src/algorithms/graph/euler_path.js | 2 +- src/algorithms/graph/kruskal.js | 4 ++-- src/algorithms/graph/prim.js | 4 ++-- src/algorithms/graph/topological_sort.js | 2 +- src/algorithms/search/bfs.js | 2 +- src/algorithms/sorting/heap_sort.js | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 1f6b0f6..97f8a8b 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ npm install --save algorithms #### Data Structures ```javascript -require('algorithms/data_structures'); +require('algorithms/data_structure'); // or require('algorithms').DataStructure; ``` diff --git a/src/algorithms/graph/breadth_first_search.js b/src/algorithms/graph/breadth_first_search.js index b1da718..32d4139 100644 --- a/src/algorithms/graph/breadth_first_search.js +++ b/src/algorithms/graph/breadth_first_search.js @@ -1,6 +1,6 @@ 'use strict'; -var Queue = require('../../data_structures/queue'); +var Queue = require('../../data_structure/queue'); /** diff --git a/src/algorithms/graph/dijkstra.js b/src/algorithms/graph/dijkstra.js index da08795..b5f8341 100644 --- a/src/algorithms/graph/dijkstra.js +++ b/src/algorithms/graph/dijkstra.js @@ -1,6 +1,6 @@ 'use strict'; -var PriorityQueue = require('../../data_structures/priority_queue'); +var PriorityQueue = require('../../data_structure/priority_queue'); /** * Calculates the shortest paths in a graph to every node from the node s diff --git a/src/algorithms/graph/euler_path.js b/src/algorithms/graph/euler_path.js index c63c765..f5f087c 100644 --- a/src/algorithms/graph/euler_path.js +++ b/src/algorithms/graph/euler_path.js @@ -1,7 +1,7 @@ 'use strict'; -var Graph = require('../../data_structures/graph'), +var Graph = require('../../data_structure/graph'), depthFirstSearch = require('../../algorithms/graph/depth_first_search'); diff --git a/src/algorithms/graph/kruskal.js b/src/algorithms/graph/kruskal.js index 436effb..b4b068d 100644 --- a/src/algorithms/graph/kruskal.js +++ b/src/algorithms/graph/kruskal.js @@ -1,7 +1,7 @@ 'use strict'; -var DisjointSetForest = require('../../data_structures/disjoint_set_forest'), - Graph = require('../../data_structures/graph'); +var DisjointSetForest = require('../../data_structure/disjoint_set_forest'), + Graph = require('../../data_structure/graph'); /** diff --git a/src/algorithms/graph/prim.js b/src/algorithms/graph/prim.js index 603f490..2af5611 100644 --- a/src/algorithms/graph/prim.js +++ b/src/algorithms/graph/prim.js @@ -1,7 +1,7 @@ 'use strict'; -var PriorityQueue = require('../../data_structures/priority_queue'), - Graph = require('../../data_structures/graph'); +var PriorityQueue = require('../../data_structure/priority_queue'), + Graph = require('../../data_structure/graph'); /** diff --git a/src/algorithms/graph/topological_sort.js b/src/algorithms/graph/topological_sort.js index 0d4176f..9807169 100644 --- a/src/algorithms/graph/topological_sort.js +++ b/src/algorithms/graph/topological_sort.js @@ -1,6 +1,6 @@ 'use strict'; -var Stack = require('../../data_structures/stack'), +var Stack = require('../../data_structure/stack'), depthFirstSearch = require('../../algorithms/graph/depth_first_search'); /** diff --git a/src/algorithms/search/bfs.js b/src/algorithms/search/bfs.js index 98bcfac..68011a5 100644 --- a/src/algorithms/search/bfs.js +++ b/src/algorithms/search/bfs.js @@ -1,5 +1,5 @@ 'use strict'; -var Queue = require('../../data_structures/queue.js'); +var Queue = require('../../data_structure/queue.js'); /** * Breadth-first search for binary trees diff --git a/src/algorithms/sorting/heap_sort.js b/src/algorithms/sorting/heap_sort.js index 9d8f53e..8943bef 100644 --- a/src/algorithms/sorting/heap_sort.js +++ b/src/algorithms/sorting/heap_sort.js @@ -1,5 +1,5 @@ 'use strict'; -var MinHeap = require('../../data_structures/heap').MinHeap; +var MinHeap = require('../../data_structure/heap').MinHeap; /** * Heap sort first creates a valid heap data structure. Next it From 84282481d5e7a87c0cc1514c8aa23ecf36ccac8f Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 14 Nov 2014 13:27:06 +0100 Subject: [PATCH 167/280] bundle Update browser bundle with latest changes --- bundle/algorithms.browser.min.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bundle/algorithms.browser.min.js b/bundle/algorithms.browser.min.js index 1207571..c3c339b 100644 --- a/bundle/algorithms.browser.min.js +++ b/bundle/algorithms.browser.min.js @@ -1,3 +1,3 @@ -/* algorithms.js v0.8.0 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ -!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":48}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":42,"../../data_structures/graph":43}],10:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],18:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":57}],19:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],21:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],22:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":48}],23:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":57}],26:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],27:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":45}],28:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":57}],29:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":57}],31:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":57}],33:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":57}],34:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],36:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],37:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],38:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;ei[e][n-1]?e--:n--;return s.split("").reverse().join("")};r.exports=e},{}],39:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":57}],46:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],47:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r) -},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[52])(52)})}({},function(){return this}()); \ No newline at end of file +/* algorithms.js v0.8.1 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ +!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structure/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structure/queue":49}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structure/disjoint_set_forest":43,"../../data_structure/graph":44}],10:[function(t,r){"use strict";var e=t("../../data_structure/priority_queue"),n=t("../../data_structure/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],18:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":58}],19:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],21:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],22:[function(t,r){"use strict";var e=t("../../data_structure/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structure/queue.js":49}],23:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":58}],26:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],27:[function(t,r){"use strict";var e=t("../../data_structure/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structure/heap":46}],28:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":58}],29:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":58}],31:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":58}],33:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":58}],34:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],36:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],37:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],38:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length;e++)i[e]=new Int32Array(r.length+1);for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=t[e-1]==r[n-1]?i[e-1][n-1]+1:Math.max(i[e][n-1],i[e-1][n]);e=t.length,n=r.length;for(var o="";0!==i[e][n];)t[e-1]===r[n-1]?(o=t[e-1]+o,e--,n--):i[e-1][n]>i[e][n-1]?e--:n--;return o};r.exports=e},{}],39:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length+1;e++)i[e]=new Int32Array(r.length+1);var o={},s=0;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)t[e-1]==r[n-1]?(i[e][n]=i[e-1][n-1]+1,i[e][n]>s&&(o.i=e,o.j=n,s=i[e][n])):i[e][n]=0;var a="";return s&&(a=t.substring(o.i-s,o.i)),a};r.exports=e},{}],40:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":58}],47:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],48:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1 +},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[53])(53)})}({},function(){return this}()); \ No newline at end of file From 742bc1b270cb7deae03461babb0a88d44a2f1e96 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 14 Nov 2014 13:27:51 +0100 Subject: [PATCH 168/280] 0.8.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ce06d3..4eca822 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.8.0", + "version": "0.8.1", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" From 45191b38774ea5c8e8f2e45ab49f11f665a5b79d Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sun, 16 Nov 2014 23:11:50 +0100 Subject: [PATCH 169/280] 0.8.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4eca822..3586319 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.8.1", + "version": "0.8.2", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" From 409eca55defa46a01d56b450c00f7e06220bba6d Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Thu, 29 Jan 2015 16:55:54 +0100 Subject: [PATCH 170/280] Update Copyright year --- LICENSE | 2 +- Makefile | 2 +- bundle/algorithms.browser.min.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LICENSE b/LICENSE index af77b3e..83ed47e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Felipe Ribeiro +Copyright (c) 2015 Felipe Ribeiro Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index 76283f3..7554225 100644 --- a/Makefile +++ b/Makefile @@ -30,5 +30,5 @@ coveralls: VERSION := $(shell node -e "console.log(require('./package.json').version);") browser_bundle: setup - browserify $(realpath src/index.js) --s algorithms | uglifyjs -c -m --screw-ie8 --wrap --preamble "/* algorithms.js v$(VERSION) | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */" > bundle/algorithms.browser.min.js + browserify $(realpath src/index.js) --s algorithms | uglifyjs -c -m --screw-ie8 --wrap --preamble "/* algorithms.js v$(VERSION) | (c) 2015 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */" > bundle/algorithms.browser.min.js diff --git a/bundle/algorithms.browser.min.js b/bundle/algorithms.browser.min.js index c3c339b..5cc8a3c 100644 --- a/bundle/algorithms.browser.min.js +++ b/bundle/algorithms.browser.min.js @@ -1,3 +1,3 @@ -/* algorithms.js v0.8.1 | (c) 2014 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ +/* algorithms.js v0.8.2 | (c) 2015 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ !function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structure/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structure/queue":49}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structure/disjoint_set_forest":43,"../../data_structure/graph":44}],10:[function(t,r){"use strict";var e=t("../../data_structure/priority_queue"),n=t("../../data_structure/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],18:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":58}],19:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],21:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],22:[function(t,r){"use strict";var e=t("../../data_structure/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structure/queue.js":49}],23:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":58}],26:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],27:[function(t,r){"use strict";var e=t("../../data_structure/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structure/heap":46}],28:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":58}],29:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":58}],31:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":58}],33:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":58}],34:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],36:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],37:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],38:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length;e++)i[e]=new Int32Array(r.length+1);for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=t[e-1]==r[n-1]?i[e-1][n-1]+1:Math.max(i[e][n-1],i[e-1][n]);e=t.length,n=r.length;for(var o="";0!==i[e][n];)t[e-1]===r[n-1]?(o=t[e-1]+o,e--,n--):i[e-1][n]>i[e][n-1]?e--:n--;return o};r.exports=e},{}],39:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length+1;e++)i[e]=new Int32Array(r.length+1);var o={},s=0;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)t[e-1]==r[n-1]?(i[e][n]=i[e-1][n-1]+1,i[e][n]>s&&(o.i=e,o.j=n,s=i[e][n])):i[e][n]=0;var a="";return s&&(a=t.substring(o.i-s,o.i)),a};r.exports=e},{}],40:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":58}],47:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],48:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1 },e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[53])(53)})}({},function(){return this}()); \ No newline at end of file From fe506eddf9f26c17bb0837f54bdfa032aed106ed Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 3 Feb 2015 16:22:55 +0100 Subject: [PATCH 171/280] Update README.md Add dependency badges --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 97f8a8b..32d8feb 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ [![Build Status](https://travis-ci.org/felipernb/algorithms.js.png?branch=master)](https://travis-ci.org/felipernb/algorithms.js) [![Coverage Status](https://coveralls.io/repos/felipernb/algorithms.js/badge.png?branch=master)](https://coveralls.io/r/felipernb/algorithms.js?branch=master) +[![Dependency Status](https://david-dm.org/felipernb/algorithms.js.svg)](https://david-dm.org/felipernb/algorithms.js) +[![devDependency Status](https://david-dm.org/felipernb/algorithms.js/dev-status.svg)](https://david-dm.org/felipernb/algorithms.js#info=devDependencies) ![](http://www.quickmeme.com/img/8d/8d30a19413145512ad5a05c46ec0da545df5ed79e113fcf076dc03c7514eb631.jpg) From 1e39cd447161b3552f4fc87cd61ff8dbcd43a4c5 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 3 Feb 2015 16:25:30 +0100 Subject: [PATCH 172/280] Update devDependencies --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 3586319..6008aa9 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,10 @@ "main": "./index.js", "dependencies": {}, "devDependencies": { - "coveralls": "^2.10.0", - "istanbul": "^0.2.10", + "coveralls": "^2.11.2", + "istanbul": "^0.3.5", "jshint": "~2.4.4", - "mocha": "^1.20.0" + "mocha": "^2.1.0" }, "repository": { "type": "git", From f0ddd46ee50d75c21c381eb3bf58ca9063a8be25 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 10 Feb 2015 11:48:37 +0100 Subject: [PATCH 173/280] DataStructures package in plural seems to make more sense --- Makefile | 3 --- README.md | 4 ++-- bundle/algorithms.browser.min.js | 4 ++-- src/algorithms/graph/breadth_first_search.js | 2 +- src/algorithms/graph/dijkstra.js | 2 +- src/algorithms/graph/euler_path.js | 2 +- src/algorithms/graph/kruskal.js | 4 ++-- src/algorithms/graph/prim.js | 4 ++-- src/algorithms/graph/topological_sort.js | 2 +- src/algorithms/search/bfs.js | 2 +- src/algorithms/sorting/heap_sort.js | 2 +- src/data_structure.js | 15 --------------- src/data_structures.js | 15 +++++++++++++++ src/{data_structure => data_structures}/bst.js | 0 .../disjoint_set_forest.js | 0 src/{data_structure => data_structures}/graph.js | 0 .../hash_table.js | 0 src/{data_structure => data_structures}/heap.js | 0 .../linked_list.js | 0 .../priority_queue.js | 0 src/{data_structure => data_structures}/queue.js | 0 src/{data_structure => data_structures}/set.js | 0 src/{data_structure => data_structures}/stack.js | 0 src/index.js | 2 +- src/test/algorithms/graph/SPFA.js | 2 +- src/test/algorithms/graph/bellman_ford.js | 2 +- src/test/algorithms/graph/bfs_shortest_path.js | 2 +- src/test/algorithms/graph/breadth_first_search.js | 2 +- src/test/algorithms/graph/depth_first_search.js | 2 +- src/test/algorithms/graph/dijkstra.js | 2 +- src/test/algorithms/graph/euler_path.js | 2 +- src/test/algorithms/graph/floyd_warshall.js | 2 +- .../algorithms/graph/minimum_spanning_tree.js | 2 +- src/test/algorithms/graph/topological_sort.js | 2 +- src/test/algorithms/searching/bfs.js | 2 +- src/test/algorithms/searching/dfs.js | 2 +- src/test/data_structures/bst.js | 2 +- src/test/data_structures/disjoint_set_forest.js | 2 +- src/test/data_structures/graph.js | 2 +- src/test/data_structures/hash_table.js | 2 +- src/test/data_structures/heap.js | 2 +- src/test/data_structures/linked_list.js | 2 +- src/test/data_structures/priority_queue.js | 2 +- src/test/data_structures/queue.js | 2 +- src/test/data_structures/set.js | 2 +- src/test/data_structures/stack.js | 2 +- 46 files changed, 52 insertions(+), 55 deletions(-) delete mode 100644 src/data_structure.js create mode 100644 src/data_structures.js rename src/{data_structure => data_structures}/bst.js (100%) rename src/{data_structure => data_structures}/disjoint_set_forest.js (100%) rename src/{data_structure => data_structures}/graph.js (100%) rename src/{data_structure => data_structures}/hash_table.js (100%) rename src/{data_structure => data_structures}/heap.js (100%) rename src/{data_structure => data_structures}/linked_list.js (100%) rename src/{data_structure => data_structures}/priority_queue.js (100%) rename src/{data_structure => data_structures}/queue.js (100%) rename src/{data_structure => data_structures}/set.js (100%) rename src/{data_structure => data_structures}/stack.js (100%) diff --git a/Makefile b/Makefile index 7554225..0278110 100644 --- a/Makefile +++ b/Makefile @@ -13,9 +13,6 @@ dist: all cp README.md _build cp CHANGELOG _build -release: dist - cd _build; npm publish - jshint: setup jshint src diff --git a/README.md b/README.md index 32d8feb..160879d 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,9 @@ npm install --save algorithms #### Data Structures ```javascript -require('algorithms/data_structure'); +require('algorithms/data_structures'); // or -require('algorithms').DataStructure; +require('algorithms').DataStructures; ``` * BST diff --git a/bundle/algorithms.browser.min.js b/bundle/algorithms.browser.min.js index 5cc8a3c..5fa3492 100644 --- a/bundle/algorithms.browser.min.js +++ b/bundle/algorithms.browser.min.js @@ -1,3 +1,3 @@ /* algorithms.js v0.8.2 | (c) 2015 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ -!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structure/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structure/queue":49}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structure/disjoint_set_forest":43,"../../data_structure/graph":44}],10:[function(t,r){"use strict";var e=t("../../data_structure/priority_queue"),n=t("../../data_structure/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],18:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":58}],19:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],21:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],22:[function(t,r){"use strict";var e=t("../../data_structure/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structure/queue.js":49}],23:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":58}],26:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],27:[function(t,r){"use strict";var e=t("../../data_structure/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structure/heap":46}],28:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":58}],29:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":58}],31:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":58}],33:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":58}],34:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],36:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],37:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],38:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length;e++)i[e]=new Int32Array(r.length+1);for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=t[e-1]==r[n-1]?i[e-1][n-1]+1:Math.max(i[e][n-1],i[e-1][n]);e=t.length,n=r.length;for(var o="";0!==i[e][n];)t[e-1]===r[n-1]?(o=t[e-1]+o,e--,n--):i[e-1][n]>i[e][n-1]?e--:n--;return o};r.exports=e},{}],39:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length+1;e++)i[e]=new Int32Array(r.length+1);var o={},s=0;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)t[e-1]==r[n-1]?(i[e][n]=i[e-1][n-1]+1,i[e][n]>s&&(o.i=e,o.j=n,s=i[e][n])):i[e][n]=0;var a="";return s&&(a=t.substring(o.i-s,o.i)),a};r.exports=e},{}],40:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":58}],47:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],48:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1 -},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[53])(53)})}({},function(){return this}()); \ No newline at end of file +!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":49}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":43,"../../data_structures/graph":44}],10:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],18:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":58}],19:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],21:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],22:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":49}],23:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":58}],26:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],27:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":46}],28:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":58}],29:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":58}],31:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":58}],33:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":58}],34:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],36:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],37:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],38:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length;e++)i[e]=new Int32Array(r.length+1);for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=t[e-1]==r[n-1]?i[e-1][n-1]+1:Math.max(i[e][n-1],i[e-1][n]);e=t.length,n=r.length;for(var o="";0!==i[e][n];)t[e-1]===r[n-1]?(o=t[e-1]+o,e--,n--):i[e-1][n]>i[e][n-1]?e--:n--;return o};r.exports=e},{}],39:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length+1;e++)i[e]=new Int32Array(r.length+1);var o={},s=0;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)t[e-1]==r[n-1]?(i[e][n]=i[e-1][n-1]+1,i[e][n]>s&&(o.i=e,o.j=n,s=i[e][n])):i[e][n]=0;var a="";return s&&(a=t.substring(o.i-s,o.i)),a};r.exports=e},{}],40:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":58}],47:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],48:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[53])(53)})}({},function(){return this}()); \ No newline at end of file diff --git a/src/algorithms/graph/breadth_first_search.js b/src/algorithms/graph/breadth_first_search.js index 32d4139..b1da718 100644 --- a/src/algorithms/graph/breadth_first_search.js +++ b/src/algorithms/graph/breadth_first_search.js @@ -1,6 +1,6 @@ 'use strict'; -var Queue = require('../../data_structure/queue'); +var Queue = require('../../data_structures/queue'); /** diff --git a/src/algorithms/graph/dijkstra.js b/src/algorithms/graph/dijkstra.js index b5f8341..da08795 100644 --- a/src/algorithms/graph/dijkstra.js +++ b/src/algorithms/graph/dijkstra.js @@ -1,6 +1,6 @@ 'use strict'; -var PriorityQueue = require('../../data_structure/priority_queue'); +var PriorityQueue = require('../../data_structures/priority_queue'); /** * Calculates the shortest paths in a graph to every node from the node s diff --git a/src/algorithms/graph/euler_path.js b/src/algorithms/graph/euler_path.js index f5f087c..c63c765 100644 --- a/src/algorithms/graph/euler_path.js +++ b/src/algorithms/graph/euler_path.js @@ -1,7 +1,7 @@ 'use strict'; -var Graph = require('../../data_structure/graph'), +var Graph = require('../../data_structures/graph'), depthFirstSearch = require('../../algorithms/graph/depth_first_search'); diff --git a/src/algorithms/graph/kruskal.js b/src/algorithms/graph/kruskal.js index b4b068d..436effb 100644 --- a/src/algorithms/graph/kruskal.js +++ b/src/algorithms/graph/kruskal.js @@ -1,7 +1,7 @@ 'use strict'; -var DisjointSetForest = require('../../data_structure/disjoint_set_forest'), - Graph = require('../../data_structure/graph'); +var DisjointSetForest = require('../../data_structures/disjoint_set_forest'), + Graph = require('../../data_structures/graph'); /** diff --git a/src/algorithms/graph/prim.js b/src/algorithms/graph/prim.js index 2af5611..603f490 100644 --- a/src/algorithms/graph/prim.js +++ b/src/algorithms/graph/prim.js @@ -1,7 +1,7 @@ 'use strict'; -var PriorityQueue = require('../../data_structure/priority_queue'), - Graph = require('../../data_structure/graph'); +var PriorityQueue = require('../../data_structures/priority_queue'), + Graph = require('../../data_structures/graph'); /** diff --git a/src/algorithms/graph/topological_sort.js b/src/algorithms/graph/topological_sort.js index 9807169..0d4176f 100644 --- a/src/algorithms/graph/topological_sort.js +++ b/src/algorithms/graph/topological_sort.js @@ -1,6 +1,6 @@ 'use strict'; -var Stack = require('../../data_structure/stack'), +var Stack = require('../../data_structures/stack'), depthFirstSearch = require('../../algorithms/graph/depth_first_search'); /** diff --git a/src/algorithms/search/bfs.js b/src/algorithms/search/bfs.js index 68011a5..98bcfac 100644 --- a/src/algorithms/search/bfs.js +++ b/src/algorithms/search/bfs.js @@ -1,5 +1,5 @@ 'use strict'; -var Queue = require('../../data_structure/queue.js'); +var Queue = require('../../data_structures/queue.js'); /** * Breadth-first search for binary trees diff --git a/src/algorithms/sorting/heap_sort.js b/src/algorithms/sorting/heap_sort.js index 8943bef..9d8f53e 100644 --- a/src/algorithms/sorting/heap_sort.js +++ b/src/algorithms/sorting/heap_sort.js @@ -1,5 +1,5 @@ 'use strict'; -var MinHeap = require('../../data_structure/heap').MinHeap; +var MinHeap = require('../../data_structures/heap').MinHeap; /** * Heap sort first creates a valid heap data structure. Next it diff --git a/src/data_structure.js b/src/data_structure.js deleted file mode 100644 index df774ed..0000000 --- a/src/data_structure.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -// Data Structures -module.exports = { - BST: require('./data_structure/bst'), - Graph: require('./data_structure/graph'), - HashTable: require('./data_structure/hash_table'), - Heap: require('./data_structure/heap'), - LinkedList: require('./data_structure/linked_list'), - PriorityQueue: require('./data_structure/priority_queue'), - Queue: require('./data_structure/queue'), - Stack: require('./data_structure/stack'), - Set: require('./data_structure/set'), - DisjointSetForest: require('./data_structure/disjoint_set_forest') -}; diff --git a/src/data_structures.js b/src/data_structures.js new file mode 100644 index 0000000..005ac04 --- /dev/null +++ b/src/data_structures.js @@ -0,0 +1,15 @@ +'use strict'; + +// Data Structures +module.exports = { + BST: require('./data_structures/bst'), + Graph: require('./data_structures/graph'), + HashTable: require('./data_structures/hash_table'), + Heap: require('./data_structures/heap'), + LinkedList: require('./data_structures/linked_list'), + PriorityQueue: require('./data_structures/priority_queue'), + Queue: require('./data_structures/queue'), + Stack: require('./data_structures/stack'), + Set: require('./data_structures/set'), + DisjointSetForest: require('./data_structures/disjoint_set_forest') +}; diff --git a/src/data_structure/bst.js b/src/data_structures/bst.js similarity index 100% rename from src/data_structure/bst.js rename to src/data_structures/bst.js diff --git a/src/data_structure/disjoint_set_forest.js b/src/data_structures/disjoint_set_forest.js similarity index 100% rename from src/data_structure/disjoint_set_forest.js rename to src/data_structures/disjoint_set_forest.js diff --git a/src/data_structure/graph.js b/src/data_structures/graph.js similarity index 100% rename from src/data_structure/graph.js rename to src/data_structures/graph.js diff --git a/src/data_structure/hash_table.js b/src/data_structures/hash_table.js similarity index 100% rename from src/data_structure/hash_table.js rename to src/data_structures/hash_table.js diff --git a/src/data_structure/heap.js b/src/data_structures/heap.js similarity index 100% rename from src/data_structure/heap.js rename to src/data_structures/heap.js diff --git a/src/data_structure/linked_list.js b/src/data_structures/linked_list.js similarity index 100% rename from src/data_structure/linked_list.js rename to src/data_structures/linked_list.js diff --git a/src/data_structure/priority_queue.js b/src/data_structures/priority_queue.js similarity index 100% rename from src/data_structure/priority_queue.js rename to src/data_structures/priority_queue.js diff --git a/src/data_structure/queue.js b/src/data_structures/queue.js similarity index 100% rename from src/data_structure/queue.js rename to src/data_structures/queue.js diff --git a/src/data_structure/set.js b/src/data_structures/set.js similarity index 100% rename from src/data_structure/set.js rename to src/data_structures/set.js diff --git a/src/data_structure/stack.js b/src/data_structures/stack.js similarity index 100% rename from src/data_structure/stack.js rename to src/data_structures/stack.js diff --git a/src/index.js b/src/index.js index b94900f..95c99fb 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ 'use strict'; var lib = { - DataStructure: require('./data_structure'), + DataStructures: require('./data_structures'), Graph: require('./graph'), Math: require('./math'), Search: require('./search'), diff --git a/src/test/algorithms/graph/SPFA.js b/src/test/algorithms/graph/SPFA.js index dcf3e6d..db23a35 100644 --- a/src/test/algorithms/graph/SPFA.js +++ b/src/test/algorithms/graph/SPFA.js @@ -2,7 +2,7 @@ var root = require('../../../'), SPFA = root.Graph.SPFA, - Graph = root.DataStructure.Graph, + Graph = root.DataStructures.Graph, assert = require('assert'); describe('SPFA Algorithm', function () { diff --git a/src/test/algorithms/graph/bellman_ford.js b/src/test/algorithms/graph/bellman_ford.js index d4ec90b..53dbe2f 100644 --- a/src/test/algorithms/graph/bellman_ford.js +++ b/src/test/algorithms/graph/bellman_ford.js @@ -2,7 +2,7 @@ var root = require('../../../'), bellmanFord = root.Graph.bellmanFord, - Graph = root.DataStructure.Graph, + Graph = root.DataStructures.Graph, assert = require('assert'); describe('Bellman-Ford Algorithm', function () { diff --git a/src/test/algorithms/graph/bfs_shortest_path.js b/src/test/algorithms/graph/bfs_shortest_path.js index 5300f88..bf8af32 100644 --- a/src/test/algorithms/graph/bfs_shortest_path.js +++ b/src/test/algorithms/graph/bfs_shortest_path.js @@ -2,7 +2,7 @@ var root = require('../../../'), bfsShortestPath = root.Graph.bfsShortestPath, - Graph = root.DataStructure.Graph, + Graph = root.DataStructures.Graph, assert = require('assert'); diff --git a/src/test/algorithms/graph/breadth_first_search.js b/src/test/algorithms/graph/breadth_first_search.js index 457da6f..9bc62a7 100644 --- a/src/test/algorithms/graph/breadth_first_search.js +++ b/src/test/algorithms/graph/breadth_first_search.js @@ -2,7 +2,7 @@ var root = require('../../../'), breadthFirstSearch = root.Graph.breadthFirstSearch, - Graph = root.DataStructure.Graph, + Graph = root.DataStructures.Graph, assert = require('assert'); diff --git a/src/test/algorithms/graph/depth_first_search.js b/src/test/algorithms/graph/depth_first_search.js index fb9382e..ea651c5 100644 --- a/src/test/algorithms/graph/depth_first_search.js +++ b/src/test/algorithms/graph/depth_first_search.js @@ -2,7 +2,7 @@ var root = require('../../../'), depthFirstSearch = root.Graph.depthFirstSearch, - Graph = root.DataStructure.Graph, + Graph = root.DataStructures.Graph, assert = require('assert'); describe('Depth First Search Algorithm', function () { diff --git a/src/test/algorithms/graph/dijkstra.js b/src/test/algorithms/graph/dijkstra.js index edf2300..e3eb998 100644 --- a/src/test/algorithms/graph/dijkstra.js +++ b/src/test/algorithms/graph/dijkstra.js @@ -2,7 +2,7 @@ var root = require('../../../'), dijkstra = root.Graph.dijkstra, - Graph = root.DataStructure.Graph, + Graph = root.DataStructures.Graph, assert = require('assert'); describe('Dijkstra Algorithm', function () { diff --git a/src/test/algorithms/graph/euler_path.js b/src/test/algorithms/graph/euler_path.js index 6bf384c..53ad7f0 100644 --- a/src/test/algorithms/graph/euler_path.js +++ b/src/test/algorithms/graph/euler_path.js @@ -3,7 +3,7 @@ var root = require('../../../'), eulerPath = root.Graph.eulerPath, - Graph = root.DataStructure.Graph, + Graph = root.DataStructures.Graph, assert = require('assert'); diff --git a/src/test/algorithms/graph/floyd_warshall.js b/src/test/algorithms/graph/floyd_warshall.js index 3cab6d3..39003ba 100644 --- a/src/test/algorithms/graph/floyd_warshall.js +++ b/src/test/algorithms/graph/floyd_warshall.js @@ -2,7 +2,7 @@ var root = require('../../../'), floydWarshall = root.Graph.floydWarshall, - Graph = root.DataStructure.Graph, + Graph = root.DataStructures.Graph, assert = require('assert'); diff --git a/src/test/algorithms/graph/minimum_spanning_tree.js b/src/test/algorithms/graph/minimum_spanning_tree.js index d72e314..93fecf7 100644 --- a/src/test/algorithms/graph/minimum_spanning_tree.js +++ b/src/test/algorithms/graph/minimum_spanning_tree.js @@ -4,7 +4,7 @@ var root = require('../../../'), kruskal = root.Graph.kruskal, prim = root.Graph.prim, depthFirstSearch = root.Graph.depthFirstSearch, - Graph = root.DataStructure.Graph, + Graph = root.DataStructures.Graph, assert = require('assert'); diff --git a/src/test/algorithms/graph/topological_sort.js b/src/test/algorithms/graph/topological_sort.js index 0ec4133..c8b9009 100644 --- a/src/test/algorithms/graph/topological_sort.js +++ b/src/test/algorithms/graph/topological_sort.js @@ -2,7 +2,7 @@ var root = require('../../../'), topologicalSort = root.Graph.topologicalSort, - Graph = root.DataStructure.Graph, + Graph = root.DataStructures.Graph, assert = require('assert'); describe('Topological Sort', function () { diff --git a/src/test/algorithms/searching/bfs.js b/src/test/algorithms/searching/bfs.js index 14f79a7..5c5882e 100644 --- a/src/test/algorithms/searching/bfs.js +++ b/src/test/algorithms/searching/bfs.js @@ -1,7 +1,7 @@ 'use strict'; var root = require('../../..'), - BST = root.DataStructure.BST, + BST = root.DataStructures.BST, bfs = root.Search.bfs, assert = require('assert'); diff --git a/src/test/algorithms/searching/dfs.js b/src/test/algorithms/searching/dfs.js index 3e53ca9..5a295e5 100644 --- a/src/test/algorithms/searching/dfs.js +++ b/src/test/algorithms/searching/dfs.js @@ -1,7 +1,7 @@ 'use strict'; var root = require('../../..'), - BST = root.DataStructure.BST, + BST = root.DataStructures.BST, dfs = root.Search.dfs, assert = require('assert'); diff --git a/src/test/data_structures/bst.js b/src/test/data_structures/bst.js index 72b194c..b0432d6 100644 --- a/src/test/data_structures/bst.js +++ b/src/test/data_structures/bst.js @@ -1,7 +1,7 @@ 'use strict'; var root = require('../..'), - BST = root.DataStructure.BST, + BST = root.DataStructures.BST, bfs = root.Search.bfs, assert = require('assert'); diff --git a/src/test/data_structures/disjoint_set_forest.js b/src/test/data_structures/disjoint_set_forest.js index 6e75c03..abdb16e 100644 --- a/src/test/data_structures/disjoint_set_forest.js +++ b/src/test/data_structures/disjoint_set_forest.js @@ -1,6 +1,6 @@ 'use strict'; -var DisjointSetForest = require('../..').DataStructure.DisjointSetForest, +var DisjointSetForest = require('../..').DataStructures.DisjointSetForest, assert = require('assert'); diff --git a/src/test/data_structures/graph.js b/src/test/data_structures/graph.js index 709edf2..fcecbbd 100644 --- a/src/test/data_structures/graph.js +++ b/src/test/data_structures/graph.js @@ -1,6 +1,6 @@ 'use strict'; -var Graph = require('../..').DataStructure.Graph, +var Graph = require('../..').DataStructures.Graph, assert = require('assert'); describe('Graph - Adjacency list', function () { diff --git a/src/test/data_structures/hash_table.js b/src/test/data_structures/hash_table.js index c9a8370..86ede97 100644 --- a/src/test/data_structures/hash_table.js +++ b/src/test/data_structures/hash_table.js @@ -1,6 +1,6 @@ 'use strict'; -var HashTable = require('../..').DataStructure.HashTable, +var HashTable = require('../..').DataStructures.HashTable, assert = require('assert'); describe('Hash Table', function () { diff --git a/src/test/data_structures/heap.js b/src/test/data_structures/heap.js index 1bf4585..7772d9a 100644 --- a/src/test/data_structures/heap.js +++ b/src/test/data_structures/heap.js @@ -1,6 +1,6 @@ 'use strict'; -var heap = require('../..').DataStructure.Heap, +var heap = require('../..').DataStructures.Heap, assert = require('assert'); describe('Min Heap', function () { diff --git a/src/test/data_structures/linked_list.js b/src/test/data_structures/linked_list.js index 66636da..5eadd60 100644 --- a/src/test/data_structures/linked_list.js +++ b/src/test/data_structures/linked_list.js @@ -1,6 +1,6 @@ 'use strict'; -var LinkedList = require('../..').DataStructure.LinkedList, +var LinkedList = require('../..').DataStructures.LinkedList, assert = require('assert'); describe('LinkedList', function () { diff --git a/src/test/data_structures/priority_queue.js b/src/test/data_structures/priority_queue.js index e2b5f06..33728ef 100644 --- a/src/test/data_structures/priority_queue.js +++ b/src/test/data_structures/priority_queue.js @@ -1,6 +1,6 @@ 'use strict'; -var PriorityQueue = require('../..').DataStructure.PriorityQueue, +var PriorityQueue = require('../..').DataStructures.PriorityQueue, assert = require('assert'); describe('Min Priority Queue', function () { diff --git a/src/test/data_structures/queue.js b/src/test/data_structures/queue.js index 8ede8f9..1915cca 100644 --- a/src/test/data_structures/queue.js +++ b/src/test/data_structures/queue.js @@ -1,6 +1,6 @@ 'use strict'; -var Queue = require('../..').DataStructure.Queue, +var Queue = require('../..').DataStructures.Queue, assert = require('assert'); describe('Queue', function () { diff --git a/src/test/data_structures/set.js b/src/test/data_structures/set.js index c31b2cd..ab604c3 100644 --- a/src/test/data_structures/set.js +++ b/src/test/data_structures/set.js @@ -1,6 +1,6 @@ 'use strict'; -var HashSet = require('../..').DataStructure.Set, +var HashSet = require('../..').DataStructures.Set, assert = require('assert'); describe('HashSet', function () { diff --git a/src/test/data_structures/stack.js b/src/test/data_structures/stack.js index 6790745..2fa5fd9 100644 --- a/src/test/data_structures/stack.js +++ b/src/test/data_structures/stack.js @@ -1,6 +1,6 @@ 'use strict'; -var Stack = require('../..').DataStructure.Stack, +var Stack = require('../..').DataStructures.Stack, assert = require('assert'); describe('Stack', function () { From a21002b2dc1b32d22ccaefe8ceaf21eca2cb8c4e Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 11 Feb 2015 18:51:37 +0100 Subject: [PATCH 174/280] 0.9.0 --- bundle/algorithms.browser.min.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bundle/algorithms.browser.min.js b/bundle/algorithms.browser.min.js index 5fa3492..dcc67db 100644 --- a/bundle/algorithms.browser.min.js +++ b/bundle/algorithms.browser.min.js @@ -1,3 +1,3 @@ -/* algorithms.js v0.8.2 | (c) 2015 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ +/* algorithms.js v0.9.0 | (c) 2015 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ !function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":49}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":43,"../../data_structures/graph":44}],10:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],18:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":58}],19:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],21:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],22:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":49}],23:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":58}],26:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],27:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":46}],28:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":58}],29:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":58}],31:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":58}],33:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":58}],34:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],36:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],37:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],38:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length;e++)i[e]=new Int32Array(r.length+1);for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=t[e-1]==r[n-1]?i[e-1][n-1]+1:Math.max(i[e][n-1],i[e-1][n]);e=t.length,n=r.length;for(var o="";0!==i[e][n];)t[e-1]===r[n-1]?(o=t[e-1]+o,e--,n--):i[e-1][n]>i[e][n-1]?e--:n--;return o};r.exports=e},{}],39:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length+1;e++)i[e]=new Int32Array(r.length+1);var o={},s=0;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)t[e-1]==r[n-1]?(i[e][n]=i[e-1][n-1]+1,i[e][n]>s&&(o.i=e,o.j=n,s=i[e][n])):i[e][n]=0;var a="";return s&&(a=t.substring(o.i-s,o.i)),a};r.exports=e},{}],40:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":58}],47:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],48:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[53])(53)})}({},function(){return this}()); \ No newline at end of file diff --git a/package.json b/package.json index 6008aa9..801d20f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.8.2", + "version": "0.9.0", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "directories": { "test": "test" From 5628fbfaf197a43f4e5f9634c40c0c7c0cd0675d Mon Sep 17 00:00:00 2001 From: Juan Lopes Date: Fri, 13 Feb 2015 12:34:51 -0200 Subject: [PATCH 175/280] adding fenwick tree implementation --- src/data_structures.js | 3 +- src/data_structures/fenwick_tree.js | 37 ++++++++++++++++++++++++ src/test/data_structures/fenwick_tree.js | 37 ++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/data_structures/fenwick_tree.js create mode 100644 src/test/data_structures/fenwick_tree.js diff --git a/src/data_structures.js b/src/data_structures.js index 005ac04..b88cf99 100644 --- a/src/data_structures.js +++ b/src/data_structures.js @@ -11,5 +11,6 @@ module.exports = { Queue: require('./data_structures/queue'), Stack: require('./data_structures/stack'), Set: require('./data_structures/set'), - DisjointSetForest: require('./data_structures/disjoint_set_forest') + DisjointSetForest: require('./data_structures/disjoint_set_forest'), + FenwickTree: require('./data_structures/fenwick_tree') }; diff --git a/src/data_structures/fenwick_tree.js b/src/data_structures/fenwick_tree.js new file mode 100644 index 0000000..4ecad9c --- /dev/null +++ b/src/data_structures/fenwick_tree.js @@ -0,0 +1,37 @@ +'use strict'; + +/** + * Fenwick Tree (Binary Indexed Tree) + */ +function FenwickTree(length) { + this._elements = new Array(length+1); + for(var i=0; i 0; index -= (index&-index)) + sum += this._elements[index]; + return sum; +}; + +/** +* Returns the sum of all value between two indexes in O(log n) +*/ +FenwickTree.prototype.rangeSum = function(fromIndex, toIndex) { + return this.prefixSum(toIndex) - this.prefixSum(fromIndex-1); +}; + +module.exports = FenwickTree; diff --git a/src/test/data_structures/fenwick_tree.js b/src/test/data_structures/fenwick_tree.js new file mode 100644 index 0000000..88cfae3 --- /dev/null +++ b/src/test/data_structures/fenwick_tree.js @@ -0,0 +1,37 @@ +'use strict'; + +var FenwickTree = require('../..').DataStructures.FenwickTree, + assert = require('assert'); + +describe('FenwickTree', function () { + it('should allow prefix queries', function () { + var tree = new FenwickTree(10); + tree.adjust(5, 42); + tree.adjust(7, 43); + tree.adjust(9, 44); + + + assert.equal(tree.prefixSum(0), 0); + assert.equal(tree.prefixSum(1), 0); + assert.equal(tree.prefixSum(2), 0); + assert.equal(tree.prefixSum(3), 0); + assert.equal(tree.prefixSum(4), 0); + assert.equal(tree.prefixSum(5), 42); + assert.equal(tree.prefixSum(6), 42); + assert.equal(tree.prefixSum(7), 42+43); + assert.equal(tree.prefixSum(8), 42+43); + assert.equal(tree.prefixSum(9), 42+43+44); + assert.equal(tree.prefixSum(10), 42+43+44); + }); + + it('should allow range queries', function () { + var tree = new FenwickTree(10); + tree.adjust(5, 42); + tree.adjust(7, 43); + tree.adjust(9, 44); + + + assert.equal(tree.rangeSum(6, 10), 43+44); + assert.equal(tree.rangeSum(5, 7), 42+43); + }); +}); From 9bb0bb95ea0bcc6678bb0a17c0567b1232598974 Mon Sep 17 00:00:00 2001 From: Juan Lopes Date: Fri, 13 Feb 2015 15:36:22 -0200 Subject: [PATCH 176/280] fixing spacing --- src/data_structures/fenwick_tree.js | 16 ++++++++-------- src/test/data_structures/fenwick_tree.js | 12 ++++++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/data_structures/fenwick_tree.js b/src/data_structures/fenwick_tree.js index 4ecad9c..518fa02 100644 --- a/src/data_structures/fenwick_tree.js +++ b/src/data_structures/fenwick_tree.js @@ -4,25 +4,25 @@ * Fenwick Tree (Binary Indexed Tree) */ function FenwickTree(length) { - this._elements = new Array(length+1); - for(var i=0; i 0; index -= (index&-index)) + for (; index > 0 ; index -= (index&-index)) sum += this._elements[index]; return sum; }; @@ -30,8 +30,8 @@ FenwickTree.prototype.prefixSum = function(index) { /** * Returns the sum of all value between two indexes in O(log n) */ -FenwickTree.prototype.rangeSum = function(fromIndex, toIndex) { - return this.prefixSum(toIndex) - this.prefixSum(fromIndex-1); +FenwickTree.prototype.rangeSum = function (fromIndex, toIndex) { + return this.prefixSum(toIndex) - this.prefixSum(fromIndex - 1); }; module.exports = FenwickTree; diff --git a/src/test/data_structures/fenwick_tree.js b/src/test/data_structures/fenwick_tree.js index 88cfae3..8f99d4a 100644 --- a/src/test/data_structures/fenwick_tree.js +++ b/src/test/data_structures/fenwick_tree.js @@ -18,10 +18,10 @@ describe('FenwickTree', function () { assert.equal(tree.prefixSum(4), 0); assert.equal(tree.prefixSum(5), 42); assert.equal(tree.prefixSum(6), 42); - assert.equal(tree.prefixSum(7), 42+43); - assert.equal(tree.prefixSum(8), 42+43); - assert.equal(tree.prefixSum(9), 42+43+44); - assert.equal(tree.prefixSum(10), 42+43+44); + assert.equal(tree.prefixSum(7), 42 + 43); + assert.equal(tree.prefixSum(8), 42 + 43); + assert.equal(tree.prefixSum(9), 42 + 43 + 44); + assert.equal(tree.prefixSum(10), 42 + 43 + 44); }); it('should allow range queries', function () { @@ -31,7 +31,7 @@ describe('FenwickTree', function () { tree.adjust(9, 44); - assert.equal(tree.rangeSum(6, 10), 43+44); - assert.equal(tree.rangeSum(5, 7), 42+43); + assert.equal(tree.rangeSum(6, 10), 43 + 44); + assert.equal(tree.rangeSum(5, 7), 42 + 43); }); }); From 64483ab085d85442635f6ea5d51e6063dccabee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20F=C3=B6hring?= Date: Fri, 20 Feb 2015 11:36:38 +0100 Subject: [PATCH 177/280] Add docs badge to README [ci skip] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 160879d..9d9e9b7 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![Coverage Status](https://coveralls.io/repos/felipernb/algorithms.js/badge.png?branch=master)](https://coveralls.io/r/felipernb/algorithms.js?branch=master) [![Dependency Status](https://david-dm.org/felipernb/algorithms.js.svg)](https://david-dm.org/felipernb/algorithms.js) [![devDependency Status](https://david-dm.org/felipernb/algorithms.js/dev-status.svg)](https://david-dm.org/felipernb/algorithms.js#info=devDependencies) +[![Inline docs](http://inch-ci.org/github/felipernb/algorithms.js.svg?branch=master)](http://inch-ci.org/github/felipernb/algorithms.js) ![](http://www.quickmeme.com/img/8d/8d30a19413145512ad5a05c46ec0da545df5ed79e113fcf076dc03c7514eb631.jpg) From 1d1fffae56ecab7bd67956498a5164ed75bf86fd Mon Sep 17 00:00:00 2001 From: Juan Lopes Date: Fri, 20 Feb 2015 11:10:37 -0200 Subject: [PATCH 178/280] adding comments to fenwick tree --- AUTHORS | 1 + package.json | 3 +- src/data_structures/fenwick_tree.js | 54 +++++++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index fed2c19..19283c6 100644 --- a/AUTHORS +++ b/AUTHORS @@ -12,3 +12,4 @@ eush77 geakstr nitinsaroha tayllan +Juan Lopes diff --git a/package.json b/package.json index 801d20f..a2ec61c 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,8 @@ "BrunoRB ", "geakstr ", "Matt R. Wilson ", - "Gaurav Mittal " + "Gaurav Mittal ", + "Juan Lopes " ], "license": "MIT", "bugs": { diff --git a/src/data_structures/fenwick_tree.js b/src/data_structures/fenwick_tree.js index 518fa02..0180f92 100644 --- a/src/data_structures/fenwick_tree.js +++ b/src/data_structures/fenwick_tree.js @@ -2,6 +2,25 @@ /** * Fenwick Tree (Binary Indexed Tree) + * + * The fenwick tree is a tree in the sense it represents a structure where + * the leafs are the original array values and each parent has the sum of its + * two children. E.g., for an array [1, 2, 3, 4], we have: + * + * 10 + * 3 7 + * 1 2 3 4 + * + * But some nodes aren't really important. In fact every right child isn't + * needed to compute the prefix sum (as its value is just the parent's value + * minus the left child), so we can store the tree in a compact array structure + * like this: + * + * 1 3 3 10 + * + * Here we assume all the operations will be on a 1-based array for two + * reasons: (1) the bit operations become rather easy and (2) it's better to + * reason about the range sum (prefix(b) - prefix(a-1)) on a 1-based array. */ function FenwickTree(length) { this._elements = new Array(length + 1); @@ -13,14 +32,45 @@ function FenwickTree(length) { * Adds value to the array at specified index in O(log n) */ FenwickTree.prototype.adjust = function (index, value) { + /* + This function goes up the tree adding the value to all parent nodes. + + In the array, to know where a index is in the tree, just look at where is + the rightmost bit. 1 is a leaf, because the rightmost bit is at position 0. + 2 (10) is 1 level above the leafs. 4 (100) is 2 levels above the leafs. + + Going up the tree means pushing the rightmost bit far to the left. We do + this by adding only the bit itself to the index. Eventually we skip + some levels that aren't represented in the array. E.g. starting at 3 (11), + it's imediate parent is 11b + 1b = 100b. We started at a leaf and skipped + the level-1 node, because it wasn't represented in the array + (a right child). + + Note: (index&-index) finds the rightmost bit in index. + */ for (; index < this._elements.length ; index += (index&-index)) this._elements[index] += value; }; /** -* Returns the sum of all value up to specified index in O(log n) +* Returns the sum of all values up to specified index in O(log n) */ FenwickTree.prototype.prefixSum = function (index) { + /* + This function goes up the tree adding the required nodes to sum the prefix. + + The key here is to sum every node that isn't in the same subtree as an + already seen node. In practice we proceed always getting a node's uncle + (the sibling of the node's parent). So, if we start at the index 7, we must + go to 6 (7's uncle), then to 4 (6's uncle), then we stop, because 4 has + no uncle. + + Binary-wise, this is the same as erasing the rightmost bit of the index. + E.g. 7 (111) -> 6 (110) -> 4 (100). + + Note: (index&-index) finds the rightmost bit in index. + */ + var sum = 0; for (; index > 0 ; index -= (index&-index)) sum += this._elements[index]; @@ -28,7 +78,7 @@ FenwickTree.prototype.prefixSum = function (index) { }; /** -* Returns the sum of all value between two indexes in O(log n) +* Returns the sum of all values between two indexes in O(log n) */ FenwickTree.prototype.rangeSum = function (fromIndex, toIndex) { return this.prefixSum(toIndex) - this.prefixSum(fromIndex - 1); From 6d41da9f6a34a61596865e289ba2587134884de1 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Fri, 20 Feb 2015 15:27:59 +0100 Subject: [PATCH 179/280] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9d9e9b7..e199726 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ require('algorithms').DataStructures; * Stack * Set (HashSet) * DisjointSetForest +* FenwickTree #### Graph algorithms From b880ddfcee470f006421fec0baf8d1f8560f58b7 Mon Sep 17 00:00:00 2001 From: Juan Lopes Date: Fri, 20 Feb 2015 12:46:55 -0200 Subject: [PATCH 180/280] Tail call optimize largest quicksort partition to improve space complexity --- src/algorithms/sorting/quicksort.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/algorithms/sorting/quicksort.js b/src/algorithms/sorting/quicksort.js index 4df58bd..aff9875 100644 --- a/src/algorithms/sorting/quicksort.js +++ b/src/algorithms/sorting/quicksort.js @@ -10,10 +10,17 @@ var quicksortInit = function (array, comparatorFn) { var comparator = new Comparator(comparatorFn); return (function quicksort(array, lo, hi) { - if (lo < hi) { + while (lo < hi) { var p = partition(array, comparator, lo, hi); - quicksort(array, lo, p - 1); - quicksort(array, p + 1, hi); + //Chooses only the smallest partition to use recursion on and + //tail-optimize the other. This guarantees O(log n) space in worst case. + if (p-lo < hi-p) { + quicksort(array, lo, p - 1); + lo = p+1; + } else { + quicksort(array, p + 1, hi); + hi = p-1; + } } return array; From 4536a78e4373861a55d23651fddfcab861875f3b Mon Sep 17 00:00:00 2001 From: Juan Lopes Date: Fri, 20 Feb 2015 12:58:08 -0200 Subject: [PATCH 181/280] fixing spacing --- src/algorithms/sorting/quicksort.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/algorithms/sorting/quicksort.js b/src/algorithms/sorting/quicksort.js index aff9875..446b7c0 100644 --- a/src/algorithms/sorting/quicksort.js +++ b/src/algorithms/sorting/quicksort.js @@ -14,12 +14,12 @@ var quicksortInit = function (array, comparatorFn) { var p = partition(array, comparator, lo, hi); //Chooses only the smallest partition to use recursion on and //tail-optimize the other. This guarantees O(log n) space in worst case. - if (p-lo < hi-p) { + if (p - lo < hi - p) { quicksort(array, lo, p - 1); - lo = p+1; + lo = p + 1; } else { quicksort(array, p + 1, hi); - hi = p-1; + hi = p - 1; } } From fe1c5415b23eb4c80148ec3d3aa22333dc926a1c Mon Sep 17 00:00:00 2001 From: Artem Gilmudinov Date: Mon, 3 Aug 2015 20:40:06 +0300 Subject: [PATCH 182/280] lcm algorithms based on Euclidean and Stein's algorithms --- src/algorithms/math/lcm.js | 30 ++++++++++++++++++++++++++++++ src/math.js | 1 + src/test/algorithms/math/lcm.js | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 src/algorithms/math/lcm.js create mode 100644 src/test/algorithms/math/lcm.js diff --git a/src/algorithms/math/lcm.js b/src/algorithms/math/lcm.js new file mode 100644 index 0000000..5b0b777 --- /dev/null +++ b/src/algorithms/math/lcm.js @@ -0,0 +1,30 @@ +'use strict'; + +var gcd = require('./gcd.js'); + +/** + * Algorithm to calculate Least Common Multiple based on Euclidean algorithm + * + * @param Number + * @param Number + * + * @return Number + */ +var lcmDivisionBased = function(a, b) { + return (a * b) / gcd(a, b); +}; + +/** + * Algorithm to calculate Least Common Multiple based on Stein's Algorithm + * + * @param Number + * @param Number + * + * @return Number + */ +var lcmBinaryIterative = function(a, b) { + return (a * b) / gcd.binary(a, b); +}; + +lcmDivisionBased.binary = lcmBinaryIterative; +module.exports = lcmDivisionBased; diff --git a/src/math.js b/src/math.js index b439a83..6431ac2 100644 --- a/src/math.js +++ b/src/math.js @@ -6,6 +6,7 @@ module.exports = { fisherYates: require('./algorithms/math/fisher_yates'), gcd: require('./algorithms/math/gcd'), extendedEuclidean: require('./algorithms/math/extended_euclidean'), + lcm: require('./algorithms/math/lcm'), newtonSqrt: require('./algorithms/math/newton_sqrt'), reservoirSampling: require('./algorithms/math/reservoir_sampling'), fastPower: require('./algorithms/math/fast_power'), diff --git a/src/test/algorithms/math/lcm.js b/src/test/algorithms/math/lcm.js new file mode 100644 index 0000000..764fd44 --- /dev/null +++ b/src/test/algorithms/math/lcm.js @@ -0,0 +1,32 @@ +'use strict'; + +var root = require('../../..'), + lcm = root.Math.lcm, + assert = require('assert'); + +describe('LCM', function () { + it('should calculate the correct LCM between two numbers ' + + 'using Euclidean algorithm', function () { + assert.equal(lcm(2, 3), 6); + assert.equal(lcm(0, 1), 0); + assert.equal(lcm(4, 9), 36); + assert.equal(lcm(39, 81), 1053); + assert.equal(lcm(10000000, 2), 10000000); + assert.equal(lcm(35, 49), 245); + assert.equal(lcm(7, 49), 49); + assert.equal(lcm(7, 5), 35); + }); + + it('should calculate the correct LCM between two numbers ' + + 'using the binary method', function () { + var lcmb = lcm.binary; + assert.equal(lcmb(2, 3), 6); + assert.equal(lcmb(0, 1), 0); + assert.equal(lcmb(4, 9), 36); + assert.equal(lcmb(39, 81), 1053); + assert.equal(lcmb(10000000, 2), 10000000); + assert.equal(lcmb(35, 49), 245); + assert.equal(lcmb(7, 49), 49); + assert.equal(lcmb(7, 5), 35); + }); +}); From 218089e8228fd3d9e2d401a15fd6731833c1b0f7 Mon Sep 17 00:00:00 2001 From: Artem Gilmudinov Date: Mon, 3 Aug 2015 20:48:22 +0300 Subject: [PATCH 183/280] fix spacing --- src/algorithms/math/lcm.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/algorithms/math/lcm.js b/src/algorithms/math/lcm.js index 5b0b777..b179b16 100644 --- a/src/algorithms/math/lcm.js +++ b/src/algorithms/math/lcm.js @@ -10,7 +10,7 @@ var gcd = require('./gcd.js'); * * @return Number */ -var lcmDivisionBased = function(a, b) { +var lcmDivisionBased = function (a, b) { return (a * b) / gcd(a, b); }; @@ -22,7 +22,7 @@ var lcmDivisionBased = function(a, b) { * * @return Number */ -var lcmBinaryIterative = function(a, b) { +var lcmBinaryIterative = function (a, b) { return (a * b) / gcd.binary(a, b); }; From 1cb5b972d7d9be3185a1e7b8d2ef77952bfc09ac Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 4 Aug 2015 16:00:38 +0200 Subject: [PATCH 184/280] Use eslint for linting instead of an old version of jshint --- .eslintrc | 91 +++++++++++++++++++ .jshintrc | 25 ----- Makefile | 8 +- package.json | 2 +- src/algorithms/graph/SPFA.js | 6 +- src/algorithms/graph/bellman_ford.js | 2 +- src/algorithms/graph/breadth_first_search.js | 2 +- src/algorithms/graph/depth_first_search.js | 2 +- src/algorithms/graph/euler_path.js | 4 +- src/algorithms/graph/floyd_warshall.js | 4 +- src/algorithms/graph/prim.js | 4 +- src/algorithms/math/fast_power.js | 2 +- src/algorithms/math/gcd.js | 3 +- src/algorithms/math/power_set.js | 9 +- src/algorithms/sorting/counting_sort.js | 3 +- src/algorithms/sorting/radix_sort.js | 3 +- src/algorithms/sorting/selection_sort.js | 2 +- src/algorithms/string/hamming.js | 4 +- src/algorithms/string/huffman.js | 6 +- src/algorithms/string/levenshtein.js | 2 +- .../string/longest_common_subsequence.js | 2 +- .../string/longest_common_substring.js | 2 +- src/data_structures/disjoint_set_forest.js | 8 +- src/test/algorithms/graph/SPFA.js | 6 +- .../algorithms/graph/minimum_spanning_tree.js | 4 +- src/test/algorithms/math/fisher_yates.js | 2 + src/test/algorithms/math/power_set.js | 2 +- .../sorting/sorting_tests_helper.js | 2 +- src/test/data_structures/bst.js | 2 +- .../data_structures/disjoint_set_forest.js | 2 +- src/util/comparator.js | 2 +- 31 files changed, 144 insertions(+), 74 deletions(-) create mode 100644 .eslintrc delete mode 100644 .jshintrc diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..020dc76 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,91 @@ +{ + "env": { + "jasmine": true, + "node": true, + "mocha": true, + "browser": true, + "builtin": true + }, + "globals": { + "describe": false, + "it": false, + "before": false, + "beforeEach": false, + "after": false, + "afterEach": false, + "system": false, + "phantom": false + }, + "rules": { + "block-scoped-var": 2, + "camelcase": 2, + "comma-style": [ + 2, + "last" + ], + "curly": [ + 0, + "all" + ], + "dot-notation": [ + 2, + { + "allowKeywords": true, + "allowPattern": "^[a-z]+(_[a-z]+)+$" + } + ], + "eqeqeq": [ + 2, + "allow-null" + ], + "strict": [ + 2, + "global" + ], + "guard-for-in": 2, + "max-len": [ + 2, + 80, + 2 + ], + "new-cap": 2, + "no-caller": 2, + "no-cond-assign": [ + 2, + "except-parens" + ], + "no-debugger": 2, + "no-empty": 2, + "no-eval": 2, + "no-extend-native": 2, + "no-extra-parens": 0, + "no-irregular-whitespace": 2, + "no-iterator": 2, + "no-loop-func": 2, + "no-multi-str": 2, + "no-new": 2, + "no-plusplus": 0, + "no-proto": 2, + "no-script-url": 2, + "no-sequences": 2, + "no-shadow": 0, + "no-undef": 2, + "no-underscore-dangle": 0, + "no-unused-vars": 2, + "no-use-before-define": 0, + "no-with": 2, + "quotes": [ + 2, + "single" + ], + "semi": [ + 0, + "never" + ], + "valid-typeof": 2, + "wrap-iife": [ + 2, + "inside" + ] + } +} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 360f591..0000000 --- a/.jshintrc +++ /dev/null @@ -1,25 +0,0 @@ -{ - "node": true, - "browser": true, - "camelcase": true, - "immed": true, - "indent": 2, - "newcap": true, - "noempty": true, - "quotmark": "single", - "undef": true, - "unused": true, - "strict": true, - "maxlen": 80, - "white": true, - "trailing": true, - "curly": false, - "globals": { - "describe" : false, - "it" : false, - "before" : false, - "beforeEach" : false, - "after" : false, - "afterEach" : false - } -} diff --git a/Makefile b/Makefile index 0278110..1151423 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -all: jshint coverage +all: lint coverage setup: npm install @@ -13,10 +13,10 @@ dist: all cp README.md _build cp CHANGELOG _build -jshint: setup - jshint src +lint: setup + eslint src -test: jshint +test: lint mocha -R spec --recursive src/test coverage: setup diff --git a/package.json b/package.json index a2ec61c..0a4a922 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ "dependencies": {}, "devDependencies": { "coveralls": "^2.11.2", + "eslint": "^1.0.0", "istanbul": "^0.3.5", - "jshint": "~2.4.4", "mocha": "^2.1.0" }, "repository": { diff --git a/src/algorithms/graph/SPFA.js b/src/algorithms/graph/SPFA.js index 23d1000..c9affff 100644 --- a/src/algorithms/graph/SPFA.js +++ b/src/algorithms/graph/SPFA.js @@ -8,7 +8,7 @@ * @param {string} start the starting node * */ -function SPFA(graph, s) { +function spfa(graph, s) { var distance = {}; var previous = {}; var queue = {}; @@ -30,7 +30,7 @@ function SPFA(graph, s) { }); var currNode; - while (head != tail) { + while (head !== tail) { currNode = queue[head++]; isInQue[currNode] = false; var neighbors = graph.neighbors(currNode); @@ -61,4 +61,4 @@ function SPFA(graph, s) { }; } -module.exports = SPFA; +module.exports = spfa; diff --git a/src/algorithms/graph/bellman_ford.js b/src/algorithms/graph/bellman_ford.js index 14b5e7f..5d669f9 100644 --- a/src/algorithms/graph/bellman_ford.js +++ b/src/algorithms/graph/bellman_ford.js @@ -61,7 +61,7 @@ var bellmanFord = function (graph, startNode) { } // If the loop did not break early, then there is a negative-weighted cycle. - if (iteration == adjacencyListSize) { + if (iteration === adjacencyListSize) { // Empty 'distance' object indicates Negative-Weighted Cycle return { distance: {} diff --git a/src/algorithms/graph/breadth_first_search.js b/src/algorithms/graph/breadth_first_search.js index b1da718..79c2ab3 100644 --- a/src/algorithms/graph/breadth_first_search.js +++ b/src/algorithms/graph/breadth_first_search.js @@ -41,7 +41,7 @@ var normalizeCallbacks = function (callbacks, seenVertices) { return false; } }; - }()); + })(); var noop = function () {}; callbacks.onTraversal = callbacks.onTraversal || noop; diff --git a/src/algorithms/graph/depth_first_search.js b/src/algorithms/graph/depth_first_search.js index 739e72c..1adc30d 100644 --- a/src/algorithms/graph/depth_first_search.js +++ b/src/algorithms/graph/depth_first_search.js @@ -41,7 +41,7 @@ var normalizeCallbacks = function (callbacks, seenVertices) { } return false; }; - }()); + })(); var noop = function () {}; callbacks.beforeTraversal = callbacks.beforeTraversal || noop; diff --git a/src/algorithms/graph/euler_path.js b/src/algorithms/graph/euler_path.js index c63c765..d33c9b0 100644 --- a/src/algorithms/graph/euler_path.js +++ b/src/algorithms/graph/euler_path.js @@ -48,12 +48,12 @@ var eulerEndpoints = function (graph) { var start, finish, v; graph.vertices.forEach(function (vertex) { - if (rank[vertex] == 1) { + if (rank[vertex] === 1) { if (start) { throw new Error('Duplicate start vertex.'); } start = vertex; - } else if (rank[vertex] == -1) { + } else if (rank[vertex] === -1) { if (finish) { throw new Error('Duplicate finish vertex.'); } diff --git a/src/algorithms/graph/floyd_warshall.js b/src/algorithms/graph/floyd_warshall.js index a064bf8..7fe9b74 100644 --- a/src/algorithms/graph/floyd_warshall.js +++ b/src/algorithms/graph/floyd_warshall.js @@ -72,7 +72,7 @@ var floydWarshall = function (graph) { var path = [src]; - if (src != dest) { + if (src !== dest) { (function pushInOrder(src, dest) { if (middleVertex[src][dest] === undefined) { path.push(dest); @@ -81,7 +81,7 @@ var floydWarshall = function (graph) { pushInOrder(src, middle); pushInOrder(middle, dest); } - }(src, dest)); + })(src, dest); } return path; diff --git a/src/algorithms/graph/prim.js b/src/algorithms/graph/prim.js index 603f490..dac9aad 100644 --- a/src/algorithms/graph/prim.js +++ b/src/algorithms/graph/prim.js @@ -25,7 +25,7 @@ var prim = function (graph) { q.insert(vertex, Infinity); }); - var relax = function (neighbor) { + var relax = function (vertex, neighbor) { var weight = graph.edge(vertex, neighbor); if (weight < q.priority(neighbor)) { q.changePriority(neighbor, weight); @@ -45,7 +45,7 @@ var prim = function (graph) { mst.addVertex(vertex); } - graph.neighbors(vertex).forEach(relax); + graph.neighbors(vertex).forEach(relax.bind(null, vertex)); } return mst; diff --git a/src/algorithms/math/fast_power.js b/src/algorithms/math/fast_power.js index a3d7a91..ce5bbcc 100644 --- a/src/algorithms/math/fast_power.js +++ b/src/algorithms/math/fast_power.js @@ -22,7 +22,7 @@ var fastPower = function (base, power, mul, identity) { mul = multiplicationOperator; identity = 1; } - if (power < 0 || Math.floor(power) != power) { + if (power < 0 || Math.floor(power) !== power) { throw new Error('Power must be a positive integer or zero.'); } diff --git a/src/algorithms/math/gcd.js b/src/algorithms/math/gcd.js index 7468778..b58cf67 100644 --- a/src/algorithms/math/gcd.js +++ b/src/algorithms/math/gcd.js @@ -43,9 +43,10 @@ var gcdBinaryIterative = function (a, b) { return a; } + var shift; // Let shift = log(K), where K is the greatest power of 2 // dividing both a and b - for (var shift = 0; ((a | b) & 1) === 0; ++shift) { + for (shift = 0; ((a | b) & 1) === 0; ++shift) { a >>= 1; b >>= 1; } diff --git a/src/algorithms/math/power_set.js b/src/algorithms/math/power_set.js index 585342c..716cb32 100644 --- a/src/algorithms/math/power_set.js +++ b/src/algorithms/math/power_set.js @@ -15,8 +15,9 @@ var powerSetIterative = function (array) { var powerSet = []; var cache = []; + var i; - for (var i = 0; i < array.length; i++) { + for (i = 0; i < array.length; i++) { cache[i] = true; } @@ -46,11 +47,9 @@ var powerSetIterative = function (array) { var powerSetRecursive = function (array) { if (array.length === 0) { return []; - } - else if (array.length == 1) { + } else if (array.length === 1) { return [ [], [ array[0] ] ]; - } - else { + } else { var powerSet = []; var firstElem = array[0]; diff --git a/src/algorithms/sorting/counting_sort.js b/src/algorithms/sorting/counting_sort.js index 0814b34..087de59 100644 --- a/src/algorithms/sorting/counting_sort.js +++ b/src/algorithms/sorting/counting_sort.js @@ -15,8 +15,9 @@ var countingSort = function (array) { var max = maximumKey(array); var auxiliaryArray = []; var length = array.length; + var i; - for (var i = 0; i < length; i++) { + for (i = 0; i < length; i++) { var position = array[i].key; if (auxiliaryArray[position] === undefined) { diff --git a/src/algorithms/sorting/radix_sort.js b/src/algorithms/sorting/radix_sort.js index 33eef98..78f51d4 100644 --- a/src/algorithms/sorting/radix_sort.js +++ b/src/algorithms/sorting/radix_sort.js @@ -40,8 +40,9 @@ var radixSort = function (array) { var auxiliaryCountingSort = function (array, mod) { var length = array.length; var bucket = []; + var i; - for (var i = 0; i < 10; i++) { + for (i = 0; i < 10; i++) { bucket[i] = []; } diff --git a/src/algorithms/sorting/selection_sort.js b/src/algorithms/sorting/selection_sort.js index f35ed12..4451049 100644 --- a/src/algorithms/sorting/selection_sort.js +++ b/src/algorithms/sorting/selection_sort.js @@ -13,7 +13,7 @@ var selectionSort = function (a, comparatorFn) { min = j; } } - if (min != i) { + if (min !== i) { var tmp = a[i]; a[i] = a[min]; a[min] = tmp; diff --git a/src/algorithms/string/hamming.js b/src/algorithms/string/hamming.js index 5dccf95..ec783cf 100644 --- a/src/algorithms/string/hamming.js +++ b/src/algorithms/string/hamming.js @@ -9,14 +9,14 @@ 'use strict'; var hamming = function (a, b) { - if (a.length != b.length) { + if (a.length !== b.length) { throw new Error('Strings must be equal in length'); } var dist = 0; for (var i = 0; i < a.length; i++) { - if (a[i] != b[i]) { + if (a[i] !== b[i]) { dist++; } } diff --git a/src/algorithms/string/huffman.js b/src/algorithms/string/huffman.js index 5895535..644018f 100644 --- a/src/algorithms/string/huffman.js +++ b/src/algorithms/string/huffman.js @@ -26,7 +26,7 @@ var compress = function (string) { currentBlock = (currentBlock << 1) | char; currentBlockSize += 1; - if (currentBlockSize == MAX_BLOCK_SIZE) { + if (currentBlockSize === MAX_BLOCK_SIZE) { blocks.push(currentBlock); currentBlock = currentBlockSize = 0; } @@ -54,7 +54,7 @@ var decompress = function (array) { if (!array.length) { return ''; } - else if (array.length == 1) { + else if (array.length === 1) { throw new Error('Compressed array must be either empty ' + 'or at least 2 blocks big.'); } @@ -145,7 +145,7 @@ huffman.encode = function (string, compressed) { unroll(a); unroll(b); } - }(root)); + })(root); var encoding = letters.reduce(function (acc, letter) { acc[letter.char] = letter.code.split('').reverse().join(''); diff --git a/src/algorithms/string/levenshtein.js b/src/algorithms/string/levenshtein.js index c738002..4f88f42 100644 --- a/src/algorithms/string/levenshtein.js +++ b/src/algorithms/string/levenshtein.js @@ -39,7 +39,7 @@ var levenshtein = function (a, b) { editDistance[i - 1][j], // if we delete the char from a editDistance[i][j - 1] // if we add the char from b ) + - (a[i - 1] != b[j - 1] ? 1 : 0); + (a[i - 1] !== b[j - 1] ? 1 : 0); } } diff --git a/src/algorithms/string/longest_common_subsequence.js b/src/algorithms/string/longest_common_subsequence.js index c698ba7..5f2d72a 100644 --- a/src/algorithms/string/longest_common_subsequence.js +++ b/src/algorithms/string/longest_common_subsequence.js @@ -20,7 +20,7 @@ var longestCommonSubsequence = function (s1, s2) { // Fill in the cache for (i = 1; i <= s1.length; i++) { for (j = 1; j <= s2.length; j++) { - if (s1[i - 1] == s2[j - 1]) { + if (s1[i - 1] === s2[j - 1]) { cache[i][j] = cache[i - 1][j - 1] + 1; } else { cache[i][j] = Math.max(cache[i][j - 1], cache[i - 1][j]); diff --git a/src/algorithms/string/longest_common_substring.js b/src/algorithms/string/longest_common_substring.js index 8a349f9..d083fcf 100644 --- a/src/algorithms/string/longest_common_substring.js +++ b/src/algorithms/string/longest_common_substring.js @@ -23,7 +23,7 @@ var longestCommonSubstring = function (s1, s2) { // Fill in the cache for (i = 1; i <= s1.length; i++) { for (j = 1; j <= s2.length; j++) { - if (s1[i - 1] == s2[j - 1]) { + if (s1[i - 1] === s2[j - 1]) { cache[i][j] = cache[i - 1][j - 1] + 1; if (cache[i][j] > lcsLength) { lcsPosition.i = i; diff --git a/src/data_structures/disjoint_set_forest.js b/src/data_structures/disjoint_set_forest.js index e9028b0..99b4c02 100644 --- a/src/data_structures/disjoint_set_forest.js +++ b/src/data_structures/disjoint_set_forest.js @@ -35,7 +35,7 @@ DisjointSetForest.prototype.sameSubset = function (element) { var root = this.root(element); return [].slice.call(arguments, 1).every(function (element) { this._introduce(element); - return this.root(element) == root; + return this.root(element) === root; }.bind(this)); }; @@ -51,7 +51,7 @@ DisjointSetForest.prototype.sameSubset = function (element) { */ DisjointSetForest.prototype.root = function (element) { this._introduce(element); - if (this._parents[element] != element) { + if (this._parents[element] !== element) { this._parents[element] = this.root(this._parents[element]); } return this._parents[element]; @@ -94,10 +94,10 @@ DisjointSetForest.prototype.merge = function merge(element1, element2) { this._parents[root1] = root2; this._sizes[root2] += this._sizes[root1]; } - else if (root1 != root2) { + else if (root1 !== root2) { this._parents[root2] = root1; this._sizes[root1] += this._sizes[root2]; - if (this._ranks[root1] == this._ranks[root2]) { + if (this._ranks[root1] === this._ranks[root2]) { this._ranks[root1] += 1; } } diff --git a/src/test/algorithms/graph/SPFA.js b/src/test/algorithms/graph/SPFA.js index db23a35..0560e8e 100644 --- a/src/test/algorithms/graph/SPFA.js +++ b/src/test/algorithms/graph/SPFA.js @@ -1,7 +1,7 @@ 'use strict'; var root = require('../../../'), - SPFA = root.Graph.SPFA, + spfa = root.Graph.SPFA, Graph = root.DataStructures.Graph, assert = require('assert'); @@ -19,7 +19,7 @@ describe('SPFA Algorithm', function () { graph.addEdge('e', 'd', -3); graph.addEdge('d', 'c', 5); - var shortestPaths = SPFA(graph, 'a'); + var shortestPaths = spfa(graph, 'a'); assert.equal(shortestPaths.distance.a, 0); assert.equal(shortestPaths.distance.d, -2); @@ -30,7 +30,7 @@ describe('SPFA Algorithm', function () { // It'll cause a Negative-Weighted Cycle. graph.addEdge('c', 'a', -9); - shortestPaths = SPFA(graph, 'a'); + shortestPaths = spfa(graph, 'a'); // The 'distance' object is empty assert.equal(shortestPaths.distance.a, undefined); diff --git a/src/test/algorithms/graph/minimum_spanning_tree.js b/src/test/algorithms/graph/minimum_spanning_tree.js index 93fecf7..1191886 100644 --- a/src/test/algorithms/graph/minimum_spanning_tree.js +++ b/src/test/algorithms/graph/minimum_spanning_tree.js @@ -45,7 +45,7 @@ describe('Minimum Spanning Tree', function () { * @return {boolean} */ var isForest = function (graph, connectivity) { - if (graph.directed || numberOfConnectedComponents(graph) != connectivity) { + if (graph.directed || numberOfConnectedComponents(graph) !== connectivity) { return false; } var numberOfEdges = 0; @@ -57,7 +57,7 @@ describe('Minimum Spanning Tree', function () { } }); }); - return graph.vertices.size == numberOfEdges + connectivity; + return graph.vertices.size === numberOfEdges + connectivity; }; diff --git a/src/test/algorithms/math/fisher_yates.js b/src/test/algorithms/math/fisher_yates.js index 8142dc2..7112538 100644 --- a/src/test/algorithms/math/fisher_yates.js +++ b/src/test/algorithms/math/fisher_yates.js @@ -14,9 +14,11 @@ describe('Fisher-Yates', function () { describe('should be able to be used as Array.suffle', function () { var a = [1, 2, 3, 4, 5]; assert.equal(a.shuffle, undefined); + /* eslint-disable no-extend-native */ Array.prototype.shuffle = function () { fisherYates(this); }; + /* eslint-enable no-extend-native */ a.shuffle(); assert.notDeepEqual(a, [1, 2, 3, 4, 5]); }); diff --git a/src/test/algorithms/math/power_set.js b/src/test/algorithms/math/power_set.js index aba6ea6..d10ce66 100644 --- a/src/test/algorithms/math/power_set.js +++ b/src/test/algorithms/math/power_set.js @@ -7,7 +7,7 @@ var math = require('../../..').Math, function testArrayEqual(a, b) { var arrayEqual = true; a.forEach(function (elem, index) { - if (a[index] != b[index]) { + if (a[index] !== b[index]) { arrayEqual = false; } }); diff --git a/src/test/algorithms/sorting/sorting_tests_helper.js b/src/test/algorithms/sorting/sorting_tests_helper.js index e01f43f..68932a9 100644 --- a/src/test/algorithms/sorting/sorting_tests_helper.js +++ b/src/test/algorithms/sorting/sorting_tests_helper.js @@ -30,7 +30,7 @@ module.exports = { ['z', 'car', 'apple', 'banana']); var reverseSort = function (a, b) { - if (a == b) return 0; + if (a === b) return 0; return a < b ? 1 : -1; }; assert.deepEqual(sortFn([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], diff --git a/src/test/data_structures/bst.js b/src/test/data_structures/bst.js index b0432d6..190e168 100644 --- a/src/test/data_structures/bst.js +++ b/src/test/data_structures/bst.js @@ -170,7 +170,7 @@ describe('Binary Search Tree', function () { describe('Binary Search Tree with custom comparator', function () { var strLenCompare = function (a, b) { - if (a.length == b.length) return 0; + if (a.length === b.length) return 0; return a.length < b.length ? -1 : 1; }; diff --git a/src/test/data_structures/disjoint_set_forest.js b/src/test/data_structures/disjoint_set_forest.js index abdb16e..a640cdb 100644 --- a/src/test/data_structures/disjoint_set_forest.js +++ b/src/test/data_structures/disjoint_set_forest.js @@ -60,7 +60,7 @@ describe('Disjoint Set Forest', function () { var forest = new DisjointSetForest(); var assertInside = function (value, set) { return set.some(function (element) { - return element == value; + return element === value; }); }; assert.equal(forest.root(0), 0); diff --git a/src/util/comparator.js b/src/util/comparator.js index 44e268b..e35578d 100644 --- a/src/util/comparator.js +++ b/src/util/comparator.js @@ -18,7 +18,7 @@ function Comparator(compareFn) { * Default implementation for the compare function */ Comparator.prototype.compare = function (a, b) { - if (a == b) return 0; + if (a === b) return 0; return a < b ? -1 : 1; }; From dae9e342f182e61147dc9ddb436b8daf62813c5a Mon Sep 17 00:00:00 2001 From: Artem Gilmudinov Date: Tue, 4 Aug 2015 19:35:42 +0300 Subject: [PATCH 185/280] LCM corner cases --- src/algorithms/math/lcm.js | 14 ++++++++++++-- src/test/algorithms/math/lcm.js | 12 ++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/algorithms/math/lcm.js b/src/algorithms/math/lcm.js index b179b16..555cf37 100644 --- a/src/algorithms/math/lcm.js +++ b/src/algorithms/math/lcm.js @@ -11,7 +11,12 @@ var gcd = require('./gcd.js'); * @return Number */ var lcmDivisionBased = function (a, b) { - return (a * b) / gcd(a, b); + if (a === 0 || b === 0) { + return 0; + } + a = Math.abs(a); + b = Math.abs(b); + return a / gcd(a, b) * b; }; /** @@ -23,7 +28,12 @@ var lcmDivisionBased = function (a, b) { * @return Number */ var lcmBinaryIterative = function (a, b) { - return (a * b) / gcd.binary(a, b); + if (a === 0 || b === 0) { + return 0; + } + a = Math.abs(a); + b = Math.abs(b); + return a / gcd.binary(a, b) * b; }; lcmDivisionBased.binary = lcmBinaryIterative; diff --git a/src/test/algorithms/math/lcm.js b/src/test/algorithms/math/lcm.js index 764fd44..0104b33 100644 --- a/src/test/algorithms/math/lcm.js +++ b/src/test/algorithms/math/lcm.js @@ -15,6 +15,12 @@ describe('LCM', function () { assert.equal(lcm(35, 49), 245); assert.equal(lcm(7, 49), 49); assert.equal(lcm(7, 5), 35); + assert.equal(lcm(0, 0), 0); + assert.equal(lcm(0, 9), 0); + assert.equal(lcm(0, -9), 0); + assert.equal(lcm(-9, -18), 18); + assert.equal(lcm(-7, 9), 63); + assert.equal(lcm(-7, -9), 63); }); it('should calculate the correct LCM between two numbers ' + @@ -28,5 +34,11 @@ describe('LCM', function () { assert.equal(lcmb(35, 49), 245); assert.equal(lcmb(7, 49), 49); assert.equal(lcmb(7, 5), 35); + assert.equal(lcmb(0, 0), 0); + assert.equal(lcmb(0, 9), 0); + assert.equal(lcmb(0, -9), 0); + assert.equal(lcmb(-9, -18), 18); + assert.equal(lcmb(-7, 9), 63); + assert.equal(lcmb(-7, -9), 63); }); }); From 3ac982e1530956ebec39a0c79cb4048b9e789d2f Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 4 Aug 2015 21:00:08 +0200 Subject: [PATCH 186/280] Update dependencies --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 0a4a922..7549e24 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,10 @@ "main": "./index.js", "dependencies": {}, "devDependencies": { - "coveralls": "^2.11.2", + "coveralls": "^2.11.3", "eslint": "^1.0.0", - "istanbul": "^0.3.5", - "mocha": "^2.1.0" + "istanbul": "^0.3.17", + "mocha": "^2.2.5" }, "repository": { "type": "git", From 586ab8e8e01466d9731ce95462bb5518973dfde5 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 4 Aug 2015 21:08:20 +0200 Subject: [PATCH 187/280] Add pre-commit hook --- Makefile | 4 ++-- package.json | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 1151423..f77dbe5 100644 --- a/Makefile +++ b/Makefile @@ -14,10 +14,10 @@ dist: all cp CHANGELOG _build lint: setup - eslint src + npm run lint test: lint - mocha -R spec --recursive src/test + npm test coverage: setup istanbul cover ./node_modules/.bin/_mocha -- -R spec --recursive src/test diff --git a/package.json b/package.json index 7549e24..7038b53 100644 --- a/package.json +++ b/package.json @@ -2,16 +2,22 @@ "name": "algorithms", "version": "0.9.0", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", - "directories": { - "test": "test" - }, "main": "./index.js", + "scripts": { + "lint": "eslint src/", + "test": "mocha -R spec --recursive src/test" + }, + "pre-commit": [ + "lint", + "test" + ], "dependencies": {}, "devDependencies": { "coveralls": "^2.11.3", "eslint": "^1.0.0", "istanbul": "^0.3.17", - "mocha": "^2.2.5" + "mocha": "^2.2.5", + "pre-commit": "^1.1.1" }, "repository": { "type": "git", From 4c90c34eed237e2b219aacf8e85e3ef1cb15915f Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 4 Aug 2015 21:18:58 +0200 Subject: [PATCH 188/280] Remove duplicated code from LCM --- src/algorithms/math/lcm.js | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/algorithms/math/lcm.js b/src/algorithms/math/lcm.js index 555cf37..bd29e8d 100644 --- a/src/algorithms/math/lcm.js +++ b/src/algorithms/math/lcm.js @@ -3,38 +3,46 @@ var gcd = require('./gcd.js'); /** - * Algorithm to calculate Least Common Multiple based on Euclidean algorithm + * Calcule the Least Common Multiple with a given Greatest Common Denominator + * function * * @param Number * @param Number + * @param Function * * @return Number */ -var lcmDivisionBased = function (a, b) { - if (a === 0 || b === 0) { +var genericLCM = function (gcdFunction, a, b) { + if (a === 0 || b === 0) { return 0; } a = Math.abs(a); b = Math.abs(b); - return a / gcd(a, b) * b; + return a / gcdFunction(a, b) * b; }; +/** + * Algorithm to calculate Least Common Multiple based on Euclidean algorithm + * calls the generic LCM function passing the division based GCD calculator + * + * @param Number + * @param Number + * + * @return Number + */ +var lcmDivisionBased = genericLCM.bind(null, gcd); + /** * Algorithm to calculate Least Common Multiple based on Stein's Algorithm + * calls the generic LCM function passing the binary interative GCD calculator * * @param Number * @param Number * * @return Number */ -var lcmBinaryIterative = function (a, b) { - if (a === 0 || b === 0) { - return 0; - } - a = Math.abs(a); - b = Math.abs(b); - return a / gcd.binary(a, b) * b; -}; +var lcmBinaryIterative = genericLCM.bind(null, gcd.binary); -lcmDivisionBased.binary = lcmBinaryIterative; -module.exports = lcmDivisionBased; +var lcm = lcmDivisionBased; +lcm.binary = lcmBinaryIterative; +module.exports = lcm; From 525c9c051cb5cf6f3111d2bfc55dd55ff1435928 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 5 Aug 2015 09:56:20 +0200 Subject: [PATCH 189/280] Add LCM to the README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e199726..b8bfce4 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ require('algorithms').Math; * fisherYates * gcd (Greatest common divisor) * extendedEuclidean +* lcm (Least common multiple) * newtonSqrt * reservoirSampling * fastPower From 6d986399eaeca6c4c47bbbd7a09223ab7eb2d229 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 5 Aug 2015 09:57:16 +0200 Subject: [PATCH 190/280] 0.9.1 --- bundle/algorithms.browser.min.js | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bundle/algorithms.browser.min.js b/bundle/algorithms.browser.min.js index dcc67db..271bbe5 100644 --- a/bundle/algorithms.browser.min.js +++ b/bundle/algorithms.browser.min.js @@ -1,3 +1,3 @@ -/* algorithms.js v0.9.0 | (c) 2015 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ -!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u==o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":49}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":43,"../../data_structures/graph":44}],10:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r){var e=t.edge(u,r);er||Math.floor(r)!=r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;for(var e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],18:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":58}],19:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];for(var r=[],e=[],n=0;nt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],21:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],22:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":49}],23:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":58}],26:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=[],i=t.length,o=0;i>o;o++){var s=t[o].key;void 0===e[s]&&(e[s]=[]),e[s].push(t[o])}t=[];var a=0;for(o=0;r>=o;o++)if(void 0!==e[o])for(var u=e[o].length,h=0;u>h;h++)t[a++]=e[o][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],27:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":46}],28:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":58}],29:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne){var s=i(r,n,e,o);t(r,e,s-1),t(r,s+1,o)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":58}],31:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){for(var e=t.length,n=[],i=0;10>i;i++)n[i]=[];for(i=0;e>i;i++){var o=parseInt((t[i].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[i])}var s=0;for(i=0;10>i;i++)for(var a=n[i].length,u=0;a>u;u++)t[s++]=n[i][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],32:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!=o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":58}],33:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":58}],34:[function(t,r){"use strict";var e=function(t,r){if(t.length!=r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i==n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1==t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),_=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(_):_}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],36:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],37:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!=r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],38:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length;e++)i[e]=new Int32Array(r.length+1);for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=t[e-1]==r[n-1]?i[e-1][n-1]+1:Math.max(i[e][n-1],i[e-1][n]);e=t.length,n=r.length;for(var o="";0!==i[e][n];)t[e-1]===r[n-1]?(o=t[e-1]+o,e--,n--):i[e-1][n]>i[e][n-1]?e--:n--;return o};r.exports=e},{}],39:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length+1;e++)i[e]=new Int32Array(r.length+1);var o={},s=0;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)t[e-1]==r[n-1]?(i[e][n]=i[e-1][n-1]+1,i[e][n]>s&&(o.i=e,o.j=n,s=i[e][n])):i[e][n]=0;var a="";return s&&(a=t.substring(o.i-s,o.i)),a};r.exports=e},{}],40:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":58}],47:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],48:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[53])(53)})}({},function(){return this}()); \ No newline at end of file +/* algorithms.js v0.9.1 | (c) 2015 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ +!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u===o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":51}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":44,"../../data_structures/graph":46}],10:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r,e){var n=t.edge(r,e);nr||Math.floor(r)!==r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;var e;for(e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],19:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":60}],20:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];var r,e=[],n=[];for(r=0;rt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],22:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],23:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":51}],24:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":60}],27:[function(t,r){"use strict";var e=function(t){var r,e=n(t),i=[],o=t.length;for(r=0;o>r;r++){var s=t[r].key;void 0===i[s]&&(i[s]=[]),i[s].push(t[r])}t=[];var a=0;for(r=0;e>=r;r++)if(void 0!==i[r])for(var u=i[r].length,h=0;u>h;h++)t[a++]=i[r][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],28:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":48}],29:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":60}],30:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne;){var s=i(r,n,e,o);o-s>s-e?(t(r,e,s-1),e=s+1):(t(r,s+1,o),o=s-1)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":60}],32:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){var e,n=t.length,i=[];for(e=0;10>e;e++)i[e]=[];for(e=0;n>e;e++){var o=parseInt((t[e].key/Math.pow(10,r)).toFixed(r))%10;i[o].push(t[e])}var s=0;for(e=0;10>e;e++)for(var a=i[e].length,u=0;a>u;u++)t[s++]=i[e][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],33:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!==o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":60}],34:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":60}],35:[function(t,r){"use strict";var e=function(t,r){if(t.length!==r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i===n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1===t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),m=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(m):m}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],37:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],38:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!==r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],39:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length;e++)i[e]=new Int32Array(r.length+1);for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=t[e-1]===r[n-1]?i[e-1][n-1]+1:Math.max(i[e][n-1],i[e-1][n]);e=t.length,n=r.length;for(var o="";0!==i[e][n];)t[e-1]===r[n-1]?(o=t[e-1]+o,e--,n--):i[e-1][n]>i[e][n-1]?e--:n--;return o};r.exports=e},{}],40:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length+1;e++)i[e]=new Int32Array(r.length+1);var o={},s=0;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)t[e-1]===r[n-1]?(i[e][n]=i[e-1][n-1]+1,i[e][n]>s&&(o.i=e,o.j=n,s=i[e][n])):i[e][n]=0;var a="";return s&&(a=t.substring(o.i-s,o.i)),a};r.exports=e},{}],41:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]0;t-=t&-t)r+=this._elements[t];return r},e.prototype.rangeSum=function(t,r){return this.prefixSum(r)-this.prefixSum(t-1)},r.exports=e},{}],46:[function(t,r){"use strict";function e(t){this.directed=void 0===t?!0:!!t,this.adjList=Object.create(null),this.vertices=new n}var n=t("./set"),i=function(t){return""+t};e.prototype.addVertex=function(t){if(t=i(t),this.vertices.contains(t))throw new Error('Vertex "'+t+'" has already been added');this.vertices.add(t),this.adjList[t]=Object.create(null)},e.prototype.addEdge=function(t,r,e){t=i(t),r=i(r),e=void 0===e?1:e,this.adjList[t]||this.addVertex(t),this.adjList[r]||this.addVertex(r),this.adjList[t][r]=(this.adjList[t][r]||0)+e,this.directed||(this.adjList[r][t]=(this.adjList[r][t]||0)+e)},e.prototype.neighbors=function(t){return Object.keys(this.adjList[i(t)])},e.prototype.edge=function(t,r){return this.adjList[i(t)][i(r)]},r.exports=e},{"./set":52}],47:[function(t,r){"use strict";function e(t){this._table=new Array(t||64),this._items=0,Object.defineProperty(this,"capacity",{get:function(){return this._table.length}}),Object.defineProperty(this,"size",{get:function(){return this._items}})}var n=t("./linked_list");e.prototype.hash=function(t){"string"!=typeof t&&(t=JSON.stringify(t));for(var r=0,e=0;e1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":60}],49:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],50:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[55])(55)})}({},function(){return this}()); \ No newline at end of file diff --git a/package.json b/package.json index 7038b53..d417386 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.9.0", + "version": "0.9.1", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "main": "./index.js", "scripts": { From 2fbfe2075f91a838c0e1d2db4e849b42f27f8cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20Falc=C3=A3o?= Date: Thu, 20 Aug 2015 00:35:10 -0300 Subject: [PATCH 191/280] AVL Tree AVL Tree data structure and its test. --- src/data_structures.js | 1 + src/data_structures/avl_tree.js | 528 +++++++++++++++++++++++++++ src/test/data_structures/avl-tree.js | 109 ++++++ 3 files changed, 638 insertions(+) create mode 100644 src/data_structures/avl_tree.js create mode 100644 src/test/data_structures/avl-tree.js diff --git a/src/data_structures.js b/src/data_structures.js index b88cf99..b14d633 100644 --- a/src/data_structures.js +++ b/src/data_structures.js @@ -2,6 +2,7 @@ // Data Structures module.exports = { + AVLTree: require('./data_structures/avl_tree'), BST: require('./data_structures/bst'), Graph: require('./data_structures/graph'), HashTable: require('./data_structures/hash_table'), diff --git a/src/data_structures/avl_tree.js b/src/data_structures/avl_tree.js new file mode 100644 index 0000000..ac4bbae --- /dev/null +++ b/src/data_structures/avl_tree.js @@ -0,0 +1,528 @@ +'use strict'; + +/** + * AVL Tree + */ +function AVLTree() { + this.root = null; +} + +/** + * Tree node + */ +function Node(value, left, right, parent, height) { + this.value = value; + this.left = left; + this.right = right; + this.parent = parent; + this.height = height; +} + +/** + * Calculates the height of a node based on height + * property of all his children. + */ +AVLTree.prototype.getNodeHeight = function(node) { + if (node.left !== null && node.right !== null) { + var height = Math.max(node.left.height, node.right.height); + height += 1; + return height; + } else if (node.left !== null) { + return node.left.height + 1; + } else if (node.right !== null) { + return node.right.height + 1; + } else { + return 1; + } +}; + +/** + * Verifies if the given node is balanced. + */ +AVLTree.prototype.isNodeBalanced = function(node) { + if (node.left !== null && node.right !== null) { + return (Math.abs(node.left.height - node.right.height) <= 1); + } + if (node.right !== null && node.left === null) { + return node.right.height < 2; + } + if (node.left !== null && node.right === null) { + return node.left.height < 2; + } + return true; +}; + +/** + * When a removal happens, some nodes need to be + * restructured. Gets and return these nodes. + */ +AVLTree.prototype.getNodesToRestructureAfterRemove = function(traveledNodes) { + // z is last traveled node - imbalance found at z + var zIndex = traveledNodes.length; + zIndex -= 1; + var z = traveledNodes[zIndex]; + + // y should be child of z with larger height + // (cannot be ancestor of removed node) + var y; + if (z.left !== null && z.right !== null) { + y = (z.left === y) ? z.right : z.left; + } else if (z.left !== null && z.right === null) { + y = z.left; + } else if (z.right !== null && z.left === null) { + y = z.right; + } + + // x should be tallest child of y + // If children same height, x should be child of y + // that has same orientation as z to y + var x; + if (y.left !== null && y.right !== null) { + if (y.left.height > y.right.height) { + x = y.left; + } else if (y.left.height < y.right.height) { + x = y.right; + } else if (y.left.height === y.right.height) { + x = (z.left === y) ? y.left : y.right; + } + } else if (y.left !== null && y.right === null) { + x = y.left; + } else if (y.right !== null && y.left === null) { + x = y.right; + } + return [x, y, z]; +}; + +/** + * When a insertion happens, some nodes need to be + * restructured. Gets and return these nodes. + */ +AVLTree.prototype.getNodesToRestructureAfterInsert = function(traveledNodes) { + // z is last traveled node - imbalance found at z + var zIndex = traveledNodes.length; + zIndex -= 1; + var z = traveledNodes[zIndex]; + + // y should be child of z with larger height + // (must be ancestor of inserted node) + // therefore, last traveled node is correct. + var yIndex = traveledNodes.length; + yIndex -= 2; + var y = traveledNodes[yIndex]; + + // x should be tallest child of y + // If children same height, x should be ancestor + // of inserted node (in traveled path) + var x; + if (y.left !== null && y.right !== null) { + if (y.left.height > y.right.height) { + x = y.left; + } else if (y.left.height < y.right.height) { + x = y.right; + } else if (y.left.height === y.right.height) { + var xIndex = traveledNodes.length; + xIndex -= 3; + x = traveledNodes[xIndex]; + } + } else if (y.left !== null && y.right === null) { + x = y.left; + } else if (y.right !== null && y.left === null) { + x = y.right; + } + return [x, y, z]; +} + +/** + * Keep the height balance property by walking to + * root and checking for invalid heights. + */ +AVLTree.prototype.keepHeightBalance = function(node, afterRemove) { + var current = node; + var traveledNodes = []; + while (current !== null) { + traveledNodes.push(current); + current.height = this.getNodeHeight(current); + if (!this.isNodeBalanced(current)) { + var nodesToBeRestructured = (afterRemove) ? + this.getNodesToRestructureAfterRemove(traveledNodes) : + this.getNodesToRestructureAfterInsert(traveledNodes); + this.restructure(nodesToBeRestructured); + } + current = current.parent; + } +}; + +/** + * Identifies and calls the appropriate pattern + * rotator. + */ +AVLTree.prototype.restructure = function(nodesToRestructure) { + var x = nodesToRestructure[0]; + var y = nodesToRestructure[1]; + var z = nodesToRestructure[2]; + + // Determine Rotation Pattern + if (z.right === y && y.right === x) { + this.rightRight(x, y, z); + } else if (z.left === y && y.left === x) { + this.leftLeft(x, y, z); + } else if (z.right === y && y.left === x) { + this.rightLeft(x, y, z); + } else if (z.left === y && y.right === x) { + this.leftRight(x, y, z); + } +}; + +/** + * Right-right rotation pattern. + */ +AVLTree.prototype.rightRight = function(x, y, z) { + // pass z parent to y and move y's left to z's right + if (z.parent !== null) { + var orientation = (z.parent.left === z) ? 'left' : 'right'; + z.parent[orientation] = y; + y.parent = z.parent; + } else { + this.root = y; + y.parent = null; + } + + // z adopts y's left. + z.right = y.left; + if (z.right !== null) { + z.right.parent = z; + } + // y adopts z + y.left = z; + z.parent = y; + + // Correct each nodes height - order matters, children first + x.height = this.getNodeHeight(x); + z.height = this.getNodeHeight(z); + y.height = this.getNodeHeight(y); +}; + +/** + * Left-left rotation pattern. + */ +AVLTree.prototype.leftLeft = function(x, y, z) { + //pass z parent to y and move y's right to z's left + if (z.parent !== null) { + var orientation = (z.parent.left === z) ? 'left' : 'right'; + z.parent[orientation] = y; + y.parent = z.parent; + } else { + this.root = y; + y.parent = null; + } + + z.left = y.right; + if (z.left !== null) { + z.left.parent = z; + } + //fix y right child + y.right = z; + z.parent = y; + + // Correct each nodes height - order matters, children first + x.height = this.getNodeHeight(x); + z.height = this.getNodeHeight(z); + y.height = this.getNodeHeight(y); +}; + +/** + * Right-left rotation pattern. + */ +AVLTree.prototype.rightLeft = function(x, y, z) { + //pass z parent to x + if (z.parent !== null) { + var orientation = (z.parent.left === z) ? 'left' : 'right'; + z.parent[orientation] = x; + x.parent = z.parent; + } else { + this.root = x; + x.parent = null; + } + + // Adoptions + z.right = x.left; + if (z.right !== null) { + z.right.parent = z; + } + y.left = x.right; + if (y.left !== null) { + y.left.parent = y; + } + + // Point to new children (x new parent) + x.left = z; + x.right = y; + x.left.parent = x; + x.right.parent = x; + + // Correct each nodes height - order matters, children first + y.height = this.getNodeHeight(y); + z.height = this.getNodeHeight(z); + x.height = this.getNodeHeight(x); +}; + +/** + * Left-right rotation pattern. + */ +AVLTree.prototype.leftRight = function(x, y, z) { + //pass z parent to x + if (z.parent !== null) { + var orientation = (z.parent.left === z) ? 'left' : 'right'; + z.parent[orientation] = x; + x.parent = z.parent; + } else { + this.root = x; + x.parent = null; + } + + // Adoptions + z.left = x.right; + if (z.left !== null) { + z.left.parent = z; + } + y.right = x.left; + if (y.right !== null) { + y.right.parent = y; + } + + // Point to new children (x new parent) + x.right = z; + x.left = y; + x.left.parent = x; + x.right.parent = x; + + // Correct each nodes height - order matters, children first + y.height = this.getNodeHeight(y); + z.height = this.getNodeHeight(z); + x.height = this.getNodeHeight(x); +}; + +/** + * Inserts a value as a Node of an AVL Tree. + */ +AVLTree.prototype.insert = function(value, current) { + if (this.root === null) { + this.root = new Node(value, null, null, null, 1); + this.keepHeightBalance(this.root); + return; + } + + var insertKey; + current = current || this.root; + if (current.value > value) { + insertKey = 'left'; + } else { + insertKey = 'right'; + } + + if (!current[insertKey]) { + current[insertKey] = new Node(value, null, null, current); + this.keepHeightBalance(current[insertKey], false); + } else { + this.insert(value, current[insertKey]); + } +}; + +/** + * In-order traversal from the given node. + */ +AVLTree.prototype.inOrder = function(current, callback) { + if (!current) { + return; + } + this.inOrder(current.left, callback); + if (typeof callback === 'function') { + callback(current); + } + this.inOrder(current.right, callback); +}; + +/** + * Post-order traversal from the given node. + */ +AVLTree.prototype.postOrder = function(current, callback) { + if (!current) { + return; + } + if (typeof callback === 'function') { + callback(current); + } + this.postOrder(current.left, callback); + this.postOrder(current.right, callback); +}; + +/** + * Pre-order traversal from the given node. + */ +AVLTree.prototype.preOrder = function(current, callback) { + if (!current) { + return; + } + if (typeof callback === 'function') { + callback(current); + } + this.preOrder(current.left, callback); + this.preOrder(current.right, callback); +}; + +/** + * Finds a node by its value. + */ +AVLTree.prototype.find = function(value) { + return this._find(value, this.root); +}; + +/** + * Finds a node by its value in the given sub-tree. + */ +AVLTree.prototype._find = function(value, current) { + if (!current) { + return null; + } + + if (current.value === value) { + return current; + } + if (current.value > value) { + return this._find(value, current.left); + } + if (current.value < value) { + return this._find(value, current.right); + } +}; + +/** + * Replaces the given child with the new one, + * for the given parent. + */ +AVLTree.prototype.replaceChild = function(parent, oldChild, newChild) { + if (parent === null) { + this.root = newChild; + if (this.root !== null) { + this.root.parent = null; + } + } else { + if (parent.left === oldChild) { + parent.left = newChild; + } else { + parent.right = newChild; + } + if (newChild) { + newChild.parent = parent; + } + } +}; + +/** + * Removes a node by its value. + */ +AVLTree.prototype.remove = function(value) { + var node = this.find(value); + if (!node) { + return false; + } + + if (node.left && node.right) { + var min = this.findMin(node.right); + var temp = node.value; + node.value = min.value; + min.value = temp; + return this.remove(min); + } else { + if (node.left) { + this.replaceChild(node.parent, node, node.left); + this.keepHeightBalance(node.left, true); + } else if (node.right) { + this.replaceChild(node.parent, node, node.right); + this.keepHeightBalance(node.right, true); + } else { + this.replaceChild(node.parent, node, null); + this.keepHeightBalance(node.parent, true); + } + return true; + } +}; + +/** + * Finds the node with minimum value in the given + * sub-tree. + */ +AVLTree.prototype._findMin = function(node, current) { + current = current || { + value: Infinity + }; + if (!node) { + return current; + } + if (current.value > node.value) { + current = node; + } + return this._findMin(node.left, current); +}; + +/** + * Finds the node with maximum value in the given + * sub-tree. + */ +AVLTree.prototype._findMax = function(node, current) { + current = current || { + value: -Infinity + }; + if (!node) { + return current; + } + if (current.value < node.value) { + current = node; + } + return this._findMax(node.right, current); +}; + +/** + * Finds the node with minimum value in the whole tree. + */ +AVLTree.prototype.findMin = function() { + return this._findMin(this.root); +}; + +/** + * Finds the node with maximum value in the whole tree. + */ +AVLTree.prototype.findMax = function() { + return this._findMax(this.root); +}; + +/** + * Verifies if the tree is balanced. + */ +AVLTree.prototype.isTreeBalanced = function() { + var current = this.root; + + if (!current) { + return true; + } + return this._isBalanced(current._left) && + this._isBalanced(current._right) && + Math.abs(this._getNodeHeight(current._left) - + this._getNodeHeight(current._right)) <= 1; +}; + +/** + * Calculates the height of the tree based on height + * property. + */ +AVLTree.prototype.getTreeHeight = function() { + var current = this.root; + + if (!current) { + return 0; + } + return 1 + Math.max(this.getNodeHeight(current._left), + this._getNodeHeight(current._right)); +}; + +module.exports = AVLTree; diff --git a/src/test/data_structures/avl-tree.js b/src/test/data_structures/avl-tree.js new file mode 100644 index 0000000..e6869a4 --- /dev/null +++ b/src/test/data_structures/avl-tree.js @@ -0,0 +1,109 @@ +'use strict'; + +var root = require('../..'), + AVLTree = root.DataStructures.AVLTree, + assert = require('assert'); + +describe('AVL Tree', function () { + it('should start with null root', function () { + assert.equal(new AVLTree().root, null); + }); + + it('should insert and single rotate (leftRight) properly', function () { + var avlTree = new AVLTree(); + avlTree.insert(9); + avlTree.insert(3); + avlTree.insert(5); + + assert.equal(avlTree.root.value, 5); + assert.equal(avlTree.root.left.value, 3); + assert.equal(avlTree.root.right.value, 9); + + assert.equal(avlTree.root.height, 2); + assert.equal(avlTree.root.left.height, 1); + assert.equal(avlTree.root.right.height, 1); + }); + + it('should insert and single rotate (rightLeft) properly', function () { + var avlTree = new AVLTree(); + avlTree.insert(50); + avlTree.insert(75); + avlTree.insert(60); + + assert.equal(avlTree.root.value, 60); + assert.equal(avlTree.root.left.value, 50); + assert.equal(avlTree.root.right.value, 75); + + assert.equal(avlTree.root.height, 2); + assert.equal(avlTree.root.left.height, 1); + assert.equal(avlTree.root.right.height, 1); + }); + + it('should insert and double rotate (leftLeft) properly', function () { + var avlTree = new AVLTree(); + avlTree.insert(50); + avlTree.insert(25); + avlTree.insert(10); + + assert.equal(avlTree.root.value, 25); + assert.equal(avlTree.root.left.value, 10); + assert.equal(avlTree.root.right.value, 50); + + assert.equal(avlTree.root.height, 2); + assert.equal(avlTree.root.left.height, 1); + assert.equal(avlTree.root.right.height, 1); + }); + + it('should insert and double rotate (rightRight) properly', function () { + var avlTree = new AVLTree(); + avlTree.insert(50); + avlTree.insert(75); + avlTree.insert(100); + + assert.equal(avlTree.root.value, 75); + assert.equal(avlTree.root.left.value, 50); + assert.equal(avlTree.root.right.value, 100); + + assert.equal(avlTree.root.height, 2); + assert.equal(avlTree.root.left.height, 1); + assert.equal(avlTree.root.right.height, 1); + }); + + it('should insert multiple nodes and balance properly (1)', function () { + var avlTree = new AVLTree(); + avlTree.insert(30); + avlTree.insert(15); + avlTree.insert(60); + avlTree.insert(90); + avlTree.insert(100); + + assert.equal(avlTree.root.value, 30); + assert.equal(avlTree.root.left.value, 15); + assert.equal(avlTree.root.right.value, 90); + assert.equal(avlTree.root.right.left.value, 60); + assert.equal(avlTree.root.right.right.value, 100); + + assert.equal(avlTree.root.height, 3); + assert.equal(avlTree.root.left.height, 1); + assert.equal(avlTree.root.right.height, 2); + assert.equal(avlTree.root.right.left.height, 1); + assert.equal(avlTree.root.right.right.height, 1); + }); + + it('should remove nodes and balance properly (2)', function () { + var avlTree = new AVLTree(); + avlTree.insert(55); + avlTree.insert(25); + avlTree.insert(11); + avlTree.insert(1); + avlTree.remove(55); + + assert.equal(avlTree.root.value, 11); + assert.equal(avlTree.root.height, 2); + + assert.equal(avlTree.root.left.value, 1); + assert.equal(avlTree.root.left.height, 1); + assert.equal(avlTree.root.right.value, 25); + assert.equal(avlTree.root.right.height, 1); + }); + }); From 820c9c5874055a353e075227e359f5df90fd1da0 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sat, 22 Aug 2015 08:52:57 -0300 Subject: [PATCH 192/280] More linting rules --- .eslintrc | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.eslintrc b/.eslintrc index 020dc76..68afc94 100644 --- a/.eslintrc +++ b/.eslintrc @@ -23,6 +23,7 @@ 2, "last" ], + "consistent-return": 0, "curly": [ 0, "all" @@ -74,13 +75,24 @@ "no-unused-vars": 2, "no-use-before-define": 0, "no-with": 2, + "space-after-keywords": [ + 2, + "always" + ], + "space-before-function-paren": [ + 2, + { + "anonymous": "always", + "named": "never" + } + ], "quotes": [ 2, "single" ], "semi": [ - 0, - "never" + 2, + "always" ], "valid-typeof": 2, "wrap-iife": [ From 2e9adce481917876dc08dd975bf935b10a042067 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Mon, 24 Aug 2015 19:26:45 -0300 Subject: [PATCH 193/280] Update travis configuration --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 267f03a..fbfee74 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: node_js +sudo: false node_js: - - "0.10" + - "0.12" script: "make" after_success: "make coveralls" From 67f9b5d9b8b2c7e089e14d60bf3798f50dbf23f9 Mon Sep 17 00:00:00 2001 From: Evandro Eisinger Date: Mon, 24 Aug 2015 20:46:52 -0300 Subject: [PATCH 194/280] fixed lint errors --- src/data_structures/avl_tree.js | 50 ++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/data_structures/avl_tree.js b/src/data_structures/avl_tree.js index ac4bbae..0853179 100644 --- a/src/data_structures/avl_tree.js +++ b/src/data_structures/avl_tree.js @@ -22,7 +22,7 @@ function Node(value, left, right, parent, height) { * Calculates the height of a node based on height * property of all his children. */ -AVLTree.prototype.getNodeHeight = function(node) { +AVLTree.prototype.getNodeHeight = function (node) { if (node.left !== null && node.right !== null) { var height = Math.max(node.left.height, node.right.height); height += 1; @@ -39,7 +39,7 @@ AVLTree.prototype.getNodeHeight = function(node) { /** * Verifies if the given node is balanced. */ -AVLTree.prototype.isNodeBalanced = function(node) { +AVLTree.prototype.isNodeBalanced = function (node) { if (node.left !== null && node.right !== null) { return (Math.abs(node.left.height - node.right.height) <= 1); } @@ -56,7 +56,7 @@ AVLTree.prototype.isNodeBalanced = function(node) { * When a removal happens, some nodes need to be * restructured. Gets and return these nodes. */ -AVLTree.prototype.getNodesToRestructureAfterRemove = function(traveledNodes) { +AVLTree.prototype.getNodesToRestructureAfterRemove = function (traveledNodes) { // z is last traveled node - imbalance found at z var zIndex = traveledNodes.length; zIndex -= 1; @@ -97,7 +97,7 @@ AVLTree.prototype.getNodesToRestructureAfterRemove = function(traveledNodes) { * When a insertion happens, some nodes need to be * restructured. Gets and return these nodes. */ -AVLTree.prototype.getNodesToRestructureAfterInsert = function(traveledNodes) { +AVLTree.prototype.getNodesToRestructureAfterInsert = function (traveledNodes) { // z is last traveled node - imbalance found at z var zIndex = traveledNodes.length; zIndex -= 1; @@ -130,13 +130,13 @@ AVLTree.prototype.getNodesToRestructureAfterInsert = function(traveledNodes) { x = y.right; } return [x, y, z]; -} +}; /** * Keep the height balance property by walking to * root and checking for invalid heights. */ -AVLTree.prototype.keepHeightBalance = function(node, afterRemove) { +AVLTree.prototype.keepHeightBalance = function (node, afterRemove) { var current = node; var traveledNodes = []; while (current !== null) { @@ -156,7 +156,7 @@ AVLTree.prototype.keepHeightBalance = function(node, afterRemove) { * Identifies and calls the appropriate pattern * rotator. */ -AVLTree.prototype.restructure = function(nodesToRestructure) { +AVLTree.prototype.restructure = function (nodesToRestructure) { var x = nodesToRestructure[0]; var y = nodesToRestructure[1]; var z = nodesToRestructure[2]; @@ -176,7 +176,7 @@ AVLTree.prototype.restructure = function(nodesToRestructure) { /** * Right-right rotation pattern. */ -AVLTree.prototype.rightRight = function(x, y, z) { +AVLTree.prototype.rightRight = function (x, y, z) { // pass z parent to y and move y's left to z's right if (z.parent !== null) { var orientation = (z.parent.left === z) ? 'left' : 'right'; @@ -205,7 +205,7 @@ AVLTree.prototype.rightRight = function(x, y, z) { /** * Left-left rotation pattern. */ -AVLTree.prototype.leftLeft = function(x, y, z) { +AVLTree.prototype.leftLeft = function (x, y, z) { //pass z parent to y and move y's right to z's left if (z.parent !== null) { var orientation = (z.parent.left === z) ? 'left' : 'right'; @@ -233,7 +233,7 @@ AVLTree.prototype.leftLeft = function(x, y, z) { /** * Right-left rotation pattern. */ -AVLTree.prototype.rightLeft = function(x, y, z) { +AVLTree.prototype.rightLeft = function (x, y, z) { //pass z parent to x if (z.parent !== null) { var orientation = (z.parent.left === z) ? 'left' : 'right'; @@ -269,7 +269,7 @@ AVLTree.prototype.rightLeft = function(x, y, z) { /** * Left-right rotation pattern. */ -AVLTree.prototype.leftRight = function(x, y, z) { +AVLTree.prototype.leftRight = function (x, y, z) { //pass z parent to x if (z.parent !== null) { var orientation = (z.parent.left === z) ? 'left' : 'right'; @@ -305,7 +305,7 @@ AVLTree.prototype.leftRight = function(x, y, z) { /** * Inserts a value as a Node of an AVL Tree. */ -AVLTree.prototype.insert = function(value, current) { +AVLTree.prototype.insert = function (value, current) { if (this.root === null) { this.root = new Node(value, null, null, null, 1); this.keepHeightBalance(this.root); @@ -331,7 +331,7 @@ AVLTree.prototype.insert = function(value, current) { /** * In-order traversal from the given node. */ -AVLTree.prototype.inOrder = function(current, callback) { +AVLTree.prototype.inOrder = function (current, callback) { if (!current) { return; } @@ -345,7 +345,7 @@ AVLTree.prototype.inOrder = function(current, callback) { /** * Post-order traversal from the given node. */ -AVLTree.prototype.postOrder = function(current, callback) { +AVLTree.prototype.postOrder = function (current, callback) { if (!current) { return; } @@ -359,7 +359,7 @@ AVLTree.prototype.postOrder = function(current, callback) { /** * Pre-order traversal from the given node. */ -AVLTree.prototype.preOrder = function(current, callback) { +AVLTree.prototype.preOrder = function (current, callback) { if (!current) { return; } @@ -373,14 +373,14 @@ AVLTree.prototype.preOrder = function(current, callback) { /** * Finds a node by its value. */ -AVLTree.prototype.find = function(value) { +AVLTree.prototype.find = function (value) { return this._find(value, this.root); }; /** * Finds a node by its value in the given sub-tree. */ -AVLTree.prototype._find = function(value, current) { +AVLTree.prototype._find = function (value, current) { if (!current) { return null; } @@ -400,7 +400,7 @@ AVLTree.prototype._find = function(value, current) { * Replaces the given child with the new one, * for the given parent. */ -AVLTree.prototype.replaceChild = function(parent, oldChild, newChild) { +AVLTree.prototype.replaceChild = function (parent, oldChild, newChild) { if (parent === null) { this.root = newChild; if (this.root !== null) { @@ -421,7 +421,7 @@ AVLTree.prototype.replaceChild = function(parent, oldChild, newChild) { /** * Removes a node by its value. */ -AVLTree.prototype.remove = function(value) { +AVLTree.prototype.remove = function (value) { var node = this.find(value); if (!node) { return false; @@ -452,7 +452,7 @@ AVLTree.prototype.remove = function(value) { * Finds the node with minimum value in the given * sub-tree. */ -AVLTree.prototype._findMin = function(node, current) { +AVLTree.prototype._findMin = function (node, current) { current = current || { value: Infinity }; @@ -469,7 +469,7 @@ AVLTree.prototype._findMin = function(node, current) { * Finds the node with maximum value in the given * sub-tree. */ -AVLTree.prototype._findMax = function(node, current) { +AVLTree.prototype._findMax = function (node, current) { current = current || { value: -Infinity }; @@ -485,21 +485,21 @@ AVLTree.prototype._findMax = function(node, current) { /** * Finds the node with minimum value in the whole tree. */ -AVLTree.prototype.findMin = function() { +AVLTree.prototype.findMin = function () { return this._findMin(this.root); }; /** * Finds the node with maximum value in the whole tree. */ -AVLTree.prototype.findMax = function() { +AVLTree.prototype.findMax = function () { return this._findMax(this.root); }; /** * Verifies if the tree is balanced. */ -AVLTree.prototype.isTreeBalanced = function() { +AVLTree.prototype.isTreeBalanced = function () { var current = this.root; if (!current) { @@ -515,7 +515,7 @@ AVLTree.prototype.isTreeBalanced = function() { * Calculates the height of the tree based on height * property. */ -AVLTree.prototype.getTreeHeight = function() { +AVLTree.prototype.getTreeHeight = function () { var current = this.root; if (!current) { From f237b8c3ef03a84387ebc9e2fc4bf231a9c32409 Mon Sep 17 00:00:00 2001 From: Evandro Eisinger Date: Mon, 24 Aug 2015 20:47:43 -0300 Subject: [PATCH 195/280] added collatz conjecture algorithm --- src/algorithms/math/collatz_conjecture.js | 42 +++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/algorithms/math/collatz_conjecture.js diff --git a/src/algorithms/math/collatz_conjecture.js b/src/algorithms/math/collatz_conjecture.js new file mode 100644 index 0000000..6581cb6 --- /dev/null +++ b/src/algorithms/math/collatz_conjecture.js @@ -0,0 +1,42 @@ +'use strict'; + +// cache algorithm results +var cache = {1: 1}; + +/** + * Collatz Conjecture algorithm + * + * @param Number + * @return Number + */ + +function calculateCollatzConjecture(number) { + if (number in cache) return cache[number]; + if (number % 2 === 0) return cache[number] = number >> 1; + + cache[number] = number * 3 + 1; +} + +/** + * Generate Collatz Conjecture + * + * @param Number + * @return Array + */ + +function generateCollatzConjecture(number) { + var collatzConjecture = []; + + do { + number = calculateCollatzConjecture(number); + collatzConjecture.push(number); + } while (number !== 1) + + return collatzConjecture; +} + +// export Collatz Conjecture methods +module.exports = { + generate: generateCollatzConjecture, + calculate: calculateCollatzConjecture, +}; From 3694aaac56101b67b7acae7b0a7391124468ff11 Mon Sep 17 00:00:00 2001 From: Evandro Eisinger Date: Mon, 24 Aug 2015 21:13:00 -0300 Subject: [PATCH 196/280] added Collatz Conjecture algorithm to math module --- src/math.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/math.js b/src/math.js index 6431ac2..4122059 100644 --- a/src/math.js +++ b/src/math.js @@ -12,5 +12,6 @@ module.exports = { fastPower: require('./algorithms/math/fast_power'), nextPermutation: require('./algorithms/math/next_permutation'), powerSet: require('./algorithms/math/power_set'), - shannonEntropy: require('./algorithms/math/shannon_entropy') + shannonEntropy: require('./algorithms/math/shannon_entropy'), + collatzConjecture: require('./algorithms/math/collatz_conjecture'), }; From 239b92e78c2180edc33b2a312610a13e8203c093 Mon Sep 17 00:00:00 2001 From: Evandro Eisinger Date: Mon, 24 Aug 2015 21:13:50 -0300 Subject: [PATCH 197/280] improved collatz calculate method to return even numbers --- src/algorithms/math/collatz_conjecture.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/math/collatz_conjecture.js b/src/algorithms/math/collatz_conjecture.js index 6581cb6..3c2af72 100644 --- a/src/algorithms/math/collatz_conjecture.js +++ b/src/algorithms/math/collatz_conjecture.js @@ -14,7 +14,7 @@ function calculateCollatzConjecture(number) { if (number in cache) return cache[number]; if (number % 2 === 0) return cache[number] = number >> 1; - cache[number] = number * 3 + 1; + return cache[number] = number * 3 + 1; } /** From 82e05b091dd3138e5c06e27a2fbde2f00b6a900b Mon Sep 17 00:00:00 2001 From: Evandro Eisinger Date: Mon, 24 Aug 2015 21:14:18 -0300 Subject: [PATCH 198/280] added tests for Collatz Algorithm --- .../algorithms/math/collatz_conjecture.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/test/algorithms/math/collatz_conjecture.js diff --git a/src/test/algorithms/math/collatz_conjecture.js b/src/test/algorithms/math/collatz_conjecture.js new file mode 100644 index 0000000..bba8a45 --- /dev/null +++ b/src/test/algorithms/math/collatz_conjecture.js @@ -0,0 +1,24 @@ +'use strict'; + +var math = require('../../..').Math, + collatzConjecture = math.collatzConjecture, + assert = require('assert'); + +describe('Collatz Conjecture', function () { + it('should return odd numbers divided by two', function () { + assert.equal(collatzConjecture.calculate(200), 100); + assert.equal(collatzConjecture.calculate(222), 111); + assert.equal(collatzConjecture.calculate(444), 222); + }); + + it('should return even numbers multiplied by 3 + 1', function () { + assert.equal(collatzConjecture.calculate(111), 334); + assert.equal(collatzConjecture.calculate(333), 1000); + assert.equal(collatzConjecture.calculate(555), 1666); + }); + + it('should return Collatz Conjecture sequence ', function () { + assert.deepEqual(collatzConjecture.generate(10), [5, 16, 8, 4, 2, 1]); + }); +}); + From bcecbb3abf1940dda0b2422bc86289cc4791807b Mon Sep 17 00:00:00 2001 From: Evandro Eisinger Date: Mon, 24 Aug 2015 21:24:46 -0300 Subject: [PATCH 199/280] added collatz conjecture to readme and sort algorithms lists --- README.md | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index b8bfce4..0cd4bff 100644 --- a/README.md +++ b/README.md @@ -29,18 +29,18 @@ require('algorithms').DataStructures; ``` * BST +* DisjointSetForest +* FenwickTree * Graph * HashTable * Heap - * MinHeap * MaxHeap + * MinHeap * LinkedList * PriorityQueue * Queue -* Stack * Set (HashSet) -* DisjointSetForest -* FenwickTree +* Stack #### Graph algorithms @@ -50,17 +50,17 @@ require('algorithms/graph'); require('algorithms').Graph; ``` -* topologicalSort -* eulerPath -* depthFirstSearch * breadthFirstSearch +* depthFirstSearch +* eulerPath +* topologicalSort ##### Shortest path +* bellmanFord * bfsShortestPath * dijkstra -* SPFA (Shortest Path Faster Algorithm) -* bellmanFord * floydWarshall +* SPFA (Shortest Path Faster Algorithm) ##### Minimum spanning tree * prim @@ -73,17 +73,17 @@ require('algorithms/math'); // or require('algorithms').Math; ``` - +* collatzConjecture +* extendedEuclidean +* fastPower * fibonacci * fisherYates * gcd (Greatest common divisor) -* extendedEuclidean * lcm (Least common multiple) * newtonSqrt -* reservoirSampling -* fastPower * nextPermutation * powerSet +* reservoirSampling * shannonEntropy #### Search algorithms @@ -98,8 +98,8 @@ require('algorithms').Search; * binarySearch * dfs (depth-first search for binary trees) * inOrder (default) - * preOrder * postOrder + * preOrder #### Sorting algorithms @@ -112,10 +112,10 @@ require('algorithms').Sorting; * bubbleSort * countingSort * heapSort +* insertionSort * quicksort -* selectionSort * radixSort -* insertionSort +* selectionSort * shellSort #### String algorithms @@ -126,14 +126,12 @@ require('algorithms/string'); require('algorithms').String; ``` -* levenshtein -* rabinKarp -* knuthMorrisPratt +* hamming * huffman - * encode * decode -* hamming + * encode +* knuthMorrisPratt +* levenshtein * longestCommonSubsequence * longestCommonSubstring - - +* rabinKarp From 873f6e58d1ad0079d85cf9e0ecb8f095533e150e Mon Sep 17 00:00:00 2001 From: Evandro Eisinger Date: Mon, 24 Aug 2015 21:25:43 -0300 Subject: [PATCH 200/280] added my name to contributors list --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d417386..ed3e50e 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,8 @@ "geakstr ", "Matt R. Wilson ", "Gaurav Mittal ", - "Juan Lopes " + "Juan Lopes ", + "Evandro Eisinger " ], "license": "MIT", "bugs": { From a3bc73c23707aef5c18b0a746032a4cbb7c5a8d3 Mon Sep 17 00:00:00 2001 From: Artem Gilmudinov Date: Tue, 25 Aug 2015 23:10:54 +0300 Subject: [PATCH 201/280] primality tests (naive and trial division) --- src/algorithms/math/primality_tests.js | 53 +++++++++++++++++++++ src/math.js | 1 + src/test/algorithms/math/primality_tests.js | 32 +++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 src/algorithms/math/primality_tests.js create mode 100644 src/test/algorithms/math/primality_tests.js diff --git a/src/algorithms/math/primality_tests.js b/src/algorithms/math/primality_tests.js new file mode 100644 index 0000000..b0d0f22 --- /dev/null +++ b/src/algorithms/math/primality_tests.js @@ -0,0 +1,53 @@ +'use strict'; + +/** +* Checks whether a number is prime using a given primality test +* +* @param Function +* @param Number +* +* @return Boolean +*/ +var genericPrimalityTest = function (primalityTest, n) { + if (n <= 1) { + return false; + } + return primalityTest(n); +}; + +/** +* Checks whether a number is prime using the naive algorithm O(n) +* +* @param Number +* +* @return Boolean +*/ +var naiveTest = function (n) { + for (var i = 2; i < n; ++i) { + if (n % i === 0) { + return false; + } + } + return true; +}; + +/** +* Checks whether a number is prime using the trial divison algorithm O(sqrt(n)) +* +* @param Number +* +* @return Boolean +*/ +var trialDivisionTest = function (n) { + for (var i = 2; i * i <= n; ++i) { + if (n % i === 0) { + return false; + } + } + return true; +}; + +var obj = {}; +obj.naiveTest = genericPrimalityTest.bind(null, naiveTest); +obj.trialDivisionTest = genericPrimalityTest.bind(null, trialDivisionTest); +module.exports = obj; diff --git a/src/math.js b/src/math.js index 6431ac2..759170f 100644 --- a/src/math.js +++ b/src/math.js @@ -8,6 +8,7 @@ module.exports = { extendedEuclidean: require('./algorithms/math/extended_euclidean'), lcm: require('./algorithms/math/lcm'), newtonSqrt: require('./algorithms/math/newton_sqrt'), + primalityTests: require('./algorithms/math/primality_tests'), reservoirSampling: require('./algorithms/math/reservoir_sampling'), fastPower: require('./algorithms/math/fast_power'), nextPermutation: require('./algorithms/math/next_permutation'), diff --git a/src/test/algorithms/math/primality_tests.js b/src/test/algorithms/math/primality_tests.js new file mode 100644 index 0000000..834d77b --- /dev/null +++ b/src/test/algorithms/math/primality_tests.js @@ -0,0 +1,32 @@ +'use strict'; + +var root = require('../../..'), + primalityTests = root.Math.primalityTests, + assert = require('assert'), + s = 'should correctly determine whether a number is prime'; + +describe('Primality Tests', function () { + describe('#naiveTest()', function () { + it(s, function () { + f(primalityTests.naiveTest); + }); + }); + describe('#trialDivisionTest()', function () { + it(s, function () { + f(primalityTests.trialDivisionTest); + }); + }); +}); + +var f = function (primalityTest) { + assert.equal(primalityTest(1), false); + assert.equal(primalityTest(2), true); + assert.equal(primalityTest(3), true); + assert.equal(primalityTest(4), false); + assert.equal(primalityTest(5), true); + assert.equal(primalityTest(14), false); + assert.equal(primalityTest(21), false); + assert.equal(primalityTest(37), true); + assert.equal(primalityTest(209), false); + assert.equal(primalityTest(211), true); +}; From ccb721f2e1c759b6a33b7225113aca2cb299ffa4 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 25 Aug 2015 18:09:21 -0300 Subject: [PATCH 202/280] Improve test converage for avl tree --- src/test/data_structures/avl-tree.js | 170 ++++++++++++++++++++++++++- 1 file changed, 168 insertions(+), 2 deletions(-) diff --git a/src/test/data_structures/avl-tree.js b/src/test/data_structures/avl-tree.js index e6869a4..f6b2724 100644 --- a/src/test/data_structures/avl-tree.js +++ b/src/test/data_structures/avl-tree.js @@ -1,8 +1,8 @@ 'use strict'; var root = require('../..'), - AVLTree = root.DataStructures.AVLTree, - assert = require('assert'); + AVLTree = root.DataStructures.AVLTree, + assert = require('assert'); describe('AVL Tree', function () { it('should start with null root', function () { @@ -106,4 +106,170 @@ describe('AVL Tree', function () { assert.equal(avlTree.root.right.value, 25); assert.equal(avlTree.root.right.height, 1); }); + + it('should always keep the tree balanced', function () { + var avlTree = new AVLTree(); + + avlTree.insert(50); + avlTree.insert(100); + avlTree.insert(200); + + // 100 + // 50 200 + assert.equal(avlTree.root.value, 100); + assert.equal(avlTree.root.height, 2); + assert.equal(avlTree.root.left.value, 50); + assert.equal(avlTree.root.left.height, 1); + assert.equal(avlTree.root.right.value, 200); + assert.equal(avlTree.root.right.height, 1); + + avlTree.insert(1); + avlTree.insert(2); + avlTree.insert(75); + + // 50 + // 2 100 + // 1 75 200 + assert.equal(avlTree.root.value, 50); + assert.equal(avlTree.root.height, 3); + assert.equal(avlTree.root.left.value, 2); + assert.equal(avlTree.root.left.height, 2); + assert.equal(avlTree.root.right.value, 100); + assert.equal(avlTree.root.right.height, 2); + assert.equal(avlTree.root.left.left.value, 1); + assert.equal(avlTree.root.right.left.value, 75); + assert.equal(avlTree.root.right.right.value, 200); + + avlTree.insert(80); + avlTree.insert(4); + avlTree.insert(5); + avlTree.insert(6); + avlTree.insert(7); + + // 50 + // 5 100 + // 2 6 75 200 + // 1 4 7 80 + assert.equal(avlTree.root.value, 50); + assert.equal(avlTree.root.height, 4); + assert.equal(avlTree.root.left.value, 5); + assert.equal(avlTree.root.left.height, 3); + assert.equal(avlTree.root.right.value, 100); + assert.equal(avlTree.root.right.height, 3); + assert.equal(avlTree.root.left.left.value, 2); + assert.equal(avlTree.root.left.left.left.value, 1); + assert.equal(avlTree.root.left.left.right.value, 4); + assert.equal(avlTree.root.left.right.value, 6); + assert.equal(avlTree.root.left.right.right.value, 7); + assert.equal(avlTree.root.right.left.value, 75); + assert.equal(avlTree.root.right.left.right.value, 80); + assert.equal(avlTree.root.right.right.value, 200); + + avlTree.insert(20); + avlTree.insert(40); + avlTree.insert(30); + avlTree.insert(15); + + // 50 + // 5 100 + // 2 20 75 200 + // 1 4 7 30 80 + // 6 15 40 + assert.equal(avlTree.root.value, 50); + assert.equal(avlTree.root.height, 5); + assert.equal(avlTree.root.left.value, 5); + assert.equal(avlTree.root.left.height, 4); + assert.equal(avlTree.root.right.value, 100); + assert.equal(avlTree.root.right.height, 3); + assert.equal(avlTree.root.left.left.value, 2); + assert.equal(avlTree.root.left.left.left.value, 1); + assert.equal(avlTree.root.left.left.right.value, 4); + assert.equal(avlTree.root.left.right.value, 20); + assert.equal(avlTree.root.left.right.left.value, 7); + assert.equal(avlTree.root.left.right.left.left.value, 6); + assert.equal(avlTree.root.left.right.left.right.value, 15); + assert.equal(avlTree.root.left.right.right.value, 30); + assert.equal(avlTree.root.left.right.right.right.value, 40); + assert.equal(avlTree.root.right.left.value, 75); + assert.equal(avlTree.root.right.left.right.value, 80); + assert.equal(avlTree.root.right.right.value, 200); + }); + + it('should return the parents before the children when '+ + 'traversing in preorder', function () { + var avlTree = new AVLTree(); + + avlTree.insert(50); + avlTree.insert(100); + avlTree.insert(200); + avlTree.insert(1); + avlTree.insert(2); + avlTree.insert(75); + avlTree.insert(80); + avlTree.insert(4); + avlTree.insert(5); + avlTree.insert(6); + avlTree.insert(7); + avlTree.insert(20); + avlTree.insert(40); + avlTree.insert(30); + avlTree.insert(15); + + var expectedPreOrder = [50, 5, 2, 1, 4, 20, 7, 6, + 15, 30, 40, 100, 75, 80, 200]; + var preOrder = []; + avlTree.preOrder(avlTree.root, function (n) { + preOrder.push(n.value); + }); + assert.deepEqual(expectedPreOrder, preOrder); + }); + + it('should return the children before the parents when '+ + 'traversing in postorder', function () { + var avlTree = new AVLTree(); + + avlTree.insert(50); + avlTree.insert(100); + avlTree.insert(200); + avlTree.insert(1); + avlTree.insert(2); + avlTree.insert(75); + avlTree.insert(80); + avlTree.insert(4); + avlTree.insert(5); + avlTree.insert(6); + avlTree.insert(7); + avlTree.insert(20); + avlTree.insert(40); + avlTree.insert(30); + avlTree.insert(15); + + var expectedPostOrder = [1, 4, 2, 6, 15, 7, 40, 30, + 20, 5, 80, 75, 200, 100, 50]; + var postOrder = []; + avlTree.postOrder(avlTree.root, function (n) { + postOrder.push(n.value); + }); + assert.deepEqual(expectedPostOrder, postOrder); + }); + + + it('should return the sorted elements when traversing in order', function () { + var avlTree = new AVLTree(); + var a = []; + var i; + for (i = 0; i < 1000; i++) { + var x = Math.round(Math.random() * 100000); + avlTree.insert(x); + a.push(x); + } + a.sort(function (a, b) { return a - b; }); + + var b = []; + avlTree.inOrder(avlTree.root, function (node) { b.push(node.value); }); + assert.equal(a.length, b.length); + for (i = 0; i < a.length; i++) { + assert.equal(a[i], b[i]); + } + }); }); From 6ae820846df3e7b9c15527c903395afb4ce21e3b Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 25 Aug 2015 18:09:40 -0300 Subject: [PATCH 203/280] Fix style and remove multiple returns in avl-tree --- src/data_structures/avl_tree.js | 80 +++++++++++++++------------------ 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/src/data_structures/avl_tree.js b/src/data_structures/avl_tree.js index 0853179..8d9291f 100644 --- a/src/data_structures/avl_tree.js +++ b/src/data_structures/avl_tree.js @@ -23,33 +23,31 @@ function Node(value, left, right, parent, height) { * property of all his children. */ AVLTree.prototype.getNodeHeight = function (node) { + var height = 1; if (node.left !== null && node.right !== null) { - var height = Math.max(node.left.height, node.right.height); - height += 1; - return height; + height = Math.max(node.left.height, node.right.height) + 1; } else if (node.left !== null) { - return node.left.height + 1; + height = node.left.height + 1; } else if (node.right !== null) { - return node.right.height + 1; - } else { - return 1; + height = node.right.height + 1; } + return height; }; /** * Verifies if the given node is balanced. */ AVLTree.prototype.isNodeBalanced = function (node) { + var isBalanced = true; + if (node.left !== null && node.right !== null) { - return (Math.abs(node.left.height - node.right.height) <= 1); - } - if (node.right !== null && node.left === null) { - return node.right.height < 2; + isBalanced = (Math.abs(node.left.height - node.right.height) <= 1); + } else if (node.right !== null && node.left === null) { + isBalanced = node.right.height < 2; + } else if (node.left !== null && node.right === null) { + isBalanced = node.left.height < 2; } - if (node.left !== null && node.right === null) { - return node.left.height < 2; - } - return true; + return isBalanced; }; /** @@ -58,8 +56,7 @@ AVLTree.prototype.isNodeBalanced = function (node) { */ AVLTree.prototype.getNodesToRestructureAfterRemove = function (traveledNodes) { // z is last traveled node - imbalance found at z - var zIndex = traveledNodes.length; - zIndex -= 1; + var zIndex = traveledNodes.length - 1; var z = traveledNodes[zIndex]; // y should be child of z with larger height @@ -99,15 +96,13 @@ AVLTree.prototype.getNodesToRestructureAfterRemove = function (traveledNodes) { */ AVLTree.prototype.getNodesToRestructureAfterInsert = function (traveledNodes) { // z is last traveled node - imbalance found at z - var zIndex = traveledNodes.length; - zIndex -= 1; + var zIndex = traveledNodes.length - 1; var z = traveledNodes[zIndex]; // y should be child of z with larger height // (must be ancestor of inserted node) // therefore, last traveled node is correct. - var yIndex = traveledNodes.length; - yIndex -= 2; + var yIndex = traveledNodes.length - 2; var y = traveledNodes[yIndex]; // x should be tallest child of y @@ -120,8 +115,7 @@ AVLTree.prototype.getNodesToRestructureAfterInsert = function (traveledNodes) { } else if (y.left.height < y.right.height) { x = y.right; } else if (y.left.height === y.right.height) { - var xIndex = traveledNodes.length; - xIndex -= 3; + var xIndex = traveledNodes.length - 3; x = traveledNodes[xIndex]; } } else if (y.left !== null && y.right === null) { @@ -349,11 +343,12 @@ AVLTree.prototype.postOrder = function (current, callback) { if (!current) { return; } + + this.postOrder(current.left, callback); + this.postOrder(current.right, callback); if (typeof callback === 'function') { callback(current); } - this.postOrder(current.left, callback); - this.postOrder(current.right, callback); }; /** @@ -385,15 +380,16 @@ AVLTree.prototype._find = function (value, current) { return null; } + var node; if (current.value === value) { - return current; - } - if (current.value > value) { - return this._find(value, current.left); - } - if (current.value < value) { - return this._find(value, current.right); + node = current; + } else if (current.value > value) { + node = this._find(value, current.left); + } else if (current.value < value) { + node = this._find(value, current.right); } + + return node; }; /** @@ -433,19 +429,17 @@ AVLTree.prototype.remove = function (value) { node.value = min.value; min.value = temp; return this.remove(min); + } else if (node.left) { + this.replaceChild(node.parent, node, node.left); + this.keepHeightBalance(node.left, true); + } else if (node.right) { + this.replaceChild(node.parent, node, node.right); + this.keepHeightBalance(node.right, true); } else { - if (node.left) { - this.replaceChild(node.parent, node, node.left); - this.keepHeightBalance(node.left, true); - } else if (node.right) { - this.replaceChild(node.parent, node, node.right); - this.keepHeightBalance(node.right, true); - } else { - this.replaceChild(node.parent, node, null); - this.keepHeightBalance(node.parent, true); - } - return true; + this.replaceChild(node.parent, node, null); + this.keepHeightBalance(node.parent, true); } + return true; }; /** From c023f6d58f49982b588c20088b50648eb6ca4265 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 25 Aug 2015 18:19:52 -0300 Subject: [PATCH 204/280] Style in primality-tests --- src/algorithms/math/primality_tests.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/algorithms/math/primality_tests.js b/src/algorithms/math/primality_tests.js index b0d0f22..e86e796 100644 --- a/src/algorithms/math/primality_tests.js +++ b/src/algorithms/math/primality_tests.js @@ -39,7 +39,8 @@ var naiveTest = function (n) { * @return Boolean */ var trialDivisionTest = function (n) { - for (var i = 2; i * i <= n; ++i) { + var sqrt = Math.sqrt(n); + for (var i = 2; i <= sqrt; ++i) { if (n % i === 0) { return false; } @@ -47,7 +48,7 @@ var trialDivisionTest = function (n) { return true; }; -var obj = {}; -obj.naiveTest = genericPrimalityTest.bind(null, naiveTest); -obj.trialDivisionTest = genericPrimalityTest.bind(null, trialDivisionTest); -module.exports = obj; +module.exports = { + naiveTest: genericPrimalityTest.bind(null, naiveTest), + trialDivisionTest: genericPrimalityTest.bind(null, trialDivisionTest) +}; From ab9d8117d3a1ce85e1fa2798ad5b6fb0a9a47143 Mon Sep 17 00:00:00 2001 From: Gibran Malheiros Date: Thu, 27 Aug 2015 16:29:20 -0300 Subject: [PATCH 205/280] wrote some tests for the greatest difference algorithm --- .../algorithms/math/greatest_difference.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/algorithms/math/greatest_difference.js diff --git a/src/test/algorithms/math/greatest_difference.js b/src/test/algorithms/math/greatest_difference.js new file mode 100644 index 0000000..714be1d --- /dev/null +++ b/src/test/algorithms/math/greatest_difference.js @@ -0,0 +1,19 @@ +'use strict'; + +var assert = require('assert'); +var math = require('../../..').Math; +var greatestDifference = math.greatestDifference; + +describe('Greatest Difference', function () { + it('should return 7 for [5, 8, 6, 1]', function () { + assert.equal(greatestDifference([5, 8, 6, 1]), 7); + }); + + it('should return 4 for [7, 8, 4]', function () { + assert.equal(greatestDifference([7, 8, 4]), 4); + }); + + it('should return 38 for the Lost numbers', function () { + assert.equal(greatestDifference([4, 8, 15, 16, 23, 42]), 38); + }); +}); From cece9de6263bcee4fd7f9d7bf181af3ddcee5f16 Mon Sep 17 00:00:00 2001 From: Gibran Malheiros Date: Thu, 27 Aug 2015 16:30:33 -0300 Subject: [PATCH 206/280] implemented the greatest difference algorithm --- src/algorithms/math/greatest_difference.js | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/algorithms/math/greatest_difference.js diff --git a/src/algorithms/math/greatest_difference.js b/src/algorithms/math/greatest_difference.js new file mode 100644 index 0000000..85b1b7b --- /dev/null +++ b/src/algorithms/math/greatest_difference.js @@ -0,0 +1,28 @@ +'use strict'; + +/** + * Find the greatest difference between two numbers in a set + * This solution has a cost of O(n) + * + * @param {number[]} numbers + * @returns {number} + */ + +var greatestDifference = function (numbers) { + var index = 0; + var largest = numbers[0]; + var length = numbers.length; + var number; + var smallest = numbers[0]; + + for (index; index < length; index++) { + number = numbers[index]; + + if (number > largest) largest = number; + if (number < smallest) smallest = number; + } + + return largest - smallest; +}; + +module.exports = greatestDifference; From 9991e21ac0524a4fe38c2573d678d516b0fbbf11 Mon Sep 17 00:00:00 2001 From: Gibran Malheiros Date: Thu, 27 Aug 2015 16:32:09 -0300 Subject: [PATCH 207/280] updated references to include the greatest difference algorithm --- README.md | 1 + src/math.js | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 0cd4bff..766f612 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ require('algorithms').Math; * fibonacci * fisherYates * gcd (Greatest common divisor) +* greatestDifference * lcm (Least common multiple) * newtonSqrt * nextPermutation diff --git a/src/math.js b/src/math.js index 8fc4257..3276a7e 100644 --- a/src/math.js +++ b/src/math.js @@ -15,4 +15,5 @@ module.exports = { powerSet: require('./algorithms/math/power_set'), shannonEntropy: require('./algorithms/math/shannon_entropy'), collatzConjecture: require('./algorithms/math/collatz_conjecture'), + greatestDifference: require('./algorithms/math/greatest_difference') }; From 3f19e657c77b80b858ca8865d96536c021fb31bd Mon Sep 17 00:00:00 2001 From: Gibran Malheiros Date: Thu, 27 Aug 2015 16:33:14 -0300 Subject: [PATCH 208/280] updated authors and contributors to include my name --- AUTHORS | 1 + package.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 19283c6..39c9fbc 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,3 +13,4 @@ geakstr nitinsaroha tayllan Juan Lopes +Gibran Malheiros diff --git a/package.json b/package.json index ed3e50e..6edc652 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,8 @@ "Matt R. Wilson ", "Gaurav Mittal ", "Juan Lopes ", - "Evandro Eisinger " + "Evandro Eisinger ", + "Gibran Malheiros " ], "license": "MIT", "bugs": { From 83bbf9ddb9fb810d6324abfb77c877e50ceeeeb3 Mon Sep 17 00:00:00 2001 From: Evandro Eisinger Date: Thu, 27 Aug 2015 18:43:34 -0300 Subject: [PATCH 209/280] Update AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 19283c6..06b1932 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,3 +13,4 @@ geakstr nitinsaroha tayllan Juan Lopes +Evandro Eisinger From 485bf7e3ac0424eaeaca722af5c720ee4175e27e Mon Sep 17 00:00:00 2001 From: quietshu Date: Fri, 28 Aug 2015 14:49:14 +0800 Subject: [PATCH 210/280] Treap --- src/data_structures.js | 1 + src/data_structures/treap.js | 198 ++++++++++++++++++++++++++++++ src/test/data_structures/treap.js | 103 ++++++++++++++++ 3 files changed, 302 insertions(+) create mode 100644 src/data_structures/treap.js create mode 100644 src/test/data_structures/treap.js diff --git a/src/data_structures.js b/src/data_structures.js index b14d633..43cbbc1 100644 --- a/src/data_structures.js +++ b/src/data_structures.js @@ -4,6 +4,7 @@ module.exports = { AVLTree: require('./data_structures/avl_tree'), BST: require('./data_structures/bst'), + Treap: require('./data_structures/treap'), Graph: require('./data_structures/graph'), HashTable: require('./data_structures/hash_table'), Heap: require('./data_structures/heap'), diff --git a/src/data_structures/treap.js b/src/data_structures/treap.js new file mode 100644 index 0000000..10693c6 --- /dev/null +++ b/src/data_structures/treap.js @@ -0,0 +1,198 @@ +'use strict'; + +/** + * Tree node + */ +function Node(value, left, right) { + this.value = value; + this.children = [left, right]; + this.size = 1; + this.key = Math.random(); +} + +Node.prototype.resize = function () { + return this.size = this.children[0].size + this.children[1].size + 1; +}; + +/** + * Zigzag rotate of tree nodes + */ +Node.prototype.rotate = function (side) { + var temp = this.children[side]; + + // Rotate + this.children[side] = temp.children[1 - side]; + temp.children[1 - side] = this; + + this.resize(); + temp.resize(); + + return temp; +}; + +/** + * Treap + */ +function Treap() { + /** + * nil: virtual node represent 'null' + * It's very convenient to avoid special judges in rotate operations. + */ + this.nil = new Node(0, 0, 0); + this.nil.size = 0; + this.nil.key = 1; + + this.root = this.nil; +} + +/** + * Using an object to pass reference of Node, + * nodeRef = { + * node: node + * } + * just like `*node` usage in C/C++. + */ +Treap.prototype._insert = function (nodeRef, value) { + if (nodeRef.node == this.nil) { + nodeRef.node = new Node(value, this.nil, this.nil); + return; + } + + if (nodeRef.node.value == value) { + // Duplicated + return; + } + + // Pass to childnodes + var side = ~~(value > nodeRef.node.value); + var newNodeRef = { + node: nodeRef.node.children[side] + }; + this._insert(newNodeRef, value); + nodeRef.node.children[side] = newNodeRef.node; + + // Keep balance + if (newNodeRef.node.key < nodeRef.node.key) { + nodeRef.node = nodeRef.node.rotate(side); + } else { + nodeRef.node.resize(); + } +}; + +Treap.prototype._find = function (nodeRef, value) { + if (nodeRef.node == this.nil) { + // Empty tree + return false; + } + if (nodeRef.node.value == value) { + // Found! + return true; + } + + // Search within childnodes + var side = ~~(value > nodeRef.node.value); + var newNodeRef = { + node: nodeRef.node.children[side] + }; + return this._find(newNodeRef, value); +}; + +Treap.prototype._minimum = function (nodeRef) { + if (nodeRef.node == this.nil) { + // Empty tree, returns Infinity + return Infinity; + } + + var newNodeRef = { + node: nodeRef.node.children[0] // Left child + }; + return Math.min(nodeRef.node.value, this._minimum(newNodeRef)); +}; + +Treap.prototype._maximum = function (nodeRef) { + if (nodeRef.node == this.nil) { + // Empty tree, returns -Infinity + return -Infinity; + } + + var newNodeRef = { + node: nodeRef.node.children[1] // Right child + }; + return Math.max(nodeRef.node.value, this._maximum(newNodeRef)); +}; + +Treap.prototype._remove = function (nodeRef, value) { + if (nodeRef.node == this.nil) { + // Empty node, value not found + return; + } + + if (nodeRef.node.value == value) { + if (nodeRef.node.children[0] == this.nil && nodeRef.node.children[1] == this.nil) { + // Leaf node, set to nil + nodeRef.node = this.nil; + return; + } + /** + * Rotate up the child which has a smaller key + * notice nil node has the biggest key, it will always stay behind + */ + var side = ~~(nodeRef.node.children[0].key > nodeRef.node.children[1].key); + nodeRef.node = nodeRef.node.rotate(side); + + var newNodeRef = { + node: nodeRef.node.children[1 - side] + }; + this._remove(newNodeRef, value); + nodeRef.node.children[1 - side] = newNodeRef.node; + } else { + var side = ~~(value > nodeRef.node.value); + var newNodeRef = { + node: nodeRef.node.children[side] + }; + this._remove(newNodeRef, value); + nodeRef.node.children[side] = newNodeRef.node; + } + + nodeRef.node.resize(); +}; + +Treap.prototype.insert = function (value) { + var rootRef = { + node: this.root + }; + this._insert(rootRef, value); + + // Reset root from reference + this.root = rootRef.node; +}; + +Treap.prototype.find = function (value) { + return this._find({ + node: this.root + }, value); +}; + +Treap.prototype.minimum = function () { + return this._minimum({ + node: this.root + }); +}; + +Treap.prototype.maximum = function () { + return this._maximum({ + node: this.root + }); +}; + +Treap.prototype.remove = function (value) { + var rootRef = { + node: this.root + }; + this._remove(rootRef, value); + + // Reset root from reference + this.root = rootRef.node; +} + +module.exports = Treap; diff --git a/src/test/data_structures/treap.js b/src/test/data_structures/treap.js new file mode 100644 index 0000000..8a053a5 --- /dev/null +++ b/src/test/data_structures/treap.js @@ -0,0 +1,103 @@ +'use strict'; + +var root = require('../..'), + Treap = root.DataStructures.Treap, + assert = require('assert'); + +describe('Treap', function () { + var treap; + before(function () { + treap = new Treap(); + }); + + it('should insert elements', function () { + treap.insert(3); + treap.insert(2); + treap.insert(10); + treap.insert(-1); + treap.insert(100); + treap.insert(101); + treap.insert(1); + assert.equal(treap.root.size, 7); + treap.insert(-100); + assert.equal(treap.root.size, 8); + }); + + it('should remove elements correctly', function () { + // Value that not exist + treap.remove(200); + assert.equal(treap.root.size, 8); + treap.remove(100); + assert.equal(treap.root.size, 7); + treap.remove(1); + treap.remove(-1); + treap.remove(-1); + treap.remove(101); + assert.equal(treap.root.size, 4); + }); + + it('should insert and remove elements', function () { + // [-100, 2, 3, 10] + treap.insert(200); + // [-100, 2, 3, 10, 200] + assert.equal(treap.root.size, 5); + treap.remove(-100); + // [2, 3, 10, 200] + assert.equal(treap.root.size, 4); + treap.insert(1); + treap.remove(1); + treap.insert(1); + // [1, 2, 3, 10, 200] + treap.remove(200); + treap.insert(100); + // [1, 2, 3, 10, 100] + assert.equal(treap.root.size, 5); + }); + + it('should check if an element exists', function () { + // [1, 2, 3, 10, 100] + assert.equal(treap.find(1), true); + assert.equal(treap.find(2), true); + assert.equal(treap.find(3), true); + assert.equal(treap.find(10), true); + assert.equal(treap.find(100), true); + assert.equal(treap.find(200), false); + assert.equal(treap.find(-100), false); + assert.equal(treap.find(-1), false); + assert.equal(treap.find(101), false); + }); + + it('should get minimum element', function () { + // [1, 2, 3, 10, 100] + assert.equal(treap.minimum(), 1); + treap.remove(1); + // [2, 3, 10, 100] + assert.equal(treap.minimum(), 2); + treap.insert(-100); + // [-100, 2, 3, 10, 100] + assert.equal(treap.minimum(), -100); + treap.remove(-100); + // [2, 3, 10, 100] + assert.equal(treap.minimum(), 2); + }); + + it('should get maximum element', function () { + // [2, 3, 10, 100] + assert.equal(treap.maximum(), 100); + treap.remove(100); + // [2, 3, 10] + assert.equal(treap.maximum(), 10); + treap.remove(10); + // [2, 3] + assert.equal(treap.maximum(), 3); + treap.remove(3); + // [2] + assert.equal(treap.maximum(), 2); + treap.insert(1); + // [1, 2] + assert.equal(treap.maximum(), 2); + treap.remove(2); + // [1] + assert.equal(treap.maximum(), 1); + }); +}); From 48b3dfd256da6a9d48bf9545d36daab8665df146 Mon Sep 17 00:00:00 2001 From: quietshu Date: Fri, 28 Aug 2015 14:57:43 +0800 Subject: [PATCH 211/280] Fix style. --- src/data_structures/treap.js | 284 +++++++++++++++--------------- src/test/data_structures/treap.js | 138 +++++++-------- 2 files changed, 211 insertions(+), 211 deletions(-) diff --git a/src/data_structures/treap.js b/src/data_structures/treap.js index 10693c6..b9a3238 100644 --- a/src/data_structures/treap.js +++ b/src/data_structures/treap.js @@ -4,45 +4,45 @@ * Tree node */ function Node(value, left, right) { - this.value = value; - this.children = [left, right]; - this.size = 1; - this.key = Math.random(); + this.value = value; + this.children = [left, right]; + this.size = 1; + this.key = Math.random(); } -Node.prototype.resize = function () { - return this.size = this.children[0].size + this.children[1].size + 1; +Node.prototype.resize = function() { + return this.size = this.children[0].size + this.children[1].size + 1; }; /** * Zigzag rotate of tree nodes */ -Node.prototype.rotate = function (side) { - var temp = this.children[side]; +Node.prototype.rotate = function(side) { + var temp = this.children[side]; - // Rotate - this.children[side] = temp.children[1 - side]; - temp.children[1 - side] = this; + // Rotate + this.children[side] = temp.children[1 - side]; + temp.children[1 - side] = this; - this.resize(); - temp.resize(); + this.resize(); + temp.resize(); - return temp; + return temp; }; /** * Treap */ function Treap() { - /** - * nil: virtual node represent 'null' - * It's very convenient to avoid special judges in rotate operations. - */ - this.nil = new Node(0, 0, 0); - this.nil.size = 0; - this.nil.key = 1; - - this.root = this.nil; + /** + * nil: virtual node represent 'null' + * It's very convenient to avoid special judges in rotate operations. + */ + this.nil = new Node(0, 0, 0); + this.nil.size = 0; + this.nil.key = 1; + + this.root = this.nil; } /** @@ -52,147 +52,147 @@ function Treap() { * } * just like `*node` usage in C/C++. */ -Treap.prototype._insert = function (nodeRef, value) { - if (nodeRef.node == this.nil) { - nodeRef.node = new Node(value, this.nil, this.nil); - return; - } - - if (nodeRef.node.value == value) { - // Duplicated - return; - } - - // Pass to childnodes - var side = ~~(value > nodeRef.node.value); - var newNodeRef = { - node: nodeRef.node.children[side] - }; - this._insert(newNodeRef, value); - nodeRef.node.children[side] = newNodeRef.node; - - // Keep balance - if (newNodeRef.node.key < nodeRef.node.key) { - nodeRef.node = nodeRef.node.rotate(side); - } else { - nodeRef.node.resize(); - } +Treap.prototype._insert = function(nodeRef, value) { + if (nodeRef.node == this.nil) { + nodeRef.node = new Node(value, this.nil, this.nil); + return; + } + + if (nodeRef.node.value == value) { + // Duplicated + return; + } + + // Pass to childnodes + var side = ~~(value > nodeRef.node.value); + var newNodeRef = { + node: nodeRef.node.children[side] + }; + this._insert(newNodeRef, value); + nodeRef.node.children[side] = newNodeRef.node; + + // Keep balance + if (newNodeRef.node.key < nodeRef.node.key) { + nodeRef.node = nodeRef.node.rotate(side); + } else { + nodeRef.node.resize(); + } }; -Treap.prototype._find = function (nodeRef, value) { - if (nodeRef.node == this.nil) { - // Empty tree - return false; - } - if (nodeRef.node.value == value) { - // Found! - return true; - } - - // Search within childnodes - var side = ~~(value > nodeRef.node.value); - var newNodeRef = { - node: nodeRef.node.children[side] - }; - return this._find(newNodeRef, value); +Treap.prototype._find = function(nodeRef, value) { + if (nodeRef.node == this.nil) { + // Empty tree + return false; + } + if (nodeRef.node.value == value) { + // Found! + return true; + } + + // Search within childnodes + var side = ~~(value > nodeRef.node.value); + var newNodeRef = { + node: nodeRef.node.children[side] + }; + return this._find(newNodeRef, value); }; -Treap.prototype._minimum = function (nodeRef) { - if (nodeRef.node == this.nil) { - // Empty tree, returns Infinity - return Infinity; - } +Treap.prototype._minimum = function(nodeRef) { + if (nodeRef.node == this.nil) { + // Empty tree, returns Infinity + return Infinity; + } - var newNodeRef = { - node: nodeRef.node.children[0] // Left child - }; - return Math.min(nodeRef.node.value, this._minimum(newNodeRef)); + var newNodeRef = { + node: nodeRef.node.children[0] // Left child + }; + return Math.min(nodeRef.node.value, this._minimum(newNodeRef)); }; -Treap.prototype._maximum = function (nodeRef) { - if (nodeRef.node == this.nil) { - // Empty tree, returns -Infinity - return -Infinity; - } +Treap.prototype._maximum = function(nodeRef) { + if (nodeRef.node == this.nil) { + // Empty tree, returns -Infinity + return -Infinity; + } - var newNodeRef = { - node: nodeRef.node.children[1] // Right child - }; - return Math.max(nodeRef.node.value, this._maximum(newNodeRef)); + var newNodeRef = { + node: nodeRef.node.children[1] // Right child + }; + return Math.max(nodeRef.node.value, this._maximum(newNodeRef)); }; -Treap.prototype._remove = function (nodeRef, value) { - if (nodeRef.node == this.nil) { - // Empty node, value not found - return; - } - - if (nodeRef.node.value == value) { - if (nodeRef.node.children[0] == this.nil && nodeRef.node.children[1] == this.nil) { - // Leaf node, set to nil - nodeRef.node = this.nil; - return; - } - /** - * Rotate up the child which has a smaller key - * notice nil node has the biggest key, it will always stay behind - */ - var side = ~~(nodeRef.node.children[0].key > nodeRef.node.children[1].key); - nodeRef.node = nodeRef.node.rotate(side); - - var newNodeRef = { - node: nodeRef.node.children[1 - side] - }; - this._remove(newNodeRef, value); - nodeRef.node.children[1 - side] = newNodeRef.node; - } else { - var side = ~~(value > nodeRef.node.value); - var newNodeRef = { - node: nodeRef.node.children[side] - }; - this._remove(newNodeRef, value); - nodeRef.node.children[side] = newNodeRef.node; - } - - nodeRef.node.resize(); +Treap.prototype._remove = function(nodeRef, value) { + if (nodeRef.node == this.nil) { + // Empty node, value not found + return; + } + + if (nodeRef.node.value == value) { + if (nodeRef.node.children[0] == this.nil && nodeRef.node.children[1] == this.nil) { + // Leaf node, set to nil + nodeRef.node = this.nil; + return; + } + /** + * Rotate up the child which has a smaller key + * notice nil node has the biggest key, it will always stay behind + */ + var side = ~~(nodeRef.node.children[0].key > nodeRef.node.children[1].key); + nodeRef.node = nodeRef.node.rotate(side); + + var newNodeRef = { + node: nodeRef.node.children[1 - side] + }; + this._remove(newNodeRef, value); + nodeRef.node.children[1 - side] = newNodeRef.node; + } else { + var side = ~~(value > nodeRef.node.value); + var newNodeRef = { + node: nodeRef.node.children[side] + }; + this._remove(newNodeRef, value); + nodeRef.node.children[side] = newNodeRef.node; + } + + nodeRef.node.resize(); }; -Treap.prototype.insert = function (value) { - var rootRef = { - node: this.root - }; - this._insert(rootRef, value); +Treap.prototype.insert = function(value) { + var rootRef = { + node: this.root + }; + this._insert(rootRef, value); - // Reset root from reference - this.root = rootRef.node; + // Reset root from reference + this.root = rootRef.node; }; -Treap.prototype.find = function (value) { - return this._find({ - node: this.root - }, value); +Treap.prototype.find = function(value) { + return this._find({ + node: this.root + }, value); }; -Treap.prototype.minimum = function () { - return this._minimum({ - node: this.root - }); +Treap.prototype.minimum = function() { + return this._minimum({ + node: this.root + }); }; -Treap.prototype.maximum = function () { - return this._maximum({ - node: this.root - }); +Treap.prototype.maximum = function() { + return this._maximum({ + node: this.root + }); }; -Treap.prototype.remove = function (value) { - var rootRef = { - node: this.root - }; - this._remove(rootRef, value); +Treap.prototype.remove = function(value) { + var rootRef = { + node: this.root + }; + this._remove(rootRef, value); - // Reset root from reference - this.root = rootRef.node; + // Reset root from reference + this.root = rootRef.node; } module.exports = Treap; diff --git a/src/test/data_structures/treap.js b/src/test/data_structures/treap.js index 8a053a5..9470f42 100644 --- a/src/test/data_structures/treap.js +++ b/src/test/data_structures/treap.js @@ -1,16 +1,16 @@ 'use strict'; var root = require('../..'), - Treap = root.DataStructures.Treap, - assert = require('assert'); + Treap = root.DataStructures.Treap, + assert = require('assert'); -describe('Treap', function () { +describe('Treap', function() { var treap; - before(function () { - treap = new Treap(); + before(function() { + treap = new Treap(); }); - it('should insert elements', function () { + it('should insert elements', function() { treap.insert(3); treap.insert(2); treap.insert(10); @@ -23,81 +23,81 @@ describe('Treap', function () { assert.equal(treap.root.size, 8); }); - it('should remove elements correctly', function () { - // Value that not exist - treap.remove(200); + it('should remove elements correctly', function() { + // Value that not exist + treap.remove(200); assert.equal(treap.root.size, 8); - treap.remove(100); + treap.remove(100); assert.equal(treap.root.size, 7); - treap.remove(1); - treap.remove(-1); - treap.remove(-1); - treap.remove(101); + treap.remove(1); + treap.remove(-1); + treap.remove(-1); + treap.remove(101); assert.equal(treap.root.size, 4); }); - it('should insert and remove elements', function () { - // [-100, 2, 3, 10] - treap.insert(200); - // [-100, 2, 3, 10, 200] + it('should insert and remove elements', function() { + // [-100, 2, 3, 10] + treap.insert(200); + // [-100, 2, 3, 10, 200] assert.equal(treap.root.size, 5); - treap.remove(-100); - // [2, 3, 10, 200] + treap.remove(-100); + // [2, 3, 10, 200] assert.equal(treap.root.size, 4); - treap.insert(1); - treap.remove(1); - treap.insert(1); - // [1, 2, 3, 10, 200] - treap.remove(200); - treap.insert(100); - // [1, 2, 3, 10, 100] + treap.insert(1); + treap.remove(1); + treap.insert(1); + // [1, 2, 3, 10, 200] + treap.remove(200); + treap.insert(100); + // [1, 2, 3, 10, 100] assert.equal(treap.root.size, 5); }); - it('should check if an element exists', function () { - // [1, 2, 3, 10, 100] - assert.equal(treap.find(1), true); - assert.equal(treap.find(2), true); - assert.equal(treap.find(3), true); - assert.equal(treap.find(10), true); - assert.equal(treap.find(100), true); - assert.equal(treap.find(200), false); - assert.equal(treap.find(-100), false); - assert.equal(treap.find(-1), false); - assert.equal(treap.find(101), false); + it('should check if an element exists', function() { + // [1, 2, 3, 10, 100] + assert.equal(treap.find(1), true); + assert.equal(treap.find(2), true); + assert.equal(treap.find(3), true); + assert.equal(treap.find(10), true); + assert.equal(treap.find(100), true); + assert.equal(treap.find(200), false); + assert.equal(treap.find(-100), false); + assert.equal(treap.find(-1), false); + assert.equal(treap.find(101), false); }); - it('should get minimum element', function () { - // [1, 2, 3, 10, 100] - assert.equal(treap.minimum(), 1); - treap.remove(1); - // [2, 3, 10, 100] - assert.equal(treap.minimum(), 2); - treap.insert(-100); - // [-100, 2, 3, 10, 100] - assert.equal(treap.minimum(), -100); - treap.remove(-100); - // [2, 3, 10, 100] - assert.equal(treap.minimum(), 2); + it('should get minimum element', function() { + // [1, 2, 3, 10, 100] + assert.equal(treap.minimum(), 1); + treap.remove(1); + // [2, 3, 10, 100] + assert.equal(treap.minimum(), 2); + treap.insert(-100); + // [-100, 2, 3, 10, 100] + assert.equal(treap.minimum(), -100); + treap.remove(-100); + // [2, 3, 10, 100] + assert.equal(treap.minimum(), 2); }); - it('should get maximum element', function () { - // [2, 3, 10, 100] - assert.equal(treap.maximum(), 100); - treap.remove(100); - // [2, 3, 10] - assert.equal(treap.maximum(), 10); - treap.remove(10); - // [2, 3] - assert.equal(treap.maximum(), 3); - treap.remove(3); - // [2] - assert.equal(treap.maximum(), 2); - treap.insert(1); - // [1, 2] - assert.equal(treap.maximum(), 2); - treap.remove(2); - // [1] - assert.equal(treap.maximum(), 1); + it('should get maximum element', function() { + // [2, 3, 10, 100] + assert.equal(treap.maximum(), 100); + treap.remove(100); + // [2, 3, 10] + assert.equal(treap.maximum(), 10); + treap.remove(10); + // [2, 3] + assert.equal(treap.maximum(), 3); + treap.remove(3); + // [2] + assert.equal(treap.maximum(), 2); + treap.insert(1); + // [1, 2] + assert.equal(treap.maximum(), 2); + treap.remove(2); + // [1] + assert.equal(treap.maximum(), 1); }); -}); +}); \ No newline at end of file From 4820cf6c74e7c0cb1e0a126ce327fc3db1289cfe Mon Sep 17 00:00:00 2001 From: quietshu Date: Fri, 28 Aug 2015 15:08:45 +0800 Subject: [PATCH 212/280] Fix eslint problems. --- src/data_structures/treap.js | 56 +++++++++++++++++-------------- src/test/data_structures/treap.js | 16 ++++----- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/data_structures/treap.js b/src/data_structures/treap.js index b9a3238..7e5430a 100644 --- a/src/data_structures/treap.js +++ b/src/data_structures/treap.js @@ -10,14 +10,14 @@ function Node(value, left, right) { this.key = Math.random(); } -Node.prototype.resize = function() { +Node.prototype.resize = function () { return this.size = this.children[0].size + this.children[1].size + 1; }; /** * Zigzag rotate of tree nodes */ -Node.prototype.rotate = function(side) { +Node.prototype.rotate = function (side) { var temp = this.children[side]; // Rotate @@ -52,13 +52,13 @@ function Treap() { * } * just like `*node` usage in C/C++. */ -Treap.prototype._insert = function(nodeRef, value) { - if (nodeRef.node == this.nil) { +Treap.prototype._insert = function (nodeRef, value) { + if (nodeRef.node === this.nil) { nodeRef.node = new Node(value, this.nil, this.nil); return; } - if (nodeRef.node.value == value) { + if (nodeRef.node.value === value) { // Duplicated return; } @@ -79,12 +79,12 @@ Treap.prototype._insert = function(nodeRef, value) { } }; -Treap.prototype._find = function(nodeRef, value) { - if (nodeRef.node == this.nil) { +Treap.prototype._find = function (nodeRef, value) { + if (nodeRef.node === this.nil) { // Empty tree return false; } - if (nodeRef.node.value == value) { + if (nodeRef.node.value === value) { // Found! return true; } @@ -97,8 +97,8 @@ Treap.prototype._find = function(nodeRef, value) { return this._find(newNodeRef, value); }; -Treap.prototype._minimum = function(nodeRef) { - if (nodeRef.node == this.nil) { +Treap.prototype._minimum = function (nodeRef) { + if (nodeRef.node === this.nil) { // Empty tree, returns Infinity return Infinity; } @@ -109,8 +109,8 @@ Treap.prototype._minimum = function(nodeRef) { return Math.min(nodeRef.node.value, this._minimum(newNodeRef)); }; -Treap.prototype._maximum = function(nodeRef) { - if (nodeRef.node == this.nil) { +Treap.prototype._maximum = function (nodeRef) { + if (nodeRef.node === this.nil) { // Empty tree, returns -Infinity return -Infinity; } @@ -121,14 +121,18 @@ Treap.prototype._maximum = function(nodeRef) { return Math.max(nodeRef.node.value, this._maximum(newNodeRef)); }; -Treap.prototype._remove = function(nodeRef, value) { - if (nodeRef.node == this.nil) { +Treap.prototype._remove = function (nodeRef, value) { + if (nodeRef.node === this.nil) { // Empty node, value not found return; } - if (nodeRef.node.value == value) { - if (nodeRef.node.children[0] == this.nil && nodeRef.node.children[1] == this.nil) { + var side; + var newNodeRef; + + if (nodeRef.node.value === value) { + if (nodeRef.node.children[0] === this.nil && + nodeRef.node.children[1] === this.nil) { // Leaf node, set to nil nodeRef.node = this.nil; return; @@ -137,17 +141,17 @@ Treap.prototype._remove = function(nodeRef, value) { * Rotate up the child which has a smaller key * notice nil node has the biggest key, it will always stay behind */ - var side = ~~(nodeRef.node.children[0].key > nodeRef.node.children[1].key); + side = ~~(nodeRef.node.children[0].key > nodeRef.node.children[1].key); nodeRef.node = nodeRef.node.rotate(side); - var newNodeRef = { + newNodeRef = { node: nodeRef.node.children[1 - side] }; this._remove(newNodeRef, value); nodeRef.node.children[1 - side] = newNodeRef.node; } else { - var side = ~~(value > nodeRef.node.value); - var newNodeRef = { + side = ~~(value > nodeRef.node.value); + newNodeRef = { node: nodeRef.node.children[side] }; this._remove(newNodeRef, value); @@ -157,7 +161,7 @@ Treap.prototype._remove = function(nodeRef, value) { nodeRef.node.resize(); }; -Treap.prototype.insert = function(value) { +Treap.prototype.insert = function (value) { var rootRef = { node: this.root }; @@ -167,25 +171,25 @@ Treap.prototype.insert = function(value) { this.root = rootRef.node; }; -Treap.prototype.find = function(value) { +Treap.prototype.find = function (value) { return this._find({ node: this.root }, value); }; -Treap.prototype.minimum = function() { +Treap.prototype.minimum = function () { return this._minimum({ node: this.root }); }; -Treap.prototype.maximum = function() { +Treap.prototype.maximum = function () { return this._maximum({ node: this.root }); }; -Treap.prototype.remove = function(value) { +Treap.prototype.remove = function (value) { var rootRef = { node: this.root }; @@ -193,6 +197,6 @@ Treap.prototype.remove = function(value) { // Reset root from reference this.root = rootRef.node; -} +}; module.exports = Treap; diff --git a/src/test/data_structures/treap.js b/src/test/data_structures/treap.js index 9470f42..b7711d8 100644 --- a/src/test/data_structures/treap.js +++ b/src/test/data_structures/treap.js @@ -4,13 +4,13 @@ var root = require('../..'), Treap = root.DataStructures.Treap, assert = require('assert'); -describe('Treap', function() { +describe('Treap', function () { var treap; - before(function() { + before(function () { treap = new Treap(); }); - it('should insert elements', function() { + it('should insert elements', function () { treap.insert(3); treap.insert(2); treap.insert(10); @@ -23,7 +23,7 @@ describe('Treap', function() { assert.equal(treap.root.size, 8); }); - it('should remove elements correctly', function() { + it('should remove elements correctly', function () { // Value that not exist treap.remove(200); assert.equal(treap.root.size, 8); @@ -36,7 +36,7 @@ describe('Treap', function() { assert.equal(treap.root.size, 4); }); - it('should insert and remove elements', function() { + it('should insert and remove elements', function () { // [-100, 2, 3, 10] treap.insert(200); // [-100, 2, 3, 10, 200] @@ -54,7 +54,7 @@ describe('Treap', function() { assert.equal(treap.root.size, 5); }); - it('should check if an element exists', function() { + it('should check if an element exists', function () { // [1, 2, 3, 10, 100] assert.equal(treap.find(1), true); assert.equal(treap.find(2), true); @@ -67,7 +67,7 @@ describe('Treap', function() { assert.equal(treap.find(101), false); }); - it('should get minimum element', function() { + it('should get minimum element', function () { // [1, 2, 3, 10, 100] assert.equal(treap.minimum(), 1); treap.remove(1); @@ -81,7 +81,7 @@ describe('Treap', function() { assert.equal(treap.minimum(), 2); }); - it('should get maximum element', function() { + it('should get maximum element', function () { // [2, 3, 10, 100] assert.equal(treap.maximum(), 100); treap.remove(100); From f9171a87c0bb6d1f23a8404e7deee1c3e7740bfb Mon Sep 17 00:00:00 2001 From: Evandro Eisinger Date: Sun, 30 Aug 2015 00:47:25 -0300 Subject: [PATCH 213/280] added short bubble sort algorithm test --- src/test/algorithms/sorting/short_bubble_sort.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/test/algorithms/sorting/short_bubble_sort.js diff --git a/src/test/algorithms/sorting/short_bubble_sort.js b/src/test/algorithms/sorting/short_bubble_sort.js new file mode 100644 index 0000000..6837bb3 --- /dev/null +++ b/src/test/algorithms/sorting/short_bubble_sort.js @@ -0,0 +1,14 @@ +'use strict'; + +var shortBubbleSort = require('../../..').Sorting.shortBubbleSort, + sortingTestsHelper = require('./sorting_tests_helper'); + +describe('Short Bubble Sort', function () { + it('should sort the given array', function () { + sortingTestsHelper.testSort(shortBubbleSort); + }); + + it('should sort the array with a specific comparison function', function () { + sortingTestsHelper.testSortWithComparisonFn(shortBubbleSort); + }); +}); From 46f7a0897f6f63585f166690bff14cf303aed94a Mon Sep 17 00:00:00 2001 From: Evandro Eisinger Date: Sun, 30 Aug 2015 00:48:06 -0300 Subject: [PATCH 214/280] added short bubble sort algorithm --- src/algorithms/sorting/short_bubble_sort.js | 30 +++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/algorithms/sorting/short_bubble_sort.js diff --git a/src/algorithms/sorting/short_bubble_sort.js b/src/algorithms/sorting/short_bubble_sort.js new file mode 100644 index 0000000..5b900e2 --- /dev/null +++ b/src/algorithms/sorting/short_bubble_sort.js @@ -0,0 +1,30 @@ +'use strict'; + +var Comparator = require('../../util/comparator'); + +/** + * short bubble sort algorithm + * worst: O(n^2) best: O(n) + */ + +function shortBubbleSort(array, comparatorFn) { + var comparator = new Comparator(comparatorFn); + var length = array.length; + var i = 0; + + for (i; i < length; i++) { + var current = array[i]; + var next = array[i+1]; + + if (next === undefined) break; + if (comparator.lessThanOrEqual(current, next)) continue; + + array[i+1] = current; + array[i] = next; + i = -1; + } + + return array; +} + +module.exports = shortBubbleSort; From 564be420867dd3e14a5ce88d1e85e61c05f0bd5d Mon Sep 17 00:00:00 2001 From: Evandro Eisinger Date: Sun, 30 Aug 2015 00:48:52 -0300 Subject: [PATCH 215/280] added shortBubbleSort algorithm --- README.md | 1 + src/sorting.js | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 0cd4bff..efd75f1 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,7 @@ require('algorithms').Sorting; * radixSort * selectionSort * shellSort +* shortBubbleSort #### String algorithms diff --git a/src/sorting.js b/src/sorting.js index 6499d73..332e9ab 100644 --- a/src/sorting.js +++ b/src/sorting.js @@ -3,6 +3,7 @@ // Sorting algorithms module.exports = { bubbleSort: require('./algorithms/sorting/bubble_sort'), + shortBubbleSort: require('./algorithms/sorting/short_bubble_sort'), countingSort: require('./algorithms/sorting/counting_sort'), heapSort: require('./algorithms/sorting/heap_sort'), mergeSort: require('./algorithms/sorting/merge_sort'), From 85dba035b900f5aa5ce65b01a6e147e8c3c9ad34 Mon Sep 17 00:00:00 2001 From: Evandro Eisinger Date: Mon, 31 Aug 2015 11:52:18 -0300 Subject: [PATCH 216/280] improved algorithm readability and added a better documentation --- src/algorithms/sorting/short_bubble_sort.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/algorithms/sorting/short_bubble_sort.js b/src/algorithms/sorting/short_bubble_sort.js index 5b900e2..81b5a90 100644 --- a/src/algorithms/sorting/short_bubble_sort.js +++ b/src/algorithms/sorting/short_bubble_sort.js @@ -9,19 +9,25 @@ var Comparator = require('../../util/comparator'); function shortBubbleSort(array, comparatorFn) { var comparator = new Comparator(comparatorFn); - var length = array.length; + var length = array.length - 1; var i = 0; for (i; i < length; i++) { var current = array[i]; var next = array[i+1]; - if (next === undefined) break; - if (comparator.lessThanOrEqual(current, next)) continue; - - array[i+1] = current; - array[i] = next; - i = -1; + /** + * If the current value if greater than the next: + * - set current value to next value; + * - and set next value to current value; + * - then reset iterator counter to scan for values to be sorted. + */ + + if (comparator.greaterThan(current, next)) { + array[i+1] = current; + array[i] = next; + i = -1; + } } return array; From 02cf281cc4ac3818f00781b8afc8b1c0bb189e5c Mon Sep 17 00:00:00 2001 From: Evandro Eisinger Date: Mon, 31 Aug 2015 12:00:56 -0300 Subject: [PATCH 217/280] updated doc. --- src/algorithms/sorting/short_bubble_sort.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/sorting/short_bubble_sort.js b/src/algorithms/sorting/short_bubble_sort.js index 81b5a90..4632208 100644 --- a/src/algorithms/sorting/short_bubble_sort.js +++ b/src/algorithms/sorting/short_bubble_sort.js @@ -20,7 +20,7 @@ function shortBubbleSort(array, comparatorFn) { * If the current value if greater than the next: * - set current value to next value; * - and set next value to current value; - * - then reset iterator counter to scan for values to be sorted. + * - then reset iterator counter to rescan for values to be sorted. */ if (comparator.greaterThan(current, next)) { From 02208ecede17abacc3ac3a3ca0a901ae865cd6cc Mon Sep 17 00:00:00 2001 From: quietshu Date: Fri, 16 Oct 2015 20:56:23 +0800 Subject: [PATCH 218/280] Test for balance, rotation and duplicate values, improve code style --- src/data_structures/treap.js | 169 +++++++++++------------------- src/test/data_structures/treap.js | 87 +++++++++++++++ 2 files changed, 148 insertions(+), 108 deletions(-) diff --git a/src/data_structures/treap.js b/src/data_structures/treap.js index 7e5430a..8c5fbc5 100644 --- a/src/data_structures/treap.js +++ b/src/data_structures/treap.js @@ -7,11 +7,19 @@ function Node(value, left, right) { this.value = value; this.children = [left, right]; this.size = 1; + this.height = 1; this.key = Math.random(); } +/** + * Computer the number of childnodes + */ Node.prototype.resize = function () { - return this.size = this.children[0].size + this.children[1].size + 1; + this.size = (this.children[0] ? this.children[0].size : 0) + + (this.children[1] ? this.children[1].size : 0) + 1; + this.height = Math.max(this.children[0] ? this.children[0].height : 0, + this.children[1] ? this.children[1].height : 0) + 1; + return this; }; /** @@ -34,169 +42,114 @@ Node.prototype.rotate = function (side) { * Treap */ function Treap() { - /** - * nil: virtual node represent 'null' - * It's very convenient to avoid special judges in rotate operations. - */ - this.nil = new Node(0, 0, 0); - this.nil.size = 0; - this.nil.key = 1; - - this.root = this.nil; + this.root = null; } /** - * Using an object to pass reference of Node, - * nodeRef = { - * node: node - * } - * just like `*node` usage in C/C++. + * Insert new value into the subtree of `node` */ -Treap.prototype._insert = function (nodeRef, value) { - if (nodeRef.node === this.nil) { - nodeRef.node = new Node(value, this.nil, this.nil); - return; +Treap.prototype._insert = function (node, value) { + if (node === null) { + return new Node(value, null, null); } - if (nodeRef.node.value === value) { - // Duplicated - return; - } + // Passing to childnodes and update + var side = ~~(value > node.value); + node.children[side] = this._insert(node.children[side], value); - // Pass to childnodes - var side = ~~(value > nodeRef.node.value); - var newNodeRef = { - node: nodeRef.node.children[side] - }; - this._insert(newNodeRef, value); - nodeRef.node.children[side] = newNodeRef.node; - - // Keep balance - if (newNodeRef.node.key < nodeRef.node.key) { - nodeRef.node = nodeRef.node.rotate(side); + // Keep it balance + if (node.children[side].key < node.key) { + return node.rotate(side); } else { - nodeRef.node.resize(); + return node.resize(); } }; -Treap.prototype._find = function (nodeRef, value) { - if (nodeRef.node === this.nil) { +Treap.prototype._find = function (node, value) { + if (node === null) { // Empty tree return false; } - if (nodeRef.node.value === value) { + if (node.value === value) { // Found! return true; } // Search within childnodes - var side = ~~(value > nodeRef.node.value); - var newNodeRef = { - node: nodeRef.node.children[side] - }; - return this._find(newNodeRef, value); + var side = ~~(value > node.value); + return this._find(node.children[side], value); }; -Treap.prototype._minimum = function (nodeRef) { - if (nodeRef.node === this.nil) { +Treap.prototype._minimum = function (node) { + if (node === null) { // Empty tree, returns Infinity return Infinity; } - var newNodeRef = { - node: nodeRef.node.children[0] // Left child - }; - return Math.min(nodeRef.node.value, this._minimum(newNodeRef)); + return Math.min(node.value, this._minimum(node.children[0])); }; -Treap.prototype._maximum = function (nodeRef) { - if (nodeRef.node === this.nil) { +Treap.prototype._maximum = function (node) { + if (node === null) { // Empty tree, returns -Infinity return -Infinity; } - var newNodeRef = { - node: nodeRef.node.children[1] // Right child - }; - return Math.max(nodeRef.node.value, this._maximum(newNodeRef)); + return Math.max(node.value, this._maximum(node.children[1])); }; -Treap.prototype._remove = function (nodeRef, value) { - if (nodeRef.node === this.nil) { +Treap.prototype._remove = function (node, value) { + if (node === null) { // Empty node, value not found - return; + return null; } var side; - var newNodeRef; - - if (nodeRef.node.value === value) { - if (nodeRef.node.children[0] === this.nil && - nodeRef.node.children[1] === this.nil) { - // Leaf node, set to nil - nodeRef.node = this.nil; - return; + + if (node.value === value) { + if (node.children[0] === null && node.children[1] === null) { + // It's a leaf, set to null + return null; } - /** - * Rotate up the child which has a smaller key - * notice nil node has the biggest key, it will always stay behind - */ - side = ~~(nodeRef.node.children[0].key > nodeRef.node.children[1].key); - nodeRef.node = nodeRef.node.rotate(side); - - newNodeRef = { - node: nodeRef.node.children[1 - side] - }; - this._remove(newNodeRef, value); - nodeRef.node.children[1 - side] = newNodeRef.node; + + // Rotate to a subtree and remove it + side = (node.children[0] === null ? 1 : 0); + node = node.rotate(side); + node.children[1 - side] = this._remove(node.children[1 - side], value); + return node.resize(); } else { - side = ~~(value > nodeRef.node.value); - newNodeRef = { - node: nodeRef.node.children[side] - }; - this._remove(newNodeRef, value); - nodeRef.node.children[side] = newNodeRef.node; + side = ~~(value > node.value); + node.children[side] = this._remove(node.children[side], value); + return node.resize(); } - - nodeRef.node.resize(); }; Treap.prototype.insert = function (value) { - var rootRef = { - node: this.root - }; - this._insert(rootRef, value); - - // Reset root from reference - this.root = rootRef.node; + this.root = this._insert(this.root, value); }; Treap.prototype.find = function (value) { - return this._find({ - node: this.root - }, value); + return this._find(this.root, value); }; Treap.prototype.minimum = function () { - return this._minimum({ - node: this.root - }); + return this._minimum(this.root); }; Treap.prototype.maximum = function () { - return this._maximum({ - node: this.root - }); + return this._maximum(this.root); }; Treap.prototype.remove = function (value) { - var rootRef = { - node: this.root - }; - this._remove(rootRef, value); + this.root = this._remove(this.root, value); +}; + +Treap.prototype.size = function () { + return this.root ? this.root.size : 0; +}; - // Reset root from reference - this.root = rootRef.node; +Treap.prototype.height = function () { + return this.root ? this.root.height : 0; }; module.exports = Treap; diff --git a/src/test/data_structures/treap.js b/src/test/data_structures/treap.js index b7711d8..55c991d 100644 --- a/src/test/data_structures/treap.js +++ b/src/test/data_structures/treap.js @@ -100,4 +100,91 @@ describe('Treap', function () { // [1] assert.equal(treap.maximum(), 1); }); + + it('should handle dumplicated elements', function () { + treap.insert(1); + // [1, 1] + assert.equal(treap.size(), 2); + treap.insert(-1); + // [-1, 1, 1] + assert.equal(treap.size(), 3); + treap.remove(1); + // [-1, 1] + assert.equal(treap.size(), 2); + treap.insert(-1); + treap.insert(-1); + treap.insert(-1); + // [-1, -1, -1, -1, 1] + assert.equal(treap.size(), 5); + treap.remove(-1); + treap.remove(1); + treap.remove(-1); + treap.remove(-1); + treap.remove(-1); + assert.equal(treap.size(), 0); + }); + + it('should keep balance', function () { + // Insert 1023 elements randomly + for (var i = 0; i < 1023; ++i) { + treap.insert(Math.random()); + } + assert.equal(treap.size(), 1023); + // The averange height should be 23 (with an error of 5) + assert(Math.abs(treap.height() - 23) < 5); + }); + + it('should rotate correctly', function () { + // Force clear the tree + treap.root = null; + treap.insert(1); + // 1 + assert.equal(treap.height(), 1); + + // Make the tree definite + treap.root.key = 2; + treap.insert(2); + /** + * 2 + * / + * 1 + * + */ + assert.equal(treap.height(), 2); + + treap.root.key = 1; + treap.insert(3); + /** + * 3 + * / + * 2 + * / + * 1 + * + */ + assert.equal(treap.height(), 3); + assert.equal(treap.root.value, 3); + + treap.root = treap.root.rotate(0); + /** + * 2 + * / \ + * 1 3 + * + */ + assert.equal(treap.height(), 2); + assert.equal(treap.root.value, 2); + + treap.root = treap.root.rotate(0); + /** + * 1 + * \ + * 2 + * \ + * 3 + * + */ + assert.equal(treap.height(), 3); + assert.equal(treap.root.value, 1); + }); }); \ No newline at end of file From 4435a15a02d0f3c4a6233e7e1c42da496f4e9c27 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 20 Oct 2015 11:42:07 +0200 Subject: [PATCH 219/280] Update dependencies --- .travis.yml | 2 +- package.json | 10 +++++----- src/algorithms/math/collatz_conjecture.js | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index fbfee74..0775871 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js sudo: false node_js: - - "0.12" + - "4.1" script: "make" after_success: "make coveralls" diff --git a/package.json b/package.json index 6edc652..b2cf23e 100644 --- a/package.json +++ b/package.json @@ -13,11 +13,11 @@ ], "dependencies": {}, "devDependencies": { - "coveralls": "^2.11.3", - "eslint": "^1.0.0", - "istanbul": "^0.3.17", - "mocha": "^2.2.5", - "pre-commit": "^1.1.1" + "coveralls": "^2.11.4", + "eslint": "^1.7.2", + "istanbul": "^0.4.0", + "mocha": "^2.3.3", + "pre-commit": "^1.1.2" }, "repository": { "type": "git", diff --git a/src/algorithms/math/collatz_conjecture.js b/src/algorithms/math/collatz_conjecture.js index 3c2af72..303bb21 100644 --- a/src/algorithms/math/collatz_conjecture.js +++ b/src/algorithms/math/collatz_conjecture.js @@ -30,7 +30,7 @@ function generateCollatzConjecture(number) { do { number = calculateCollatzConjecture(number); collatzConjecture.push(number); - } while (number !== 1) + } while (number !== 1); return collatzConjecture; } From f706569e60c49d733650399bcd1743aaa5dad524 Mon Sep 17 00:00:00 2001 From: quietshu Date: Thu, 5 Nov 2015 05:41:52 +0800 Subject: [PATCH 220/280] =?UTF-8?q?Geometry,=20basic=20B=C3=A9zier-curve?= =?UTF-8?q?=20algorithm=20(and=20its=20test)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/algorithms/geometry/bezier_curve.js | 59 ++++++++++++++++++++ src/geometry.js | 6 ++ src/index.js | 1 + src/test/algorithms/geometry/bezier_curve.js | 35 ++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 src/algorithms/geometry/bezier_curve.js create mode 100644 src/geometry.js create mode 100644 src/test/algorithms/geometry/bezier_curve.js diff --git a/src/algorithms/geometry/bezier_curve.js b/src/algorithms/geometry/bezier_curve.js new file mode 100644 index 0000000..7b1cade --- /dev/null +++ b/src/algorithms/geometry/bezier_curve.js @@ -0,0 +1,59 @@ +'use strict'; + +/** + * 2D bezier-curve, https://en.wikipedia.org/wiki/B%C3%A9zier_curve + * Usage: + * var b = new BezierCurve([ [0, 0], [10, 3] ]); + * b.get(0.5); // [5, 1.5] + */ + +/** + * Generates a bezier-curve from a series of points + * @param Array array of control points ([[x0, y0], [x1, y1]]) + */ +var BezierCurve = function (array) { + var n = array.length; + + // The binomial coefficient + var c = [1]; + var i, j; + for (i = 1; i < n; ++i) { + c.push(0); + for (j = i; j >= 1; --j) { + c[j] += c[j - 1]; + } + } + + // the i-th control point times the coefficient + var p = []; + for (i = 0; i < n; ++i) { + p.push([c[i] * array[i][0], c[i] * array[i][1]]); + } + + this.p = p; + this.n = n; +}; + +/** + * @param Number float variable from 0 to 1 + */ +BezierCurve.prototype.get = function (t) { + var res = [0, 0], i; + var a = 1, b = 1; + + // The coefficient + var c = []; + for (i = 0; i < this.n; ++i) { + c.push(a); + a *= t; + } + + for (i = this.n - 1; i >= 0; --i) { + res[0] += this.p[i][0] * c[i] * b; + res[1] += this.p[i][1] * c[i] * b; + b *= 1 - t; + } + return res; +}; + +module.exports = BezierCurve; diff --git a/src/geometry.js b/src/geometry.js new file mode 100644 index 0000000..7c709f0 --- /dev/null +++ b/src/geometry.js @@ -0,0 +1,6 @@ +'use strict'; + +// Geometry algorithms +module.exports = { + bezierCurve: require('./algorithms/geometry/bezier_curve') +}; diff --git a/src/index.js b/src/index.js index 95c99fb..15f7bb5 100644 --- a/src/index.js +++ b/src/index.js @@ -3,6 +3,7 @@ var lib = { DataStructures: require('./data_structures'), Graph: require('./graph'), + Geometry: require('./geometry'), Math: require('./math'), Search: require('./search'), Sorting: require('./sorting'), diff --git a/src/test/algorithms/geometry/bezier_curve.js b/src/test/algorithms/geometry/bezier_curve.js new file mode 100644 index 0000000..d3cfc19 --- /dev/null +++ b/src/test/algorithms/geometry/bezier_curve.js @@ -0,0 +1,35 @@ +'use strict'; + +var root = require('../../../'), + BezierCurve = root.Geometry.bezierCurve, + assert = require('assert'); + +// Testing with http://pomax.github.io/bezierjs/ + +describe('Bézier-Curve Algorithm', function () { + it('should get a linear Bézier-curve', function () { + var b = new BezierCurve([[0, 0], [10, 3]]); + + // Ends + assert.deepEqual(b.get(0), [0, 0]); + assert.deepEqual(b.get(1), [10, 3]); + + // Middle + assert.deepEqual(b.get(0.5), [5, 1.5]); + + // 1/4 and 3/4 + assert.deepEqual(b.get(0.25), [2.5, 0.75]); + assert.deepEqual(b.get(0.75), [7.5, 2.25]); + }); + it('should get a quadratic Bézier-curve', function () { + var b = new BezierCurve([[150, 40], [80, 30], [105, 150]]); + + assert.deepEqual(b.get(0.5), [103.75, 62.5]); + assert.deepEqual(b.get(0.25), [120.9375, 43.125]); + }); + it('should get a cubic Bézier-curve', function () { + var b = new BezierCurve([[150, 40], [80, 30], [105, 150], [100, 100]]); + + assert.deepEqual(b.get(0.5), [100.625, 85]); + }); +}); From bbebc16efc496e55c0fd91848827abe69f9e03ab Mon Sep 17 00:00:00 2001 From: Siarhei Padlozny Date: Wed, 20 Apr 2016 20:36:03 +0300 Subject: [PATCH 221/280] Add ternary search --- package.json | 1 + src/algorithms/search/ternary_search.js | 23 ++++++++++++++++++ src/search.js | 1 + .../algorithms/searching/ternary_search.js | 24 +++++++++++++++++++ 4 files changed, 49 insertions(+) create mode 100644 src/algorithms/search/ternary_search.js create mode 100644 src/test/algorithms/searching/ternary_search.js diff --git a/package.json b/package.json index b2cf23e..379ada8 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "eslint": "^1.7.2", "istanbul": "^0.4.0", "mocha": "^2.3.3", + "chai": "^3.5.0", "pre-commit": "^1.1.2" }, "repository": { diff --git a/src/algorithms/search/ternary_search.js b/src/algorithms/search/ternary_search.js new file mode 100644 index 0000000..2d3efe6 --- /dev/null +++ b/src/algorithms/search/ternary_search.js @@ -0,0 +1,23 @@ +'use strict'; + +/** + * Finds the maximum of unimodal function fn() within [left, right] + * To find the minimum, revert the if/else statement or revert the comparison. + * Time complexity: O(log(n)) + */ + +var ternarySearch = function (fn, left, right, precision) { + while (true) { + if (Math.abs(right - left) < precision) + return (left + right) / 2; + + var leftThird = left + (right - left) / 3, + rightThird = right - (right - left) / 3; + + if (fn(leftThird) < fn(rightThird)) + left = leftThird; else + right = rightThird; + } +}; + +module.exports = ternarySearch; diff --git a/src/search.js b/src/search.js index b78f914..5084cdf 100644 --- a/src/search.js +++ b/src/search.js @@ -4,5 +4,6 @@ module.exports = { bfs: require('./algorithms/search/bfs'), binarySearch: require('./algorithms/search/binarysearch'), + ternarySearch: require('./algorithms/search/ternary_search'), dfs: require('./algorithms/search/dfs') }; diff --git a/src/test/algorithms/searching/ternary_search.js b/src/test/algorithms/searching/ternary_search.js new file mode 100644 index 0000000..006ef7e --- /dev/null +++ b/src/test/algorithms/searching/ternary_search.js @@ -0,0 +1,24 @@ +'use strict'; + +require('chai').should(); + +var ternarySearch = require('../../..').Search.ternarySearch, + eps = 1e-6; + +var fn1 = function (x) { + return -Math.pow(x - 2, 2) + 4; +}; + +var fn2 = function (x) { + return -2 * Math.cos(x); +}; + +describe('Ternary search', function () { + it('should find the maximum of passed function', function () { + ternarySearch(fn1, 0.0, 4.0, eps).should.be.closeTo(2.0, eps); + ternarySearch(fn1, 1.0, 1.1, eps).should.be.closeTo(1.1, eps); + + ternarySearch(fn2, -2.0, 2.0, eps).should.be.closeTo(2.0, eps); + ternarySearch(fn2, 0, 2 * Math.PI, eps).should.be.closeTo(Math.PI, eps); + }); +}); From 221073894a44d9625016d9f867e937fff7d98405 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 27 Apr 2016 08:57:18 +0200 Subject: [PATCH 222/280] Update eslint --- .eslintrc | 8 ++------ package.json | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.eslintrc b/.eslintrc index 68afc94..bd98450 100644 --- a/.eslintrc +++ b/.eslintrc @@ -13,8 +13,7 @@ "beforeEach": false, "after": false, "afterEach": false, - "system": false, - "phantom": false + "Int32Array": false }, "rules": { "block-scoped-var": 2, @@ -75,10 +74,7 @@ "no-unused-vars": 2, "no-use-before-define": 0, "no-with": 2, - "space-after-keywords": [ - 2, - "always" - ], + "keyword-spacing": 2, "space-before-function-paren": [ 2, { diff --git a/package.json b/package.json index b2cf23e..beed33b 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "dependencies": {}, "devDependencies": { "coveralls": "^2.11.4", - "eslint": "^1.7.2", + "eslint": "^2.8.0", "istanbul": "^0.4.0", "mocha": "^2.3.3", "pre-commit": "^1.1.2" From 8da8f202dd517502ee9abdb92839addb5e7ba179 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 27 Apr 2016 09:04:16 +0200 Subject: [PATCH 223/280] Update nodejs in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0775871..649494c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js sudo: false node_js: - - "4.1" + - "5.1" script: "make" after_success: "make coveralls" From 73f2099f90b32a04a5a421220baa0e52329ab18f Mon Sep 17 00:00:00 2001 From: Siarhei Padlozny Date: Sat, 30 Apr 2016 22:54:08 +0300 Subject: [PATCH 224/280] Remove chai dependency --- package.json | 1 - src/algorithms/search/ternary_search.js | 6 ++---- src/test/algorithms/searching/ternary_search.js | 15 +++++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 379ada8..b2cf23e 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,6 @@ "eslint": "^1.7.2", "istanbul": "^0.4.0", "mocha": "^2.3.3", - "chai": "^3.5.0", "pre-commit": "^1.1.2" }, "repository": { diff --git a/src/algorithms/search/ternary_search.js b/src/algorithms/search/ternary_search.js index 2d3efe6..1f4c361 100644 --- a/src/algorithms/search/ternary_search.js +++ b/src/algorithms/search/ternary_search.js @@ -7,10 +7,7 @@ */ var ternarySearch = function (fn, left, right, precision) { - while (true) { - if (Math.abs(right - left) < precision) - return (left + right) / 2; - + while (Math.abs(right - left) > precision) { var leftThird = left + (right - left) / 3, rightThird = right - (right - left) / 3; @@ -18,6 +15,7 @@ var ternarySearch = function (fn, left, right, precision) { left = leftThird; else right = rightThird; } + return (left + right) / 2; }; module.exports = ternarySearch; diff --git a/src/test/algorithms/searching/ternary_search.js b/src/test/algorithms/searching/ternary_search.js index 006ef7e..b117815 100644 --- a/src/test/algorithms/searching/ternary_search.js +++ b/src/test/algorithms/searching/ternary_search.js @@ -1,8 +1,7 @@ 'use strict'; -require('chai').should(); - var ternarySearch = require('../../..').Search.ternarySearch, + assert = require('assert'), eps = 1e-6; var fn1 = function (x) { @@ -13,12 +12,16 @@ var fn2 = function (x) { return -2 * Math.cos(x); }; +var closeEnough = function (a, b, precision) { + return Math.abs(a - b) < precision; +}; + describe('Ternary search', function () { it('should find the maximum of passed function', function () { - ternarySearch(fn1, 0.0, 4.0, eps).should.be.closeTo(2.0, eps); - ternarySearch(fn1, 1.0, 1.1, eps).should.be.closeTo(1.1, eps); + assert(closeEnough(ternarySearch(fn1, 0.0, 4.0, eps), 2.0, eps)); + assert(closeEnough(ternarySearch(fn1, 0.0, 1.0, eps), 1.0, eps)); - ternarySearch(fn2, -2.0, 2.0, eps).should.be.closeTo(2.0, eps); - ternarySearch(fn2, 0, 2 * Math.PI, eps).should.be.closeTo(Math.PI, eps); + assert(closeEnough(ternarySearch(fn2, -2.0, 2.0, eps), 2.0, eps)); + assert(closeEnough(ternarySearch(fn2, 0.0, 2*Math.PI, eps), Math.PI, eps)); }); }); From f3737b1a7dafcaff35b3c74dc54818bf3f424981 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 4 May 2016 15:11:03 -0400 Subject: [PATCH 225/280] Use objects instead of array to represent points in Bezier-Curve --- src/algorithms/geometry/bezier_curve.js | 74 ++++++++++---------- src/test/algorithms/geometry/bezier_curve.js | 55 ++++++++------- 2 files changed, 66 insertions(+), 63 deletions(-) diff --git a/src/algorithms/geometry/bezier_curve.js b/src/algorithms/geometry/bezier_curve.js index 7b1cade..16f4f8f 100644 --- a/src/algorithms/geometry/bezier_curve.js +++ b/src/algorithms/geometry/bezier_curve.js @@ -3,57 +3,55 @@ /** * 2D bezier-curve, https://en.wikipedia.org/wiki/B%C3%A9zier_curve * Usage: - * var b = new BezierCurve([ [0, 0], [10, 3] ]); - * b.get(0.5); // [5, 1.5] + * var b = new BezierCurve([{x: 0, y: 0}, {x: 10, y: 3}]); + * b.get(0.5); // {x: 5, y: 1.5} */ /** * Generates a bezier-curve from a series of points - * @param Array array of control points ([[x0, y0], [x1, y1]]) + * @param Array array of control points ([{x: x0, y: y0}, {x: x1, y: y1}]) */ -var BezierCurve = function (array) { - var n = array.length; - - // The binomial coefficient - var c = [1]; - var i, j; - for (i = 1; i < n; ++i) { - c.push(0); - for (j = i; j >= 1; --j) { - c[j] += c[j - 1]; - } +var BezierCurve = function (points) { + this.n = points.length; + this.p = []; + + // The binomial coefficient + var c = [1]; + var i, j; + for (i = 1; i < this.n; ++i) { + c.push(0); + for (j = i; j >= 1; --j) { + c[j] += c[j - 1]; } + } - // the i-th control point times the coefficient - var p = []; - for (i = 0; i < n; ++i) { - p.push([c[i] * array[i][0], c[i] * array[i][1]]); - } - - this.p = p; - this.n = n; + // the i-th control point times the coefficient + for (i = 0; i < this.n; ++i) { + this.p.push({x: c[i] * points[i].x, y: c[i] * points[i].y}); + } }; /** * @param Number float variable from 0 to 1 */ BezierCurve.prototype.get = function (t) { - var res = [0, 0], i; - var a = 1, b = 1; - - // The coefficient - var c = []; - for (i = 0; i < this.n; ++i) { - c.push(a); - a *= t; - } - - for (i = this.n - 1; i >= 0; --i) { - res[0] += this.p[i][0] * c[i] * b; - res[1] += this.p[i][1] * c[i] * b; - b *= 1 - t; - } - return res; + var res = {x: 0, y: 0}; + var i; + var a = 1, b = 1; + + // The coefficient + var c = []; + for (i = 0; i < this.n; ++i) { + c.push(a); + a *= t; + } + + for (i = this.n - 1; i >= 0; --i) { + res.x += this.p[i].x * c[i] * b; + res.y += this.p[i].y * c[i] * b; + b *= 1 - t; + } + return res; }; module.exports = BezierCurve; diff --git a/src/test/algorithms/geometry/bezier_curve.js b/src/test/algorithms/geometry/bezier_curve.js index d3cfc19..6a0e537 100644 --- a/src/test/algorithms/geometry/bezier_curve.js +++ b/src/test/algorithms/geometry/bezier_curve.js @@ -7,29 +7,34 @@ var root = require('../../../'), // Testing with http://pomax.github.io/bezierjs/ describe('Bézier-Curve Algorithm', function () { - it('should get a linear Bézier-curve', function () { - var b = new BezierCurve([[0, 0], [10, 3]]); - - // Ends - assert.deepEqual(b.get(0), [0, 0]); - assert.deepEqual(b.get(1), [10, 3]); - - // Middle - assert.deepEqual(b.get(0.5), [5, 1.5]); - - // 1/4 and 3/4 - assert.deepEqual(b.get(0.25), [2.5, 0.75]); - assert.deepEqual(b.get(0.75), [7.5, 2.25]); - }); - it('should get a quadratic Bézier-curve', function () { - var b = new BezierCurve([[150, 40], [80, 30], [105, 150]]); - - assert.deepEqual(b.get(0.5), [103.75, 62.5]); - assert.deepEqual(b.get(0.25), [120.9375, 43.125]); - }); - it('should get a cubic Bézier-curve', function () { - var b = new BezierCurve([[150, 40], [80, 30], [105, 150], [100, 100]]); - - assert.deepEqual(b.get(0.5), [100.625, 85]); - }); + it('should get a linear Bézier-curve', function () { + var b = new BezierCurve([{x: 0, y: 0}, {x: 10, y: 3}]); + + // Ends + assert.deepEqual(b.get(0), {x: 0, y: 0}); + assert.deepEqual(b.get(1), {x: 10, y: 3}); + + // Middle + assert.deepEqual(b.get(0.5), {x: 5, y: 1.5}); + + // 1/4 and 3/4 + assert.deepEqual(b.get(0.25), {x: 2.5, y: 0.75}); + assert.deepEqual(b.get(0.75), {x: 7.5, y: 2.25}); + }); + it('should get a quadratic Bézier-curve', function () { + var b = new BezierCurve([{x: 150, y: 40}, + {x: 80, y: 30}, + {x: 105, y: 150}]); + + assert.deepEqual(b.get(0.5), {x: 103.75, y: 62.5}); + assert.deepEqual(b.get(0.25), {x: 120.9375, y: 43.125}); + }); + it('should get a cubic Bézier-curve', function () { + var b = new BezierCurve([{x: 150, y: 40}, + {x: 80, y: 30}, + {x: 105, y: 150}, + {x: 100, y: 100}]); + + assert.deepEqual(b.get(0.5), {x: 100.625, y: 85}); + }); }); From 17272516db5d0276385091b29c1adb22c2d85669 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 4 May 2016 15:16:30 -0400 Subject: [PATCH 226/280] Add Bezier-Curve to Readme --- README.md | 10 ++++++++++ src/geometry.js | 2 +- src/test/algorithms/geometry/bezier_curve.js | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 78913bd..c09d13c 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,16 @@ require('algorithms').DataStructures; * Set (HashSet) * Stack +#### Geometry algorithms + +```javascript +require('algorithms/geometry'); +// or +require('algorithms').Geometry; +``` + +* BezierCurve + #### Graph algorithms ```javascript diff --git a/src/geometry.js b/src/geometry.js index 7c709f0..7040652 100644 --- a/src/geometry.js +++ b/src/geometry.js @@ -2,5 +2,5 @@ // Geometry algorithms module.exports = { - bezierCurve: require('./algorithms/geometry/bezier_curve') + BezierCurve: require('./algorithms/geometry/bezier_curve') }; diff --git a/src/test/algorithms/geometry/bezier_curve.js b/src/test/algorithms/geometry/bezier_curve.js index 6a0e537..5b0dea0 100644 --- a/src/test/algorithms/geometry/bezier_curve.js +++ b/src/test/algorithms/geometry/bezier_curve.js @@ -1,7 +1,7 @@ 'use strict'; var root = require('../../../'), - BezierCurve = root.Geometry.bezierCurve, + BezierCurve = root.Geometry.BezierCurve, assert = require('assert'); // Testing with http://pomax.github.io/bezierjs/ From fa26c1f10c055de1edbf4069ffc7a7a39138ff6d Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 4 May 2016 15:21:34 -0400 Subject: [PATCH 227/280] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c09d13c..0f43fc6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # algorithms.js -[![Build Status](https://travis-ci.org/felipernb/algorithms.js.png?branch=master)](https://travis-ci.org/felipernb/algorithms.js) -[![Coverage Status](https://coveralls.io/repos/felipernb/algorithms.js/badge.png?branch=master)](https://coveralls.io/r/felipernb/algorithms.js?branch=master) +[![Build Status](https://travis-ci.org/felipernb/algorithms.js.svg?branch=master)](https://travis-ci.org/felipernb/algorithms.js) +[![Coverage Status](https://coveralls.io/repos/github/felipernb/algorithms.js/badge.svg?branch=master)](https://coveralls.io/github/felipernb/algorithms.js?branch=master) [![Dependency Status](https://david-dm.org/felipernb/algorithms.js.svg)](https://david-dm.org/felipernb/algorithms.js) [![devDependency Status](https://david-dm.org/felipernb/algorithms.js/dev-status.svg)](https://david-dm.org/felipernb/algorithms.js#info=devDependencies) [![Inline docs](http://inch-ci.org/github/felipernb/algorithms.js.svg?branch=master)](http://inch-ci.org/github/felipernb/algorithms.js) From 5e8a15b7bc603dcceada2ea5c872f96eae63e4dc Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 4 May 2016 15:56:15 -0400 Subject: [PATCH 228/280] 0.10.0 --- bundle/algorithms.browser.min.js | 7 ++++--- package.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/bundle/algorithms.browser.min.js b/bundle/algorithms.browser.min.js index 271bbe5..714a25c 100644 --- a/bundle/algorithms.browser.min.js +++ b/bundle/algorithms.browser.min.js @@ -1,3 +1,4 @@ -/* algorithms.js v0.9.1 | (c) 2015 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ -!function(t,r){r.true=t,!function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof r?n=r:"undefined"!=typeof self&&(n=self),n.algorithms=e()}}(function(){return function t(r,e,n){function i(s,a){if(!e[s]){if(!r[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=e[s]={exports:{}};r[s][0].call(c.exports,function(t){var e=r[s][1][t];return i(e?e:t)},c,c.exports,t,r,e,n)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;st.vertices.size)))return{distance:{}}}}return{distance:e,previous:n}}r.exports=e},{}],2:[function(t,r){"use strict";var e=function(t,r){var e={},n={},i=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){i.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,u,h=i.length;for(u=0;o>u;++u){for(var c=!1,f=0;h>f;f++)s=e[i[f].source]+i[f].weight,a=e[i[f].target],a>s&&(c=!0,e[i[f].target]=s,n[i[f].target]=i[f].source);if(!c)break}return u===o?{distance:{}}:{distance:e,previous:n}};r.exports=e},{}],3:[function(t,r){"use strict";var e=t("./breadth_first_search"),n=function(t,r){var n={},i={};return n[r]=0,e(t,r,{onTraversal:function(t,r){n[r]=n[t]+1,i[r]=t}}),{distance:n,previous:i}};r.exports=n},{"./breadth_first_search":4}],4:[function(t,r){"use strict";var e=t("../../data_structures/queue"),n=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){var o=new e;o.push(r),i=n(i,[r]);for(var s,a=function(t){i.allowTraversal(s,t)&&(i.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),i.enterVertex(s),t.neighbors(s).forEach(a),i.leaveVertex(s)};r.exports=i},{"../../data_structures/queue":51}],5:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){i(t,r,e(n,[r]))},i=function t(r,e,n){n.enterVertex(e),r.neighbors(e).forEach(function(i){n.allowTraversal(e,i)&&(n.beforeTraversal(e,i),t(r,i,n),n.afterTraversal(e,i))}),n.leaveVertex(e)};r.exports=n},{}],6:[function(t,r){"use strict";function e(t,r){var e={},i={},o=new n;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var n=e[s]+t.edge(s,r);nr&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(i.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),i};r.exports=i},{"../../data_structures/disjoint_set_forest":44,"../../data_structures/graph":46}],10:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),n=t("../../data_structures/graph"),i=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new n(!1),i=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r,e){var n=t.edge(r,e);nr||Math.floor(r)!==r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===i)throw new Error("The power is zero, but identity value not set.");return i}for(var o,s=function(t){o=void 0===o?t:n(o,t)},a=t;r;r>>>=1,a=n(a,a))1&r&&s(a);return o};r.exports=n},{}],14:[function(t,r){"use strict";var e=t("./fast_power"),n=function(t){return 2>t?t:n(t-1)+n(t-2)},i=function(t){for(var r=0,e=1,n=t,i=1;t>i;i++)n=e+r,r=e,e=n;return n},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],n=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},i=e(r,t,n,[[1,0],[0,1]]);return i[0][1]};i.exponential=n,i.withMemoization=o,i.direct=s,i.logarithmic=a,r.exports=i},{"./fast_power":13}],15:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),n=t[r];t[r]=t[e],t[e]=n}};r.exports=e},{}],16:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},n=function(t,r){if(0===t)return r;if(0===r)return t;var e;for(e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var n;do{for(;0===(1&r);)r>>=1;t>r&&(n=r,r=t,t=n),r-=t}while(0!==r);return t<n?s=i:o=i;while(Math.abs(n-t)>r&&e>a);var u=Math.round(i);return u*u===t&&(i=u),i};r.exports=e},{}],19:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){if(!t.length)return!1;for(var n=new e(r),i=t.length-1;i&&n.greaterThanOrEqual(t[i-1],t[i]);)i-=1;if(!i)return!1;for(var o=t[--i],s=t.length-1;n.lessThanOrEqual(t[s],o);)s-=1;t[i]=t[s],t[s]=o;for(var a=i,u=t.length;++a<--u;){var h=t[a];t[a]=t[u],t[u]=h}return!0};r.exports=n},{"../../util/comparator":60}],20:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];var r,e=[],n=[];for(r=0;rt.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),n=r;ni&&(e[i]=t[n])}return e};r.exports=e},{}],22:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],23:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),n=function(t,r){var n=new e;n.push(t);for(var i;!n.isEmpty();)i=n.pop(),r(i.value),i.left&&n.push(i.left),i.right&&n.push(i.right)};r.exports=n},{"../../data_structures/queue.js":51}],24:[function(t,r){"use strict";var e=function(t,r){for(var e=0,n=t.length-1;n>=e;){var i=(n-e>>1)+e;if(t[i]===r)return i;t[i]a;a++){for(var u=0,h=0;o>h;h++)if(n.greaterThan(t[h],t[h+1])){var c=t[h];t[h]=t[h+1],t[h+1]=c,u=h,s=!0}if(!s)return t;o=u}return t};r.exports=n},{"../../util/comparator":60}],27:[function(t,r){"use strict";var e=function(t){var r,e=n(t),i=[],o=t.length;for(r=0;o>r;r++){var s=t[r].key;void 0===i[s]&&(i[s]=[]),i[s].push(t[r])}t=[];var a=0;for(r=0;e>=r;r++)if(void 0!==i[r])for(var u=i[r].length,h=0;u>h;h++)t[a++]=i[r][h];return t},n=function(t){for(var r=t[0].key,e=t.length,n=1;e>n;n++)t[n].key>r&&(r=t[n].key);return r};r.exports=e},{}],28:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,n=function(t,r){var n=new e(r);n.heapify(t);for(var i=[];!n.isEmpty();)i.push(n.extract());return i};r.exports=n},{"../../data_structures/heap":48}],29:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=1,o=t.length;o>i;i++){for(var s=t[i],a=i;a>0&&n.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=n},{"../../util/comparator":60}],30:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){var n=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=i(o,s,n)}return r}(t)},i=function(t,r,e){for(var n=0,i=0,o=[];ne;){var s=i(r,n,e,o);o-s>s-e?(t(r,e,s-1),e=s+1):(t(r,s+1,o),o=s-1)}return r}(t,0,t.length-1)},i=function(t,r,e,n){o(t,Math.floor(Math.random()*(n-e))+e,n);for(var i=n,s=e,a=e;n>a;a++)r.lessThan(t[a],t[i])&&(o(t,a,s),s++);return o(t,s,i),s},o=function(t,r,e){var n=t[e];t[e]=t[r],t[r]=n};r.exports=n},{"../../util/comparator":60}],32:[function(t,r){"use strict";var e=function(t){for(var r=i(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=n(t,o);return t},n=function(t,r){var e,n=t.length,i=[];for(e=0;10>e;e++)i[e]=[];for(e=0;n>e;e++){var o=parseInt((t[e].key/Math.pow(10,r)).toFixed(r))%10;i[o].push(t[e])}var s=0;for(e=0;10>e;e++)for(var a=i[e].length,u=0;a>u;u++)t[s++]=i[e][u];return t},i=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],33:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=t.length,o=0;i-1>o;o++){for(var s=o,a=o+1;i>a;a++)n.greaterThan(t[s],t[a])&&(s=a);if(s!==o){var u=t[o];t[o]=t[s],t[s]=u}}return t};r.exports=n},{"../../util/comparator":60}],34:[function(t,r){"use strict";var e=t("../../util/comparator"),n=function(t,r){for(var n=new e(r),i=0,o=t.length-1,s=parseInt((o-i+1)/2),a=0,u=0,h=0;s>=1;){for(a=i+s;o>=a;a+=1){for(h=t[a],u=a-s;u>=i&&n.greaterThan(t[u],h);)t[u+s]=t[u],u-=s;t[u+s]=h}s=parseInt(s/2)}return t};r.exports=n},{"../../util/comparator":60}],35:[function(t,r){"use strict";var e=function(t,r){if(t.length!==r.length)throw new Error("Strings must be equal in length");for(var e=0,n=0;n>>0).toString(2).length,i=function(t){var r=[],e=0,i=0;return t.split("").forEach(function(t){e=e<<1|t,i+=1,i===n&&(r.push(e),e=i=0)}),i?r.push(e,i):r.push(n),r},o=function(t){if(!t.length)return"";if(1===t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(n+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),i=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-i)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var n=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--f){var l=c(),p=c();l.code="0",p.code="1";var g={count:l.count+p.count,parts:[l,p]};a.push(g)}var d=c();d.code=n.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],n=r.parts[1];e.code+=r.code,n.code+=r.code,t(e),t(n)}}(d);var v=n.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),m=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?i(m):m}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),n=[],i=r.split("").reduce(function(t,r){t+=r;var i=e[t];return i&&(n.push(i),t=""),t},"");if(i)throw new Error("Invalid string to decode.");return n.join("")},r.exports=e},{}],37:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,i=r.length,o=0,s=0,a=n(r);e>o+s;)if(r[s]===t[o+s]){if(s===i-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},n=function(t){var r=t.length,e=[],n=2,i=0;for(e[0]=-1,e[1]=0;r>n;)t[n-1]===t[i]?(++i,e[n]=i,++n):i>0?i=e[i]:(e[n]=0,++n);return e};r.exports=e},{}],38:[function(t,r){"use strict";var e=function(t,r){var e,n,i=[];for(e=0;e<=t.length;e++)i[e]=[],i[e][0]=e;for(n=0;n<=r.length;n++)i[0][n]=n;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=Math.min(i[e-1][n-1],i[e-1][n],i[e][n-1])+(t[e-1]!==r[n-1]?1:0);return i[t.length][r.length]};r.exports=e},{}],39:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length;e++)i[e]=new Int32Array(r.length+1);for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)i[e][n]=t[e-1]===r[n-1]?i[e-1][n-1]+1:Math.max(i[e][n-1],i[e-1][n]);e=t.length,n=r.length;for(var o="";0!==i[e][n];)t[e-1]===r[n-1]?(o=t[e-1]+o,e--,n--):i[e-1][n]>i[e][n-1]?e--:n--;return o};r.exports=e},{}],40:[function(t,r){"use strict";var e=function(t,r){var e,n,i=new Array(t.length+1);for(e=0;e<=t.length+1;e++)i[e]=new Int32Array(r.length+1);var o={},s=0;for(e=1;e<=t.length;e++)for(n=1;n<=r.length;n++)t[e-1]===r[n-1]?(i[e][n]=i[e-1][n-1]+1,i[e][n]>s&&(o.i=e,o.j=n,s=i[e][n])):i[e][n]=0;var a="";return s&&(a=t.substring(o.i-s,o.i)),a};r.exports=e},{}],41:[function(t,r){"use strict";var e=997,n=function(t,r){if(0===r.length)return 0;for(var n,o=i(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===n?n=i(s):(n-=s.charCodeAt(0)*Math.pow(e,r.length-1),n*=e,n+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===n&&r===s)return a===r.length?0:a-r.length+1;return-1},i=function(t){for(var r=0,n=0;n2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var n=this.root(r),i=this.root(e);return this._ranks[n]0;t-=t&-t)r+=this._elements[t];return r},e.prototype.rangeSum=function(t,r){return this.prefixSum(r)-this.prefixSum(t-1)},r.exports=e},{}],46:[function(t,r){"use strict";function e(t){this.directed=void 0===t?!0:!!t,this.adjList=Object.create(null),this.vertices=new n}var n=t("./set"),i=function(t){return""+t};e.prototype.addVertex=function(t){if(t=i(t),this.vertices.contains(t))throw new Error('Vertex "'+t+'" has already been added');this.vertices.add(t),this.adjList[t]=Object.create(null)},e.prototype.addEdge=function(t,r,e){t=i(t),r=i(r),e=void 0===e?1:e,this.adjList[t]||this.addVertex(t),this.adjList[r]||this.addVertex(r),this.adjList[t][r]=(this.adjList[t][r]||0)+e,this.directed||(this.adjList[r][t]=(this.adjList[r][t]||0)+e)},e.prototype.neighbors=function(t){return Object.keys(this.adjList[i(t)])},e.prototype.edge=function(t,r){return this.adjList[i(t)][i(r)]},r.exports=e},{"./set":52}],47:[function(t,r){"use strict";function e(t){this._table=new Array(t||64),this._items=0,Object.defineProperty(this,"capacity",{get:function(){return this._table.length}}),Object.defineProperty(this,"size",{get:function(){return this._items}})}var n=t("./linked_list");e.prototype.hash=function(t){"string"!=typeof t&&(t=JSON.stringify(t));for(var r=0,e=0;e1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t)},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},n.prototype=new e,r.exports={MinHeap:e,MaxHeap:n}},{"../util/comparator":60}],49:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function n(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new n(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],50:[function(t,r){"use strict";function e(t){var r=this;n.call(this,function(t,e){return r.priority(t)t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[55])(55)})}({},function(){return this}()); \ No newline at end of file +/* algorithms.js v0.10.0 | (c) 2015 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ +!function(t,r){r.true=t,function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var i;i="undefined"!=typeof window?window:"undefined"!=typeof r?r:"undefined"!=typeof self?self:this,i.algorithms=e()}}(function(){return function t(r,e,i){function n(s,a){if(!e[s]){if(!r[s]){var h="function"==typeof require&&require;if(!a&&h)return h(s,!0);if(o)return o(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var l=e[s]={exports:{}};r[s][0].call(l.exports,function(t){var e=r[s][1][t];return n(e?e:t)},l,l.exports,t,r,e,i)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;s=1;--e)i[e]+=i[e-1];for(r=0;r=0;--r)e.x+=this.p[r].x*o[r]*n,e.y+=this.p[r].y*o[r]*n,n*=1-t;return e},r.exports=e},{}],2:[function(t,r){"use strict";function e(t,r){var e={},i={},n={},o={},s={},a=0,h=1;e[r]=0,n[0]=r,o[r]=!0,s[r]=1,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0,o[t]=!1,s[t]=0)});for(var u;a!==h;){u=n[a++],o[u]=!1;for(var l=t.neighbors(u),c=0;ct.vertices.size)))return{distance:{}}}}return{distance:e,previous:i}}r.exports=e},{}],3:[function(t,r){"use strict";var e=function(t,r){var e={},i={},n=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){n.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,h,u=n.length;for(h=0;o>h;++h){for(var l=!1,c=0;u>c;c++)s=e[n[c].source]+n[c].weight,a=e[n[c].target],a>s&&(l=!0,e[n[c].target]=s,i[n[c].target]=n[c].source);if(!l)break}return h===o?{distance:{}}:{distance:e,previous:i}};r.exports=e},{}],4:[function(t,r){"use strict";var e=t("./breadth_first_search"),i=function(t,r){var i={},n={};return i[r]=0,e(t,r,{onTraversal:function(t,r){i[r]=i[t]+1,n[r]=t}}),{distance:i,previous:n}};r.exports=i},{"./breadth_first_search":5}],5:[function(t,r){"use strict";var e=t("../../data_structures/queue"),i=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){var o=new e;o.push(r),n=i(n,[r]);for(var s,a=function(t){n.allowTraversal(s,t)&&(n.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),n.enterVertex(s),t.neighbors(s).forEach(a),n.leaveVertex(s)};r.exports=n},{"../../data_structures/queue":58}],6:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){n(t,r,e(i,[r]))},n=function t(r,e,i){i.enterVertex(e),r.neighbors(e).forEach(function(n){i.allowTraversal(e,n)&&(i.beforeTraversal(e,n),t(r,n,i),i.afterTraversal(e,n))}),i.leaveVertex(e)};r.exports=i},{}],7:[function(t,r){"use strict";function e(t,r){var e={},n={},o=new i;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var i=e[s]+t.edge(s,r);ir&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(n.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),n};r.exports=n},{"../../data_structures/disjoint_set_forest":51,"../../data_structures/graph":53}],11:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),i=t("../../data_structures/graph"),n=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new i(!1),n=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r,e){var i=t.edge(r,e);i>1:3*t+1}function i(t){var r=[];do t=e(t),r.push(t);while(1!==t);return r}var n={1:1};r.exports={generate:i,calculate:e}},{}],14:[function(t,r){"use strict";var e=function(t,r){for(var e,i,n=0,o=1,s=1,a=0,h=r,u=t;0!==h;)e=Math.floor(u/h),i=h,h=u-e*h,u=i,i=n,n=o-e*n,o=i,i=s,s=a-e*s,a=i;return{x:o,y:a}};r.exports=e},{}],15:[function(t,r){"use strict";var e=function(t,r){return t*r},i=function(t,r,i,n){if(void 0===i&&(i=e,n=1),0>r||Math.floor(r)!==r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===n)throw new Error("The power is zero, but identity value not set.");return n}for(var o,s=function(t){o=void 0===o?t:i(o,t)},a=t;r;r>>>=1,a=i(a,a))1&r&&s(a);return o};r.exports=i},{}],16:[function(t,r){"use strict";var e=t("./fast_power"),i=function(t){return 2>t?t:i(t-1)+i(t-2)},n=function(t){for(var r=0,e=1,i=t,n=1;t>n;n++)i=e+r,r=e,e=i;return i},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],i=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},n=e(r,t,i,[[1,0],[0,1]]);return n[0][1]};n.exponential=i,n.withMemoization=o,n.direct=s,n.logarithmic=a,r.exports=n},{"./fast_power":15}],17:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),i=t[r];t[r]=t[e],t[e]=i}};r.exports=e},{}],18:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},i=function(t,r){if(0===t)return r;if(0===r)return t;var e;for(e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var i;do{for(;0===(1&r);)r>>=1;t>r&&(i=r,r=t,t=i),r-=t}while(0!==r);return t<e;e++)r=t[e],r>i&&(i=r),o>r&&(o=r);return i-o};r.exports=e},{}],20:[function(t,r){"use strict";var e=t("./gcd.js"),i=function(t,r,e){return 0===r||0===e?0:(r=Math.abs(r),e=Math.abs(e),r/t(r,e)*e)},n=i.bind(null,e),o=i.bind(null,e.binary),s=n;s.binary=o,r.exports=s},{"./gcd.js":18}],21:[function(t,r){"use strict";var e=function(t,r,e){r=r||1e-7,e=e||1e7;var i,n,o=t,s=0,a=0;do a++,n=(o-s)/2+s,i=n*n,t>i?s=n:o=n;while(Math.abs(i-t)>r&&e>a);var h=Math.round(n);return h*h===t&&(n=h),n};r.exports=e},{}],22:[function(t,r){"use strict";var e=t("../../util/comparator"),i=function(t,r){if(!t.length)return!1;for(var i=new e(r),n=t.length-1;n&&i.greaterThanOrEqual(t[n-1],t[n]);)n-=1;if(!n)return!1;for(var o=t[--n],s=t.length-1;i.lessThanOrEqual(t[s],o);)s-=1;t[n]=t[s],t[s]=o;for(var a=n,h=t.length;++a<--h;){var u=t[a];t[a]=t[h],t[h]=u}return!0};r.exports=i},{"../../util/comparator":69}],23:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];var r,e=[],i=[];for(r=0;r=r?!1:t(r)},i=function(t){for(var r=2;t>r;++r)if(t%r===0)return!1;return!0},n=function(t){for(var r=Math.sqrt(t),e=2;r>=e;++e)if(t%e===0)return!1;return!0};r.exports={naiveTest:e.bind(null,i),trialDivisionTest:e.bind(null,n)}},{}],25:[function(t,r){"use strict";var e=function(t,r){if(r>t.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),i=r;in&&(e[n]=t[i])}return e};r.exports=e},{}],26:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],27:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),i=function(t,r){var i=new e;i.push(t);for(var n;!i.isEmpty();)n=i.pop(),r(n.value),n.left&&i.push(n.left),n.right&&i.push(n.right)};r.exports=i},{"../../data_structures/queue.js":58}],28:[function(t,r){"use strict";var e=function(t,r){for(var e=0,i=t.length-1;i>=e;){var n=(i-e>>1)+e;if(t[n]===r)return n;t[n]i;){var n=r+(e-r)/3,o=e-(e-r)/3;t(n)a;a++){for(var h=0,u=0;o>u;u++)if(i.greaterThan(t[u],t[u+1])){var l=t[u];t[u]=t[u+1],t[u+1]=l,h=u,s=!0}if(!s)return t;o=h}return t};r.exports=i},{"../../util/comparator":69}],32:[function(t,r){"use strict";var e=function(t){var r,e=i(t),n=[],o=t.length;for(r=0;o>r;r++){var s=t[r].key;void 0===n[s]&&(n[s]=[]),n[s].push(t[r])}t=[];var a=0;for(r=0;e>=r;r++)if(void 0!==n[r])for(var h=n[r].length,u=0;h>u;u++)t[a++]=n[r][u];return t},i=function(t){for(var r=t[0].key,e=t.length,i=1;e>i;i++)t[i].key>r&&(r=t[i].key);return r};r.exports=e},{}],33:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,i=function(t,r){var i=new e(r);i.heapify(t);for(var n=[];!i.isEmpty();)n.push(i.extract());return n};r.exports=i},{"../../data_structures/heap":55}],34:[function(t,r){"use strict";var e=t("../../util/comparator"),i=function(t,r){for(var i=new e(r),n=1,o=t.length;o>n;n++){for(var s=t[n],a=n;a>0&&i.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=i},{"../../util/comparator":69}],35:[function(t,r){"use strict";var e=t("../../util/comparator"),i=function(t,r){var i=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=n(o,s,i)}return r}(t)},n=function(t,r,e){for(var i=0,n=0,o=[];ie;){var s=n(r,i,e,o);o-s>s-e?(t(r,e,s-1),e=s+1):(t(r,s+1,o),o=s-1)}return r}(t,0,t.length-1)},n=function(t,r,e,i){o(t,Math.floor(Math.random()*(i-e))+e,i);for(var n=i,s=e,a=e;i>a;a++)r.lessThan(t[a],t[n])&&(o(t,a,s),s++);return o(t,s,n),s},o=function(t,r,e){var i=t[e];t[e]=t[r],t[r]=i};r.exports=i},{"../../util/comparator":69}],37:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=i(t,o);return t},i=function(t,r){var e,i=t.length,n=[];for(e=0;10>e;e++)n[e]=[];for(e=0;i>e;e++){var o=parseInt((t[e].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[e])}var s=0;for(e=0;10>e;e++)for(var a=n[e].length,h=0;a>h;h++)t[s++]=n[e][h];return t},n=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],38:[function(t,r){"use strict";var e=t("../../util/comparator"),i=function(t,r){for(var i=new e(r),n=t.length,o=0;n-1>o;o++){for(var s=o,a=o+1;n>a;a++)i.greaterThan(t[s],t[a])&&(s=a);if(s!==o){var h=t[o];t[o]=t[s],t[s]=h}}return t};r.exports=i},{"../../util/comparator":69}],39:[function(t,r){"use strict";var e=t("../../util/comparator"),i=function(t,r){for(var i=new e(r),n=0,o=t.length-1,s=parseInt((o-n+1)/2),a=0,h=0,u=0;s>=1;){for(a=n+s;o>=a;a+=1){for(u=t[a],h=a-s;h>=n&&i.greaterThan(t[h],u);)t[h+s]=t[h],h-=s;t[h+s]=u}s=parseInt(s/2)}return t};r.exports=i},{"../../util/comparator":69}],40:[function(t,r){"use strict";function e(t,r){var e=new i(r),n=t.length-1,o=0;for(o;n>o;o++){var s=t[o],a=t[o+1];e.greaterThan(s,a)&&(t[o+1]=s,t[o]=a,o=-1)}return t}var i=t("../../util/comparator");r.exports=e},{"../../util/comparator":69}],41:[function(t,r){"use strict";var e=function(t,r){if(t.length!==r.length)throw new Error("Strings must be equal in length");for(var e=0,i=0;i>>0).toString(2).length,n=function(t){var r=[],e=0,n=0;return t.split("").forEach(function(t){e=e<<1|t,n+=1,n===i&&(r.push(e),e=n=0)}),n?r.push(e,n):r.push(i),r},o=function(t){if(!t.length)return"";if(1===t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(i+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),n=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-n)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var i=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--c){var f=l(),p=l();f.code="0",p.code="1";var g={count:f.count+p.count,parts:[f,p]};a.push(g)}var d=l();d.code=i.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],i=r.parts[1];e.code+=r.code,i.code+=r.code,t(e),t(i)}}(d);var v=i.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),m=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?n(m):m}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),i=[],n=r.split("").reduce(function(t,r){t+=r;var n=e[t];return n&&(i.push(n),t=""),t},"");if(n)throw new Error("Invalid string to decode.");return i.join("")},r.exports=e},{}],43:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,n=r.length,o=0,s=0,a=i(r);e>o+s;)if(r[s]===t[o+s]){if(s===n-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},i=function(t){var r=t.length,e=[],i=2,n=0;for(e[0]=-1,e[1]=0;r>i;)t[i-1]===t[n]?(++n,e[i]=n,++i):n>0?n=e[n]:(e[i]=0,++i);return e};r.exports=e},{}],44:[function(t,r){"use strict";var e=function(t,r){var e,i,n=[];for(e=0;e<=t.length;e++)n[e]=[],n[e][0]=e;for(i=0;i<=r.length;i++)n[0][i]=i;for(e=1;e<=t.length;e++)for(i=1;i<=r.length;i++)n[e][i]=Math.min(n[e-1][i-1],n[e-1][i],n[e][i-1])+(t[e-1]!==r[i-1]?1:0);return n[t.length][r.length]};r.exports=e},{}],45:[function(t,r){"use strict";var e=function(t,r){var e,i,n=new Array(t.length+1);for(e=0;e<=t.length;e++)n[e]=new Int32Array(r.length+1);for(e=1;e<=t.length;e++)for(i=1;i<=r.length;i++)n[e][i]=t[e-1]===r[i-1]?n[e-1][i-1]+1:Math.max(n[e][i-1],n[e-1][i]);e=t.length,i=r.length;for(var o="";0!==n[e][i];)t[e-1]===r[i-1]?(o=t[e-1]+o,e--,i--):n[e-1][i]>n[e][i-1]?e--:i--;return o};r.exports=e},{}],46:[function(t,r){"use strict";var e=function(t,r){var e,i,n=new Array(t.length+1);for(e=0;e<=t.length+1;e++)n[e]=new Int32Array(r.length+1);var o={},s=0;for(e=1;e<=t.length;e++)for(i=1;i<=r.length;i++)t[e-1]===r[i-1]?(n[e][i]=n[e-1][i-1]+1,n[e][i]>s&&(o.i=e,o.j=i,s=n[e][i])):n[e][i]=0;var a="";return s&&(a=t.substring(o.i-s,o.i)),a};r.exports=e},{}],47:[function(t,r){"use strict";var e=997,i=function(t,r){if(0===r.length)return 0;for(var i,o=n(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===i?i=n(s):(i-=s.charCodeAt(0)*Math.pow(e,r.length-1),i*=e,i+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===i&&r===s)return a===r.length?0:a-r.length+1;return-1},n=function(t){for(var r=0,i=0;ir.right.height?n=r.left:r.left.heighto.right.height)r=o.left;else if(o.left.heightt?"left":"right",r[e]?this.insert(t,r[e]):(r[e]=new i(t,null,null,r),this.keepHeightBalance(r[e],!1))},e.prototype.inOrder=function(t,r){t&&(this.inOrder(t.left,r),"function"==typeof r&&r(t),this.inOrder(t.right,r))},e.prototype.postOrder=function(t,r){t&&(this.postOrder(t.left,r),this.postOrder(t.right,r),"function"==typeof r&&r(t))},e.prototype.preOrder=function(t,r){t&&("function"==typeof r&&r(t),this.preOrder(t.left,r),this.preOrder(t.right,r))},e.prototype.find=function(t){return this._find(t,this.root)},e.prototype._find=function(t,r){if(!r)return null;var e;return r.value===t?e=r:r.value>t?e=this._find(t,r.left):r.valuet.value&&(r=t),this._findMin(t.left,r)):r},e.prototype._findMax=function(t,r){return r=r||{value:-(1/0)},t?(r.value2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var i=this.root(r),n=this.root(e);return this._ranks[i]0;t-=t&-t)r+=this._elements[t];return r},e.prototype.rangeSum=function(t,r){return this.prefixSum(r)-this.prefixSum(t-1)},r.exports=e},{}],53:[function(t,r){"use strict";function e(t){this.directed=void 0===t?!0:!!t,this.adjList=Object.create(null),this.vertices=new i}var i=t("./set"),n=function(t){return""+t};e.prototype.addVertex=function(t){if(t=n(t),this.vertices.contains(t))throw new Error('Vertex "'+t+'" has already been added');this.vertices.add(t),this.adjList[t]=Object.create(null)},e.prototype.addEdge=function(t,r,e){t=n(t),r=n(r),e=void 0===e?1:e,this.adjList[t]||this.addVertex(t),this.adjList[r]||this.addVertex(r),this.adjList[t][r]=(this.adjList[t][r]||0)+e,this.directed||(this.adjList[r][t]=(this.adjList[r][t]||0)+e)},e.prototype.neighbors=function(t){return Object.keys(this.adjList[n(t)])},e.prototype.edge=function(t,r){return this.adjList[n(t)][n(r)]},r.exports=e},{"./set":59}],54:[function(t,r){"use strict";function e(t){this._table=new Array(t||64),this._items=0,Object.defineProperty(this,"capacity",{get:function(){return this._table.length}}),Object.defineProperty(this,"size",{get:function(){return this._items}})}var i=t("./linked_list");e.prototype.hash=function(t){"string"!=typeof t&&(t=JSON.stringify(t));for(var r=0,e=0;e1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t); + +},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},i.prototype=new e,r.exports={MinHeap:e,MaxHeap:i}},{"../util/comparator":69}],56:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function i(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new i(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],57:[function(t,r){"use strict";function e(t){var r=this;i.call(this,function(t,e){return r.priority(t)t.value);return t.children[i]=this._insert(t.children[i],r),t.children[i].keyt.value);return this._find(t.children[e],r)},i.prototype._minimum=function(t){return null===t?1/0:Math.min(t.value,this._minimum(t.children[0]))},i.prototype._maximum=function(t){return null===t?-(1/0):Math.max(t.value,this._maximum(t.children[1]))},i.prototype._remove=function(t,r){if(null===t)return null;var e;return t.value===r?null===t.children[0]&&null===t.children[1]?null:(e=null===t.children[0]?1:0,t=t.rotate(e),t.children[1-e]=this._remove(t.children[1-e],r),t.resize()):(e=~~(r>t.value),t.children[e]=this._remove(t.children[e],r),t.resize())},i.prototype.insert=function(t){this.root=this._insert(this.root,t)},i.prototype.find=function(t){return this._find(this.root,t)},i.prototype.minimum=function(){return this._minimum(this.root)},i.prototype.maximum=function(){return this._maximum(this.root)},i.prototype.remove=function(t){this.root=this._remove(this.root,t)},i.prototype.size=function(){return this.root?this.root.size:0},i.prototype.height=function(){return this.root?this.root.height:0},r.exports=i},{}],62:[function(t,r){"use strict";r.exports={BezierCurve:t("./algorithms/geometry/bezier_curve")}},{"./algorithms/geometry/bezier_curve":1}],63:[function(t,r){"use strict";r.exports={topologicalSort:t("./algorithms/graph/topological_sort"),dijkstra:t("./algorithms/graph/dijkstra"),SPFA:t("./algorithms/graph/SPFA"),bellmanFord:t("./algorithms/graph/bellman_ford"),eulerPath:t("./algorithms/graph/euler_path"),depthFirstSearch:t("./algorithms/graph/depth_first_search"),kruskal:t("./algorithms/graph/kruskal"),breadthFirstSearch:t("./algorithms/graph/breadth_first_search"),bfsShortestPath:t("./algorithms/graph/bfs_shortest_path"),prim:t("./algorithms/graph/prim"),floydWarshall:t("./algorithms/graph/floyd_warshall")}},{"./algorithms/graph/SPFA":2,"./algorithms/graph/bellman_ford":3,"./algorithms/graph/bfs_shortest_path":4,"./algorithms/graph/breadth_first_search":5,"./algorithms/graph/depth_first_search":6,"./algorithms/graph/dijkstra":7,"./algorithms/graph/euler_path":8,"./algorithms/graph/floyd_warshall":9,"./algorithms/graph/kruskal":10,"./algorithms/graph/prim":11,"./algorithms/graph/topological_sort":12}],64:[function(t,r){"use strict";var e={DataStructures:t("./data_structures"),Graph:t("./graph"),Geometry:t("./geometry"),Math:t("./math"),Search:t("./search"),Sorting:t("./sorting"),String:t("./string")};r.exports=e},{"./data_structures":48,"./geometry":62,"./graph":63,"./math":65,"./search":66,"./sorting":67,"./string":68}],65:[function(t,r){"use strict";r.exports={fibonacci:t("./algorithms/math/fibonacci"),fisherYates:t("./algorithms/math/fisher_yates"),gcd:t("./algorithms/math/gcd"),extendedEuclidean:t("./algorithms/math/extended_euclidean"),lcm:t("./algorithms/math/lcm"),newtonSqrt:t("./algorithms/math/newton_sqrt"),primalityTests:t("./algorithms/math/primality_tests"),reservoirSampling:t("./algorithms/math/reservoir_sampling"),fastPower:t("./algorithms/math/fast_power"),nextPermutation:t("./algorithms/math/next_permutation"),powerSet:t("./algorithms/math/power_set"),shannonEntropy:t("./algorithms/math/shannon_entropy"),collatzConjecture:t("./algorithms/math/collatz_conjecture"),greatestDifference:t("./algorithms/math/greatest_difference")}},{"./algorithms/math/collatz_conjecture":13,"./algorithms/math/extended_euclidean":14,"./algorithms/math/fast_power":15,"./algorithms/math/fibonacci":16,"./algorithms/math/fisher_yates":17,"./algorithms/math/gcd":18,"./algorithms/math/greatest_difference":19,"./algorithms/math/lcm":20,"./algorithms/math/newton_sqrt":21,"./algorithms/math/next_permutation":22,"./algorithms/math/power_set":23,"./algorithms/math/primality_tests":24,"./algorithms/math/reservoir_sampling":25,"./algorithms/math/shannon_entropy":26}],66:[function(t,r){"use strict";r.exports={bfs:t("./algorithms/search/bfs"),binarySearch:t("./algorithms/search/binarysearch"),ternarySearch:t("./algorithms/search/ternary_search"),dfs:t("./algorithms/search/dfs")}},{"./algorithms/search/bfs":27,"./algorithms/search/binarysearch":28,"./algorithms/search/dfs":29,"./algorithms/search/ternary_search":30}],67:[function(t,r){"use strict";r.exports={bubbleSort:t("./algorithms/sorting/bubble_sort"),shortBubbleSort:t("./algorithms/sorting/short_bubble_sort"),countingSort:t("./algorithms/sorting/counting_sort"),heapSort:t("./algorithms/sorting/heap_sort"),mergeSort:t("./algorithms/sorting/merge_sort"),quicksort:t("./algorithms/sorting/quicksort"),selectionSort:t("./algorithms/sorting/selection_sort"),radixSort:t("./algorithms/sorting/radix_sort"),insertionSort:t("./algorithms/sorting/insertion_sort"),shellSort:t("./algorithms/sorting/shell_sort")}},{"./algorithms/sorting/bubble_sort":31,"./algorithms/sorting/counting_sort":32,"./algorithms/sorting/heap_sort":33,"./algorithms/sorting/insertion_sort":34,"./algorithms/sorting/merge_sort":35,"./algorithms/sorting/quicksort":36,"./algorithms/sorting/radix_sort":37,"./algorithms/sorting/selection_sort":38,"./algorithms/sorting/shell_sort":39,"./algorithms/sorting/short_bubble_sort":40}],68:[function(t,r){"use strict";r.exports={levenshtein:t("./algorithms/string/levenshtein"),rabinKarp:t("./algorithms/string/rabin_karp"),knuthMorrisPratt:t("./algorithms/string/knuth_morris_pratt"),huffman:t("./algorithms/string/huffman"),hamming:t("./algorithms/string/hamming"),longestCommonSubsequence:t("./algorithms/string/longest_common_subsequence"),longestCommonSubstring:t("./algorithms/string/longest_common_substring")}},{"./algorithms/string/hamming":41,"./algorithms/string/huffman":42,"./algorithms/string/knuth_morris_pratt":43,"./algorithms/string/levenshtein":44,"./algorithms/string/longest_common_subsequence":45,"./algorithms/string/longest_common_substring":46,"./algorithms/string/rabin_karp":47}],69:[function(t,r){"use strict";function e(t){t&&(this.compare=t)}e.prototype.compare=function(t,r){return t===r?0:r>t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[64])(64)})}({},function(){return this}()); \ No newline at end of file diff --git a/package.json b/package.json index beed33b..50448ef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "algorithms", - "version": "0.9.1", + "version": "0.10.0", "description": "Traditional computer science algorithms and data structures implemented in JavaScript", "main": "./index.js", "scripts": { From abaca334896598218085124667eb0b844cd0e63b Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 4 May 2016 16:11:29 -0400 Subject: [PATCH 229/280] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0f43fc6..65cac35 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![Dependency Status](https://david-dm.org/felipernb/algorithms.js.svg)](https://david-dm.org/felipernb/algorithms.js) [![devDependency Status](https://david-dm.org/felipernb/algorithms.js/dev-status.svg)](https://david-dm.org/felipernb/algorithms.js#info=devDependencies) [![Inline docs](http://inch-ci.org/github/felipernb/algorithms.js.svg?branch=master)](http://inch-ci.org/github/felipernb/algorithms.js) +[![npm](https://img.shields.io/npm/dt/algorithms.svg?maxAge=2592000)](https://www.npmjs.com/package/algorithms) ![](http://www.quickmeme.com/img/8d/8d30a19413145512ad5a05c46ec0da545df5ed79e113fcf076dc03c7514eb631.jpg) From d9e0295eedc29f795e665218c698351e4c8fd8fe Mon Sep 17 00:00:00 2001 From: Amila Welihinda Date: Mon, 20 Jun 2016 17:07:59 -0700 Subject: [PATCH 230/280] Added stable and modern node versions to travis ci --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 649494c..2f427ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,8 @@ language: node_js sudo: false node_js: - - "5.1" + - '4' + - '5.1' + - '6' script: "make" after_success: "make coveralls" From e496a6f3047647d92fe8785d5721c2971797fa32 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 21 Jun 2016 07:31:39 +0200 Subject: [PATCH 231/280] Use Google JS style guide --- .eslintrc | 95 +----------- README.md | 4 + bundle/algorithms.browser.min.js | 5 +- package.json | 3 +- src/algorithms/geometry/bezier_curve.js | 12 +- src/algorithms/graph/SPFA.js | 2 +- src/algorithms/graph/bellman_ford.js | 6 +- src/algorithms/graph/bfs_shortest_path.js | 9 +- src/algorithms/graph/breadth_first_search.js | 22 ++- src/algorithms/graph/depth_first_search.js | 39 +++-- src/algorithms/graph/dijkstra.js | 4 +- src/algorithms/graph/euler_path.js | 37 +++-- src/algorithms/graph/floyd_warshall.js | 23 ++- src/algorithms/graph/kruskal.js | 16 +-- src/algorithms/graph/prim.js | 19 ++- src/algorithms/graph/topological_sort.js | 14 +- src/algorithms/math/collatz_conjecture.js | 12 +- src/algorithms/math/extended_euclidean.js | 14 +- src/algorithms/math/fast_power.js | 13 +- src/algorithms/math/fibonacci.js | 20 +-- src/algorithms/math/fisher_yates.js | 2 +- src/algorithms/math/gcd.js | 5 +- src/algorithms/math/greatest_difference.js | 2 +- src/algorithms/math/lcm.js | 4 +- src/algorithms/math/newton_sqrt.js | 5 +- src/algorithms/math/next_permutation.js | 4 +- src/algorithms/math/power_set.js | 33 ++--- src/algorithms/math/primality_tests.js | 6 +- src/algorithms/math/reservoir_sampling.js | 4 +- src/algorithms/math/shannon_entropy.js | 8 +- src/algorithms/search/bfs.js | 2 +- src/algorithms/search/binarysearch.js | 6 +- src/algorithms/search/dfs.js | 6 +- src/algorithms/search/ternary_search.js | 6 +- src/algorithms/sorting/bubble_sort.js | 2 +- src/algorithms/sorting/counting_sort.js | 44 +++--- src/algorithms/sorting/heap_sort.js | 3 +- src/algorithms/sorting/insertion_sort.js | 6 +- src/algorithms/sorting/merge_sort.js | 30 ++-- src/algorithms/sorting/quicksort.js | 55 ++++--- src/algorithms/sorting/radix_sort.js | 54 +++---- src/algorithms/sorting/selection_sort.js | 2 +- src/algorithms/sorting/shell_sort.js | 20 +-- src/algorithms/sorting/short_bubble_sort.js | 5 +- src/algorithms/string/hamming.js | 2 +- src/algorithms/string/huffman.js | 55 ++++--- src/algorithms/string/knuth_morris_pratt.js | 90 ++++++------ src/algorithms/string/levenshtein.js | 7 +- .../string/longest_common_subsequence.js | 5 +- .../string/longest_common_substring.js | 5 +- src/algorithms/string/rabin_karp.js | 34 ++--- src/data_structures/avl_tree.js | 70 ++++----- src/data_structures/bst.js | 19 +-- src/data_structures/disjoint_set_forest.js | 19 +-- src/data_structures/fenwick_tree.js | 12 +- src/data_structures/graph.js | 14 +- src/data_structures/hash_table.js | 29 ++-- src/data_structures/heap.js | 22 +-- src/data_structures/linked_list.js | 21 ++- src/data_structures/priority_queue.js | 13 +- src/data_structures/queue.js | 12 +- src/data_structures/set.js | 14 +- src/data_structures/stack.js | 2 +- src/data_structures/treap.js | 50 ++++--- src/test/algorithms/geometry/bezier_curve.js | 14 +- src/test/algorithms/graph/SPFA.js | 12 +- src/test/algorithms/graph/bellman_ford.js | 12 +- .../algorithms/graph/bfs_shortest_path.js | 77 +++++----- .../algorithms/graph/breadth_first_search.js | 41 +++--- .../algorithms/graph/depth_first_search.js | 31 ++-- src/test/algorithms/graph/dijkstra.js | 12 +- src/test/algorithms/graph/euler_path.js | 36 +++-- src/test/algorithms/graph/floyd_warshall.js | 87 ++++++----- .../algorithms/graph/minimum_spanning_tree.js | 114 +++++++-------- src/test/algorithms/graph/topological_sort.js | 83 ++++++----- .../algorithms/math/collatz_conjecture.js | 14 +- .../algorithms/math/extended_euclidean.js | 10 +- src/test/algorithms/math/fast_power.js | 42 +++--- src/test/algorithms/math/fibonacci.js | 30 ++-- src/test/algorithms/math/fisher_yates.js | 14 +- src/test/algorithms/math/gcd.js | 41 +++--- .../algorithms/math/greatest_difference.js | 8 +- src/test/algorithms/math/lcm.js | 74 +++++----- src/test/algorithms/math/newton_sqrt.js | 13 +- src/test/algorithms/math/next_permutation.js | 48 +++---- src/test/algorithms/math/power_set.js | 27 ++-- src/test/algorithms/math/primality_tests.js | 36 ++--- .../algorithms/math/reservoir_sampling.js | 19 ++- src/test/algorithms/math/shannon_entropy.js | 4 +- src/test/algorithms/searching/bfs.js | 17 ++- src/test/algorithms/searching/binarysearch.js | 9 +- src/test/algorithms/searching/dfs.js | 20 +-- .../algorithms/searching/ternary_search.js | 18 +-- src/test/algorithms/sorting/bubble_sort.js | 10 +- src/test/algorithms/sorting/counting_sort.js | 8 +- src/test/algorithms/sorting/heap_sort.js | 10 +- src/test/algorithms/sorting/insertion_sort.js | 11 +- src/test/algorithms/sorting/merge_sort.js | 10 +- src/test/algorithms/sorting/quicksort.js | 10 +- src/test/algorithms/sorting/radix_sort.js | 14 +- src/test/algorithms/sorting/selection_sort.js | 10 +- src/test/algorithms/sorting/shell_sort.js | 11 +- .../algorithms/sorting/short_bubble_sort.js | 10 +- .../sorting/sorting_tests_helper.js | 9 +- src/test/algorithms/string/hamming.js | 28 ++-- src/test/algorithms/string/huffman.js | 33 +++-- .../algorithms/string/knuth_morris_pratt.js | 9 +- src/test/algorithms/string/levenshtein.js | 8 +- .../string/longest_common_subsequence.js | 8 +- .../string/longest_common_substring.js | 8 +- src/test/algorithms/string/rabin_karp.js | 10 +- src/test/data_structures/avl-tree.js | 45 +++--- src/test/data_structures/bst.js | 136 +++++++++--------- .../data_structures/disjoint_set_forest.js | 47 +++--- src/test/data_structures/fenwick_tree.js | 12 +- src/test/data_structures/graph.js | 30 ++-- src/test/data_structures/hash_table.js | 44 +++--- src/test/data_structures/heap.js | 24 ++-- src/test/data_structures/linked_list.js | 57 ++++---- src/test/data_structures/priority_queue.js | 16 +-- src/test/data_structures/queue.js | 39 +++-- src/test/data_structures/set.js | 24 ++-- src/test/data_structures/stack.js | 34 +++-- src/test/data_structures/treap.js | 100 ++++++------- src/test/util/comparator.js | 14 +- src/util/comparator.js | 16 +-- 126 files changed, 1407 insertions(+), 1589 deletions(-) diff --git a/.eslintrc b/.eslintrc index bd98450..e548bbd 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,99 +1,10 @@ { + "extends": "google", "env": { - "jasmine": true, "node": true, - "mocha": true, - "browser": true, - "builtin": true - }, - "globals": { - "describe": false, - "it": false, - "before": false, - "beforeEach": false, - "after": false, - "afterEach": false, - "Int32Array": false + "mocha": true }, "rules": { - "block-scoped-var": 2, - "camelcase": 2, - "comma-style": [ - 2, - "last" - ], - "consistent-return": 0, - "curly": [ - 0, - "all" - ], - "dot-notation": [ - 2, - { - "allowKeywords": true, - "allowPattern": "^[a-z]+(_[a-z]+)+$" - } - ], - "eqeqeq": [ - 2, - "allow-null" - ], - "strict": [ - 2, - "global" - ], - "guard-for-in": 2, - "max-len": [ - 2, - 80, - 2 - ], - "new-cap": 2, - "no-caller": 2, - "no-cond-assign": [ - 2, - "except-parens" - ], - "no-debugger": 2, - "no-empty": 2, - "no-eval": 2, - "no-extend-native": 2, - "no-extra-parens": 0, - "no-irregular-whitespace": 2, - "no-iterator": 2, - "no-loop-func": 2, - "no-multi-str": 2, - "no-new": 2, - "no-plusplus": 0, - "no-proto": 2, - "no-script-url": 2, - "no-sequences": 2, - "no-shadow": 0, - "no-undef": 2, - "no-underscore-dangle": 0, - "no-unused-vars": 2, - "no-use-before-define": 0, - "no-with": 2, - "keyword-spacing": 2, - "space-before-function-paren": [ - 2, - { - "anonymous": "always", - "named": "never" - } - ], - "quotes": [ - 2, - "single" - ], - "semi": [ - 2, - "always" - ], - "valid-typeof": 2, - "wrap-iife": [ - 2, - "inside" - ] + "valid-jsdoc": 0 } } diff --git a/README.md b/README.md index 65cac35..bc8d7cb 100644 --- a/README.md +++ b/README.md @@ -148,3 +148,7 @@ require('algorithms').String; * longestCommonSubsequence * longestCommonSubstring * rabinKarp + +### Contributing + +This project uses [Google JavaScript Style Guide](https://google.github.io/styleguide/javascriptguide.xml) which can be a bit strict, but is really helpful to have more readable and less error-prone code diff --git a/bundle/algorithms.browser.min.js b/bundle/algorithms.browser.min.js index 714a25c..3b32752 100644 --- a/bundle/algorithms.browser.min.js +++ b/bundle/algorithms.browser.min.js @@ -1,4 +1,3 @@ /* algorithms.js v0.10.0 | (c) 2015 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */ -!function(t,r){r.true=t,function(e){if("object"==typeof t&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var i;i="undefined"!=typeof window?window:"undefined"!=typeof r?r:"undefined"!=typeof self?self:this,i.algorithms=e()}}(function(){return function t(r,e,i){function n(s,a){if(!e[s]){if(!r[s]){var h="function"==typeof require&&require;if(!a&&h)return h(s,!0);if(o)return o(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var l=e[s]={exports:{}};r[s][0].call(l.exports,function(t){var e=r[s][1][t];return n(e?e:t)},l,l.exports,t,r,e,i)}return e[s].exports}for(var o="function"==typeof require&&require,s=0;s=1;--e)i[e]+=i[e-1];for(r=0;r=0;--r)e.x+=this.p[r].x*o[r]*n,e.y+=this.p[r].y*o[r]*n,n*=1-t;return e},r.exports=e},{}],2:[function(t,r){"use strict";function e(t,r){var e={},i={},n={},o={},s={},a=0,h=1;e[r]=0,n[0]=r,o[r]=!0,s[r]=1,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0,o[t]=!1,s[t]=0)});for(var u;a!==h;){u=n[a++],o[u]=!1;for(var l=t.neighbors(u),c=0;ct.vertices.size)))return{distance:{}}}}return{distance:e,previous:i}}r.exports=e},{}],3:[function(t,r){"use strict";var e=function(t,r){var e={},i={},n=[],o=0;t.vertices.forEach(function(r){t.neighbors(r).forEach(function(e){n.push({source:r,target:e,weight:t.edge(r,e)})}),e[r]=1/0,++o}),e[r]=0;var s,a,h,u=n.length;for(h=0;o>h;++h){for(var l=!1,c=0;u>c;c++)s=e[n[c].source]+n[c].weight,a=e[n[c].target],a>s&&(l=!0,e[n[c].target]=s,i[n[c].target]=n[c].source);if(!l)break}return h===o?{distance:{}}:{distance:e,previous:i}};r.exports=e},{}],4:[function(t,r){"use strict";var e=t("./breadth_first_search"),i=function(t,r){var i={},n={};return i[r]=0,e(t,r,{onTraversal:function(t,r){i[r]=i[t]+1,n[r]=t}}),{distance:i,previous:n}};r.exports=i},{"./breadth_first_search":5}],5:[function(t,r){"use strict";var e=t("../../data_structures/queue"),i=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t=r.reduce(function(t,r){return t[r]=!0,t},{});return function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.onTraversal=t.onTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},n=function(t,r,n){var o=new e;o.push(r),n=i(n,[r]);for(var s,a=function(t){n.allowTraversal(s,t)&&(n.onTraversal(s,t),o.push(t))};!o.isEmpty();)s=o.pop(),n.enterVertex(s),t.neighbors(s).forEach(a),n.leaveVertex(s)};r.exports=n},{"../../data_structures/queue":58}],6:[function(t,r){"use strict";var e=function(t,r){t=t||{},t.allowTraversal=t.allowTraversal||function(){var t={};return r.forEach(function(r){t[r]=!0}),function(r,e){return t[e]?!1:(t[e]=!0,!0)}}();var e=function(){};return t.beforeTraversal=t.beforeTraversal||e,t.afterTraversal=t.afterTraversal||e,t.enterVertex=t.enterVertex||e,t.leaveVertex=t.leaveVertex||e,t},i=function(t,r,i){n(t,r,e(i,[r]))},n=function t(r,e,i){i.enterVertex(e),r.neighbors(e).forEach(function(n){i.allowTraversal(e,n)&&(i.beforeTraversal(e,n),t(r,n,i),i.afterTraversal(e,n))}),i.leaveVertex(e)};r.exports=i},{}],7:[function(t,r){"use strict";function e(t,r){var e={},n={},o=new i;e[r]=0,t.vertices.forEach(function(t){t!==r&&(e[t]=1/0),o.insert(t,e[t])});for(var s,a=function(r){var i=e[s]+t.edge(s,r);ir&&o.push({ends:[r,e],weight:t.edge(r,e)})})}),o.sort(function(t,r){return t.weight-r.weight}).forEach(function(t){r.sameSubset(t.ends[0],t.ends[1])||(n.addEdge(t.ends[0],t.ends[1],t.weight),r.merge(t.ends[0],t.ends[1]))}),n};r.exports=n},{"../../data_structures/disjoint_set_forest":51,"../../data_structures/graph":53}],11:[function(t,r){"use strict";var e=t("../../data_structures/priority_queue"),i=t("../../data_structures/graph"),n=function(t){if(t.directed)throw new Error("Can't build MST of a directed graph.");var r=new i(!1),n=Object.create(null),o=new e;t.vertices.forEach(function(t){o.insert(t,1/0)});for(var s=function(r,e){var i=t.edge(r,e);i>1:3*t+1}function i(t){var r=[];do t=e(t),r.push(t);while(1!==t);return r}var n={1:1};r.exports={generate:i,calculate:e}},{}],14:[function(t,r){"use strict";var e=function(t,r){for(var e,i,n=0,o=1,s=1,a=0,h=r,u=t;0!==h;)e=Math.floor(u/h),i=h,h=u-e*h,u=i,i=n,n=o-e*n,o=i,i=s,s=a-e*s,a=i;return{x:o,y:a}};r.exports=e},{}],15:[function(t,r){"use strict";var e=function(t,r){return t*r},i=function(t,r,i,n){if(void 0===i&&(i=e,n=1),0>r||Math.floor(r)!==r)throw new Error("Power must be a positive integer or zero.");if(!r){if(void 0===n)throw new Error("The power is zero, but identity value not set.");return n}for(var o,s=function(t){o=void 0===o?t:i(o,t)},a=t;r;r>>>=1,a=i(a,a))1&r&&s(a);return o};r.exports=i},{}],16:[function(t,r){"use strict";var e=t("./fast_power"),i=function(t){return 2>t?t:i(t-1)+i(t-2)},n=function(t){for(var r=0,e=1,i=t,n=1;t>n;n++)i=e+r,r=e,e=i;return i},o=function(){var t=[0,1],r=function(e){return void 0===t[e]&&(t[e]=r(e-1)+r(e-2)),t[e]};return r}(),s=function(t){var r=(1+Math.sqrt(5))/2;return Math.floor(Math.pow(r,t)/Math.sqrt(5)+.5)},a=function(t){var r=[[1,1],[1,0]],i=function(t,r){return[[t[0][0]*r[0][0]+t[0][1]*r[1][0],t[0][0]*r[0][1]+t[0][1]*r[1][1]],[t[1][0]*r[0][0]+t[1][1]*r[1][0],t[1][0]*r[0][1]+t[1][1]*r[1][1]]]},n=e(r,t,i,[[1,0],[0,1]]);return n[0][1]};n.exponential=i,n.withMemoization=o,n.direct=s,n.logarithmic=a,r.exports=n},{"./fast_power":15}],17:[function(t,r){"use strict";var e=function(t){for(var r=t.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),i=t[r];t[r]=t[e],t[e]=i}};r.exports=e},{}],18:[function(t,r){"use strict";var e=function(t,r){var e=t;for(t=Math.max(t,r),r=Math.min(e,r);0!==r;)e=r,r=t%r,t=e;return t},i=function(t,r){if(0===t)return r;if(0===r)return t;var e;for(e=0;0===(1&(t|r));++e)t>>=1,r>>=1;for(;0===(1&t);)t>>=1;var i;do{for(;0===(1&r);)r>>=1;t>r&&(i=r,r=t,t=i),r-=t}while(0!==r);return t<e;e++)r=t[e],r>i&&(i=r),o>r&&(o=r);return i-o};r.exports=e},{}],20:[function(t,r){"use strict";var e=t("./gcd.js"),i=function(t,r,e){return 0===r||0===e?0:(r=Math.abs(r),e=Math.abs(e),r/t(r,e)*e)},n=i.bind(null,e),o=i.bind(null,e.binary),s=n;s.binary=o,r.exports=s},{"./gcd.js":18}],21:[function(t,r){"use strict";var e=function(t,r,e){r=r||1e-7,e=e||1e7;var i,n,o=t,s=0,a=0;do a++,n=(o-s)/2+s,i=n*n,t>i?s=n:o=n;while(Math.abs(i-t)>r&&e>a);var h=Math.round(n);return h*h===t&&(n=h),n};r.exports=e},{}],22:[function(t,r){"use strict";var e=t("../../util/comparator"),i=function(t,r){if(!t.length)return!1;for(var i=new e(r),n=t.length-1;n&&i.greaterThanOrEqual(t[n-1],t[n]);)n-=1;if(!n)return!1;for(var o=t[--n],s=t.length-1;i.lessThanOrEqual(t[s],o);)s-=1;t[n]=t[s],t[s]=o;for(var a=n,h=t.length;++a<--h;){var u=t[a];t[a]=t[h],t[h]=u}return!0};r.exports=i},{"../../util/comparator":69}],23:[function(t,r){"use strict";var e=function(t){if(0===t.length)return[];var r,e=[],i=[];for(r=0;r=r?!1:t(r)},i=function(t){for(var r=2;t>r;++r)if(t%r===0)return!1;return!0},n=function(t){for(var r=Math.sqrt(t),e=2;r>=e;++e)if(t%e===0)return!1;return!0};r.exports={naiveTest:e.bind(null,i),trialDivisionTest:e.bind(null,n)}},{}],25:[function(t,r){"use strict";var e=function(t,r){if(r>t.length)throw new Error("Sample size exceeds the total number of elements.");for(var e=t.slice(0,r),i=r;in&&(e[n]=t[i])}return e};r.exports=e},{}],26:[function(t,r){"use strict";var e=function(t){var r=t.reduce(function(t,r){return t[r]=t[r]+1||1,t},{}),e=Object.keys(r).map(function(e){return r[e]/t.length});return e.reduce(function(t,r){return t-r*Math.log(r)},0)*Math.LOG2E};r.exports=e},{}],27:[function(t,r){"use strict";var e=t("../../data_structures/queue.js"),i=function(t,r){var i=new e;i.push(t);for(var n;!i.isEmpty();)n=i.pop(),r(n.value),n.left&&i.push(n.left),n.right&&i.push(n.right)};r.exports=i},{"../../data_structures/queue.js":58}],28:[function(t,r){"use strict";var e=function(t,r){for(var e=0,i=t.length-1;i>=e;){var n=(i-e>>1)+e;if(t[n]===r)return n;t[n]i;){var n=r+(e-r)/3,o=e-(e-r)/3;t(n)a;a++){for(var h=0,u=0;o>u;u++)if(i.greaterThan(t[u],t[u+1])){var l=t[u];t[u]=t[u+1],t[u+1]=l,h=u,s=!0}if(!s)return t;o=h}return t};r.exports=i},{"../../util/comparator":69}],32:[function(t,r){"use strict";var e=function(t){var r,e=i(t),n=[],o=t.length;for(r=0;o>r;r++){var s=t[r].key;void 0===n[s]&&(n[s]=[]),n[s].push(t[r])}t=[];var a=0;for(r=0;e>=r;r++)if(void 0!==n[r])for(var h=n[r].length,u=0;h>u;u++)t[a++]=n[r][u];return t},i=function(t){for(var r=t[0].key,e=t.length,i=1;e>i;i++)t[i].key>r&&(r=t[i].key);return r};r.exports=e},{}],33:[function(t,r){"use strict";var e=t("../../data_structures/heap").MinHeap,i=function(t,r){var i=new e(r);i.heapify(t);for(var n=[];!i.isEmpty();)n.push(i.extract());return n};r.exports=i},{"../../data_structures/heap":55}],34:[function(t,r){"use strict";var e=t("../../util/comparator"),i=function(t,r){for(var i=new e(r),n=1,o=t.length;o>n;n++){for(var s=t[n],a=n;a>0&&i.lessThan(s,t[a-1]);)t[a]=t[a-1],a--;t[a]=s}return t};r.exports=i},{"../../util/comparator":69}],35:[function(t,r){"use strict";var e=t("../../util/comparator"),i=function(t,r){var i=new e(r);return function t(r){if(r.length>1){var e=r.length>>1,o=t(r.slice(0,e)),s=t(r.slice(e));r=n(o,s,i)}return r}(t)},n=function(t,r,e){for(var i=0,n=0,o=[];ie;){var s=n(r,i,e,o);o-s>s-e?(t(r,e,s-1),e=s+1):(t(r,s+1,o),o=s-1)}return r}(t,0,t.length-1)},n=function(t,r,e,i){o(t,Math.floor(Math.random()*(i-e))+e,i);for(var n=i,s=e,a=e;i>a;a++)r.lessThan(t[a],t[n])&&(o(t,a,s),s++);return o(t,s,n),s},o=function(t,r,e){var i=t[e];t[e]=t[r],t[r]=i};r.exports=i},{"../../util/comparator":69}],37:[function(t,r){"use strict";var e=function(t){for(var r=n(t),e=0===r?1:1+Math.floor(Math.log(r)/Math.log(10)),o=0;e>o;o++)t=i(t,o);return t},i=function(t,r){var e,i=t.length,n=[];for(e=0;10>e;e++)n[e]=[];for(e=0;i>e;e++){var o=parseInt((t[e].key/Math.pow(10,r)).toFixed(r))%10;n[o].push(t[e])}var s=0;for(e=0;10>e;e++)for(var a=n[e].length,h=0;a>h;h++)t[s++]=n[e][h];return t},n=function(t){for(var r,e=1;er)&&(r=t[e].key);return r};r.exports=e},{}],38:[function(t,r){"use strict";var e=t("../../util/comparator"),i=function(t,r){for(var i=new e(r),n=t.length,o=0;n-1>o;o++){for(var s=o,a=o+1;n>a;a++)i.greaterThan(t[s],t[a])&&(s=a);if(s!==o){var h=t[o];t[o]=t[s],t[s]=h}}return t};r.exports=i},{"../../util/comparator":69}],39:[function(t,r){"use strict";var e=t("../../util/comparator"),i=function(t,r){for(var i=new e(r),n=0,o=t.length-1,s=parseInt((o-n+1)/2),a=0,h=0,u=0;s>=1;){for(a=n+s;o>=a;a+=1){for(u=t[a],h=a-s;h>=n&&i.greaterThan(t[h],u);)t[h+s]=t[h],h-=s;t[h+s]=u}s=parseInt(s/2)}return t};r.exports=i},{"../../util/comparator":69}],40:[function(t,r){"use strict";function e(t,r){var e=new i(r),n=t.length-1,o=0;for(o;n>o;o++){var s=t[o],a=t[o+1];e.greaterThan(s,a)&&(t[o+1]=s,t[o]=a,o=-1)}return t}var i=t("../../util/comparator");r.exports=e},{"../../util/comparator":69}],41:[function(t,r){"use strict";var e=function(t,r){if(t.length!==r.length)throw new Error("Strings must be equal in length");for(var e=0,i=0;i>>0).toString(2).length,n=function(t){var r=[],e=0,n=0;return t.split("").forEach(function(t){e=e<<1|t,n+=1,n===i&&(r.push(e),e=n=0)}),n?r.push(e,n):r.push(i),r},o=function(t){if(!t.length)return"";if(1===t.length)throw new Error("Compressed array must be either empty or at least 2 blocks big.");var r=new Array(i+1).join(0),e=t.slice(0,-2).map(function(t){return(r+(t>>>0).toString(2)).slice(-r.length)}).join(""),n=t.slice(-1)[0],o=t.slice(-2)[0];return e+=(r+(o>>>0).toString(2)).slice(-n)};e.encode=function(t,r){if(!t.length)return{encoding:{},value:r?[]:""};var e={};t.split("").forEach(function(t){e[t]=(e[t]||0)+1});var i=Object.keys(e).map(function(t){return{char:t,count:e[t]}}),o=function(t,r){return t.count-r.count},s=function(t,r){return t&&(r&&t.count1;--c){var f=l(),p=l();f.code="0",p.code="1";var g={count:f.count+p.count,parts:[f,p]};a.push(g)}var d=l();d.code=i.length>1?"":"0",function t(r){if(r.parts){var e=r.parts[0],i=r.parts[1];e.code+=r.code,i.code+=r.code,t(e),t(i)}}(d);var v=i.reduce(function(t,r){return t[r.char]=r.code.split("").reverse().join(""),t},{}),m=t.split("").map(function(t){return v[t]}).join("");return{encoding:v,value:r?n(m):m}},e.decode=function(t,r){Array.isArray(r)&&(r=o(r));var e=Object.keys(t).reduce(function(r,e){return r[t[e]]=e,r},{}),i=[],n=r.split("").reduce(function(t,r){t+=r;var n=e[t];return n&&(i.push(n),t=""),t},"");if(n)throw new Error("Invalid string to decode.");return i.join("")},r.exports=e},{}],43:[function(t,r){"use strict";var e=function(t,r){for(var e=t.length,n=r.length,o=0,s=0,a=i(r);e>o+s;)if(r[s]===t[o+s]){if(s===n-1)return o;++s}else a[s]>=0?(s=a[s],o=o+s-a[s]):(s=0,++o);return e},i=function(t){var r=t.length,e=[],i=2,n=0;for(e[0]=-1,e[1]=0;r>i;)t[i-1]===t[n]?(++n,e[i]=n,++i):n>0?n=e[n]:(e[i]=0,++i);return e};r.exports=e},{}],44:[function(t,r){"use strict";var e=function(t,r){var e,i,n=[];for(e=0;e<=t.length;e++)n[e]=[],n[e][0]=e;for(i=0;i<=r.length;i++)n[0][i]=i;for(e=1;e<=t.length;e++)for(i=1;i<=r.length;i++)n[e][i]=Math.min(n[e-1][i-1],n[e-1][i],n[e][i-1])+(t[e-1]!==r[i-1]?1:0);return n[t.length][r.length]};r.exports=e},{}],45:[function(t,r){"use strict";var e=function(t,r){var e,i,n=new Array(t.length+1);for(e=0;e<=t.length;e++)n[e]=new Int32Array(r.length+1);for(e=1;e<=t.length;e++)for(i=1;i<=r.length;i++)n[e][i]=t[e-1]===r[i-1]?n[e-1][i-1]+1:Math.max(n[e][i-1],n[e-1][i]);e=t.length,i=r.length;for(var o="";0!==n[e][i];)t[e-1]===r[i-1]?(o=t[e-1]+o,e--,i--):n[e-1][i]>n[e][i-1]?e--:i--;return o};r.exports=e},{}],46:[function(t,r){"use strict";var e=function(t,r){var e,i,n=new Array(t.length+1);for(e=0;e<=t.length+1;e++)n[e]=new Int32Array(r.length+1);var o={},s=0;for(e=1;e<=t.length;e++)for(i=1;i<=r.length;i++)t[e-1]===r[i-1]?(n[e][i]=n[e-1][i-1]+1,n[e][i]>s&&(o.i=e,o.j=i,s=n[e][i])):n[e][i]=0;var a="";return s&&(a=t.substring(o.i-s,o.i)),a};r.exports=e},{}],47:[function(t,r){"use strict";var e=997,i=function(t,r){if(0===r.length)return 0;for(var i,o=n(r),s=t.substring(0,r.length),a=r.length;a<=t.length;a++)if(void 0===i?i=n(s):(i-=s.charCodeAt(0)*Math.pow(e,r.length-1),i*=e,i+=t.charCodeAt(a),s=s.substring(1)+t[a]),o===i&&r===s)return a===r.length?0:a-r.length+1;return-1},n=function(t){for(var r=0,i=0;ir.right.height?n=r.left:r.left.heighto.right.height)r=o.left;else if(o.left.heightt?"left":"right",r[e]?this.insert(t,r[e]):(r[e]=new i(t,null,null,r),this.keepHeightBalance(r[e],!1))},e.prototype.inOrder=function(t,r){t&&(this.inOrder(t.left,r),"function"==typeof r&&r(t),this.inOrder(t.right,r))},e.prototype.postOrder=function(t,r){t&&(this.postOrder(t.left,r),this.postOrder(t.right,r),"function"==typeof r&&r(t))},e.prototype.preOrder=function(t,r){t&&("function"==typeof r&&r(t),this.preOrder(t.left,r),this.preOrder(t.right,r))},e.prototype.find=function(t){return this._find(t,this.root)},e.prototype._find=function(t,r){if(!r)return null;var e;return r.value===t?e=r:r.value>t?e=this._find(t,r.left):r.valuet.value&&(r=t),this._findMin(t.left,r)):r},e.prototype._findMax=function(t,r){return r=r||{value:-(1/0)},t?(r.value2&&t.apply(this,[].slice.call(arguments,1)),this._introduce(r),this._introduce(e);var i=this.root(r),n=this.root(e);return this._ranks[i]0;t-=t&-t)r+=this._elements[t];return r},e.prototype.rangeSum=function(t,r){return this.prefixSum(r)-this.prefixSum(t-1)},r.exports=e},{}],53:[function(t,r){"use strict";function e(t){this.directed=void 0===t?!0:!!t,this.adjList=Object.create(null),this.vertices=new i}var i=t("./set"),n=function(t){return""+t};e.prototype.addVertex=function(t){if(t=n(t),this.vertices.contains(t))throw new Error('Vertex "'+t+'" has already been added');this.vertices.add(t),this.adjList[t]=Object.create(null)},e.prototype.addEdge=function(t,r,e){t=n(t),r=n(r),e=void 0===e?1:e,this.adjList[t]||this.addVertex(t),this.adjList[r]||this.addVertex(r),this.adjList[t][r]=(this.adjList[t][r]||0)+e,this.directed||(this.adjList[r][t]=(this.adjList[r][t]||0)+e)},e.prototype.neighbors=function(t){return Object.keys(this.adjList[n(t)])},e.prototype.edge=function(t,r){return this.adjList[n(t)][n(r)]},r.exports=e},{"./set":59}],54:[function(t,r){"use strict";function e(t){this._table=new Array(t||64),this._items=0,Object.defineProperty(this,"capacity",{get:function(){return this._table.length}}),Object.defineProperty(this,"size",{get:function(){return this._items}})}var i=t("./linked_list");e.prototype.hash=function(t){"string"!=typeof t&&(t=JSON.stringify(t));for(var r=0,e=0;e1&&(r=t>>1)&&this._comparator.greaterThan(this._elements[r],this._elements[t]);t=r)this._swap(r,t); - -},e.prototype._siftDown=function(t){var r;for(t=t||1;(r=t<<1)<=this.n&&(r+1<=this.n&&this._comparator.lessThan(this._elements[r+1],this._elements[r])&&r++,!this._comparator.lessThan(this._elements[t],this._elements[r]));t=r)this._swap(t,r)},e.prototype.heapify=function(t){t&&(this._elements=t,this._elements.unshift(null));for(var r=this.n>>1;r>0;r--)this._siftDown(r)},e.prototype.forEach=function(t){var r,e=[];for(r=0;r0;r--)t(this.extract());this._elements=e},i.prototype=new e,r.exports={MinHeap:e,MaxHeap:i}},{"../util/comparator":69}],56:[function(t,r){"use strict";function e(){this._length=0,this.head=null,this.tail=null,Object.defineProperty(this,"length",{get:function(){return this._length}.bind(this)})}function i(t){this.value=t,this.prev=null,this.next=null}e.prototype.isEmpty=function(){return 0===this.length},e.prototype.add=function(t,r){if(r>this.length||0>r)throw new Error("Index out of bounds");var e=new i(t);if(void 0!==r&&r=this.length||0>t)throw new Error("Index out of bounds");for(var r=this.head,e=1;t>=e;e++)r=r.next;return r},e.prototype.del=function(t){if(t>=this.length||0>t)throw new Error("Index out of bounds");this.delNode(this.getNode(t))},e.prototype.delNode=function(t){t===this.tail?this.tail=t.prev:t.next.prev=t.prev,t===this.head?this.head=t.next:t.prev.next=t.next,this._length--},e.prototype.forEach=function(t){for(var r=this.head;r;)t(r.value),r=r.next},r.exports=e},{}],57:[function(t,r){"use strict";function e(t){var r=this;i.call(this,function(t,e){return r.priority(t)t.value);return t.children[i]=this._insert(t.children[i],r),t.children[i].keyt.value);return this._find(t.children[e],r)},i.prototype._minimum=function(t){return null===t?1/0:Math.min(t.value,this._minimum(t.children[0]))},i.prototype._maximum=function(t){return null===t?-(1/0):Math.max(t.value,this._maximum(t.children[1]))},i.prototype._remove=function(t,r){if(null===t)return null;var e;return t.value===r?null===t.children[0]&&null===t.children[1]?null:(e=null===t.children[0]?1:0,t=t.rotate(e),t.children[1-e]=this._remove(t.children[1-e],r),t.resize()):(e=~~(r>t.value),t.children[e]=this._remove(t.children[e],r),t.resize())},i.prototype.insert=function(t){this.root=this._insert(this.root,t)},i.prototype.find=function(t){return this._find(this.root,t)},i.prototype.minimum=function(){return this._minimum(this.root)},i.prototype.maximum=function(){return this._maximum(this.root)},i.prototype.remove=function(t){this.root=this._remove(this.root,t)},i.prototype.size=function(){return this.root?this.root.size:0},i.prototype.height=function(){return this.root?this.root.height:0},r.exports=i},{}],62:[function(t,r){"use strict";r.exports={BezierCurve:t("./algorithms/geometry/bezier_curve")}},{"./algorithms/geometry/bezier_curve":1}],63:[function(t,r){"use strict";r.exports={topologicalSort:t("./algorithms/graph/topological_sort"),dijkstra:t("./algorithms/graph/dijkstra"),SPFA:t("./algorithms/graph/SPFA"),bellmanFord:t("./algorithms/graph/bellman_ford"),eulerPath:t("./algorithms/graph/euler_path"),depthFirstSearch:t("./algorithms/graph/depth_first_search"),kruskal:t("./algorithms/graph/kruskal"),breadthFirstSearch:t("./algorithms/graph/breadth_first_search"),bfsShortestPath:t("./algorithms/graph/bfs_shortest_path"),prim:t("./algorithms/graph/prim"),floydWarshall:t("./algorithms/graph/floyd_warshall")}},{"./algorithms/graph/SPFA":2,"./algorithms/graph/bellman_ford":3,"./algorithms/graph/bfs_shortest_path":4,"./algorithms/graph/breadth_first_search":5,"./algorithms/graph/depth_first_search":6,"./algorithms/graph/dijkstra":7,"./algorithms/graph/euler_path":8,"./algorithms/graph/floyd_warshall":9,"./algorithms/graph/kruskal":10,"./algorithms/graph/prim":11,"./algorithms/graph/topological_sort":12}],64:[function(t,r){"use strict";var e={DataStructures:t("./data_structures"),Graph:t("./graph"),Geometry:t("./geometry"),Math:t("./math"),Search:t("./search"),Sorting:t("./sorting"),String:t("./string")};r.exports=e},{"./data_structures":48,"./geometry":62,"./graph":63,"./math":65,"./search":66,"./sorting":67,"./string":68}],65:[function(t,r){"use strict";r.exports={fibonacci:t("./algorithms/math/fibonacci"),fisherYates:t("./algorithms/math/fisher_yates"),gcd:t("./algorithms/math/gcd"),extendedEuclidean:t("./algorithms/math/extended_euclidean"),lcm:t("./algorithms/math/lcm"),newtonSqrt:t("./algorithms/math/newton_sqrt"),primalityTests:t("./algorithms/math/primality_tests"),reservoirSampling:t("./algorithms/math/reservoir_sampling"),fastPower:t("./algorithms/math/fast_power"),nextPermutation:t("./algorithms/math/next_permutation"),powerSet:t("./algorithms/math/power_set"),shannonEntropy:t("./algorithms/math/shannon_entropy"),collatzConjecture:t("./algorithms/math/collatz_conjecture"),greatestDifference:t("./algorithms/math/greatest_difference")}},{"./algorithms/math/collatz_conjecture":13,"./algorithms/math/extended_euclidean":14,"./algorithms/math/fast_power":15,"./algorithms/math/fibonacci":16,"./algorithms/math/fisher_yates":17,"./algorithms/math/gcd":18,"./algorithms/math/greatest_difference":19,"./algorithms/math/lcm":20,"./algorithms/math/newton_sqrt":21,"./algorithms/math/next_permutation":22,"./algorithms/math/power_set":23,"./algorithms/math/primality_tests":24,"./algorithms/math/reservoir_sampling":25,"./algorithms/math/shannon_entropy":26}],66:[function(t,r){"use strict";r.exports={bfs:t("./algorithms/search/bfs"),binarySearch:t("./algorithms/search/binarysearch"),ternarySearch:t("./algorithms/search/ternary_search"),dfs:t("./algorithms/search/dfs")}},{"./algorithms/search/bfs":27,"./algorithms/search/binarysearch":28,"./algorithms/search/dfs":29,"./algorithms/search/ternary_search":30}],67:[function(t,r){"use strict";r.exports={bubbleSort:t("./algorithms/sorting/bubble_sort"),shortBubbleSort:t("./algorithms/sorting/short_bubble_sort"),countingSort:t("./algorithms/sorting/counting_sort"),heapSort:t("./algorithms/sorting/heap_sort"),mergeSort:t("./algorithms/sorting/merge_sort"),quicksort:t("./algorithms/sorting/quicksort"),selectionSort:t("./algorithms/sorting/selection_sort"),radixSort:t("./algorithms/sorting/radix_sort"),insertionSort:t("./algorithms/sorting/insertion_sort"),shellSort:t("./algorithms/sorting/shell_sort")}},{"./algorithms/sorting/bubble_sort":31,"./algorithms/sorting/counting_sort":32,"./algorithms/sorting/heap_sort":33,"./algorithms/sorting/insertion_sort":34,"./algorithms/sorting/merge_sort":35,"./algorithms/sorting/quicksort":36,"./algorithms/sorting/radix_sort":37,"./algorithms/sorting/selection_sort":38,"./algorithms/sorting/shell_sort":39,"./algorithms/sorting/short_bubble_sort":40}],68:[function(t,r){"use strict";r.exports={levenshtein:t("./algorithms/string/levenshtein"),rabinKarp:t("./algorithms/string/rabin_karp"),knuthMorrisPratt:t("./algorithms/string/knuth_morris_pratt"),huffman:t("./algorithms/string/huffman"),hamming:t("./algorithms/string/hamming"),longestCommonSubsequence:t("./algorithms/string/longest_common_subsequence"),longestCommonSubstring:t("./algorithms/string/longest_common_substring")}},{"./algorithms/string/hamming":41,"./algorithms/string/huffman":42,"./algorithms/string/knuth_morris_pratt":43,"./algorithms/string/levenshtein":44,"./algorithms/string/longest_common_subsequence":45,"./algorithms/string/longest_common_substring":46,"./algorithms/string/rabin_karp":47}],69:[function(t,r){"use strict";function e(t){t&&(this.compare=t)}e.prototype.compare=function(t,r){return t===r?0:r>t?-1:1},e.prototype.lessThan=function(t,r){return this.compare(t,r)<0},e.prototype.lessThanOrEqual=function(t,r){return this.lessThan(t,r)||this.equal(t,r)},e.prototype.greaterThan=function(t,r){return this.compare(t,r)>0},e.prototype.greaterThanOrEqual=function(t,r){return this.greaterThan(t,r)||this.equal(t,r)},e.prototype.equal=function(t,r){return 0===this.compare(t,r)},e.prototype.reverse=function(){var t=this.compare;this.compare=function(r,e){return t(e,r)}},r.exports=e},{}]},{},[64])(64)})}({},function(){return this}()); \ No newline at end of file +!function(t, r) {r.true = t, function(e) {if ("object" == typeof t && "undefined" != typeof module)module.exports = e(); else if ("function" == typeof define && define.amd)define([], e); else {var i; i = "undefined" != typeof window ? window : "undefined" != typeof r ? r : "undefined" != typeof self ? self : this, i.algorithms = e();}}(function() {return function t(r, e, i) {function n(s, a) {if (!e[s]) {if (!r[s]) {var h = "function" == typeof require && require; if (!a && h) return h(s, !0); if (o) return o(s, !0); var u = new Error("Cannot find module '" + s + "'"); throw u.code = "MODULE_NOT_FOUND", u;} var l = e[s] = {exports: {}}; r[s][0].call(l.exports, function(t) {var e = r[s][1][t]; return n(e ? e : t);}, l, l.exports, t, r, e, i);} return e[s].exports;} for (var o = "function" == typeof require && require, s = 0; s < i.length; s++)n(i[s]); return n;}({1: [function(t, r) {"use strict"; var e = function(t) {this.n = t.length, this.p = []; var r, e, i = [1]; for (r = 1; r < this.n; ++r) for (i.push(0), e = r; e >= 1; --e)i[e] += i[e - 1]; for (r = 0; r < this.n; ++r) this.p.push({x: i[r] * t[r].x, y: i[r] * t[r].y});}; e.prototype.get = function(t) {var r, e = {x: 0, y: 0}, i = 1, n = 1, o = []; for (r = 0; r < this.n; ++r)o.push(i), i *= t; for (r = this.n - 1; r >= 0; --r)e.x += this.p[r].x * o[r] * n, e.y += this.p[r].y * o[r] * n, n *= 1 - t; return e;}, r.exports = e;}, {}], 2: [function(t, r) {"use strict"; function e(t, r) {var e = {}, i = {}, n = {}, o = {}, s = {}, a = 0, h = 1; e[r] = 0, n[0] = r, o[r] = !0, s[r] = 1, t.vertices.forEach(function(t) {t !== r && (e[t] = 1 / 0, o[t] = !1, s[t] = 0);}); for (var u; a !== h;) {u = n[a++], o[u] = !1; for (var l = t.neighbors(u), c = 0; c < l.length; c++) {var f = l[c], p = e[u] + t.edge(u, f); if (p < e[f] && (e[f] = p, i[f] = u, !o[f] && (n[h++] = f, o[f] = !0, s[f]++, s[f] > t.vertices.size))) return {distance: {}};}} return {distance: e, previous: i};}r.exports = e;}, {}], 3: [function(t, r) {"use strict"; var e = function(t, r) {var e = {}, i = {}, n = [], o = 0; t.vertices.forEach(function(r) {t.neighbors(r).forEach(function(e) {n.push({source: r, target: e, weight: t.edge(r, e)});}), e[r] = 1 / 0, ++o;}), e[r] = 0; var s, a, h, u = n.length; for (h = 0; o > h; ++h) {for (var l = !1, c = 0; u > c; c++)s = e[n[c].source] + n[c].weight, a = e[n[c].target], a > s && (l = !0, e[n[c].target] = s, i[n[c].target] = n[c].source); if (!l) break;} return h === o ? {distance: {}} : {distance: e, previous: i};}; r.exports = e;}, {}], 4: [function(t, r) {"use strict"; var e = t("./breadth_first_search"), i = function(t, r) {var i = {}, n = {}; return i[r] = 0, e(t, r, {onTraversal: function(t, r) {i[r] = i[t] + 1, n[r] = t;}}), {distance: i, previous: n};}; r.exports = i;}, {"./breadth_first_search": 5}], 5: [function(t, r) {"use strict"; var e = t("../../data_structures/queue"), i = function(t, r) {t = t || {}, t.allowTraversal = t.allowTraversal || function() {var t = r.reduce(function(t, r) {return t[r] = !0, t;}, {}); return function(r, e) {return t[e] ? !1 : (t[e] = !0, !0);};}(); var e = function() {}; return t.onTraversal = t.onTraversal || e, t.enterVertex = t.enterVertex || e, t.leaveVertex = t.leaveVertex || e, t;}, n = function(t, r, n) {var o = new e; o.push(r), n = i(n, [r]); for (var s, a = function(t) {n.allowTraversal(s, t) && (n.onTraversal(s, t), o.push(t));}; !o.isEmpty();)s = o.pop(), n.enterVertex(s), t.neighbors(s).forEach(a), n.leaveVertex(s);}; r.exports = n;}, {"../../data_structures/queue": 58}], 6: [function(t, r) {"use strict"; var e = function(t, r) {t = t || {}, t.allowTraversal = t.allowTraversal || function() {var t = {}; return r.forEach(function(r) {t[r] = !0;}), function(r, e) {return t[e] ? !1 : (t[e] = !0, !0);};}(); var e = function() {}; return t.beforeTraversal = t.beforeTraversal || e, t.afterTraversal = t.afterTraversal || e, t.enterVertex = t.enterVertex || e, t.leaveVertex = t.leaveVertex || e, t;}, i = function(t, r, i) {n(t, r, e(i, [r]));}, n = function t(r, e, i) {i.enterVertex(e), r.neighbors(e).forEach(function(n) {i.allowTraversal(e, n) && (i.beforeTraversal(e, n), t(r, n, i), i.afterTraversal(e, n));}), i.leaveVertex(e);}; r.exports = i;}, {}], 7: [function(t, r) {"use strict"; function e(t, r) {var e = {}, n = {}, o = new i; e[r] = 0, t.vertices.forEach(function(t) {t !== r && (e[t] = 1 / 0), o.insert(t, e[t]);}); for (var s, a = function(r) {var i = e[s] + t.edge(s, r); i < e[r] && (e[r] = i, n[r] = s, o.changePriority(r, e[r]));}; !o.isEmpty();)s = o.extract(), t.neighbors(s).forEach(a); return {distance: e, previous: n};} var i = t("../../data_structures/priority_queue"); r.exports = e;}, {"../../data_structures/priority_queue": 57}], 8: [function(t, r) {"use strict"; var e = t("../../data_structures/graph"), i = t("../../algorithms/graph/depth_first_search"), n = function(t) {var r = {}; if (t.vertices.forEach(function(e) {r[e] = t.neighbors(e).length;}), t.directed)t.vertices.forEach(function(e) {t.neighbors(e).forEach(function(t) {r[t] -= 1;});}); else {var e = !1; t.vertices.forEach(function(t) {r[t] %= 2, r[t] && (e && (r[t] = -1), e = !0);});} var i, n, o; return t.vertices.forEach(function(t) {if (1 === r[t]) {if (i) throw new Error("Duplicate start vertex."); i = t;} else if (-1 === r[t]) {if (n) throw new Error("Duplicate finish vertex."); n = t;} else {if (r[t]) throw new Error("Unexpected vertex degree for " + t); o || (o = t);}}), i || n || (i = n = o), {start: i, finish: n};}, o = function(t) {if (!t.vertices.size) return []; var r = n(t), o = [r.finish], s = new e(t.directed); return t.vertices.forEach(s.addVertex.bind(s)), i(t, r.start, {allowTraversal: function(t, r) {return !s.edge(t, r);}, beforeTraversal: function(t, r) {s.addEdge(t, r);}, afterTraversal: function(t) {o.push(t);}}), t.vertices.forEach(function(r) {if (s.neighbors(r).length < t.neighbors(r).length) throw new Error("There is no euler path for a disconnected graph.");}), o.reverse();}; r.exports = o;}, {"../../algorithms/graph/depth_first_search": 6, "../../data_structures/graph": 53}], 9: [function(t, r) {"use strict"; var e = function(t) {var r = Object.create(null); t.vertices.forEach(function(e) {r[e] = Object.create(null), t.vertices.forEach(function(i) {r[e][i] = e === i ? 0 : void 0 !== t.edge(e, i) ? t.edge(e, i) : 1 / 0;});}); var e = Object.create(null); t.vertices.forEach(function(t) {e[t] = Object.create(null);}), t.vertices.forEach(function(i) {t.vertices.forEach(function(n) {t.vertices.forEach(function(t) {var o = r[n][i] + r[i][t]; o < r[n][t] && (r[n][t] = o, e[n][t] = i);});});}), t.vertices.forEach(function(t) {if (r[t][t] < 0) throw new Error("The graph contains a negative-weighted cycle!");}); var i = function(t, i) {if (!Number.isFinite(r[t][i])) return null; var n = [t]; return t !== i && !function t(r, i) {if (void 0 === e[r][i])n.push(i); else {var o = e[r][i]; t(r, o), t(o, i);}}(t, i), n;}; return {distance: r, path: i};}; r.exports = e;}, {}], 10: [function(t, r) {"use strict"; var e = t("../../data_structures/disjoint_set_forest"), i = t("../../data_structures/graph"), n = function(t) {if (t.directed) throw new Error("Can't build MST of a directed graph."); var r = new e, n = new i(!1); t.vertices.forEach(n.addVertex.bind(n)); var o = []; return t.vertices.forEach(function(r) {t.neighbors(r).forEach(function(e) {e > r && o.push({ends: [r, e], weight: t.edge(r, e)});});}), o.sort(function(t, r) {return t.weight - r.weight;}).forEach(function(t) {r.sameSubset(t.ends[0], t.ends[1]) || (n.addEdge(t.ends[0], t.ends[1], t.weight), r.merge(t.ends[0], t.ends[1]));}), n;}; r.exports = n;}, {"../../data_structures/disjoint_set_forest": 51, "../../data_structures/graph": 53}], 11: [function(t, r) {"use strict"; var e = t("../../data_structures/priority_queue"), i = t("../../data_structures/graph"), n = function(t) {if (t.directed) throw new Error("Can't build MST of a directed graph."); var r = new i(!1), n = Object.create(null), o = new e; t.vertices.forEach(function(t) {o.insert(t, 1 / 0);}); for (var s = function(r, e) {var i = t.edge(r, e); i < o.priority(e) && (o.changePriority(e, i), n[e] = r);}; !o.isEmpty();) {var a = o.extract(!0), h = a.item, u = a.priority; n[h] ? r.addEdge(n[h], h, u) : r.addVertex(h), t.neighbors(h).forEach(s.bind(null, h));} return r;}; r.exports = n;}, {"../../data_structures/graph": 53, "../../data_structures/priority_queue": 57}], 12: [function(t, r) {"use strict"; var e = t("../../data_structures/stack"), i = t("../../algorithms/graph/depth_first_search"), n = function(t) {var r = new e, n = {}, o = 0; return t.vertices.forEach(function(e) {n[e] || i(t, e, {allowTraversal: function(t, r) {return !n[r];}, enterVertex: function(t) {n[t] = ++o;}, leaveVertex: function(t) {r.push(t);}});}), r;}; r.exports = n;}, {"../../algorithms/graph/depth_first_search": 6, "../../data_structures/stack": 60}], 13: [function(t, r) {"use strict"; function e(t) {return t in n ? n[t] : n[t] = t % 2 === 0 ? t >> 1 : 3 * t + 1;} function i(t) {var r = []; do t = e(t), r.push(t); while (1 !== t);return r;} var n = {1: 1}; r.exports = {generate: i, calculate: e};}, {}], 14: [function(t, r) {"use strict"; var e = function(t, r) {for (var e, i, n = 0, o = 1, s = 1, a = 0, h = r, u = t; 0 !== h;)e = Math.floor(u / h), i = h, h = u - e * h, u = i, i = n, n = o - e * n, o = i, i = s, s = a - e * s, a = i; return {x: o, y: a};}; r.exports = e;}, {}], 15: [function(t, r) {"use strict"; var e = function(t, r) {return t * r;}, i = function(t, r, i, n) {if (void 0 === i && (i = e, n = 1), 0 > r || Math.floor(r) !== r) throw new Error("Power must be a positive integer or zero."); if (!r) {if (void 0 === n) throw new Error("The power is zero, but identity value not set."); return n;} for (var o, s = function(t) {o = void 0 === o ? t : i(o, t);}, a = t; r; r >>>= 1, a = i(a, a))1 & r && s(a); return o;}; r.exports = i;}, {}], 16: [function(t, r) {"use strict"; var e = t("./fast_power"), i = function(t) {return 2 > t ? t : i(t - 1) + i(t - 2);}, n = function(t) {for (var r = 0, e = 1, i = t, n = 1; t > n; n++)i = e + r, r = e, e = i; return i;}, o = function() {var t = [0, 1], r = function(e) {return void 0 === t[e] && (t[e] = r(e - 1) + r(e - 2)), t[e];}; return r;}(), s = function(t) {var r = (1 + Math.sqrt(5)) / 2; return Math.floor(Math.pow(r, t) / Math.sqrt(5) + .5);}, a = function(t) {var r = [[1, 1], [1, 0]], i = function(t, r) {return [[t[0][0] * r[0][0] + t[0][1] * r[1][0], t[0][0] * r[0][1] + t[0][1] * r[1][1]], [t[1][0] * r[0][0] + t[1][1] * r[1][0], t[1][0] * r[0][1] + t[1][1] * r[1][1]]];}, n = e(r, t, i, [[1, 0], [0, 1]]); return n[0][1];}; n.exponential = i, n.withMemoization = o, n.direct = s, n.logarithmic = a, r.exports = n;}, {"./fast_power": 15}], 17: [function(t, r) {"use strict"; var e = function(t) {for (var r = t.length - 1; r > 0; r--) {var e = Math.floor(Math.random() * (r + 1)), i = t[r]; t[r] = t[e], t[e] = i;}}; r.exports = e;}, {}], 18: [function(t, r) {"use strict"; var e = function(t, r) {var e = t; for (t = Math.max(t, r), r = Math.min(e, r); 0 !== r;)e = r, r = t % r, t = e; return t;}, i = function(t, r) {if (0 === t) return r; if (0 === r) return t; var e; for (e = 0; 0 === (1 & (t | r)); ++e)t >>= 1, r >>= 1; for (;0 === (1 & t);)t >>= 1; var i; do {for (;0 === (1 & r);)r >>= 1; t > r && (i = r, r = t, t = i), r -= t;} while (0 !== r);return t << e;}; e.binary = i, r.exports = e;}, {}], 19: [function(t, r) {"use strict"; var e = function(t) {var r, e = 0, i = t[0], n = t.length, o = t[0]; for (e; n > e; e++)r = t[e], r > i && (i = r), o > r && (o = r); return i - o;}; r.exports = e;}, {}], 20: [function(t, r) {"use strict"; var e = t("./gcd.js"), i = function(t, r, e) {return 0 === r || 0 === e ? 0 : (r = Math.abs(r), e = Math.abs(e), r / t(r, e) * e);}, n = i.bind(null, e), o = i.bind(null, e.binary), s = n; s.binary = o, r.exports = s;}, {"./gcd.js": 18}], 21: [function(t, r) {"use strict"; var e = function(t, r, e) {r = r || 1e-7, e = e || 1e7; var i, n, o = t, s = 0, a = 0; do a++, n = (o - s) / 2 + s, i = n * n, t > i ? s = n : o = n; while (Math.abs(i - t) > r && e > a);var h = Math.round(n); return h * h === t && (n = h), n;}; r.exports = e;}, {}], 22: [function(t, r) {"use strict"; var e = t("../../util/comparator"), i = function(t, r) {if (!t.length) return !1; for (var i = new e(r), n = t.length - 1; n && i.greaterThanOrEqual(t[n - 1], t[n]);)n -= 1; if (!n) return !1; for (var o = t[--n], s = t.length - 1; i.lessThanOrEqual(t[s], o);)s -= 1; t[n] = t[s], t[s] = o; for (var a = n, h = t.length; ++a < --h;) {var u = t[a]; t[a] = t[h], t[h] = u;} return !0;}; r.exports = i;}, {"../../util/comparator": 69}], 23: [function(t, r) {"use strict"; var e = function(t) {if (0 === t.length) return []; var r, e = [], i = []; for (r = 0; r < t.length; r++)i[r] = !0; for (r = 0; r < Math.pow(2, t.length); r++) {e.push([]); for (var n = 0; n < t.length; n++)r % Math.pow(2, n) === 0 && (i[n] = !i[n]), i[n] && e[r].push(t[n]);} return e;}, i = function(t) {if (0 === t.length) return []; if (1 === t.length) return [[], [t[0]]]; var r = [], e = t[0]; return t.splice(0, 1), i(t).forEach(function(t) {r.push(t); var i = [e]; i.push.apply(i, t), r.push(i);}), r;}, n = e; n.recursive = i, r.exports = n;}, {}], 24: [function(t, r) {"use strict"; var e = function(t, r) {return 1 >= r ? !1 : t(r);}, i = function(t) {for (var r = 2; t > r; ++r) if (t % r === 0) return !1; return !0;}, n = function(t) {for (var r = Math.sqrt(t), e = 2; r >= e; ++e) if (t % e === 0) return !1; return !0;}; r.exports = {naiveTest: e.bind(null, i), trialDivisionTest: e.bind(null, n)};}, {}], 25: [function(t, r) {"use strict"; var e = function(t, r) {if (r > t.length) throw new Error("Sample size exceeds the total number of elements."); for (var e = t.slice(0, r), i = r; i < t.length; ++i) {var n = Math.floor(Math.random() * (i + 1)); r > n && (e[n] = t[i]);} return e;}; r.exports = e;}, {}], 26: [function(t, r) {"use strict"; var e = function(t) {var r = t.reduce(function(t, r) {return t[r] = t[r] + 1 || 1, t;}, {}), e = Object.keys(r).map(function(e) {return r[e] / t.length;}); return e.reduce(function(t, r) {return t - r * Math.log(r);}, 0) * Math.LOG2E;}; r.exports = e;}, {}], 27: [function(t, r) {"use strict"; var e = t("../../data_structures/queue.js"), i = function(t, r) {var i = new e; i.push(t); for (var n; !i.isEmpty();)n = i.pop(), r(n.value), n.left && i.push(n.left), n.right && i.push(n.right);}; r.exports = i;}, {"../../data_structures/queue.js": 58}], 28: [function(t, r) {"use strict"; var e = function(t, r) {for (var e = 0, i = t.length - 1; i >= e;) {var n = (i - e >> 1) + e; if (t[n] === r) return n; t[n] < r ? e = n + 1 : i = n - 1;} return -1;}; r.exports = e;}, {}], 29: [function(t, r) {"use strict"; var e = function(t, r) {t && (e(t.left, r), r(t.value), e(t.right, r));}, i = function(t, r) {t && (r(t.value), i(t.left, r), i(t.right, r));}, n = function(t, r) {t && (n(t.left, r), n(t.right, r), r(t.value));}; e.preOrder = i, e.postOrder = n, r.exports = e;}, {}], 30: [function(t, r) {"use strict"; var e = function(t, r, e, i) {for (;Math.abs(e - r) > i;) {var n = r + (e - r) / 3, o = e - (e - r) / 3; t(n) < t(o) ? r = n : e = o;} return (r + e) / 2;}; r.exports = e;}, {}], 31: [function(t, r) {"use strict"; var e = t("../../util/comparator"), i = function(t, r) {for (var i = new e(r), n = t.length, o = n - 1, s = !1, a = 0; n - 1 > a; a++) {for (var h = 0, u = 0; o > u; u++) if (i.greaterThan(t[u], t[u + 1])) {var l = t[u]; t[u] = t[u + 1], t[u + 1] = l, h = u, s = !0;} if (!s) return t; o = h;} return t;}; r.exports = i;}, {"../../util/comparator": 69}], 32: [function(t, r) {"use strict"; var e = function(t) {var r, e = i(t), n = [], o = t.length; for (r = 0; o > r; r++) {var s = t[r].key; void 0 === n[s] && (n[s] = []), n[s].push(t[r]);}t = []; var a = 0; for (r = 0; e >= r; r++) if (void 0 !== n[r]) for (var h = n[r].length, u = 0; h > u; u++)t[a++] = n[r][u]; return t;}, i = function(t) {for (var r = t[0].key, e = t.length, i = 1; e > i; i++)t[i].key > r && (r = t[i].key); return r;}; r.exports = e;}, {}], 33: [function(t, r) {"use strict"; var e = t("../../data_structures/heap").MinHeap, i = function(t, r) {var i = new e(r); i.heapify(t); for (var n = []; !i.isEmpty();)n.push(i.extract()); return n;}; r.exports = i;}, {"../../data_structures/heap": 55}], 34: [function(t, r) {"use strict"; var e = t("../../util/comparator"), i = function(t, r) {for (var i = new e(r), n = 1, o = t.length; o > n; n++) {for (var s = t[n], a = n; a > 0 && i.lessThan(s, t[a - 1]);)t[a] = t[a - 1], a--; t[a] = s;} return t;}; r.exports = i;}, {"../../util/comparator": 69}], 35: [function(t, r) {"use strict"; var e = t("../../util/comparator"), i = function(t, r) {var i = new e(r); return function t(r) {if (r.length > 1) {var e = r.length >> 1, o = t(r.slice(0, e)), s = t(r.slice(e)); r = n(o, s, i);} return r;}(t);}, n = function(t, r, e) {for (var i = 0, n = 0, o = []; i < t.length && n < r.length;)o.push(e.lessThan(t[i], r[n]) ? t[i++] : r[n++]); return o.concat(i < t.length ? t.slice(i) : r.slice(n));}; r.exports = i;}, {"../../util/comparator": 69}], 36: [function(t, r) {"use strict"; var e = t("../../util/comparator"), i = function(t, r) {var i = new e(r); return function t(r, e, o) {for (;o > e;) {var s = n(r, i, e, o); o - s > s - e ? (t(r, e, s - 1), e = s + 1) : (t(r, s + 1, o), o = s - 1);} return r;}(t, 0, t.length - 1);}, n = function(t, r, e, i) {o(t, Math.floor(Math.random() * (i - e)) + e, i); for (var n = i, s = e, a = e; i > a; a++)r.lessThan(t[a], t[n]) && (o(t, a, s), s++); return o(t, s, n), s;}, o = function(t, r, e) {var i = t[e]; t[e] = t[r], t[r] = i;}; r.exports = i;}, {"../../util/comparator": 69}], 37: [function(t, r) {"use strict"; var e = function(t) {for (var r = n(t), e = 0 === r ? 1 : 1 + Math.floor(Math.log(r) / Math.log(10)), o = 0; e > o; o++)t = i(t, o); return t;}, i = function(t, r) {var e, i = t.length, n = []; for (e = 0; 10 > e; e++)n[e] = []; for (e = 0; i > e; e++) {var o = parseInt((t[e].key / Math.pow(10, r)).toFixed(r)) % 10; n[o].push(t[e]);} var s = 0; for (e = 0; 10 > e; e++) for (var a = n[e].length, h = 0; a > h; h++)t[s++] = n[e][h]; return t;}, n = function(t) {for (var r, e = 1; e < t.length; e++)(void 0 === r || t[e].key > r) && (r = t[e].key); return r;}; r.exports = e;}, {}], 38: [function(t, r) {"use strict"; var e = t("../../util/comparator"), i = function(t, r) {for (var i = new e(r), n = t.length, o = 0; n - 1 > o; o++) {for (var s = o, a = o + 1; n > a; a++)i.greaterThan(t[s], t[a]) && (s = a); if (s !== o) {var h = t[o]; t[o] = t[s], t[s] = h;}} return t;}; r.exports = i;}, {"../../util/comparator": 69}], 39: [function(t, r) {"use strict"; var e = t("../../util/comparator"), i = function(t, r) {for (var i = new e(r), n = 0, o = t.length - 1, s = parseInt((o - n + 1) / 2), a = 0, h = 0, u = 0; s >= 1;) {for (a = n + s; o >= a; a += 1) {for (u = t[a], h = a - s; h >= n && i.greaterThan(t[h], u);)t[h + s] = t[h], h -= s; t[h + s] = u;}s = parseInt(s / 2);} return t;}; r.exports = i;}, {"../../util/comparator": 69}], 40: [function(t, r) {"use strict"; function e(t, r) {var e = new i(r), n = t.length - 1, o = 0; for (o; n > o; o++) {var s = t[o], a = t[o + 1]; e.greaterThan(s, a) && (t[o + 1] = s, t[o] = a, o = -1);} return t;} var i = t("../../util/comparator"); r.exports = e;}, {"../../util/comparator": 69}], 41: [function(t, r) {"use strict"; var e = function(t, r) {if (t.length !== r.length) throw new Error("Strings must be equal in length"); for (var e = 0, i = 0; i < t.length; i++)t[i] !== r[i] && e++; return e;}; r.exports = e;}, {}], 42: [function(t, r) {"use strict"; var e = {}, i = (-1 >>> 0).toString(2).length, n = function(t) {var r = [], e = 0, n = 0; return t.split("").forEach(function(t) {e = e << 1 | t, n += 1, n === i && (r.push(e), e = n = 0);}), n ? r.push(e, n) : r.push(i), r;}, o = function(t) {if (!t.length) return ""; if (1 === t.length) throw new Error("Compressed array must be either empty or at least 2 blocks big."); var r = new Array(i + 1).join(0), e = t.slice(0, -2).map(function(t) {return (r + (t >>> 0).toString(2)).slice(-r.length);}).join(""), n = t.slice(-1)[0], o = t.slice(-2)[0]; return e += (r + (o >>> 0).toString(2)).slice(-n);}; e.encode = function(t, r) {if (!t.length) return {encoding: {}, value: r ? [] : ""}; var e = {}; t.split("").forEach(function(t) {e[t] = (e[t] || 0) + 1;}); var i = Object.keys(e).map(function(t) {return {char: t, count: e[t]};}), o = function(t, r) {return t.count - r.count;}, s = function(t, r) {return t && (r && t.count < r.count || !r);}; i.sort(o); for (var a = [], h = 0, u = 0, l = function() {return s(i[h], a[u]) ? i[h++] : a[u++];}, c = i.length; c > 1; --c) {var f = l(), p = l(); f.code = "0", p.code = "1"; var g = {count: f.count + p.count, parts: [f, p]}; a.push(g);} var d = l(); d.code = i.length > 1 ? "" : "0", function t(r) {if (r.parts) {var e = r.parts[0], i = r.parts[1]; e.code += r.code, i.code += r.code, t(e), t(i);}}(d); var v = i.reduce(function(t, r) {return t[r.char] = r.code.split("").reverse().join(""), t;}, {}), m = t.split("").map(function(t) {return v[t];}).join(""); return {encoding: v, value: r ? n(m) : m};}, e.decode = function(t, r) {Array.isArray(r) && (r = o(r)); var e = Object.keys(t).reduce(function(r, e) {return r[t[e]] = e, r;}, {}), i = [], n = r.split("").reduce(function(t, r) {t += r; var n = e[t]; return n && (i.push(n), t = ""), t;}, ""); if (n) throw new Error("Invalid string to decode."); return i.join("");}, r.exports = e;}, {}], 43: [function(t, r) {"use strict"; var e = function(t, r) {for (var e = t.length, n = r.length, o = 0, s = 0, a = i(r); e > o + s;) if (r[s] === t[o + s]) {if (s === n - 1) return o; ++s;} else a[s] >= 0 ? (s = a[s], o = o + s - a[s]) : (s = 0, ++o); return e;}, i = function(t) {var r = t.length, e = [], i = 2, n = 0; for (e[0] = -1, e[1] = 0; r > i;)t[i - 1] === t[n] ? (++n, e[i] = n, ++i) : n > 0 ? n = e[n] : (e[i] = 0, ++i); return e;}; r.exports = e;}, {}], 44: [function(t, r) {"use strict"; var e = function(t, r) {var e, i, n = []; for (e = 0; e <= t.length; e++)n[e] = [], n[e][0] = e; for (i = 0; i <= r.length; i++)n[0][i] = i; for (e = 1; e <= t.length; e++) for (i = 1; i <= r.length; i++)n[e][i] = Math.min(n[e - 1][i - 1], n[e - 1][i], n[e][i - 1]) + (t[e - 1] !== r[i - 1] ? 1 : 0); return n[t.length][r.length];}; r.exports = e;}, {}], 45: [function(t, r) {"use strict"; var e = function(t, r) {var e, i, n = new Array(t.length + 1); for (e = 0; e <= t.length; e++)n[e] = new Int32Array(r.length + 1); for (e = 1; e <= t.length; e++) for (i = 1; i <= r.length; i++)n[e][i] = t[e - 1] === r[i - 1] ? n[e - 1][i - 1] + 1 : Math.max(n[e][i - 1], n[e - 1][i]); e = t.length, i = r.length; for (var o = ""; 0 !== n[e][i];)t[e - 1] === r[i - 1] ? (o = t[e - 1] + o, e--, i--) : n[e - 1][i] > n[e][i - 1] ? e-- : i--; return o;}; r.exports = e;}, {}], 46: [function(t, r) {"use strict"; var e = function(t, r) {var e, i, n = new Array(t.length + 1); for (e = 0; e <= t.length + 1; e++)n[e] = new Int32Array(r.length + 1); var o = {}, s = 0; for (e = 1; e <= t.length; e++) for (i = 1; i <= r.length; i++)t[e - 1] === r[i - 1] ? (n[e][i] = n[e - 1][i - 1] + 1, n[e][i] > s && (o.i = e, o.j = i, s = n[e][i])) : n[e][i] = 0; var a = ""; return s && (a = t.substring(o.i - s, o.i)), a;}; r.exports = e;}, {}], 47: [function(t, r) {"use strict"; var e = 997, i = function(t, r) {if (0 === r.length) return 0; for (var i, o = n(r), s = t.substring(0, r.length), a = r.length; a <= t.length; a++) if (void 0 === i ? i = n(s) : (i -= s.charCodeAt(0) * Math.pow(e, r.length - 1), i *= e, i += t.charCodeAt(a), s = s.substring(1) + t[a]), o === i && r === s) return a === r.length ? 0 : a - r.length + 1; return -1;}, n = function(t) {for (var r = 0, i = 0; i < t.length; i++)r += t.charCodeAt(i) * Math.pow(e, t.length - i - 1); return r;}; r.exports = i;}, {}], 48: [function(t, r) {"use strict"; r.exports = {AVLTree: t("./data_structures/avl_tree"), BST: t("./data_structures/bst"), Treap: t("./data_structures/treap"), Graph: t("./data_structures/graph"), HashTable: t("./data_structures/hash_table"), Heap: t("./data_structures/heap"), LinkedList: t("./data_structures/linked_list"), PriorityQueue: t("./data_structures/priority_queue"), Queue: t("./data_structures/queue"), Stack: t("./data_structures/stack"), Set: t("./data_structures/set"), DisjointSetForest: t("./data_structures/disjoint_set_forest"), FenwickTree: t("./data_structures/fenwick_tree")};}, {"./data_structures/avl_tree": 49, "./data_structures/bst": 50, "./data_structures/disjoint_set_forest": 51, "./data_structures/fenwick_tree": 52, "./data_structures/graph": 53, "./data_structures/hash_table": 54, "./data_structures/heap": 55, "./data_structures/linked_list": 56, "./data_structures/priority_queue": 57, "./data_structures/queue": 58, "./data_structures/set": 59, "./data_structures/stack": 60, "./data_structures/treap": 61}], 49: [function(t, r) {"use strict"; function e() {this.root = null;} function i(t, r, e, i, n) {this.value = t, this.left = r, this.right = e, this.parent = i, this.height = n;}e.prototype.getNodeHeight = function(t) {var r = 1; return null !== t.left && null !== t.right ? r = Math.max(t.left.height, t.right.height) + 1 : null !== t.left ? r = t.left.height + 1 : null !== t.right && (r = t.right.height + 1), r;}, e.prototype.isNodeBalanced = function(t) {var r = !0; return null !== t.left && null !== t.right ? r = Math.abs(t.left.height - t.right.height) <= 1 : null !== t.right && null === t.left ? r = t.right.height < 2 : null !== t.left && null === t.right && (r = t.left.height < 2), r;}, e.prototype.getNodesToRestructureAfterRemove = function(t) {var r, e = t.length - 1, i = t[e]; null !== i.left && null !== i.right ? r = i.left === r ? i.right : i.left : null !== i.left && null === i.right ? r = i.left : null !== i.right && null === i.left && (r = i.right); var n; return null !== r.left && null !== r.right ? r.left.height > r.right.height ? n = r.left : r.left.height < r.right.height ? n = r.right : r.left.height === r.right.height && (n = i.left === r ? r.left : r.right) : null !== r.left && null === r.right ? n = r.left : null !== r.right && null === r.left && (n = r.right), [n, r, i];}, e.prototype.getNodesToRestructureAfterInsert = function(t) {var r, e = t.length - 1, i = t[e], n = t.length - 2, o = t[n]; if (null !== o.left && null !== o.right) {if (o.left.height > o.right.height)r = o.left; else if (o.left.height < o.right.height)r = o.right; else if (o.left.height === o.right.height) {var s = t.length - 3; r = t[s];}} else null !== o.left && null === o.right ? r = o.left : null !== o.right && null === o.left && (r = o.right); return [r, o, i];}, e.prototype.keepHeightBalance = function(t, r) {for (var e = t, i = []; null !== e;) {if (i.push(e), e.height = this.getNodeHeight(e), !this.isNodeBalanced(e)) {var n = r ? this.getNodesToRestructureAfterRemove(i) : this.getNodesToRestructureAfterInsert(i); this.restructure(n);}e = e.parent;}}, e.prototype.restructure = function(t) {var r = t[0], e = t[1], i = t[2]; i.right === e && e.right === r ? this.rightRight(r, e, i) : i.left === e && e.left === r ? this.leftLeft(r, e, i) : i.right === e && e.left === r ? this.rightLeft(r, e, i) : i.left === e && e.right === r && this.leftRight(r, e, i);}, e.prototype.rightRight = function(t, r, e) {if (null !== e.parent) {var i = e.parent.left === e ? "left" : "right"; e.parent[i] = r, r.parent = e.parent;} else this.root = r, r.parent = null; e.right = r.left, null !== e.right && (e.right.parent = e), r.left = e, e.parent = r, t.height = this.getNodeHeight(t), e.height = this.getNodeHeight(e), r.height = this.getNodeHeight(r);}, e.prototype.leftLeft = function(t, r, e) {if (null !== e.parent) {var i = e.parent.left === e ? "left" : "right"; e.parent[i] = r, r.parent = e.parent;} else this.root = r, r.parent = null; e.left = r.right, null !== e.left && (e.left.parent = e), r.right = e, e.parent = r, t.height = this.getNodeHeight(t), e.height = this.getNodeHeight(e), r.height = this.getNodeHeight(r);}, e.prototype.rightLeft = function(t, r, e) {if (null !== e.parent) {var i = e.parent.left === e ? "left" : "right"; e.parent[i] = t, t.parent = e.parent;} else this.root = t, t.parent = null; e.right = t.left, null !== e.right && (e.right.parent = e), r.left = t.right, null !== r.left && (r.left.parent = r), t.left = e, t.right = r, t.left.parent = t, t.right.parent = t, r.height = this.getNodeHeight(r), e.height = this.getNodeHeight(e), t.height = this.getNodeHeight(t);}, e.prototype.leftRight = function(t, r, e) {if (null !== e.parent) {var i = e.parent.left === e ? "left" : "right"; e.parent[i] = t, t.parent = e.parent;} else this.root = t, t.parent = null; e.left = t.right, null !== e.left && (e.left.parent = e), r.right = t.left, null !== r.right && (r.right.parent = r), t.right = e, t.left = r, t.left.parent = t, t.right.parent = t, r.height = this.getNodeHeight(r), e.height = this.getNodeHeight(e), t.height = this.getNodeHeight(t);}, e.prototype.insert = function(t, r) {if (null === this.root) return this.root = new i(t, null, null, null, 1), void this.keepHeightBalance(this.root); var e; r = r || this.root, e = r.value > t ? "left" : "right", r[e] ? this.insert(t, r[e]) : (r[e] = new i(t, null, null, r), this.keepHeightBalance(r[e], !1));}, e.prototype.inOrder = function(t, r) {t && (this.inOrder(t.left, r), "function" == typeof r && r(t), this.inOrder(t.right, r));}, e.prototype.postOrder = function(t, r) {t && (this.postOrder(t.left, r), this.postOrder(t.right, r), "function" == typeof r && r(t));}, e.prototype.preOrder = function(t, r) {t && ("function" == typeof r && r(t), this.preOrder(t.left, r), this.preOrder(t.right, r));}, e.prototype.find = function(t) {return this._find(t, this.root);}, e.prototype._find = function(t, r) {if (!r) return null; var e; return r.value === t ? e = r : r.value > t ? e = this._find(t, r.left) : r.value < t && (e = this._find(t, r.right)), e;}, e.prototype.replaceChild = function(t, r, e) {null === t ? (this.root = e, null !== this.root && (this.root.parent = null)) : (t.left === r ? t.left = e : t.right = e, e && (e.parent = t));}, e.prototype.remove = function(t) {var r = this.find(t); if (!r) return !1; if (r.left && r.right) {var e = this.findMin(r.right), i = r.value; return r.value = e.value, e.value = i, this.remove(e);} return r.left ? (this.replaceChild(r.parent, r, r.left), this.keepHeightBalance(r.left, !0)) : r.right ? (this.replaceChild(r.parent, r, r.right), this.keepHeightBalance(r.right, !0)) : (this.replaceChild(r.parent, r, null), this.keepHeightBalance(r.parent, !0)), !0;}, e.prototype._findMin = function(t, r) {return r = r || {value: 1 / 0}, t ? (r.value > t.value && (r = t), this._findMin(t.left, r)) : r;}, e.prototype._findMax = function(t, r) {return r = r || {value: -(1 / 0)}, t ? (r.value < t.value && (r = t), this._findMax(t.right, r)) : r;}, e.prototype.findMin = function() {return this._findMin(this.root);}, e.prototype.findMax = function() {return this._findMax(this.root);}, e.prototype.isTreeBalanced = function() {var t = this.root; return t ? this._isBalanced(t._left) && this._isBalanced(t._right) && Math.abs(this._getNodeHeight(t._left) - this._getNodeHeight(t._right)) <= 1 : !0;}, e.prototype.getTreeHeight = function() {var t = this.root; return t ? 1 + Math.max(this.getNodeHeight(t._left), this._getNodeHeight(t._right)) : 0;}, r.exports = e;}, {}], 50: [function(t, r) {"use strict"; function e(t) {this.root = null, this._size = 0, this._comparator = new n(t), Object.defineProperty(this, "size", {get: function() {return this._size;}.bind(this)});} function i(t, r) {this.value = t, this.parent = r, this.left = null, this.right = null;} var n = t("../util/comparator"); e.prototype.insert = function(t, r) {if (!r) {if (!this.root) return this.root = new i(t), void this._size++; r = this.root;} var e = this._comparator.lessThan(t, r.value) ? "left" : "right"; r[e] ? this.insert(t, r[e]) : (r[e] = new i(t, r), this._size++);}, e.prototype.contains = function(t) {return !!this._find(t);}, e.prototype._find = function(t, r) {if (!r) {if (!this.root) return !1; r = this.root;} return r.value === t ? r : this._comparator.lessThan(t, r.value) ? r.left && this._find(t, r.left) : this._comparator.greaterThan(t, r.value) ? r.right && this._find(t, r.right) : void 0;}, e.prototype._replaceNodeInParent = function(t, r) {var e = t.parent; e ? (e[t === e.left ? "left" : "right"] = r, r && (r.parent = e)) : this.root = r;}, e.prototype._findMin = function(t) {for (var r = t; r.left;)r = r.left; return r;}, e.prototype.remove = function(t) {var r = this._find(t); if (!r) throw new Error("Item not found in the tree"); if (r.left && r.right) {var e = this._findMin(r.right); this.remove(e.value), r.value = e.value;} else this._replaceNodeInParent(r, r.left || r.right), this._size--;}, r.exports = e;}, {"../util/comparator": 69}], 51: [function(t, r) {"use strict"; function e() {this._parents = {}, this._ranks = {}, this._sizes = {};}e.prototype._introduce = function(t) {t in this._parents || (this._parents[t] = t, this._ranks[t] = 0, this._sizes[t] = 1);}, e.prototype.sameSubset = function(t) {this._introduce(t); var r = this.root(t); return [].slice.call(arguments, 1).every(function(t) {return this._introduce(t), this.root(t) === r;}.bind(this));}, e.prototype.root = function(t) {return this._introduce(t), this._parents[t] !== t && (this._parents[t] = this.root(this._parents[t])), this._parents[t];}, e.prototype.size = function(t) {return this._introduce(t), this._sizes[this.root(t)];}, e.prototype.merge = function t(r, e) {arguments.length > 2 && t.apply(this, [].slice.call(arguments, 1)), this._introduce(r), this._introduce(e); var i = this.root(r), n = this.root(e); return this._ranks[i] < this._ranks[n] ? (this._parents[i] = n, this._sizes[n] += this._sizes[i]) : i !== n && (this._parents[n] = i, this._sizes[i] += this._sizes[n], this._ranks[i] === this._ranks[n] && (this._ranks[i] += 1)), this;}, r.exports = e;}, {}], 52: [function(t, r) {"use strict"; function e(t) {this._elements = new Array(t + 1); for (var r = 0; r < this._elements.length; r++) this._elements[r] = 0;}e.prototype.adjust = function(t, r) {for (;t < this._elements.length; t += t & -t) this._elements[t] += r;}, e.prototype.prefixSum = function(t) {for (var r = 0; t > 0; t -= t & -t)r += this._elements[t]; return r;}, e.prototype.rangeSum = function(t, r) {return this.prefixSum(r) - this.prefixSum(t - 1);}, r.exports = e;}, {}], 53: [function(t, r) {"use strict"; function e(t) {this.directed = void 0 === t ? !0 : !!t, this.adjList = Object.create(null), this.vertices = new i;} var i = t("./set"), n = function(t) {return "" + t;}; e.prototype.addVertex = function(t) {if (t = n(t), this.vertices.contains(t)) throw new Error('Vertex "' + t + '" has already been added'); this.vertices.add(t), this.adjList[t] = Object.create(null);}, e.prototype.addEdge = function(t, r, e) {t = n(t), r = n(r), e = void 0 === e ? 1 : e, this.adjList[t] || this.addVertex(t), this.adjList[r] || this.addVertex(r), this.adjList[t][r] = (this.adjList[t][r] || 0) + e, this.directed || (this.adjList[r][t] = (this.adjList[r][t] || 0) + e);}, e.prototype.neighbors = function(t) {return Object.keys(this.adjList[n(t)]);}, e.prototype.edge = function(t, r) {return this.adjList[n(t)][n(r)];}, r.exports = e;}, {"./set": 59}], 54: [function(t, r) {"use strict"; function e(t) {this._table = new Array(t || 64), this._items = 0, Object.defineProperty(this, "capacity", {get: function() {return this._table.length;}}), Object.defineProperty(this, "size", {get: function() {return this._items;}});} var i = t("./linked_list"); e.prototype.hash = function(t) {"string" != typeof t && (t = JSON.stringify(t)); for (var r = 0, e = 0; e < t.length; e++)r = (r << 5) - r + t.charCodeAt(e), r &= r; return r;}, e.prototype.get = function(t) {var r, e = this._position(t); return (r = this._findInList(this._table[e], t)) ? r.value.v : void 0;}, e.prototype.put = function(t, r) {var e = this._position(t); this._table[e] || (this._table[e] = new i); var n = {k: t, v: r}, o = this._findInList(this._table[e], t); o ? o.value = n : (this._table[e].add(n), this._items++, this._items === this.capacity && this._increaseCapacity());}, e.prototype.del = function(t) {var r, e = this._position(t); (r = this._findInList(this._table[e], t)) && (this._table[e].delNode(r), this._items--);}, e.prototype._position = function(t) {return Math.abs(this.hash(t)) % this.capacity;}, e.prototype._findInList = function(t, r) {for (var e = t && t.head; e;) {if (e.value.k === r) return e; e = e.next;}}, e.prototype._increaseCapacity = function() {var t = this._table; this._table = new Array(2 * this.capacity), this._items = 0; for (var r = 0; r < t.length; r++) for (var e = t[r] && t[r].head; e;) this.put(e.value.k, e.value.v), e = e.next;}, e.prototype.forEach = function(t) {for (var r = function(r) {r.forEach(function(r) {t(r.k, r.v);});}, e = 0; e < this._table.length; e++) this._table[e] && r(this._table[e]);}, r.exports = e;}, {"./linked_list": 56}], 55: [function(t, r) {"use strict"; function e(t) {this._elements = [null], this._comparator = new n(t), Object.defineProperty(this, "n", {get: function() {return this._elements.length - 1;}.bind(this)});} function i(t) {e.call(this, t), this._comparator.reverse();} var n = t("../util/comparator"); e.prototype._swap = function(t, r) {var e = this._elements[t]; this._elements[t] = this._elements[r], this._elements[r] = e;}, e.prototype.isEmpty = function() {return 0 === this.n;}, e.prototype.insert = function(t) {this._elements.push(t), this._siftUp();}, e.prototype.extract = function() {var t = this._elements[1], r = this._elements.pop(); return this.n && (this._elements[1] = r, this._siftDown()), t;}, e.prototype._siftUp = function() {var t, r; for (t = this.n; t > 1 && (r = t >> 1) && this._comparator.greaterThan(this._elements[r], this._elements[t]); t = r) this._swap(r, t); +}, e.prototype._siftDown = function(t) {var r; for (t = t || 1; (r = t << 1) <= this.n && (r + 1 <= this.n && this._comparator.lessThan(this._elements[r + 1], this._elements[r]) && r++, !this._comparator.lessThan(this._elements[t], this._elements[r])); t = r) this._swap(t, r);}, e.prototype.heapify = function(t) {t && (this._elements = t, this._elements.unshift(null)); for (var r = this.n >> 1; r > 0; r--) this._siftDown(r);}, e.prototype.forEach = function(t) {var r, e = []; for (r = 0; r < this._elements.length; r++)e.push(this._elements[r]); for (r = this.n; r > 0; r--)t(this.extract()); this._elements = e;}, i.prototype = new e, r.exports = {MinHeap: e, MaxHeap: i};}, {"../util/comparator": 69}], 56: [function(t, r) {"use strict"; function e() {this._length = 0, this.head = null, this.tail = null, Object.defineProperty(this, "length", {get: function() {return this._length;}.bind(this)});} function i(t) {this.value = t, this.prev = null, this.next = null;}e.prototype.isEmpty = function() {return 0 === this.length;}, e.prototype.add = function(t, r) {if (r > this.length || 0 > r) throw new Error("Index out of bounds"); var e = new i(t); if (void 0 !== r && r < this.length) {var n, o; 0 === r ? (o = this.head, this.head = e) : (o = this.getNode(r), n = o.prev, n.next = e, e.prev = n), o.prev = e, e.next = o;} else this.head || (this.head = e), this.tail && (this.tail.next = e, e.prev = this.tail), this.tail = e; this._length++;}, e.prototype.get = function(t) {return this.getNode(t).value;}, e.prototype.getNode = function(t) {if (t >= this.length || 0 > t) throw new Error("Index out of bounds"); for (var r = this.head, e = 1; t >= e; e++)r = r.next; return r;}, e.prototype.del = function(t) {if (t >= this.length || 0 > t) throw new Error("Index out of bounds"); this.delNode(this.getNode(t));}, e.prototype.delNode = function(t) {t === this.tail ? this.tail = t.prev : t.next.prev = t.prev, t === this.head ? this.head = t.next : t.prev.next = t.next, this._length--;}, e.prototype.forEach = function(t) {for (var r = this.head; r;)t(r.value), r = r.next;}, r.exports = e;}, {}], 57: [function(t, r) {"use strict"; function e(t) {var r = this; i.call(this, function(t, e) {return r.priority(t) < r.priority(e) ? -1 : 1;}), this._priority = {}, t = t || {}, Object.keys(t).forEach(function(e) {r.insert(e, t[e]);});} var i = t("./heap").MinHeap; e.prototype = new i, e.prototype.insert = function(t, r) {return void 0 !== this._priority[t] ? this.changePriority(t, r) : (this._priority[t] = r, void i.prototype.insert.call(this, t));}, e.prototype.extract = function(t) {var r = i.prototype.extract.call(this); return t ? r && {item: r, priority: this._priority[r]} : r;}, e.prototype.priority = function(t) {return this._priority[t];}, e.prototype.changePriority = function(t, r) {this._priority[t] = r, this.heapify();}, r.exports = e;}, {"./heap": 55}], 58: [function(t, r) {"use strict"; function e() {this._elements = new i, Object.defineProperty(this, "length", {get: function() {return this._elements.length;}.bind(this)});} var i = t("./linked_list"); e.prototype.isEmpty = function() {return this._elements.isEmpty();}, e.prototype.push = function(t) {this._elements.add(t);}, e.prototype.pop = function() {if (this.isEmpty()) throw new Error("Empty queue"); var t = this._elements.get(0); return this._elements.del(0), t;}, e.prototype.peek = function() {if (this.isEmpty()) throw new Error("Empty queue"); return this._elements.get(0);}, e.prototype.forEach = function(t) {this._elements.forEach(t);}, r.exports = e;}, {"./linked_list": 56}], 59: [function(t, r) {"use strict"; var e = t("./hash_table"), i = function() {this._elements = new e(arguments.length), this.add.apply(this, arguments), Object.defineProperty(this, "size", {get: function() {return this._elements.size;}});}; i.prototype.add = function() {for (var t = 0; t < arguments.length; t++) this._elements.put(arguments[t], !0); return this;}, i.prototype.remove = function() {for (var t = 0; t < arguments.length; t++) this._elements.del(arguments[t]); return this;}, i.prototype.contains = function(t) {return void 0 !== this._elements.get(t);}, i.prototype.forEach = function(t) {this._elements.forEach(t);}, r.exports = i;}, {"./hash_table": 54}], 60: [function(t, r) {"use strict"; function e() {i.call(this);} var i = t("./queue"); e.prototype = new i, e.prototype.push = function(t) {this._elements.add(t, 0);}, r.exports = e;}, {"./queue": 58}], 61: [function(t, r) {"use strict"; function e(t, r, e) {this.value = t, this.children = [r, e], this.size = 1, this.height = 1, this.key = Math.random();} function i() {this.root = null;}e.prototype.resize = function() {return this.size = (this.children[0] ? this.children[0].size : 0) + (this.children[1] ? this.children[1].size : 0) + 1, this.height = Math.max(this.children[0] ? this.children[0].height : 0, this.children[1] ? this.children[1].height : 0) + 1, this;}, e.prototype.rotate = function(t) {var r = this.children[t]; return this.children[t] = r.children[1 - t], r.children[1 - t] = this, this.resize(), r.resize(), r;}, i.prototype._insert = function(t, r) {if (null === t) return new e(r, null, null); var i = ~~(r > t.value); return t.children[i] = this._insert(t.children[i], r), t.children[i].key < t.key ? t.rotate(i) : t.resize();}, i.prototype._find = function(t, r) {if (null === t) return !1; if (t.value === r) return !0; var e = ~~(r > t.value); return this._find(t.children[e], r);}, i.prototype._minimum = function(t) {return null === t ? 1 / 0 : Math.min(t.value, this._minimum(t.children[0]));}, i.prototype._maximum = function(t) {return null === t ? -(1 / 0) : Math.max(t.value, this._maximum(t.children[1]));}, i.prototype._remove = function(t, r) {if (null === t) return null; var e; return t.value === r ? null === t.children[0] && null === t.children[1] ? null : (e = null === t.children[0] ? 1 : 0, t = t.rotate(e), t.children[1 - e] = this._remove(t.children[1 - e], r), t.resize()) : (e = ~~(r > t.value), t.children[e] = this._remove(t.children[e], r), t.resize());}, i.prototype.insert = function(t) {this.root = this._insert(this.root, t);}, i.prototype.find = function(t) {return this._find(this.root, t);}, i.prototype.minimum = function() {return this._minimum(this.root);}, i.prototype.maximum = function() {return this._maximum(this.root);}, i.prototype.remove = function(t) {this.root = this._remove(this.root, t);}, i.prototype.size = function() {return this.root ? this.root.size : 0;}, i.prototype.height = function() {return this.root ? this.root.height : 0;}, r.exports = i;}, {}], 62: [function(t, r) {"use strict"; r.exports = {BezierCurve: t("./algorithms/geometry/bezier_curve")};}, {"./algorithms/geometry/bezier_curve": 1}], 63: [function(t, r) {"use strict"; r.exports = {topologicalSort: t("./algorithms/graph/topological_sort"), dijkstra: t("./algorithms/graph/dijkstra"), SPFA: t("./algorithms/graph/SPFA"), bellmanFord: t("./algorithms/graph/bellman_ford"), eulerPath: t("./algorithms/graph/euler_path"), depthFirstSearch: t("./algorithms/graph/depth_first_search"), kruskal: t("./algorithms/graph/kruskal"), breadthFirstSearch: t("./algorithms/graph/breadth_first_search"), bfsShortestPath: t("./algorithms/graph/bfs_shortest_path"), prim: t("./algorithms/graph/prim"), floydWarshall: t("./algorithms/graph/floyd_warshall")};}, {"./algorithms/graph/SPFA": 2, "./algorithms/graph/bellman_ford": 3, "./algorithms/graph/bfs_shortest_path": 4, "./algorithms/graph/breadth_first_search": 5, "./algorithms/graph/depth_first_search": 6, "./algorithms/graph/dijkstra": 7, "./algorithms/graph/euler_path": 8, "./algorithms/graph/floyd_warshall": 9, "./algorithms/graph/kruskal": 10, "./algorithms/graph/prim": 11, "./algorithms/graph/topological_sort": 12}], 64: [function(t, r) {"use strict"; var e = {DataStructures: t("./data_structures"), Graph: t("./graph"), Geometry: t("./geometry"), Math: t("./math"), Search: t("./search"), Sorting: t("./sorting"), String: t("./string")}; r.exports = e;}, {"./data_structures": 48, "./geometry": 62, "./graph": 63, "./math": 65, "./search": 66, "./sorting": 67, "./string": 68}], 65: [function(t, r) {"use strict"; r.exports = {fibonacci: t("./algorithms/math/fibonacci"), fisherYates: t("./algorithms/math/fisher_yates"), gcd: t("./algorithms/math/gcd"), extendedEuclidean: t("./algorithms/math/extended_euclidean"), lcm: t("./algorithms/math/lcm"), newtonSqrt: t("./algorithms/math/newton_sqrt"), primalityTests: t("./algorithms/math/primality_tests"), reservoirSampling: t("./algorithms/math/reservoir_sampling"), fastPower: t("./algorithms/math/fast_power"), nextPermutation: t("./algorithms/math/next_permutation"), powerSet: t("./algorithms/math/power_set"), shannonEntropy: t("./algorithms/math/shannon_entropy"), collatzConjecture: t("./algorithms/math/collatz_conjecture"), greatestDifference: t("./algorithms/math/greatest_difference")};}, {"./algorithms/math/collatz_conjecture": 13, "./algorithms/math/extended_euclidean": 14, "./algorithms/math/fast_power": 15, "./algorithms/math/fibonacci": 16, "./algorithms/math/fisher_yates": 17, "./algorithms/math/gcd": 18, "./algorithms/math/greatest_difference": 19, "./algorithms/math/lcm": 20, "./algorithms/math/newton_sqrt": 21, "./algorithms/math/next_permutation": 22, "./algorithms/math/power_set": 23, "./algorithms/math/primality_tests": 24, "./algorithms/math/reservoir_sampling": 25, "./algorithms/math/shannon_entropy": 26}], 66: [function(t, r) {"use strict"; r.exports = {bfs: t("./algorithms/search/bfs"), binarySearch: t("./algorithms/search/binarysearch"), ternarySearch: t("./algorithms/search/ternary_search"), dfs: t("./algorithms/search/dfs")};}, {"./algorithms/search/bfs": 27, "./algorithms/search/binarysearch": 28, "./algorithms/search/dfs": 29, "./algorithms/search/ternary_search": 30}], 67: [function(t, r) {"use strict"; r.exports = {bubbleSort: t("./algorithms/sorting/bubble_sort"), shortBubbleSort: t("./algorithms/sorting/short_bubble_sort"), countingSort: t("./algorithms/sorting/counting_sort"), heapSort: t("./algorithms/sorting/heap_sort"), mergeSort: t("./algorithms/sorting/merge_sort"), quicksort: t("./algorithms/sorting/quicksort"), selectionSort: t("./algorithms/sorting/selection_sort"), radixSort: t("./algorithms/sorting/radix_sort"), insertionSort: t("./algorithms/sorting/insertion_sort"), shellSort: t("./algorithms/sorting/shell_sort")};}, {"./algorithms/sorting/bubble_sort": 31, "./algorithms/sorting/counting_sort": 32, "./algorithms/sorting/heap_sort": 33, "./algorithms/sorting/insertion_sort": 34, "./algorithms/sorting/merge_sort": 35, "./algorithms/sorting/quicksort": 36, "./algorithms/sorting/radix_sort": 37, "./algorithms/sorting/selection_sort": 38, "./algorithms/sorting/shell_sort": 39, "./algorithms/sorting/short_bubble_sort": 40}], 68: [function(t, r) {"use strict"; r.exports = {levenshtein: t("./algorithms/string/levenshtein"), rabinKarp: t("./algorithms/string/rabin_karp"), knuthMorrisPratt: t("./algorithms/string/knuth_morris_pratt"), huffman: t("./algorithms/string/huffman"), hamming: t("./algorithms/string/hamming"), longestCommonSubsequence: t("./algorithms/string/longest_common_subsequence"), longestCommonSubstring: t("./algorithms/string/longest_common_substring")};}, {"./algorithms/string/hamming": 41, "./algorithms/string/huffman": 42, "./algorithms/string/knuth_morris_pratt": 43, "./algorithms/string/levenshtein": 44, "./algorithms/string/longest_common_subsequence": 45, "./algorithms/string/longest_common_substring": 46, "./algorithms/string/rabin_karp": 47}], 69: [function(t, r) {"use strict"; function e(t) {t && (this.compare = t);}e.prototype.compare = function(t, r) {return t === r ? 0 : r > t ? -1 : 1;}, e.prototype.lessThan = function(t, r) {return this.compare(t, r) < 0;}, e.prototype.lessThanOrEqual = function(t, r) {return this.lessThan(t, r) || this.equal(t, r);}, e.prototype.greaterThan = function(t, r) {return this.compare(t, r) > 0;}, e.prototype.greaterThanOrEqual = function(t, r) {return this.greaterThan(t, r) || this.equal(t, r);}, e.prototype.equal = function(t, r) {return 0 === this.compare(t, r);}, e.prototype.reverse = function() {var t = this.compare; this.compare = function(r, e) {return t(e, r);};}, r.exports = e;}, {}]}, {}, [64])(64);});}({}, function() {return this;}()); diff --git a/package.json b/package.json index 50448ef..0aec5fc 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "dependencies": {}, "devDependencies": { "coveralls": "^2.11.4", - "eslint": "^2.8.0", + "eslint": "^2.13.1", + "eslint-config-google": "^0.6.0", "istanbul": "^0.4.0", "mocha": "^2.3.3", "pre-commit": "^1.1.2" diff --git a/src/algorithms/geometry/bezier_curve.js b/src/algorithms/geometry/bezier_curve.js index 16f4f8f..7ce28c5 100644 --- a/src/algorithms/geometry/bezier_curve.js +++ b/src/algorithms/geometry/bezier_curve.js @@ -11,17 +11,18 @@ * Generates a bezier-curve from a series of points * @param Array array of control points ([{x: x0, y: y0}, {x: x1, y: y1}]) */ -var BezierCurve = function (points) { +var BezierCurve = function(points) { this.n = points.length; this.p = []; // The binomial coefficient var c = [1]; - var i, j; + var i; + var j; for (i = 1; i < this.n; ++i) { c.push(0); for (j = i; j >= 1; --j) { - c[j] += c[j - 1]; + c[j] += c[j - 1]; } } @@ -34,10 +35,11 @@ var BezierCurve = function (points) { /** * @param Number float variable from 0 to 1 */ -BezierCurve.prototype.get = function (t) { +BezierCurve.prototype.get = function(t) { var res = {x: 0, y: 0}; var i; - var a = 1, b = 1; + var a = 1; + var b = 1; // The coefficient var c = []; diff --git a/src/algorithms/graph/SPFA.js b/src/algorithms/graph/SPFA.js index c9affff..9c8c412 100644 --- a/src/algorithms/graph/SPFA.js +++ b/src/algorithms/graph/SPFA.js @@ -21,7 +21,7 @@ function spfa(graph, s) { queue[0] = s; isInQue[s] = true; cnt[s] = 1; - graph.vertices.forEach(function (v) { + graph.vertices.forEach(function(v) { if (v !== s) { distance[v] = Infinity; isInQue[v] = false; diff --git a/src/algorithms/graph/bellman_ford.js b/src/algorithms/graph/bellman_ford.js index 5d669f9..f727d4c 100644 --- a/src/algorithms/graph/bellman_ford.js +++ b/src/algorithms/graph/bellman_ford.js @@ -13,15 +13,15 @@ * the graph starting in 'startNode', or an empty object if there * exists a Negative-Weighted Cycle in the graph */ -var bellmanFord = function (graph, startNode) { +var bellmanFord = function(graph, startNode) { var minDistance = {}; var previousVertex = {}; var edges = []; var adjacencyListSize = 0; // Add all the edges from the graph to the 'edges' array - graph.vertices.forEach(function (s) { - graph.neighbors(s).forEach(function (t) { + graph.vertices.forEach(function(s) { + graph.neighbors(s).forEach(function(t) { edges.push({ source: s, target: t, diff --git a/src/algorithms/graph/bfs_shortest_path.js b/src/algorithms/graph/bfs_shortest_path.js index e583ebe..1d5c9d5 100644 --- a/src/algorithms/graph/bfs_shortest_path.js +++ b/src/algorithms/graph/bfs_shortest_path.js @@ -2,7 +2,6 @@ var breadthFirstSearch = require('./breadth_first_search'); - /** * Shortest-path algorithm based on Breadth-First Search. * Works solely on graphs with equal edge weights (but works fast). @@ -13,12 +12,13 @@ var breadthFirstSearch = require('./breadth_first_search'); * @return {{distance: Object., * previous: Object.}} */ -var bfsShortestPath = function (graph, source) { - var distance = {}, previous = {}; +var bfsShortestPath = function(graph, source) { + var distance = {}; + var previous = {}; distance[source] = 0; breadthFirstSearch(graph, source, { - onTraversal: function (vertex, neighbor) { + onTraversal: function(vertex, neighbor) { distance[neighbor] = distance[vertex] + 1; previous[neighbor] = vertex; } @@ -30,5 +30,4 @@ var bfsShortestPath = function (graph, source) { }; }; - module.exports = bfsShortestPath; diff --git a/src/algorithms/graph/breadth_first_search.js b/src/algorithms/graph/breadth_first_search.js index 79c2ab3..3fc5658 100644 --- a/src/algorithms/graph/breadth_first_search.js +++ b/src/algorithms/graph/breadth_first_search.js @@ -2,7 +2,6 @@ var Queue = require('../../data_structures/queue'); - /** * @typedef {Object} Callbacks * @param {function(vertex: *, neighbor: *): boolean} allowTraversal - @@ -14,7 +13,6 @@ var Queue = require('../../data_structures/queue'); * @param {function(vertex: *)} leaveVertex - Called when BFS leaves the vertex. */ - /** * Fill in missing callbacks. * @@ -23,27 +21,25 @@ var Queue = require('../../data_structures/queue'); * used by default allowTraversal implementation. * @return {Callbacks} The same object or new one (if null passed). */ -var normalizeCallbacks = function (callbacks, seenVertices) { +var normalizeCallbacks = function(callbacks, seenVertices) { callbacks = callbacks || {}; - callbacks.allowTraversal = callbacks.allowTraversal || (function () { - var seen = seenVertices.reduce(function (seen, vertex) { + callbacks.allowTraversal = callbacks.allowTraversal || (function() { + var seen = seenVertices.reduce(function(seen, vertex) { seen[vertex] = true; return seen; }, {}); - return function (vertex, neighbor) { + return function(vertex, neighbor) { if (!seen[neighbor]) { seen[neighbor] = true; return true; } - else { - return false; - } + return false; }; })(); - var noop = function () {}; + var noop = function() {}; callbacks.onTraversal = callbacks.onTraversal || noop; callbacks.enterVertex = callbacks.enterVertex || noop; callbacks.leaveVertex = callbacks.leaveVertex || noop; @@ -51,7 +47,6 @@ var normalizeCallbacks = function (callbacks, seenVertices) { return callbacks; }; - /** * Run Breadth-First Search from a start vertex. * Complexity (default implementation): O(V + E). @@ -60,13 +55,13 @@ var normalizeCallbacks = function (callbacks, seenVertices) { * @param {*} startVertex * @param {Callbacks} [callbacks] */ -var breadthFirstSearch = function (graph, startVertex, callbacks) { +var breadthFirstSearch = function(graph, startVertex, callbacks) { var vertexQueue = new Queue(); vertexQueue.push(startVertex); callbacks = normalizeCallbacks(callbacks, [startVertex]); var vertex; - var enqueue = function (neighbor) { + var enqueue = function(neighbor) { if (callbacks.allowTraversal(vertex, neighbor)) { callbacks.onTraversal(vertex, neighbor); vertexQueue.push(neighbor); @@ -81,5 +76,4 @@ var breadthFirstSearch = function (graph, startVertex, callbacks) { } }; - module.exports = breadthFirstSearch; diff --git a/src/algorithms/graph/depth_first_search.js b/src/algorithms/graph/depth_first_search.js index 1adc30d..8ebd242 100644 --- a/src/algorithms/graph/depth_first_search.js +++ b/src/algorithms/graph/depth_first_search.js @@ -1,6 +1,5 @@ 'use strict'; - /** * @typedef {Object} Callbacks * @param {function(vertex: *, neighbor: *): boolean} allowTraversal - @@ -14,7 +13,6 @@ * @param {function(vertex: *)} leaveVertex - Called when DFS leaves the vertex. */ - /** * Fill in missing callbacks. * @param {Callbacks} callbacks @@ -22,16 +20,16 @@ * used by default allowTraversal implementation. * @return {Callbacks} The same object or new one (if null passed). */ -var normalizeCallbacks = function (callbacks, seenVertices) { +var normalizeCallbacks = function(callbacks, seenVertices) { callbacks = callbacks || {}; - callbacks.allowTraversal = callbacks.allowTraversal || (function () { + callbacks.allowTraversal = callbacks.allowTraversal || (function() { var seen = {}; - seenVertices.forEach(function (vertex) { + seenVertices.forEach(function(vertex) { seen[vertex] = true; }); - return function (vertex, neighbor) { + return function(vertex, neighbor) { // It should still be possible to redefine other callbacks, // so we better do all at once here. @@ -43,7 +41,7 @@ var normalizeCallbacks = function (callbacks, seenVertices) { }; })(); - var noop = function () {}; + var noop = function() {}; callbacks.beforeTraversal = callbacks.beforeTraversal || noop; callbacks.afterTraversal = callbacks.afterTraversal || noop; callbacks.enterVertex = callbacks.enterVertex || noop; @@ -52,24 +50,10 @@ var normalizeCallbacks = function (callbacks, seenVertices) { return callbacks; }; - -/** - * Run Depth-First Search from a start vertex. - * Complexity (default implementation): O(V + E). - * - * @param {Graph} graph - * @param {*} startVertex - * @param {Callbacks} [callbacks] - */ -var depthFirstSearch = function (graph, startVertex, callbacks) { - dfsLoop(graph, startVertex, normalizeCallbacks(callbacks, [startVertex])); -}; - - var dfsLoop = function dfsLoop(graph, vertex, callbacks) { callbacks.enterVertex(vertex); - graph.neighbors(vertex).forEach(function (neighbor) { + graph.neighbors(vertex).forEach(function(neighbor) { if (callbacks.allowTraversal(vertex, neighbor)) { callbacks.beforeTraversal(vertex, neighbor); dfsLoop(graph, neighbor, callbacks); @@ -80,5 +64,16 @@ var dfsLoop = function dfsLoop(graph, vertex, callbacks) { callbacks.leaveVertex(vertex); }; +/** + * Run Depth-First Search from a start vertex. + * Complexity (default implementation): O(V + E). + * + * @param {Graph} graph + * @param {*} startVertex + * @param {Callbacks} [callbacks] + */ +var depthFirstSearch = function(graph, startVertex, callbacks) { + dfsLoop(graph, startVertex, normalizeCallbacks(callbacks, [startVertex])); +}; module.exports = depthFirstSearch; diff --git a/src/algorithms/graph/dijkstra.js b/src/algorithms/graph/dijkstra.js index da08795..845c3e7 100644 --- a/src/algorithms/graph/dijkstra.js +++ b/src/algorithms/graph/dijkstra.js @@ -16,7 +16,7 @@ function dijkstra(graph, s) { var q = new PriorityQueue(); // Initialize distance[s] = 0; - graph.vertices.forEach(function (v) { + graph.vertices.forEach(function(v) { if (v !== s) { distance[v] = Infinity; } @@ -24,7 +24,7 @@ function dijkstra(graph, s) { }); var currNode; - var relax = function (v) { + var relax = function(v) { var newDistance = distance[currNode] + graph.edge(currNode, v); if (newDistance < distance[v]) { distance[v] = newDistance; diff --git a/src/algorithms/graph/euler_path.js b/src/algorithms/graph/euler_path.js index d33c9b0..75bdd40 100644 --- a/src/algorithms/graph/euler_path.js +++ b/src/algorithms/graph/euler_path.js @@ -1,9 +1,7 @@ 'use strict'; - -var Graph = require('../../data_structures/graph'), - depthFirstSearch = require('../../algorithms/graph/depth_first_search'); - +var Graph = require('../../data_structures/graph'); +var depthFirstSearch = require('../../algorithms/graph/depth_first_search'); /** Examine a graph and compute pair of end vertices of the existing Euler path. * Return pair of undefined values if there is no specific choice of end points. @@ -12,29 +10,28 @@ var Graph = require('../../data_structures/graph'), * @param {Graph} Graph, must be connected and contain at least one vertex. * @return Object */ -var eulerEndpoints = function (graph) { +var eulerEndpoints = function(graph) { var rank = {}; // start -> rank = +1 // middle points -> rank = 0 // finish -> rank = -1 // Initialize ranks to be outdegrees of vertices. - graph.vertices.forEach(function (vertex) { + graph.vertices.forEach(function(vertex) { rank[vertex] = graph.neighbors(vertex).length; }); if (graph.directed) { // rank = outdegree - indegree - graph.vertices.forEach(function (vertex) { - graph.neighbors(vertex).forEach(function (neighbor) { + graph.vertices.forEach(function(vertex) { + graph.neighbors(vertex).forEach(function(neighbor) { rank[neighbor] -= 1; }); }); - } - else { + } else { // Compute ranks from vertex degree parity values. var startChosen = false; - graph.vertices.forEach(function (vertex) { + graph.vertices.forEach(function(vertex) { rank[vertex] %= 2; if (rank[vertex]) { if (startChosen) { @@ -45,9 +42,11 @@ var eulerEndpoints = function (graph) { }); } - var start, finish, v; + var start; + var finish; + var v; - graph.vertices.forEach(function (vertex) { + graph.vertices.forEach(function(vertex) { if (rank[vertex] === 1) { if (start) { throw new Error('Duplicate start vertex.'); @@ -73,7 +72,6 @@ var eulerEndpoints = function (graph) { finish: finish}; }; - /** * Compute Euler path (either walk or tour, depending on the graph). * Euler path is a trail in a graph which visits every edge exactly once. @@ -84,7 +82,7 @@ var eulerEndpoints = function (graph) { * @param {Graph} * @return Array */ -var eulerPath = function (graph) { +var eulerPath = function(graph) { if (!graph.vertices.size) { return []; } @@ -96,18 +94,18 @@ var eulerPath = function (graph) { graph.vertices.forEach(seen.addVertex.bind(seen)); depthFirstSearch(graph, endpoints.start, { - allowTraversal: function (vertex, neighbor) { + allowTraversal: function(vertex, neighbor) { return !seen.edge(vertex, neighbor); }, - beforeTraversal: function (vertex, neighbor) { + beforeTraversal: function(vertex, neighbor) { seen.addEdge(vertex, neighbor); }, - afterTraversal: function (vertex) { + afterTraversal: function(vertex) { route.push(vertex); } }); - graph.vertices.forEach(function (vertex) { + graph.vertices.forEach(function(vertex) { if (seen.neighbors(vertex).length < graph.neighbors(vertex).length) { throw new Error('There is no euler path for a disconnected graph.'); } @@ -115,5 +113,4 @@ var eulerPath = function (graph) { return route.reverse(); }; - module.exports = eulerPath; diff --git a/src/algorithms/graph/floyd_warshall.js b/src/algorithms/graph/floyd_warshall.js index 7fe9b74..681e0f6 100644 --- a/src/algorithms/graph/floyd_warshall.js +++ b/src/algorithms/graph/floyd_warshall.js @@ -1,6 +1,5 @@ 'use strict'; - /** * Floyd-Warshall algorithm. * Compute all-pairs shortest paths (a path for each pair of vertices). @@ -9,19 +8,18 @@ * @param {Graph} graph * @return {{distance, path}} */ -var floydWarshall = function (graph) { - +var floydWarshall = function(graph) { // Fill in the distances with initial values: // - 0 if source == destination; // - edge(source, destination) if there is a direct edge; // - +inf otherwise. var distance = Object.create(null); - graph.vertices.forEach(function (src) { + graph.vertices.forEach(function(src) { distance[src] = Object.create(null); - graph.vertices.forEach(function (dest) { + graph.vertices.forEach(function(dest) { if (src === dest) { distance[src][dest] = 0; - } else if (graph.edge(src, dest) !== undefined) { + } else if (graph.edge(src, dest)) { distance[src][dest] = graph.edge(src, dest); } else { distance[src][dest] = Infinity; @@ -32,13 +30,13 @@ var floydWarshall = function (graph) { // Internal vertex with the largest index along the shortest path. // Needed for path reconstruction. var middleVertex = Object.create(null); - graph.vertices.forEach(function (vertex) { + graph.vertices.forEach(function(vertex) { middleVertex[vertex] = Object.create(null); }); - graph.vertices.forEach(function (middle) { - graph.vertices.forEach(function (src) { - graph.vertices.forEach(function (dest) { + graph.vertices.forEach(function(middle) { + graph.vertices.forEach(function(src) { + graph.vertices.forEach(function(dest) { var dist = distance[src][middle] + distance[middle][dest]; if (dist < distance[src][dest]) { distance[src][dest] = dist; @@ -49,7 +47,7 @@ var floydWarshall = function (graph) { }); // Check for a negative-weighted cycle. - graph.vertices.forEach(function (vertex) { + graph.vertices.forEach(function(vertex) { if (distance[vertex][vertex] < 0) { // Negative-weighted cycle found. throw new Error('The graph contains a negative-weighted cycle!'); @@ -64,7 +62,7 @@ var floydWarshall = function (graph) { * @param {string} dest * @return {?string[]} Null if destination is unreachable. */ - var path = function (src, dest) { + var path = function(src, dest) { if (!Number.isFinite(distance[src][dest])) { // dest unreachable. return null; @@ -93,5 +91,4 @@ var floydWarshall = function (graph) { }; }; - module.exports = floydWarshall; diff --git a/src/algorithms/graph/kruskal.js b/src/algorithms/graph/kruskal.js index 436effb..fffca9d 100644 --- a/src/algorithms/graph/kruskal.js +++ b/src/algorithms/graph/kruskal.js @@ -1,8 +1,7 @@ 'use strict'; -var DisjointSetForest = require('../../data_structures/disjoint_set_forest'), - Graph = require('../../data_structures/graph'); - +var DisjointSetForest = require('../../data_structures/disjoint_set_forest'); +var Graph = require('../../data_structures/graph'); /** * Kruskal's minimum spanning tree (forest) algorithm. @@ -12,7 +11,7 @@ var DisjointSetForest = require('../../data_structures/disjoint_set_forest'), * @return {Graph} Minimum spanning tree or forest * (depending on whether input graph is connected itself). */ -var kruskal = function (graph) { +var kruskal = function(graph) { if (graph.directed) { throw new Error('Can\'t build MST of a directed graph.'); } @@ -22,8 +21,8 @@ var kruskal = function (graph) { graph.vertices.forEach(mst.addVertex.bind(mst)); var edges = []; - graph.vertices.forEach(function (vertex) { - graph.neighbors(vertex).forEach(function (neighbor) { + graph.vertices.forEach(function(vertex) { + graph.neighbors(vertex).forEach(function(neighbor) { // Compared as strings, loops intentionally omitted. if (vertex < neighbor) { edges.push({ @@ -34,9 +33,9 @@ var kruskal = function (graph) { }); }); - edges.sort(function (a, b) { + edges.sort(function(a, b) { return a.weight - b.weight; - }).forEach(function (edge) { + }).forEach(function(edge) { if (!connectedComponents.sameSubset(edge.ends[0], edge.ends[1])) { mst.addEdge(edge.ends[0], edge.ends[1], edge.weight); connectedComponents.merge(edge.ends[0], edge.ends[1]); @@ -46,5 +45,4 @@ var kruskal = function (graph) { return mst; }; - module.exports = kruskal; diff --git a/src/algorithms/graph/prim.js b/src/algorithms/graph/prim.js index dac9aad..26c2386 100644 --- a/src/algorithms/graph/prim.js +++ b/src/algorithms/graph/prim.js @@ -1,8 +1,7 @@ 'use strict'; -var PriorityQueue = require('../../data_structures/priority_queue'), - Graph = require('../../data_structures/graph'); - +var PriorityQueue = require('../../data_structures/priority_queue'); +var Graph = require('../../data_structures/graph'); /** * Prim's minimum spanning tree (forest) algorithm. @@ -12,7 +11,7 @@ var PriorityQueue = require('../../data_structures/priority_queue'), * @return {Graph} Minimum spanning tree or forest * (depending on whether input graph is connected itself). */ -var prim = function (graph) { +var prim = function(graph) { if (graph.directed) { throw new Error('Can\'t build MST of a directed graph.'); } @@ -21,11 +20,11 @@ var prim = function (graph) { var parent = Object.create(null); var q = new PriorityQueue(); - graph.vertices.forEach(function (vertex) { + graph.vertices.forEach(function(vertex) { q.insert(vertex, Infinity); }); - var relax = function (vertex, neighbor) { + var relax = function(vertex, neighbor) { var weight = graph.edge(vertex, neighbor); if (weight < q.priority(neighbor)) { q.changePriority(neighbor, weight); @@ -35,13 +34,12 @@ var prim = function (graph) { while (!q.isEmpty()) { var top = q.extract(true); - var vertex = top.item, - weight = top.priority; + var vertex = top.item; + var weight = top.priority; if (parent[vertex]) { mst.addEdge(parent[vertex], vertex, weight); - } - else { + } else { mst.addVertex(vertex); } @@ -51,5 +49,4 @@ var prim = function (graph) { return mst; }; - module.exports = prim; diff --git a/src/algorithms/graph/topological_sort.js b/src/algorithms/graph/topological_sort.js index 0d4176f..588f8d8 100644 --- a/src/algorithms/graph/topological_sort.js +++ b/src/algorithms/graph/topological_sort.js @@ -1,7 +1,7 @@ 'use strict'; -var Stack = require('../../data_structures/stack'), - depthFirstSearch = require('../../algorithms/graph/depth_first_search'); +var Stack = require('../../data_structures/stack'); +var depthFirstSearch = require('../../algorithms/graph/depth_first_search'); /** * Sorts the edges of the DAG topologically @@ -17,21 +17,21 @@ var Stack = require('../../data_structures/stack'), * @param {Graph} * @return Stack */ -var topologicalSort = function (graph) { +var topologicalSort = function(graph) { var stack = new Stack(); var firstHit = {}; var time = 0; - graph.vertices.forEach(function (node) { + graph.vertices.forEach(function(node) { if (!firstHit[node]) { depthFirstSearch(graph, node, { - allowTraversal: function (node, neighbor) { + allowTraversal: function(node, neighbor) { return !firstHit[neighbor]; }, - enterVertex: function (node) { + enterVertex: function(node) { firstHit[node] = ++time; }, - leaveVertex: function (node) { + leaveVertex: function(node) { stack.push(node); } }); diff --git a/src/algorithms/math/collatz_conjecture.js b/src/algorithms/math/collatz_conjecture.js index 303bb21..4391f10 100644 --- a/src/algorithms/math/collatz_conjecture.js +++ b/src/algorithms/math/collatz_conjecture.js @@ -9,12 +9,13 @@ var cache = {1: 1}; * @param Number * @return Number */ - function calculateCollatzConjecture(number) { - if (number in cache) return cache[number]; - if (number % 2 === 0) return cache[number] = number >> 1; + if (!(number in cache)) { + if (number % 2 === 0) cache[number] = number >> 1; + else cache[number] = number * 3 + 1; + } - return cache[number] = number * 3 + 1; + return cache[number]; } /** @@ -23,7 +24,6 @@ function calculateCollatzConjecture(number) { * @param Number * @return Array */ - function generateCollatzConjecture(number) { var collatzConjecture = []; @@ -38,5 +38,5 @@ function generateCollatzConjecture(number) { // export Collatz Conjecture methods module.exports = { generate: generateCollatzConjecture, - calculate: calculateCollatzConjecture, + calculate: calculateCollatzConjecture }; diff --git a/src/algorithms/math/extended_euclidean.js b/src/algorithms/math/extended_euclidean.js index 4cfb5f2..1b1f1ff 100644 --- a/src/algorithms/math/extended_euclidean.js +++ b/src/algorithms/math/extended_euclidean.js @@ -10,11 +10,15 @@ * * @return {Number, Number} */ -var extEuclid = function (a, b) { - var s = 0, oldS = 1; - var t = 1, oldT = 0; - var r = b, oldR = a; - var quotient, temp; +var extEuclid = function(a, b) { + var s = 0; + var oldS = 1; + var t = 1; + var oldT = 0; + var r = b; + var oldR = a; + var quotient; + var temp; while (r !== 0) { quotient = Math.floor(oldR / r); diff --git a/src/algorithms/math/fast_power.js b/src/algorithms/math/fast_power.js index ce5bbcc..f5c3454 100644 --- a/src/algorithms/math/fast_power.js +++ b/src/algorithms/math/fast_power.js @@ -1,11 +1,9 @@ 'use strict'; - -var multiplicationOperator = function (a, b) { +var multiplicationOperator = function(a, b) { return a * b; }; - /** * Raise value to a positive integer power by repeated squaring. * @@ -17,7 +15,7 @@ var multiplicationOperator = function (a, b) { * If mul is not set, defaults to 1. * @return {*} */ -var fastPower = function (base, power, mul, identity) { +var fastPower = function(base, power, mul, identity) { if (mul === undefined) { mul = multiplicationOperator; identity = 1; @@ -31,14 +29,12 @@ var fastPower = function (base, power, mul, identity) { if (identity === undefined) { throw new Error('The power is zero, but identity value not set.'); } - else { - return identity; - } + return identity; } // Iterative form of the algorithm avoids checking the same thing twice. var result; - var multiplyBy = function (value) { + var multiplyBy = function(value) { result = (result === undefined) ? value : mul(result, value); }; for (var factor = base; power; power >>>= 1, factor = mul(factor, factor)) { @@ -49,5 +45,4 @@ var fastPower = function (base, power, mul, identity) { return result; }; - module.exports = fastPower; diff --git a/src/algorithms/math/fibonacci.js b/src/algorithms/math/fibonacci.js index fe7abf1..06485f8 100644 --- a/src/algorithms/math/fibonacci.js +++ b/src/algorithms/math/fibonacci.js @@ -15,7 +15,7 @@ var power = require('./fast_power'); * @param Number * @return Number */ -var fibExponential = function (n) { +var fibExponential = function(n) { return n < 2 ? n : fibExponential(n - 1) + fibExponential(n - 2); }; @@ -25,10 +25,10 @@ var fibExponential = function (n) { * @param Number * @return Number */ -var fibLinear = function (n) { - var fibNMinus2 = 0, - fibNMinus1 = 1, - fib = n; +var fibLinear = function(n) { + var fibNMinus2 = 0; + var fibNMinus1 = 1; + var fib = n; for (var i = 1; i < n; i++) { fib = fibNMinus1 + fibNMinus2; fibNMinus2 = fibNMinus1; @@ -43,10 +43,10 @@ var fibLinear = function (n) { * @param Number * @return Number */ -var fibWithMemoization = (function () { +var fibWithMemoization = (function() { var cache = [0, 1]; - var fib = function (n) { + var fib = function(n) { if (cache[n] === undefined) { cache[n] = fib(n - 1) + fib(n - 2); } @@ -63,7 +63,7 @@ var fibWithMemoization = (function () { * @param Number * @return Number */ -var fibDirect = function (number) { +var fibDirect = function(number) { var phi = (1 + Math.sqrt(5)) / 2; return Math.floor(Math.pow(phi, number) / Math.sqrt(5) + 0.5); }; @@ -75,11 +75,11 @@ var fibDirect = function (number) { * @param Number * @return Number */ -var fibLogarithmic = function (number) { +var fibLogarithmic = function(number) { // Transforms [f_1, f_0] to [f_2, f_1] and so on. var nextFib = [[1, 1], [1, 0]]; - var matrixMultiply = function (a, b) { + var matrixMultiply = function(a, b) { return [[a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1]], [a[1][0] * b[0][0] + a[1][1] * b[1][0], diff --git a/src/algorithms/math/fisher_yates.js b/src/algorithms/math/fisher_yates.js index dad2828..5cf4122 100644 --- a/src/algorithms/math/fisher_yates.js +++ b/src/algorithms/math/fisher_yates.js @@ -4,7 +4,7 @@ * Fisher-Yates shuffles the elements in an array * in O(n) */ -var fisherYates = function (a) { +var fisherYates = function(a) { for (var i = a.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var tmp = a[i]; diff --git a/src/algorithms/math/gcd.js b/src/algorithms/math/gcd.js index b58cf67..08c590e 100644 --- a/src/algorithms/math/gcd.js +++ b/src/algorithms/math/gcd.js @@ -8,7 +8,7 @@ * * @return Number */ -var gcdDivisionBased = function (a, b) { +var gcdDivisionBased = function(a, b) { var tmp = a; a = Math.max(a, b); b = Math.min(tmp, b); @@ -32,8 +32,7 @@ var gcdDivisionBased = function (a, b) { * * @return Number */ -var gcdBinaryIterative = function (a, b) { - +var gcdBinaryIterative = function(a, b) { // GCD(0,b) == b; GCD(a,0) == a, GCD(0,0) == 0 if (a === 0) { return b; diff --git a/src/algorithms/math/greatest_difference.js b/src/algorithms/math/greatest_difference.js index 85b1b7b..edbf53a 100644 --- a/src/algorithms/math/greatest_difference.js +++ b/src/algorithms/math/greatest_difference.js @@ -8,7 +8,7 @@ * @returns {number} */ -var greatestDifference = function (numbers) { +var greatestDifference = function(numbers) { var index = 0; var largest = numbers[0]; var length = numbers.length; diff --git a/src/algorithms/math/lcm.js b/src/algorithms/math/lcm.js index bd29e8d..705330c 100644 --- a/src/algorithms/math/lcm.js +++ b/src/algorithms/math/lcm.js @@ -12,8 +12,8 @@ var gcd = require('./gcd.js'); * * @return Number */ -var genericLCM = function (gcdFunction, a, b) { - if (a === 0 || b === 0) { +var genericLCM = function(gcdFunction, a, b) { + if (a === 0 || b === 0) { return 0; } a = Math.abs(a); diff --git a/src/algorithms/math/newton_sqrt.js b/src/algorithms/math/newton_sqrt.js index 4113e89..c0a8612 100644 --- a/src/algorithms/math/newton_sqrt.js +++ b/src/algorithms/math/newton_sqrt.js @@ -7,7 +7,7 @@ * @param Number tolerance - The error margin accepted (Default 1e-7) * @param Number maxIterations - The max number of iterations (Default 1e7) */ -var sqrt = function (n, tolerance, maxIterations) { +var sqrt = function(n, tolerance, maxIterations) { tolerance = tolerance || 1e-7; maxIterations = maxIterations || 1e7; @@ -15,7 +15,8 @@ var sqrt = function (n, tolerance, maxIterations) { var lowerBound = 0; var i = 0; - var square, x; + var square; + var x; do { i++; x = (upperBound - lowerBound) / 2 + lowerBound; diff --git a/src/algorithms/math/next_permutation.js b/src/algorithms/math/next_permutation.js index eacdc77..be44b38 100644 --- a/src/algorithms/math/next_permutation.js +++ b/src/algorithms/math/next_permutation.js @@ -2,7 +2,6 @@ var Comparator = require('../../util/comparator'); - /** * Narayana's algorithm computes the subsequent permutation * in lexicographical order. @@ -13,7 +12,7 @@ var Comparator = require('../../util/comparator'); * @return {boolean} Boolean flag indicating whether the algorithm succeeded, * true unless the input permutation is lexicographically the last one. */ -var nextPermutation = function (array, compareFn) { +var nextPermutation = function(array, compareFn) { if (!array.length) { return false; } @@ -47,5 +46,4 @@ var nextPermutation = function (array, compareFn) { return true; }; - module.exports = nextPermutation; diff --git a/src/algorithms/math/power_set.js b/src/algorithms/math/power_set.js index 716cb32..b0b7d60 100644 --- a/src/algorithms/math/power_set.js +++ b/src/algorithms/math/power_set.js @@ -7,8 +7,7 @@ /** * Iterative power set calculation */ -var powerSetIterative = function (array) { - +var powerSetIterative = function(array) { if (array.length === 0) { return []; } @@ -22,11 +21,9 @@ var powerSetIterative = function (array) { } for (i = 0; i < Math.pow(2, array.length); i++) { - powerSet.push([]); for (var j = 0; j < array.length; j++) { - if (i % Math.pow(2, j) === 0) { cache[j] = !cache[j]; } @@ -34,7 +31,6 @@ var powerSetIterative = function (array) { if (cache[j]) { powerSet[i].push(array[j]); } - } } @@ -44,26 +40,25 @@ var powerSetIterative = function (array) { /** * Recursive power set calculation */ -var powerSetRecursive = function (array) { +var powerSetRecursive = function(array) { if (array.length === 0) { return []; } else if (array.length === 1) { - return [ [], [ array[0] ] ]; - } else { - var powerSet = []; - var firstElem = array[0]; + return [[], [array[0]]]; + } + var powerSet = []; + var firstElem = array[0]; - array.splice(0, 1); + array.splice(0, 1); - powerSetRecursive(array).forEach(function (elem) { - powerSet.push(elem); - var withFirstElem = [ firstElem ]; - withFirstElem.push.apply(withFirstElem, elem); - powerSet.push(withFirstElem); - }); + powerSetRecursive(array).forEach(function(elem) { + powerSet.push(elem); + var withFirstElem = [firstElem]; + withFirstElem.push.apply(withFirstElem, elem); + powerSet.push(withFirstElem); + }); - return powerSet; - } + return powerSet; }; // Use powerSetIterative as the default implementation diff --git a/src/algorithms/math/primality_tests.js b/src/algorithms/math/primality_tests.js index e86e796..4357f5c 100644 --- a/src/algorithms/math/primality_tests.js +++ b/src/algorithms/math/primality_tests.js @@ -8,7 +8,7 @@ * * @return Boolean */ -var genericPrimalityTest = function (primalityTest, n) { +var genericPrimalityTest = function(primalityTest, n) { if (n <= 1) { return false; } @@ -22,7 +22,7 @@ var genericPrimalityTest = function (primalityTest, n) { * * @return Boolean */ -var naiveTest = function (n) { +var naiveTest = function(n) { for (var i = 2; i < n; ++i) { if (n % i === 0) { return false; @@ -38,7 +38,7 @@ var naiveTest = function (n) { * * @return Boolean */ -var trialDivisionTest = function (n) { +var trialDivisionTest = function(n) { var sqrt = Math.sqrt(n); for (var i = 2; i <= sqrt; ++i) { if (n % i === 0) { diff --git a/src/algorithms/math/reservoir_sampling.js b/src/algorithms/math/reservoir_sampling.js index 3d7694d..b1cf343 100644 --- a/src/algorithms/math/reservoir_sampling.js +++ b/src/algorithms/math/reservoir_sampling.js @@ -1,6 +1,5 @@ 'use strict'; - /** * Sample random elements from the array using reservoir algorithm. * @@ -8,7 +7,7 @@ * @param {number} sampleSize * @return {Array} */ -var reservoirSampling = function (array, sampleSize) { +var reservoirSampling = function(array, sampleSize) { if (sampleSize > array.length) { throw new Error('Sample size exceeds the total number of elements.'); } @@ -22,5 +21,4 @@ var reservoirSampling = function (array, sampleSize) { return reservoir; }; - module.exports = reservoirSampling; diff --git a/src/algorithms/math/shannon_entropy.js b/src/algorithms/math/shannon_entropy.js index 5c42c30..20dabd2 100644 --- a/src/algorithms/math/shannon_entropy.js +++ b/src/algorithms/math/shannon_entropy.js @@ -6,20 +6,20 @@ * @param {Array} arr - An array of values. * @return Number */ -var shannonEntropy = function (arr) { +var shannonEntropy = function(arr) { // find the frequency of each value - var freqs = arr.reduce(function (acc, item) { + var freqs = arr.reduce(function(acc, item) { acc[item] = acc[item] + 1 || 1; return acc; }, {}); // find the probability of each value - var probs = Object.keys(freqs).map(function (key) { + var probs = Object.keys(freqs).map(function(key) { return freqs[key] / arr.length; }); // calulate the shannon entropy of the array - return probs.reduce(function (e, p) { + return probs.reduce(function(e, p) { return e - p * Math.log(p); }, 0) * Math.LOG2E; }; diff --git a/src/algorithms/search/bfs.js b/src/algorithms/search/bfs.js index 98bcfac..739d8d8 100644 --- a/src/algorithms/search/bfs.js +++ b/src/algorithms/search/bfs.js @@ -4,7 +4,7 @@ var Queue = require('../../data_structures/queue.js'); /** * Breadth-first search for binary trees */ -var bfs = function (root, callback) { +var bfs = function(root, callback) { var q = new Queue(); q.push(root); var node; diff --git a/src/algorithms/search/binarysearch.js b/src/algorithms/search/binarysearch.js index 132d8bd..701ca65 100644 --- a/src/algorithms/search/binarysearch.js +++ b/src/algorithms/search/binarysearch.js @@ -9,9 +9,9 @@ * * @return Boolean */ -var binarySearch = function (sortedArray, element) { - var init = 0, - end = sortedArray.length - 1; +var binarySearch = function(sortedArray, element) { + var init = 0; + var end = sortedArray.length - 1; while (end >= init) { var m = ((end - init) >> 1) + init; diff --git a/src/algorithms/search/dfs.js b/src/algorithms/search/dfs.js index f64fb1f..54e78d6 100644 --- a/src/algorithms/search/dfs.js +++ b/src/algorithms/search/dfs.js @@ -4,7 +4,7 @@ * Depth first search for trees * (in order) */ -var inOrder = function (node, callback) { +var inOrder = function(node, callback) { if (node) { inOrder(node.left, callback); callback(node.value); @@ -15,7 +15,7 @@ var inOrder = function (node, callback) { /** * Pre order */ -var preOrder = function (node, callback) { +var preOrder = function(node, callback) { if (node) { callback(node.value); preOrder(node.left, callback); @@ -26,7 +26,7 @@ var preOrder = function (node, callback) { /** * Post order */ -var postOrder = function (node, callback) { +var postOrder = function(node, callback) { if (node) { postOrder(node.left, callback); postOrder(node.right, callback); diff --git a/src/algorithms/search/ternary_search.js b/src/algorithms/search/ternary_search.js index 1f4c361..d9082d3 100644 --- a/src/algorithms/search/ternary_search.js +++ b/src/algorithms/search/ternary_search.js @@ -6,10 +6,10 @@ * Time complexity: O(log(n)) */ -var ternarySearch = function (fn, left, right, precision) { +var ternarySearch = function(fn, left, right, precision) { while (Math.abs(right - left) > precision) { - var leftThird = left + (right - left) / 3, - rightThird = right - (right - left) / 3; + var leftThird = left + (right - left) / 3; + var rightThird = right - (right - left) / 3; if (fn(leftThird) < fn(rightThird)) left = leftThird; else diff --git a/src/algorithms/sorting/bubble_sort.js b/src/algorithms/sorting/bubble_sort.js index cafad17..739b042 100644 --- a/src/algorithms/sorting/bubble_sort.js +++ b/src/algorithms/sorting/bubble_sort.js @@ -4,7 +4,7 @@ var Comparator = require('../../util/comparator'); /** * Bubble sort algorithm O(n^2) */ -var bubbleSort = function (a, comparatorFn) { +var bubbleSort = function(a, comparatorFn) { var comparator = new Comparator(comparatorFn); var n = a.length; var bound = n - 1; diff --git a/src/algorithms/sorting/counting_sort.js b/src/algorithms/sorting/counting_sort.js index 087de59..fac8de0 100644 --- a/src/algorithms/sorting/counting_sort.js +++ b/src/algorithms/sorting/counting_sort.js @@ -1,5 +1,26 @@ 'use strict'; +/** + * Finds the maximum key from an array of objects + * + * Asymptotic Complexity: O(array.length) + * + * @param Array + * @return Integer + */ +var maximumKey = function(array) { + var max = array[0].key; + var length = array.length; + + for (var i = 1; i < length; i++) { + if (array[i].key > max) { + max = array[i].key; + } + } + + return max; +}; + /** * Sorts an array of objects according to their 'key' property * Every object inside the array MUST have the 'key' property with @@ -11,7 +32,7 @@ * @param Array * @return Array */ -var countingSort = function (array) { +var countingSort = function(array) { var max = maximumKey(array); var auxiliaryArray = []; var length = array.length; @@ -43,25 +64,4 @@ var countingSort = function (array) { return array; }; -/** - * Finds the maximum key from an array of objects - * - * Asymptotic Complexity: O(array.length) - * - * @param Array - * @return Integer - */ -var maximumKey = function (array) { - var max = array[0].key; - var length = array.length; - - for (var i = 1; i < length; i++) { - if (array[i].key > max) { - max = array[i].key; - } - } - - return max; -}; - module.exports = countingSort; diff --git a/src/algorithms/sorting/heap_sort.js b/src/algorithms/sorting/heap_sort.js index 9d8f53e..ace35e0 100644 --- a/src/algorithms/sorting/heap_sort.js +++ b/src/algorithms/sorting/heap_sort.js @@ -6,8 +6,7 @@ var MinHeap = require('../../data_structures/heap').MinHeap; * iteratively removes the smallest element of the heap until it's * empty. The time complexity of the algorithm is O(n.lg n) */ -var heapsort = function (array, comparatorFn) { - +var heapsort = function(array, comparatorFn) { var minHeap = new MinHeap(comparatorFn); minHeap.heapify(array); diff --git a/src/algorithms/sorting/insertion_sort.js b/src/algorithms/sorting/insertion_sort.js index 8fef2a0..26af300 100644 --- a/src/algorithms/sorting/insertion_sort.js +++ b/src/algorithms/sorting/insertion_sort.js @@ -4,12 +4,12 @@ var Comparator = require('../../util/comparator'); /** * Insertion sort algorithm O(n + d) */ -var insertionSort = function (vector, comparatorFn) { +var insertionSort = function(vector, comparatorFn) { var comparator = new Comparator(comparatorFn); for (var i = 1, len = vector.length; i < len; i++) { - var aux = vector[i], - j = i; + var aux = vector[i]; + var j = i; while (j > 0 && comparator.lessThan(aux, vector[j - 1])) { vector[j] = vector[j - 1]; diff --git a/src/algorithms/sorting/merge_sort.js b/src/algorithms/sorting/merge_sort.js index 358b3e2..89a4dc0 100644 --- a/src/algorithms/sorting/merge_sort.js +++ b/src/algorithms/sorting/merge_sort.js @@ -1,11 +1,25 @@ 'use strict'; var Comparator = require('../../util/comparator'); +var merge = function(a, b, comparator) { + var i = 0; + var j = 0; + var result = []; + + while (i < a.length && j < b.length) { + result.push(comparator.lessThan(a[i], b[j]) ? a[i++] : b[j++]); + } + + // Concats the elements from the sub-array + // that has not been included yet + return result.concat((i < a.length ? a.slice(i) : b.slice(j))); +}; + /** * Merge sort * O(n.lgn) */ -var mergeSortInit = function (a, compareFn) { +var mergeSortInit = function(a, compareFn) { var comparator = new Comparator(compareFn); return (function mergeSort(a) { @@ -20,18 +34,4 @@ var mergeSortInit = function (a, compareFn) { })(a); }; -var merge = function (a, b, comparator) { - var i = 0, - j = 0, - result = []; - - while (i < a.length && j < b.length) { - result.push(comparator.lessThan(a[i], b[j]) ? a[i++] : b[j++]); - } - - // Concats the elements from the sub-array - // that has not been included yet - return result.concat((i < a.length ? a.slice(i) : b.slice(j))); -}; - module.exports = mergeSortInit; diff --git a/src/algorithms/sorting/quicksort.js b/src/algorithms/sorting/quicksort.js index 446b7c0..ceff08a 100644 --- a/src/algorithms/sorting/quicksort.js +++ b/src/algorithms/sorting/quicksort.js @@ -2,29 +2,12 @@ var Comparator = require('../../util/comparator'); /** - * Quicksort recursively sorts parts of the array in - * O(n.lg n) + * Swaps two elements in the array */ -var quicksortInit = function (array, comparatorFn) { - - var comparator = new Comparator(comparatorFn); - - return (function quicksort(array, lo, hi) { - while (lo < hi) { - var p = partition(array, comparator, lo, hi); - //Chooses only the smallest partition to use recursion on and - //tail-optimize the other. This guarantees O(log n) space in worst case. - if (p - lo < hi - p) { - quicksort(array, lo, p - 1); - lo = p + 1; - } else { - quicksort(array, p + 1, hi); - hi = p - 1; - } - } - - return array; - })(array, 0, array.length - 1); +var swap = function(array, x, y) { + var tmp = array[y]; + array[y] = array[x]; + array[x] = tmp; }; /** @@ -34,7 +17,7 @@ var quicksortInit = function (array, comparatorFn) { * * @return Number the positon of the pivot */ -var partition = function (a, comparator, lo, hi) { +var partition = function(a, comparator, lo, hi) { // pick a random element, swap with the rightmost and // use it as pivot swap(a, Math.floor(Math.random() * (hi - lo)) + lo, hi); @@ -55,12 +38,28 @@ var partition = function (a, comparator, lo, hi) { }; /** - * Swaps two elements in the array + * Quicksort recursively sorts parts of the array in + * O(n.lg n) */ -var swap = function (array, x, y) { - var tmp = array[y]; - array[y] = array[x]; - array[x] = tmp; +var quicksortInit = function(array, comparatorFn) { + var comparator = new Comparator(comparatorFn); + + return (function quicksort(array, lo, hi) { + while (lo < hi) { + var p = partition(array, comparator, lo, hi); + // Chooses only the smallest partition to use recursion on and + // tail-optimize the other. This guarantees O(log n) space in worst case. + if (p - lo < hi - p) { + quicksort(array, lo, p - 1); + lo = p + 1; + } else { + quicksort(array, p + 1, hi); + hi = p - 1; + } + } + + return array; + })(array, 0, array.length - 1); }; module.exports = quicksortInit; diff --git a/src/algorithms/sorting/radix_sort.js b/src/algorithms/sorting/radix_sort.js index 78f51d4..126766d 100644 --- a/src/algorithms/sorting/radix_sort.js +++ b/src/algorithms/sorting/radix_sort.js @@ -1,28 +1,4 @@ 'use strict'; - -/** - * Sorts an array of objects according to their 'key' property - * Every object inside the array MUST have the 'key' property with - * a integer value. - * - * Asymptotic Complexity: O(array.length * d), where 'd' represents - * the amount of digits in the larger key of the array - * - * @param Array - * @return Array - */ -var radixSort = function (array) { - var max = maximumKey(array); - var digitsMax = (max === 0 ? 1 : - 1 + Math.floor(Math.log(max) / Math.log(10))); // log base 10 - - for (var i = 0; i < digitsMax; i++) { - array = auxiliaryCountingSort(array, i); - } - - return array; -}; - /** * Auxiliary sorting method for RadixSort * Sorts an array of objects according to only one digit of @@ -37,7 +13,7 @@ var radixSort = function (array) { * @param Array * @return Array */ -var auxiliaryCountingSort = function (array, mod) { +var auxiliaryCountingSort = function(array, mod) { var length = array.length; var bucket = []; var i; @@ -47,7 +23,8 @@ var auxiliaryCountingSort = function (array, mod) { } for (i = 0; i < length; i++) { - var digit = parseInt((array[i].key / Math.pow(10, mod)).toFixed(mod)) % 10; + var digit = parseInt((array[i].key / Math.pow(10, mod)) + .toFixed(mod), 10) % 10; bucket[digit].push(array[i]); } @@ -73,7 +50,7 @@ var auxiliaryCountingSort = function (array, mod) { * @return Integer if array non-empty * Undefined otherwise */ -var maximumKey = function (a) { +var maximumKey = function(a) { var max; for (var i = 1; i < a.length; i++) { if (max === undefined || a[i].key > max) { @@ -83,4 +60,27 @@ var maximumKey = function (a) { return max; }; +/** + * Sorts an array of objects according to their 'key' property + * Every object inside the array MUST have the 'key' property with + * a integer value. + * + * Asymptotic Complexity: O(array.length * d), where 'd' represents + * the amount of digits in the larger key of the array + * + * @param Array + * @return Array + */ +var radixSort = function(array) { + var max = maximumKey(array); + var digitsMax = (max === 0 ? 1 : + 1 + Math.floor(Math.log(max) / Math.log(10))); // log base 10 + + for (var i = 0; i < digitsMax; i++) { + array = auxiliaryCountingSort(array, i); + } + + return array; +}; + module.exports = radixSort; diff --git a/src/algorithms/sorting/selection_sort.js b/src/algorithms/sorting/selection_sort.js index 4451049..5636468 100644 --- a/src/algorithms/sorting/selection_sort.js +++ b/src/algorithms/sorting/selection_sort.js @@ -3,7 +3,7 @@ var Comparator = require('../../util/comparator'); /** * Selection sort algorithm O(n^2) */ -var selectionSort = function (a, comparatorFn) { +var selectionSort = function(a, comparatorFn) { var comparator = new Comparator(comparatorFn); var n = a.length; for (var i = 0; i < n - 1; i++) { diff --git a/src/algorithms/sorting/shell_sort.js b/src/algorithms/sorting/shell_sort.js index 6530306..bdd7c11 100644 --- a/src/algorithms/sorting/shell_sort.js +++ b/src/algorithms/sorting/shell_sort.js @@ -3,24 +3,26 @@ var Comparator = require('../../util/comparator'); /** * shell sort worst:O(n lg n) best:O(n) */ -var shellSort = function (array, comparatorFn) { - var comparator = new Comparator(comparatorFn), - begin = 0, - end = array.length - 1, - gap = parseInt((end - begin + 1) / 2), - i = 0, j = 0, temp = 0; +var shellSort = function(array, comparatorFn) { + var comparator = new Comparator(comparatorFn); + var begin = 0; + var end = array.length - 1; + var gap = parseInt((end - begin + 1) / 2, 10); + var i = 0; + var j = 0; + var temp = 0; while (gap >= 1) { - for (i = begin + gap;i <= end;i += 1) { + for (i = begin + gap; i <= end; i += 1) { temp = array[i]; j = i - gap; while (j >= begin && comparator.greaterThan(array[j], temp)) { array[j + gap] = array[j]; - j = j - gap; + j -= gap; } array[j + gap] = temp; } - gap = parseInt(gap / 2); + gap = parseInt(gap / 2, 10); } return array; diff --git a/src/algorithms/sorting/short_bubble_sort.js b/src/algorithms/sorting/short_bubble_sort.js index 4632208..459fa65 100644 --- a/src/algorithms/sorting/short_bubble_sort.js +++ b/src/algorithms/sorting/short_bubble_sort.js @@ -6,7 +6,6 @@ var Comparator = require('../../util/comparator'); * short bubble sort algorithm * worst: O(n^2) best: O(n) */ - function shortBubbleSort(array, comparatorFn) { var comparator = new Comparator(comparatorFn); var length = array.length - 1; @@ -14,7 +13,7 @@ function shortBubbleSort(array, comparatorFn) { for (i; i < length; i++) { var current = array[i]; - var next = array[i+1]; + var next = array[i + 1]; /** * If the current value if greater than the next: @@ -24,7 +23,7 @@ function shortBubbleSort(array, comparatorFn) { */ if (comparator.greaterThan(current, next)) { - array[i+1] = current; + array[i + 1] = current; array[i] = next; i = -1; } diff --git a/src/algorithms/string/hamming.js b/src/algorithms/string/hamming.js index ec783cf..2cfba70 100644 --- a/src/algorithms/string/hamming.js +++ b/src/algorithms/string/hamming.js @@ -8,7 +8,7 @@ */ 'use strict'; -var hamming = function (a, b) { +var hamming = function(a, b) { if (a.length !== b.length) { throw new Error('Strings must be equal in length'); } diff --git a/src/algorithms/string/huffman.js b/src/algorithms/string/huffman.js index 644018f..8ff4e42 100644 --- a/src/algorithms/string/huffman.js +++ b/src/algorithms/string/huffman.js @@ -1,9 +1,7 @@ 'use strict'; - var huffman = {}; - /** * Maximum block size used by functions "compress", "decompress". * @@ -11,18 +9,18 @@ var huffman = {}; */ var MAX_BLOCK_SIZE = (-1 >>> 0).toString(2).length; - /** * Compress 0-1 string to int32 array. * * @param {string} string * @return {number[]} */ -var compress = function (string) { +var compress = function(string) { var blocks = []; - var currentBlock = 0, currentBlockSize = 0; + var currentBlock = 0; + var currentBlockSize = 0; - string.split('').forEach(function (char) { + string.split('').forEach(function(char) { currentBlock = (currentBlock << 1) | char; currentBlockSize += 1; @@ -35,33 +33,30 @@ var compress = function (string) { // Append last block size to the end. if (currentBlockSize) { blocks.push(currentBlock, currentBlockSize); - } - else { + } else { blocks.push(MAX_BLOCK_SIZE); } return blocks; }; - /** * Decompress int32 array back to 0-1 string. * * @param {number[]} array * @return {string} */ -var decompress = function (array) { +var decompress = function(array) { if (!array.length) { return ''; - } - else if (array.length === 1) { + } else if (array.length === 1) { throw new Error('Compressed array must be either empty ' + 'or at least 2 blocks big.'); } var padding = new Array(MAX_BLOCK_SIZE + 1).join(0); - var string = array.slice(0, -2).map(function (block) { + var string = array.slice(0, -2).map(function(block) { return (padding + (block >>> 0).toString(2)).slice(-padding.length); }).join(''); @@ -73,7 +68,6 @@ var decompress = function (array) { return string; }; - /** * Apply Huffman encoding to a string. * @@ -81,7 +75,7 @@ var decompress = function (array) { * @param {boolean} [compressed=false] - Whether compress the string to bits. * @return {{encoding: Object., value: string|number[]}} */ -huffman.encode = function (string, compressed) { +huffman.encode = function(string, compressed) { if (!string.length) { return { encoding: {}, @@ -90,21 +84,21 @@ huffman.encode = function (string, compressed) { } var counter = {}; - string.split('').forEach(function (char) { + string.split('').forEach(function(char) { counter[char] = (counter[char] || 0) + 1; }); - var letters = Object.keys(counter).map(function (char) { + var letters = Object.keys(counter).map(function(char) { return { char: char, count: counter[char] }; }); - var compare = function (a, b) { + var compare = function(a, b) { return a.count - b.count; }; - var less = function (a, b) { + var less = function(a, b) { return a && (b && (a.count < b.count) || !b); }; @@ -114,15 +108,17 @@ huffman.encode = function (string, compressed) { // this buffer. Since the letters are pushing in ascending order of frequency, // no more sorting is ever required. var buffer = []; - var lettersIndex = 0, bufferIndex = 0; + var lettersIndex = 0; + var bufferIndex = 0; - var extractMinimum = function () { + var extractMinimum = function() { return less(letters[lettersIndex], buffer[bufferIndex]) ? letters[lettersIndex++] : buffer[bufferIndex++]; }; for (var numLetters = letters.length; numLetters > 1; --numLetters) { - var a = extractMinimum(), b = extractMinimum(); + var a = extractMinimum(); + var b = extractMinimum(); a.code = '0'; b.code = '1'; var union = { @@ -139,7 +135,8 @@ huffman.encode = function (string, compressed) { // Unroll the code recursively in reverse. (function unroll(parent) { if (parent.parts) { - var a = parent.parts[0], b = parent.parts[1]; + var a = parent.parts[0]; + var b = parent.parts[1]; a.code += parent.code; b.code += parent.code; unroll(a); @@ -147,13 +144,13 @@ huffman.encode = function (string, compressed) { } })(root); - var encoding = letters.reduce(function (acc, letter) { + var encoding = letters.reduce(function(acc, letter) { acc[letter.char] = letter.code.split('').reverse().join(''); return acc; }, {}); // Finally, apply the encoding to the given string. - var result = string.split('').map(function (char) { + var result = string.split('').map(function(char) { return encoding[char]; }).join(''); @@ -163,7 +160,6 @@ huffman.encode = function (string, compressed) { }; }; - /** * Decode a Huffman-encoded string or compressed number sequence. * @@ -171,21 +167,21 @@ huffman.encode = function (string, compressed) { * @param {string|number[]} encodedString * @return {string} Decoded string. */ -huffman.decode = function (encoding, encodedString) { +huffman.decode = function(encoding, encodedString) { if (Array.isArray(encodedString)) { encodedString = decompress(encodedString); } // We can make use of the fact that encoding mapping is always one-to-one // and rely on the power of JS hashes instead of building hand-made FSMs. - var letterByCode = Object.keys(encoding).reduce(function (acc, letter) { + var letterByCode = Object.keys(encoding).reduce(function(acc, letter) { acc[encoding[letter]] = letter; return acc; }, {}); var decodedLetters = []; - var unresolved = encodedString.split('').reduce(function (code, char) { + var unresolved = encodedString.split('').reduce(function(code, char) { code += char; var letter = letterByCode[code]; if (letter) { @@ -202,5 +198,4 @@ huffman.decode = function (encoding, encodedString) { return decodedLetters.join(''); }; - module.exports = huffman; diff --git a/src/algorithms/string/knuth_morris_pratt.js b/src/algorithms/string/knuth_morris_pratt.js index 453bd4f..d5c5d1f 100644 --- a/src/algorithms/string/knuth_morris_pratt.js +++ b/src/algorithms/string/knuth_morris_pratt.js @@ -1,5 +1,40 @@ 'use strict'; +/** + * Builds the dinamic table of the given pattern + * to record how the pattern can match it self + * + * Asymptotic Complexity: O(pattern.length) + * + * @param {Array} pattern of Numbers, Strings or Characters + * or {String} + * @return {Array} of Integers + */ +var buildTable = function(pattern) { + var length = pattern.length; + var table = []; + var position = 2; + var cnd = 0; + + table[0] = -1; + table[1] = 0; + + while (position < length) { + if (pattern[position - 1] === pattern[cnd]) { + ++cnd; + table[position] = cnd; + ++position; + } else if (cnd > 0) { + cnd = table[cnd]; + } else { + table[position] = 0; + ++position; + } + } + + return table; +}; + /** * String Matching algorithm * Tries to match the given pattern inside the given text @@ -15,7 +50,7 @@ * or {String} * @return {Number} */ -var knuthMorrisPratt = function (text, pattern) { +var knuthMorrisPratt = function(text, pattern) { var textLength = text.length; var patternLength = pattern.length; var m = 0; @@ -28,57 +63,16 @@ var knuthMorrisPratt = function (text, pattern) { return m; } ++i; - } - else { - if (table[i] >= 0) { - i = table[i]; - m = m + i - table[i]; - } - else { - i = 0; - ++m; - } + } else if (table[i] >= 0) { + i = table[i]; + m = m + i - table[i]; + } else { + i = 0; + ++m; } } return textLength; }; -/** - * Builds the dinamic table of the given pattern - * to record how the pattern can match it self - * - * Asymptotic Complexity: O(pattern.length) - * - * @param {Array} pattern of Numbers, Strings or Characters - * or {String} - * @return {Array} of Integers - */ -var buildTable = function (pattern) { - var length = pattern.length; - var table = []; - var position = 2; - var cnd = 0; - - table[0] = -1; - table[1] = 0; - - while (position < length) { - if (pattern[position - 1] === pattern[cnd]) { - ++cnd; - table[position] = cnd; - ++position; - } - else if (cnd > 0) { - cnd = table[cnd]; - } - else { - table[position] = 0; - ++position; - } - } - - return table; -}; - module.exports = knuthMorrisPratt; diff --git a/src/algorithms/string/levenshtein.js b/src/algorithms/string/levenshtein.js index 4f88f42..a083abd 100644 --- a/src/algorithms/string/levenshtein.js +++ b/src/algorithms/string/levenshtein.js @@ -15,9 +15,10 @@ * @param String * @return Number */ -var levenshtein = function (a, b) { +var levenshtein = function(a, b) { var editDistance = []; - var i, j; + var i; + var j; // Initialize the edit distance matrix. The first collumn contains // the values comparing the string a to an empty string b @@ -39,7 +40,7 @@ var levenshtein = function (a, b) { editDistance[i - 1][j], // if we delete the char from a editDistance[i][j - 1] // if we add the char from b ) + - (a[i - 1] !== b[j - 1] ? 1 : 0); + (a[i - 1] === b[j - 1] ? 0 : 1); } } diff --git a/src/algorithms/string/longest_common_subsequence.js b/src/algorithms/string/longest_common_subsequence.js index 5f2d72a..5b8200b 100644 --- a/src/algorithms/string/longest_common_subsequence.js +++ b/src/algorithms/string/longest_common_subsequence.js @@ -7,11 +7,12 @@ /** * Implementation via dynamic programming */ -var longestCommonSubsequence = function (s1, s2) { +var longestCommonSubsequence = function(s1, s2) { // Multidimensional array for dynamic programming algorithm var cache = new Array(s1.length + 1); - var i, j; + var i; + var j; for (i = 0; i <= s1.length; i++) { cache[i] = new Int32Array(s2.length + 1); diff --git a/src/algorithms/string/longest_common_substring.js b/src/algorithms/string/longest_common_substring.js index d083fcf..e093e3e 100644 --- a/src/algorithms/string/longest_common_substring.js +++ b/src/algorithms/string/longest_common_substring.js @@ -7,11 +7,12 @@ /** * Implementation via dynamic programming */ -var longestCommonSubstring = function (s1, s2) { +var longestCommonSubstring = function(s1, s2) { // Multidimensional array for dynamic programming algorithm var cache = new Array(s1.length + 1); - var i, j; + var i; + var j; for (i = 0; i <= s1.length + 1; i++) { cache[i] = new Int32Array(s2.length + 1); diff --git a/src/algorithms/string/rabin_karp.js b/src/algorithms/string/rabin_karp.js index 9060e58..ad41018 100644 --- a/src/algorithms/string/rabin_karp.js +++ b/src/algorithms/string/rabin_karp.js @@ -9,6 +9,22 @@ */ var base = 997; +/** + * Creates the hash representation of 'word' + * + * @param String + * @return Number + */ +var hash = function(word) { + var h = 0; + + for (var i = 0; i < word.length; i++) { + h += word.charCodeAt(i) * Math.pow(base, word.length - i - 1); + } + + return h; +}; + /** * Calculates String Matching between two Strings * Returns true if String 'b' is contained in String 'a' @@ -20,7 +36,7 @@ var base = 997; * @param String * @return Integer */ -var rabinKarp = function (s, pattern) { +var rabinKarp = function(s, pattern) { if (pattern.length === 0) return 0; var hashPattern = hash(pattern); @@ -54,20 +70,4 @@ var rabinKarp = function (s, pattern) { return -1; }; -/** - * Creates the hash representation of 'word' - * - * @param String - * @return Number - */ -var hash = function (word) { - var h = 0; - - for (var i = 0; i < word.length; i++) { - h += word.charCodeAt(i) * Math.pow(base, word.length - i - 1); - } - - return h; -}; - module.exports = rabinKarp; diff --git a/src/data_structures/avl_tree.js b/src/data_structures/avl_tree.js index 8d9291f..471a0a6 100644 --- a/src/data_structures/avl_tree.js +++ b/src/data_structures/avl_tree.js @@ -22,7 +22,7 @@ function Node(value, left, right, parent, height) { * Calculates the height of a node based on height * property of all his children. */ -AVLTree.prototype.getNodeHeight = function (node) { +AVLTree.prototype.getNodeHeight = function(node) { var height = 1; if (node.left !== null && node.right !== null) { height = Math.max(node.left.height, node.right.height) + 1; @@ -37,7 +37,7 @@ AVLTree.prototype.getNodeHeight = function (node) { /** * Verifies if the given node is balanced. */ -AVLTree.prototype.isNodeBalanced = function (node) { +AVLTree.prototype.isNodeBalanced = function(node) { var isBalanced = true; if (node.left !== null && node.right !== null) { @@ -54,7 +54,7 @@ AVLTree.prototype.isNodeBalanced = function (node) { * When a removal happens, some nodes need to be * restructured. Gets and return these nodes. */ -AVLTree.prototype.getNodesToRestructureAfterRemove = function (traveledNodes) { +AVLTree.prototype.getNodesToRestructureAfterRemove = function(traveledNodes) { // z is last traveled node - imbalance found at z var zIndex = traveledNodes.length - 1; var z = traveledNodes[zIndex]; @@ -94,7 +94,7 @@ AVLTree.prototype.getNodesToRestructureAfterRemove = function (traveledNodes) { * When a insertion happens, some nodes need to be * restructured. Gets and return these nodes. */ -AVLTree.prototype.getNodesToRestructureAfterInsert = function (traveledNodes) { +AVLTree.prototype.getNodesToRestructureAfterInsert = function(traveledNodes) { // z is last traveled node - imbalance found at z var zIndex = traveledNodes.length - 1; var z = traveledNodes[zIndex]; @@ -130,7 +130,7 @@ AVLTree.prototype.getNodesToRestructureAfterInsert = function (traveledNodes) { * Keep the height balance property by walking to * root and checking for invalid heights. */ -AVLTree.prototype.keepHeightBalance = function (node, afterRemove) { +AVLTree.prototype.keepHeightBalance = function(node, afterRemove) { var current = node; var traveledNodes = []; while (current !== null) { @@ -150,7 +150,7 @@ AVLTree.prototype.keepHeightBalance = function (node, afterRemove) { * Identifies and calls the appropriate pattern * rotator. */ -AVLTree.prototype.restructure = function (nodesToRestructure) { +AVLTree.prototype.restructure = function(nodesToRestructure) { var x = nodesToRestructure[0]; var y = nodesToRestructure[1]; var z = nodesToRestructure[2]; @@ -170,9 +170,9 @@ AVLTree.prototype.restructure = function (nodesToRestructure) { /** * Right-right rotation pattern. */ -AVLTree.prototype.rightRight = function (x, y, z) { +AVLTree.prototype.rightRight = function(x, y, z) { // pass z parent to y and move y's left to z's right - if (z.parent !== null) { + if (z.parent) { var orientation = (z.parent.left === z) ? 'left' : 'right'; z.parent[orientation] = y; y.parent = z.parent; @@ -199,9 +199,9 @@ AVLTree.prototype.rightRight = function (x, y, z) { /** * Left-left rotation pattern. */ -AVLTree.prototype.leftLeft = function (x, y, z) { - //pass z parent to y and move y's right to z's left - if (z.parent !== null) { +AVLTree.prototype.leftLeft = function(x, y, z) { + // pass z parent to y and move y's right to z's left + if (z.parent) { var orientation = (z.parent.left === z) ? 'left' : 'right'; z.parent[orientation] = y; y.parent = z.parent; @@ -214,7 +214,7 @@ AVLTree.prototype.leftLeft = function (x, y, z) { if (z.left !== null) { z.left.parent = z; } - //fix y right child + // fix y right child y.right = z; z.parent = y; @@ -227,9 +227,9 @@ AVLTree.prototype.leftLeft = function (x, y, z) { /** * Right-left rotation pattern. */ -AVLTree.prototype.rightLeft = function (x, y, z) { - //pass z parent to x - if (z.parent !== null) { +AVLTree.prototype.rightLeft = function(x, y, z) { + // pass z parent to x + if (z.parent) { var orientation = (z.parent.left === z) ? 'left' : 'right'; z.parent[orientation] = x; x.parent = z.parent; @@ -263,9 +263,9 @@ AVLTree.prototype.rightLeft = function (x, y, z) { /** * Left-right rotation pattern. */ -AVLTree.prototype.leftRight = function (x, y, z) { - //pass z parent to x - if (z.parent !== null) { +AVLTree.prototype.leftRight = function(x, y, z) { + // pass z parent to x + if (z.parent) { var orientation = (z.parent.left === z) ? 'left' : 'right'; z.parent[orientation] = x; x.parent = z.parent; @@ -299,7 +299,7 @@ AVLTree.prototype.leftRight = function (x, y, z) { /** * Inserts a value as a Node of an AVL Tree. */ -AVLTree.prototype.insert = function (value, current) { +AVLTree.prototype.insert = function(value, current) { if (this.root === null) { this.root = new Node(value, null, null, null, 1); this.keepHeightBalance(this.root); @@ -314,18 +314,18 @@ AVLTree.prototype.insert = function (value, current) { insertKey = 'right'; } - if (!current[insertKey]) { + if (current[insertKey]) { + this.insert(value, current[insertKey]); + } else { current[insertKey] = new Node(value, null, null, current); this.keepHeightBalance(current[insertKey], false); - } else { - this.insert(value, current[insertKey]); } }; /** * In-order traversal from the given node. */ -AVLTree.prototype.inOrder = function (current, callback) { +AVLTree.prototype.inOrder = function(current, callback) { if (!current) { return; } @@ -339,7 +339,7 @@ AVLTree.prototype.inOrder = function (current, callback) { /** * Post-order traversal from the given node. */ -AVLTree.prototype.postOrder = function (current, callback) { +AVLTree.prototype.postOrder = function(current, callback) { if (!current) { return; } @@ -354,7 +354,7 @@ AVLTree.prototype.postOrder = function (current, callback) { /** * Pre-order traversal from the given node. */ -AVLTree.prototype.preOrder = function (current, callback) { +AVLTree.prototype.preOrder = function(current, callback) { if (!current) { return; } @@ -368,14 +368,14 @@ AVLTree.prototype.preOrder = function (current, callback) { /** * Finds a node by its value. */ -AVLTree.prototype.find = function (value) { +AVLTree.prototype.find = function(value) { return this._find(value, this.root); }; /** * Finds a node by its value in the given sub-tree. */ -AVLTree.prototype._find = function (value, current) { +AVLTree.prototype._find = function(value, current) { if (!current) { return null; } @@ -396,7 +396,7 @@ AVLTree.prototype._find = function (value, current) { * Replaces the given child with the new one, * for the given parent. */ -AVLTree.prototype.replaceChild = function (parent, oldChild, newChild) { +AVLTree.prototype.replaceChild = function(parent, oldChild, newChild) { if (parent === null) { this.root = newChild; if (this.root !== null) { @@ -417,7 +417,7 @@ AVLTree.prototype.replaceChild = function (parent, oldChild, newChild) { /** * Removes a node by its value. */ -AVLTree.prototype.remove = function (value) { +AVLTree.prototype.remove = function(value) { var node = this.find(value); if (!node) { return false; @@ -446,7 +446,7 @@ AVLTree.prototype.remove = function (value) { * Finds the node with minimum value in the given * sub-tree. */ -AVLTree.prototype._findMin = function (node, current) { +AVLTree.prototype._findMin = function(node, current) { current = current || { value: Infinity }; @@ -463,7 +463,7 @@ AVLTree.prototype._findMin = function (node, current) { * Finds the node with maximum value in the given * sub-tree. */ -AVLTree.prototype._findMax = function (node, current) { +AVLTree.prototype._findMax = function(node, current) { current = current || { value: -Infinity }; @@ -479,21 +479,21 @@ AVLTree.prototype._findMax = function (node, current) { /** * Finds the node with minimum value in the whole tree. */ -AVLTree.prototype.findMin = function () { +AVLTree.prototype.findMin = function() { return this._findMin(this.root); }; /** * Finds the node with maximum value in the whole tree. */ -AVLTree.prototype.findMax = function () { +AVLTree.prototype.findMax = function() { return this._findMax(this.root); }; /** * Verifies if the tree is balanced. */ -AVLTree.prototype.isTreeBalanced = function () { +AVLTree.prototype.isTreeBalanced = function() { var current = this.root; if (!current) { @@ -509,7 +509,7 @@ AVLTree.prototype.isTreeBalanced = function () { * Calculates the height of the tree based on height * property. */ -AVLTree.prototype.getTreeHeight = function () { +AVLTree.prototype.getTreeHeight = function() { var current = this.root; if (!current) { diff --git a/src/data_structures/bst.js b/src/data_structures/bst.js index 0993a19..844b650 100644 --- a/src/data_structures/bst.js +++ b/src/data_structures/bst.js @@ -16,7 +16,9 @@ function BST(compareFn) { * Read-only property for the size of the tree */ Object.defineProperty(this, 'size', { - get: function () { return this._size; }.bind(this) + get: function() { + return this._size; + }.bind(this) }); } @@ -33,7 +35,7 @@ function Node(value, parent) { /** * Insert elements to the tree respecting the BST restrictions */ -BST.prototype.insert = function (value, parent) { +BST.prototype.insert = function(value, parent) { // Set the root as the initial insertion point // if it has not been passed if (!parent) { @@ -57,12 +59,11 @@ BST.prototype.insert = function (value, parent) { /** * Returns if a tree contains an element in O(lg n) */ -BST.prototype.contains = function (e) { - return !!this._find(e); +BST.prototype.contains = function(e) { + return Boolean(this._find(e)); }; -BST.prototype._find = function (e, root) { - +BST.prototype._find = function(e, root) { if (!root) { if (this.root) root = this.root; else return false; @@ -81,7 +82,7 @@ BST.prototype._find = function (e, root) { /** * Substitute two nodes */ -BST.prototype._replaceNodeInParent = function (currNode, newNode) { +BST.prototype._replaceNodeInParent = function(currNode, newNode) { var parent = currNode.parent; if (parent) { parent[currNode === parent.left ? 'left' : 'right'] = newNode; @@ -95,7 +96,7 @@ BST.prototype._replaceNodeInParent = function (currNode, newNode) { /** * Find the minimum value in a tree */ -BST.prototype._findMin = function (root) { +BST.prototype._findMin = function(root) { var minNode = root; while (minNode.left) { minNode = minNode.left; @@ -106,7 +107,7 @@ BST.prototype._findMin = function (root) { /** * Remove an element from the BST */ -BST.prototype.remove = function (e) { +BST.prototype.remove = function(e) { var node = this._find(e); if (!node) { throw new Error('Item not found in the tree'); diff --git a/src/data_structures/disjoint_set_forest.js b/src/data_structures/disjoint_set_forest.js index 99b4c02..743c947 100644 --- a/src/data_structures/disjoint_set_forest.js +++ b/src/data_structures/disjoint_set_forest.js @@ -13,8 +13,7 @@ function DisjointSetForest() { this._sizes = {}; } - -DisjointSetForest.prototype._introduce = function (element) { +DisjointSetForest.prototype._introduce = function(element) { if (!(element in this._parents)) { this._parents[element] = element; this._ranks[element] = 0; @@ -22,7 +21,6 @@ DisjointSetForest.prototype._introduce = function (element) { } }; - /** * Check if the elements belong to the same subset. * Complexity: O(A^-1) (inverse Ackermann function) amortized. @@ -30,16 +28,15 @@ DisjointSetForest.prototype._introduce = function (element) { * @param {...*} element * @return {boolean} */ -DisjointSetForest.prototype.sameSubset = function (element) { +DisjointSetForest.prototype.sameSubset = function(element) { this._introduce(element); var root = this.root(element); - return [].slice.call(arguments, 1).every(function (element) { + return [].slice.call(arguments, 1).every(function(element) { this._introduce(element); return this.root(element) === root; }.bind(this)); }; - /** * Return the root element which represents the given element's subset. * The result does not depend on the choice of the element, @@ -49,7 +46,7 @@ DisjointSetForest.prototype.sameSubset = function (element) { * @param {*} element * @return {*} */ -DisjointSetForest.prototype.root = function (element) { +DisjointSetForest.prototype.root = function(element) { this._introduce(element); if (this._parents[element] !== element) { this._parents[element] = this.root(this._parents[element]); @@ -57,7 +54,6 @@ DisjointSetForest.prototype.root = function (element) { return this._parents[element]; }; - /** * Return the size of the given element's subset. * Complexity: O(A^-1) (inverse Ackermann function) amortized. @@ -65,12 +61,11 @@ DisjointSetForest.prototype.root = function (element) { * @param {*} element * @return {number} */ -DisjointSetForest.prototype.size = function (element) { +DisjointSetForest.prototype.size = function(element) { this._introduce(element); return this._sizes[this.root(element)]; }; - /** * Merge subsets containing two (or more) given elements into one. * Complexity: O(A^-1) (inverse Ackermann function) amortized. @@ -93,8 +88,7 @@ DisjointSetForest.prototype.merge = function merge(element1, element2) { if (this._ranks[root1] < this._ranks[root2]) { this._parents[root1] = root2; this._sizes[root2] += this._sizes[root1]; - } - else if (root1 !== root2) { + } else if (root1 !== root2) { this._parents[root2] = root1; this._sizes[root1] += this._sizes[root2]; if (this._ranks[root1] === this._ranks[root2]) { @@ -104,5 +98,4 @@ DisjointSetForest.prototype.merge = function merge(element1, element2) { return this; }; - module.exports = DisjointSetForest; diff --git a/src/data_structures/fenwick_tree.js b/src/data_structures/fenwick_tree.js index 0180f92..68d2936 100644 --- a/src/data_structures/fenwick_tree.js +++ b/src/data_structures/fenwick_tree.js @@ -24,14 +24,14 @@ */ function FenwickTree(length) { this._elements = new Array(length + 1); - for (var i = 0; i < this._elements.length ; i++) + for (var i = 0; i < this._elements.length; i++) this._elements[i] = 0; } /** * Adds value to the array at specified index in O(log n) */ -FenwickTree.prototype.adjust = function (index, value) { +FenwickTree.prototype.adjust = function(index, value) { /* This function goes up the tree adding the value to all parent nodes. @@ -48,14 +48,14 @@ FenwickTree.prototype.adjust = function (index, value) { Note: (index&-index) finds the rightmost bit in index. */ - for (; index < this._elements.length ; index += (index&-index)) + for (; index < this._elements.length; index += (index & -index)) this._elements[index] += value; }; /** * Returns the sum of all values up to specified index in O(log n) */ -FenwickTree.prototype.prefixSum = function (index) { +FenwickTree.prototype.prefixSum = function(index) { /* This function goes up the tree adding the required nodes to sum the prefix. @@ -72,7 +72,7 @@ FenwickTree.prototype.prefixSum = function (index) { */ var sum = 0; - for (; index > 0 ; index -= (index&-index)) + for (; index > 0; index -= (index & -index)) sum += this._elements[index]; return sum; }; @@ -80,7 +80,7 @@ FenwickTree.prototype.prefixSum = function (index) { /** * Returns the sum of all values between two indexes in O(log n) */ -FenwickTree.prototype.rangeSum = function (fromIndex, toIndex) { +FenwickTree.prototype.rangeSum = function(fromIndex, toIndex) { return this.prefixSum(toIndex) - this.prefixSum(fromIndex - 1); }; diff --git a/src/data_structures/graph.js b/src/data_structures/graph.js index 082ff95..a88303d 100644 --- a/src/data_structures/graph.js +++ b/src/data_structures/graph.js @@ -7,17 +7,17 @@ var HashSet = require('./set'); * @param {bool} directed */ function Graph(directed) { - this.directed = (directed === undefined ? true : !!directed); + this.directed = typeof directed === 'undefined' || Boolean(directed); this.adjList = Object.create(null); this.vertices = new HashSet(); } // Normalize vertex labels as strings -var _ = function (v) { - return '' + v; +var _ = function(v) { + return String(v); }; -Graph.prototype.addVertex = function (v) { +Graph.prototype.addVertex = function(v) { v = _(v); if (this.vertices.contains(v)) { throw new Error('Vertex "' + v + '" has already been added'); @@ -26,7 +26,7 @@ Graph.prototype.addVertex = function (v) { this.adjList[v] = Object.create(null); }; -Graph.prototype.addEdge = function (a, b, w) { +Graph.prototype.addEdge = function(a, b, w) { a = _(a); b = _(b); // If no weight is assigned to the edge, 1 is the default @@ -45,11 +45,11 @@ Graph.prototype.addEdge = function (a, b, w) { } }; -Graph.prototype.neighbors = function (v) { +Graph.prototype.neighbors = function(v) { return Object.keys(this.adjList[_(v)]); }; -Graph.prototype.edge = function (a, b) { +Graph.prototype.edge = function(a, b) { return this.adjList[_(a)][_(b)]; }; diff --git a/src/data_structures/hash_table.js b/src/data_structures/hash_table.js index 60402ee..9742346 100644 --- a/src/data_structures/hash_table.js +++ b/src/data_structures/hash_table.js @@ -2,18 +2,22 @@ var LinkedList = require('./linked_list'); +/** + * HashTable constructor + * @param Number? initially allocated size + */ function HashTable(initialCapacity) { this._table = new Array(initialCapacity || 64); this._items = 0; Object.defineProperty(this, 'capacity', { - get: function () { + get: function() { return this._table.length; } }); Object.defineProperty(this, 'size', { - get: function () { + get: function() { return this._items; } }); @@ -27,7 +31,7 @@ function HashTable(initialCapacity) { * n is the length of the string, and ^ indicates exponentiation. * (The hash value of the empty string is zero.) */ -HashTable.prototype.hash = function (s) { +HashTable.prototype.hash = function(s) { if (typeof s !== 'string') s = JSON.stringify(s); var hash = 0; for (var i = 0; i < s.length; i++) { @@ -37,15 +41,16 @@ HashTable.prototype.hash = function (s) { return hash; }; -HashTable.prototype.get = function (key) { +HashTable.prototype.get = function(key) { var i = this._position(key); var node; if ((node = this._findInList(this._table[i], key))) { return node.value.v; } + return undefined; }; -HashTable.prototype.put = function (key, value) { +HashTable.prototype.put = function(key, value) { var i = this._position(key); if (!this._table[i]) { // Hashing with chaining @@ -66,7 +71,7 @@ HashTable.prototype.put = function (key, value) { } }; -HashTable.prototype.del = function (key) { +HashTable.prototype.del = function(key) { var i = this._position(key); var node; @@ -76,11 +81,11 @@ HashTable.prototype.del = function (key) { } }; -HashTable.prototype._position = function (key) { +HashTable.prototype._position = function(key) { return Math.abs(this.hash(key)) % this.capacity; }; -HashTable.prototype._findInList = function (list, key) { +HashTable.prototype._findInList = function(list, key) { var node = list && list.head; while (node) { if (node.value.k === key) return node; @@ -88,7 +93,7 @@ HashTable.prototype._findInList = function (list, key) { } }; -HashTable.prototype._increaseCapacity = function () { +HashTable.prototype._increaseCapacity = function() { var oldTable = this._table; this._table = new Array(2 * this.capacity); this._items = 0; @@ -102,9 +107,9 @@ HashTable.prototype._increaseCapacity = function () { } }; -HashTable.prototype.forEach = function (fn) { - var applyFunction = function (linkedList) { - linkedList.forEach(function (elem) { +HashTable.prototype.forEach = function(fn) { + var applyFunction = function(linkedList) { + linkedList.forEach(function(elem) { fn(elem.k, elem.v); }); }; diff --git a/src/data_structures/heap.js b/src/data_structures/heap.js index 2d04f2b..105ba35 100644 --- a/src/data_structures/heap.js +++ b/src/data_structures/heap.js @@ -9,28 +9,28 @@ function MinHeap(compareFn) { this._comparator = new Comparator(compareFn); Object.defineProperty(this, 'n', { - get: function () { + get: function() { return this._elements.length - 1; }.bind(this) }); } -MinHeap.prototype._swap = function (a, b) { +MinHeap.prototype._swap = function(a, b) { var tmp = this._elements[a]; this._elements[a] = this._elements[b]; this._elements[b] = tmp; }; -MinHeap.prototype.isEmpty = function () { +MinHeap.prototype.isEmpty = function() { return this.n === 0; }; -MinHeap.prototype.insert = function (e) { +MinHeap.prototype.insert = function(e) { this._elements.push(e); this._siftUp(); }; -MinHeap.prototype.extract = function () { +MinHeap.prototype.extract = function() { var element = this._elements[1]; // Get the one from the bottom in insert it on top @@ -48,8 +48,9 @@ MinHeap.prototype.extract = function () { * Sift up the last element * O(lg n) */ -MinHeap.prototype._siftUp = function () { - var i, parent; +MinHeap.prototype._siftUp = function() { + var i; + var parent; for (i = this.n; i > 1 && (parent = i >> 1) && this._comparator.greaterThan( @@ -63,7 +64,7 @@ MinHeap.prototype._siftUp = function () { * Sifts down the first element * O(lg n) */ -MinHeap.prototype._siftDown = function (i) { +MinHeap.prototype._siftDown = function(i) { var c; for (i = i || 1; (c = i << 1) <= this.n; i = c) { // checks which is the smaller child to compare with @@ -78,7 +79,7 @@ MinHeap.prototype._siftDown = function (i) { } }; -MinHeap.prototype.heapify = function (a) { +MinHeap.prototype.heapify = function(a) { if (a) { this._elements = a; this._elements.unshift(null); @@ -89,7 +90,7 @@ MinHeap.prototype.heapify = function (a) { } }; -MinHeap.prototype.forEach = function (fn) { +MinHeap.prototype.forEach = function(fn) { // A copy is necessary in order to perform extract(), // get the items in sorted order and then restore the original // this._elements array @@ -114,7 +115,6 @@ MinHeap.prototype.forEach = function (fn) { * a reverse comparator; */ function MaxHeap(compareFn) { - MinHeap.call(this, compareFn); this._comparator.reverse(); } diff --git a/src/data_structures/linked_list.js b/src/data_structures/linked_list.js index 8602125..c556904 100644 --- a/src/data_structures/linked_list.js +++ b/src/data_structures/linked_list.js @@ -4,14 +4,13 @@ * Doubly-linked list */ function LinkedList() { - this._length = 0; this.head = null; this.tail = null; // Read-only length property Object.defineProperty(this, 'length', { - get: function () { + get: function() { return this._length; }.bind(this) }); @@ -31,7 +30,7 @@ function Node(value) { * * @return Boolean */ -LinkedList.prototype.isEmpty = function () { +LinkedList.prototype.isEmpty = function() { return this.length === 0; }; @@ -41,7 +40,7 @@ LinkedList.prototype.isEmpty = function () { * @param { Object } n * @param { Number } index */ -LinkedList.prototype.add = function (n, index) { +LinkedList.prototype.add = function(n, index) { if (index > this.length || index < 0) { throw new Error('Index out of bounds'); } @@ -49,8 +48,8 @@ LinkedList.prototype.add = function (n, index) { var node = new Node(n); if (index !== undefined && index < this.length) { - var prevNode, - nextNode; + var prevNode; + var nextNode; if (index === 0) { // Insert in the beginning @@ -84,7 +83,7 @@ LinkedList.prototype.add = function (n, index) { * @param { Number } index * @return misc */ -LinkedList.prototype.get = function (index) { +LinkedList.prototype.get = function(index) { return this.getNode(index).value; }; @@ -94,7 +93,7 @@ LinkedList.prototype.get = function (index) { * @param { Number } index * @return Node */ -LinkedList.prototype.getNode = function (index) { +LinkedList.prototype.getNode = function(index) { if (index >= this.length || index < 0) { throw new Error('Index out of bounds'); } @@ -112,7 +111,7 @@ LinkedList.prototype.getNode = function (index) { * * @param { Number } index */ -LinkedList.prototype.del = function (index) { +LinkedList.prototype.del = function(index) { if (index >= this.length || index < 0) { throw new Error('Index out of bounds'); } @@ -120,7 +119,7 @@ LinkedList.prototype.del = function (index) { this.delNode(this.getNode(index)); }; -LinkedList.prototype.delNode = function (node) { +LinkedList.prototype.delNode = function(node) { if (node === this.tail) { // node is the last element this.tail = node.prev; @@ -140,7 +139,7 @@ LinkedList.prototype.delNode = function (node) { /** * Performs the fn function with each element in the list */ -LinkedList.prototype.forEach = function (fn) { +LinkedList.prototype.forEach = function(fn) { var node = this.head; while (node) { fn(node.value); diff --git a/src/data_structures/priority_queue.js b/src/data_structures/priority_queue.js index 18680fb..6b394d7 100644 --- a/src/data_structures/priority_queue.js +++ b/src/data_structures/priority_queue.js @@ -8,23 +8,22 @@ var MinHeap = require('./heap').MinHeap; * and not on the element itself */ function PriorityQueue(initialItems) { - var self = this; - MinHeap.call(this, function (a, b) { + MinHeap.call(this, function(a, b) { return self.priority(a) < self.priority(b) ? -1 : 1; }); this._priority = {}; initialItems = initialItems || {}; - Object.keys(initialItems).forEach(function (item) { + Object.keys(initialItems).forEach(function(item) { self.insert(item, initialItems[item]); }); } PriorityQueue.prototype = new MinHeap(); -PriorityQueue.prototype.insert = function (item, priority) { +PriorityQueue.prototype.insert = function(item, priority) { if (this._priority[item] !== undefined) { return this.changePriority(item, priority); } @@ -32,18 +31,18 @@ PriorityQueue.prototype.insert = function (item, priority) { MinHeap.prototype.insert.call(this, item); }; -PriorityQueue.prototype.extract = function (withPriority) { +PriorityQueue.prototype.extract = function(withPriority) { var min = MinHeap.prototype.extract.call(this); return withPriority ? min && {item: min, priority: this._priority[min]} : min; }; -PriorityQueue.prototype.priority = function (item) { +PriorityQueue.prototype.priority = function(item) { return this._priority[item]; }; -PriorityQueue.prototype.changePriority = function (item, priority) { +PriorityQueue.prototype.changePriority = function(item, priority) { this._priority[item] = priority; this.heapify(); }; diff --git a/src/data_structures/queue.js b/src/data_structures/queue.js index 065b0d9..e625bef 100644 --- a/src/data_structures/queue.js +++ b/src/data_structures/queue.js @@ -9,27 +9,27 @@ function Queue() { this._elements = new LinkedList(); Object.defineProperty(this, 'length', { - get: function () { + get: function() { return this._elements.length; }.bind(this) }); } -Queue.prototype.isEmpty = function () { +Queue.prototype.isEmpty = function() { return this._elements.isEmpty(); }; /** * Adds element to the end of the queue */ -Queue.prototype.push = function (e) { +Queue.prototype.push = function(e) { this._elements.add(e); }; /** * Pops the element in the beginning of the queue */ -Queue.prototype.pop = function () { +Queue.prototype.pop = function() { if (this.isEmpty()) { throw new Error('Empty queue'); } @@ -38,7 +38,7 @@ Queue.prototype.pop = function () { return e; }; -Queue.prototype.peek = function () { +Queue.prototype.peek = function() { if (this.isEmpty()) { throw new Error('Empty queue'); } @@ -46,7 +46,7 @@ Queue.prototype.peek = function () { return this._elements.get(0); }; -Queue.prototype.forEach = function (fn) { +Queue.prototype.forEach = function(fn) { this._elements.forEach(fn); }; diff --git a/src/data_structures/set.js b/src/data_structures/set.js index e6868a3..e3f0fe0 100644 --- a/src/data_structures/set.js +++ b/src/data_structures/set.js @@ -7,36 +7,36 @@ var HashTable = require('./hash_table'); * No restriction on element types * i.e. set.add(1,'a', "b", { "foo" : "bar" }) */ -var HashSet = function () { +var HashSet = function() { this._elements = new HashTable(arguments.length); this.add.apply(this, arguments); Object.defineProperty(this, 'size', { - get: function () { + get: function() { return this._elements.size; } }); }; -HashSet.prototype.add = function () { +HashSet.prototype.add = function() { for (var i = 0; i < arguments.length; i++) { this._elements.put(arguments[i], true); } return this; }; -HashSet.prototype.remove = function () { +HashSet.prototype.remove = function() { for (var i = 0; i < arguments.length; i++) { this._elements.del(arguments[i]); } return this; }; -HashSet.prototype.contains = function (e) { - return this._elements.get(e) !== undefined; +HashSet.prototype.contains = function(e) { + return typeof this._elements.get(e) !== 'undefined'; }; -HashSet.prototype.forEach = function (fn) { +HashSet.prototype.forEach = function(fn) { this._elements.forEach(fn); }; diff --git a/src/data_structures/stack.js b/src/data_structures/stack.js index e52b4c7..de5f4ee 100644 --- a/src/data_structures/stack.js +++ b/src/data_structures/stack.js @@ -19,7 +19,7 @@ Stack.prototype = new Queue(); /** * Adds element to the top of the stack */ -Stack.prototype.push = function (e) { +Stack.prototype.push = function(e) { this._elements.add(e, 0); }; diff --git a/src/data_structures/treap.js b/src/data_structures/treap.js index 8c5fbc5..4949e56 100644 --- a/src/data_structures/treap.js +++ b/src/data_structures/treap.js @@ -14,18 +14,18 @@ function Node(value, left, right) { /** * Computer the number of childnodes */ -Node.prototype.resize = function () { - this.size = (this.children[0] ? this.children[0].size : 0) - + (this.children[1] ? this.children[1].size : 0) + 1; +Node.prototype.resize = function() { + this.size = (this.children[0] ? this.children[0].size : 0) + + (this.children[1] ? this.children[1].size : 0) + 1; this.height = Math.max(this.children[0] ? this.children[0].height : 0, - this.children[1] ? this.children[1].height : 0) + 1; + this.children[1] ? this.children[1].height : 0) + 1; return this; }; /** * Zigzag rotate of tree nodes */ -Node.prototype.rotate = function (side) { +Node.prototype.rotate = function(side) { var temp = this.children[side]; // Rotate @@ -48,7 +48,7 @@ function Treap() { /** * Insert new value into the subtree of `node` */ -Treap.prototype._insert = function (node, value) { +Treap.prototype._insert = function(node, value) { if (node === null) { return new Node(value, null, null); } @@ -59,13 +59,12 @@ Treap.prototype._insert = function (node, value) { // Keep it balance if (node.children[side].key < node.key) { - return node.rotate(side); - } else { - return node.resize(); + return node.rotate(side); } + return node.resize(); }; -Treap.prototype._find = function (node, value) { +Treap.prototype._find = function(node, value) { if (node === null) { // Empty tree return false; @@ -80,7 +79,7 @@ Treap.prototype._find = function (node, value) { return this._find(node.children[side], value); }; -Treap.prototype._minimum = function (node) { +Treap.prototype._minimum = function(node) { if (node === null) { // Empty tree, returns Infinity return Infinity; @@ -89,7 +88,7 @@ Treap.prototype._minimum = function (node) { return Math.min(node.value, this._minimum(node.children[0])); }; -Treap.prototype._maximum = function (node) { +Treap.prototype._maximum = function(node) { if (node === null) { // Empty tree, returns -Infinity return -Infinity; @@ -98,7 +97,7 @@ Treap.prototype._maximum = function (node) { return Math.max(node.value, this._maximum(node.children[1])); }; -Treap.prototype._remove = function (node, value) { +Treap.prototype._remove = function(node, value) { if (node === null) { // Empty node, value not found return null; @@ -112,43 +111,42 @@ Treap.prototype._remove = function (node, value) { return null; } - // Rotate to a subtree and remove it - side = (node.children[0] === null ? 1 : 0); - node = node.rotate(side); - node.children[1 - side] = this._remove(node.children[1 - side], value); - return node.resize(); + // Rotate to a subtree and remove it + side = (node.children[0] === null ? 1 : 0); + node = node.rotate(side); + node.children[1 - side] = this._remove(node.children[1 - side], value); } else { side = ~~(value > node.value); node.children[side] = this._remove(node.children[side], value); - return node.resize(); } + return node.resize(); }; -Treap.prototype.insert = function (value) { +Treap.prototype.insert = function(value) { this.root = this._insert(this.root, value); }; -Treap.prototype.find = function (value) { +Treap.prototype.find = function(value) { return this._find(this.root, value); }; -Treap.prototype.minimum = function () { +Treap.prototype.minimum = function() { return this._minimum(this.root); }; -Treap.prototype.maximum = function () { +Treap.prototype.maximum = function() { return this._maximum(this.root); }; -Treap.prototype.remove = function (value) { +Treap.prototype.remove = function(value) { this.root = this._remove(this.root, value); }; -Treap.prototype.size = function () { +Treap.prototype.size = function() { return this.root ? this.root.size : 0; }; -Treap.prototype.height = function () { +Treap.prototype.height = function() { return this.root ? this.root.height : 0; }; diff --git a/src/test/algorithms/geometry/bezier_curve.js b/src/test/algorithms/geometry/bezier_curve.js index 5b0dea0..9d09692 100644 --- a/src/test/algorithms/geometry/bezier_curve.js +++ b/src/test/algorithms/geometry/bezier_curve.js @@ -1,13 +1,13 @@ 'use strict'; -var root = require('../../../'), - BezierCurve = root.Geometry.BezierCurve, - assert = require('assert'); +var root = require('../../../'); +var BezierCurve = root.Geometry.BezierCurve; +var assert = require('assert'); // Testing with http://pomax.github.io/bezierjs/ -describe('Bézier-Curve Algorithm', function () { - it('should get a linear Bézier-curve', function () { +describe('Bézier-Curve Algorithm', function() { + it('should get a linear Bézier-curve', function() { var b = new BezierCurve([{x: 0, y: 0}, {x: 10, y: 3}]); // Ends @@ -21,7 +21,7 @@ describe('Bézier-Curve Algorithm', function () { assert.deepEqual(b.get(0.25), {x: 2.5, y: 0.75}); assert.deepEqual(b.get(0.75), {x: 7.5, y: 2.25}); }); - it('should get a quadratic Bézier-curve', function () { + it('should get a quadratic Bézier-curve', function() { var b = new BezierCurve([{x: 150, y: 40}, {x: 80, y: 30}, {x: 105, y: 150}]); @@ -29,7 +29,7 @@ describe('Bézier-Curve Algorithm', function () { assert.deepEqual(b.get(0.5), {x: 103.75, y: 62.5}); assert.deepEqual(b.get(0.25), {x: 120.9375, y: 43.125}); }); - it('should get a cubic Bézier-curve', function () { + it('should get a cubic Bézier-curve', function() { var b = new BezierCurve([{x: 150, y: 40}, {x: 80, y: 30}, {x: 105, y: 150}, diff --git a/src/test/algorithms/graph/SPFA.js b/src/test/algorithms/graph/SPFA.js index 0560e8e..70fa91e 100644 --- a/src/test/algorithms/graph/SPFA.js +++ b/src/test/algorithms/graph/SPFA.js @@ -1,13 +1,13 @@ 'use strict'; -var root = require('../../../'), - spfa = root.Graph.SPFA, - Graph = root.DataStructures.Graph, - assert = require('assert'); +var root = require('../../../'); +var spfa = root.Graph.SPFA; +var Graph = root.DataStructures.Graph; +var assert = require('assert'); -describe('SPFA Algorithm', function () { +describe('SPFA Algorithm', function() { it('should return the shortest paths to all nodes from a given origin', - function () { + function() { var graph = new Graph(true); graph.addEdge('a', 'b', -1); diff --git a/src/test/algorithms/graph/bellman_ford.js b/src/test/algorithms/graph/bellman_ford.js index 53dbe2f..566d294 100644 --- a/src/test/algorithms/graph/bellman_ford.js +++ b/src/test/algorithms/graph/bellman_ford.js @@ -1,13 +1,13 @@ 'use strict'; -var root = require('../../../'), - bellmanFord = root.Graph.bellmanFord, - Graph = root.DataStructures.Graph, - assert = require('assert'); +var root = require('../../../'); +var bellmanFord = root.Graph.bellmanFord; +var Graph = root.DataStructures.Graph; +var assert = require('assert'); -describe('Bellman-Ford Algorithm', function () { +describe('Bellman-Ford Algorithm', function() { it('should return the shortest paths to all nodes from a given origin', - function () { + function() { var graph = new Graph(true); graph.addEdge('a', 'b', -1); diff --git a/src/test/algorithms/graph/bfs_shortest_path.js b/src/test/algorithms/graph/bfs_shortest_path.js index bf8af32..ef04021 100644 --- a/src/test/algorithms/graph/bfs_shortest_path.js +++ b/src/test/algorithms/graph/bfs_shortest_path.js @@ -1,46 +1,45 @@ 'use strict'; -var root = require('../../../'), - bfsShortestPath = root.Graph.bfsShortestPath, - Graph = root.DataStructures.Graph, - assert = require('assert'); +var root = require('../../../'); +var bfsShortestPath = root.Graph.bfsShortestPath; +var Graph = root.DataStructures.Graph; +var assert = require('assert'); - -describe('BFS Shortest Path Algorithm', function () { +describe('BFS Shortest Path Algorithm', function() { it('should return the shortest paths to all nodes from a given origin', - function () { - var graph = new Graph(); - graph.addEdge(0, 1); - graph.addEdge(1, 2); - graph.addEdge(0, 2); - graph.addEdge(2, 3); - graph.addEdge(3, 6); - graph.addEdge(6, 2); - graph.addEdge(6, 0); - graph.addEdge(0, 4); - graph.addEdge(4, 6); - graph.addEdge(4, 5); - graph.addEdge(5, 0); - graph.addEdge('a', 'b'); + function() { + var graph = new Graph(); + graph.addEdge(0, 1); + graph.addEdge(1, 2); + graph.addEdge(0, 2); + graph.addEdge(2, 3); + graph.addEdge(3, 6); + graph.addEdge(6, 2); + graph.addEdge(6, 0); + graph.addEdge(0, 4); + graph.addEdge(4, 6); + graph.addEdge(4, 5); + graph.addEdge(5, 0); + graph.addEdge('a', 'b'); - var shortestPath = bfsShortestPath(graph, 0); + var shortestPath = bfsShortestPath(graph, 0); - assert.deepEqual(shortestPath.distance, { - 0: 0, - 1: 1, - 2: 1, - 3: 2, - 4: 1, - 5: 2, - 6: 2 - }); - assert.deepEqual(shortestPath.previous, { - 1: 0, - 2: 0, - 3: 2, - 4: 0, - 5: 4, - 6: 4 - }); - }); + assert.deepEqual(shortestPath.distance, { + 0: 0, + 1: 1, + 2: 1, + 3: 2, + 4: 1, + 5: 2, + 6: 2 + }); + assert.deepEqual(shortestPath.previous, { + 1: 0, + 2: 0, + 3: 2, + 4: 0, + 5: 4, + 6: 4 + }); + }); }); diff --git a/src/test/algorithms/graph/breadth_first_search.js b/src/test/algorithms/graph/breadth_first_search.js index 9bc62a7..263365a 100644 --- a/src/test/algorithms/graph/breadth_first_search.js +++ b/src/test/algorithms/graph/breadth_first_search.js @@ -1,15 +1,14 @@ 'use strict'; -var root = require('../../../'), - breadthFirstSearch = root.Graph.breadthFirstSearch, - Graph = root.DataStructures.Graph, - assert = require('assert'); +var root = require('../../../'); +var breadthFirstSearch = root.Graph.breadthFirstSearch; +var Graph = root.DataStructures.Graph; +var assert = require('assert'); - -describe('Breadth-First Search', function () { +describe('Breadth-First Search', function() { var graph; - before(function () { + before(function() { graph = new Graph(); graph.addEdge(1, 2); graph.addEdge(1, 5); @@ -22,23 +21,24 @@ describe('Breadth-First Search', function () { graph.addEdge('alpha', 'omega'); }); - it('should visit reachable vertices in a breadth-first manner', function () { - var enter = [], leave = []; + it('should visit reachable vertices in a breadth-first manner', function() { + var enter = []; + var leave = []; var lastEntered = null; var traversed = 0; breadthFirstSearch(graph, 1); breadthFirstSearch(graph, 1, { - enterVertex: function (vertex) { + enterVertex: function(vertex) { enter.push(vertex); lastEntered = vertex; }, - leaveVertex: function (vertex) { + leaveVertex: function(vertex) { assert.equal(lastEntered, vertex); leave.push(vertex); }, - onTraversal: function () { + onTraversal: function() { traversed += 1; } }); @@ -53,24 +53,23 @@ describe('Breadth-First Search', function () { assert.equal(enter[5], 3); }); - it('should allow user-defined allowTraversal rules', function () { + it('should allow user-defined allowTraversal rules', function() { var seen = new Graph(graph.directed); graph.vertices.forEach(seen.addVertex.bind(seen)); - var indegrees = {1: -1}, outdegrees = {}; + var indegrees = {1: -1}; + var outdegrees = {}; // Edge-centric BFS. breadthFirstSearch(graph, 1, { - allowTraversal: function (vertex, neighbor) { - if (!seen.edge(vertex, neighbor)) { + allowTraversal: function(vertex, neighbor) { + var visited = seen.edge(vertex, neighbor); + if (!visited) { seen.addEdge(vertex, neighbor); outdegrees[vertex] = (outdegrees[vertex] || 0) + 1; - return true; - } - else { - return false; } + return !visited; }, - enterVertex: function (vertex) { + enterVertex: function(vertex) { indegrees[vertex] = (indegrees[vertex] || 0) + 1; outdegrees[vertex] = outdegrees[vertex] || 0; } diff --git a/src/test/algorithms/graph/depth_first_search.js b/src/test/algorithms/graph/depth_first_search.js index ea651c5..e60b732 100644 --- a/src/test/algorithms/graph/depth_first_search.js +++ b/src/test/algorithms/graph/depth_first_search.js @@ -1,14 +1,13 @@ 'use strict'; -var root = require('../../../'), - depthFirstSearch = root.Graph.depthFirstSearch, - Graph = root.DataStructures.Graph, - assert = require('assert'); - -describe('Depth First Search Algorithm', function () { +var root = require('../../../'); +var depthFirstSearch = root.Graph.depthFirstSearch; +var Graph = root.DataStructures.Graph; +var assert = require('assert'); +describe('Depth First Search Algorithm', function() { var graph; - before(function () { + before(function() { graph = new Graph(true); graph.addEdge('one', 'three'); graph.addEdge('one', 'four'); @@ -19,19 +18,21 @@ describe('Depth First Search Algorithm', function () { }); it('should visit only the nodes reachable from the start node (inclusive)', - function () { - var enter = [], leave = []; - var numEdgeTails = 0, numEdgeHeads = 0; + function() { + var enter = []; + var leave = []; + var numEdgeTails = 0; + var numEdgeHeads = 0; depthFirstSearch(graph, 'one'); var dfsCallbacks = { enterVertex: [].push.bind(enter), leaveVertex: [].push.bind(leave), - beforeTraversal: function () { + beforeTraversal: function() { numEdgeHeads += 1; }, - afterTraversal: function () { + afterTraversal: function() { numEdgeTails += 1; } }; @@ -52,17 +53,17 @@ describe('Depth First Search Algorithm', function () { } ); - it('should allow user-defined allowTraversal rules', function () { + it('should allow user-defined allowTraversal rules', function() { var seen = new Graph(graph.directed); graph.vertices.forEach(seen.addVertex.bind(seen)); var path = ['one']; // Edge-centric DFS. depthFirstSearch(graph, path[0], { - allowTraversal: function (vertex, neighbor) { + allowTraversal: function(vertex, neighbor) { return !seen.edge(vertex, neighbor); }, - beforeTraversal: function (vertex, neighbor) { + beforeTraversal: function(vertex, neighbor) { seen.addEdge(vertex, neighbor); path.push(neighbor); } diff --git a/src/test/algorithms/graph/dijkstra.js b/src/test/algorithms/graph/dijkstra.js index e3eb998..e0346b8 100644 --- a/src/test/algorithms/graph/dijkstra.js +++ b/src/test/algorithms/graph/dijkstra.js @@ -1,13 +1,13 @@ 'use strict'; -var root = require('../../../'), - dijkstra = root.Graph.dijkstra, - Graph = root.DataStructures.Graph, - assert = require('assert'); +var root = require('../../../'); +var dijkstra = root.Graph.dijkstra; +var Graph = root.DataStructures.Graph; +var assert = require('assert'); -describe('Dijkstra Algorithm', function () { +describe('Dijkstra Algorithm', function() { it('should return the shortest paths to all nodes from a given origin', - function () { + function() { var g = new Graph(); g.addEdge('a', 'b', 5); g.addEdge('a', 'c', 10); diff --git a/src/test/algorithms/graph/euler_path.js b/src/test/algorithms/graph/euler_path.js index 53ad7f0..d28eb8c 100644 --- a/src/test/algorithms/graph/euler_path.js +++ b/src/test/algorithms/graph/euler_path.js @@ -1,39 +1,37 @@ 'use strict'; +var root = require('../../../'); +var eulerPath = root.Graph.eulerPath; +var Graph = root.DataStructures.Graph; +var assert = require('assert'); -var root = require('../../../'), - eulerPath = root.Graph.eulerPath, - Graph = root.DataStructures.Graph, - assert = require('assert'); - - -describe('Euler Path', function () { - var verifyEulerPath = function (graph, trail) { +describe('Euler Path', function() { + var verifyEulerPath = function(graph, trail) { var visited = new Graph(graph.directed); graph.vertices.forEach(visited.addVertex.bind(visited)); - trail.slice(1).reduce(function (previous, current) { + trail.slice(1).reduce(function(previous, current) { assert(graph.edge(previous, current)); assert(!visited.edge(previous, current)); visited.addEdge(previous, current); return current; }, trail[0]); - graph.vertices.forEach(function (vertex) { + graph.vertices.forEach(function(vertex) { assert.equal(graph.neighbors(vertex).length, visited.neighbors(vertex).length); }); }; - var graphFromEdges = function (directed, edges) { + var graphFromEdges = function(directed, edges) { var graph = new Graph(directed); - edges.forEach(function (edge) { + edges.forEach(function(edge) { graph.addEdge(edge[0], edge[1]); }); return graph; }; - it('should compute Euler tour over the undirected graph', function () { + it('should compute Euler tour over the undirected graph', function() { var graph = graphFromEdges(false, [ [1, 2], [1, 5], @@ -56,7 +54,7 @@ describe('Euler Path', function () { assert.equal(trail[0], trail.slice(-1)[0]); }); - it('should compute Euler walk over the undirected graph', function () { + it('should compute Euler walk over the undirected graph', function() { var graph = graphFromEdges(false, [ [1, 2], [1, 5], @@ -81,7 +79,7 @@ describe('Euler Path', function () { assert.equal(endpoints[1], 8); }); - it('should compute Euler tour over the directed graph', function () { + it('should compute Euler tour over the directed graph', function() { var graph = graphFromEdges(true, [ [0, 1], [1, 2], @@ -99,7 +97,7 @@ describe('Euler Path', function () { assert.equal(trail[0], trail.slice(-1)[0]); }); - it('should compute Euler walk over the directed graph', function () { + it('should compute Euler walk over the directed graph', function() { var graph = graphFromEdges(true, [ [5, 0], [0, 2], @@ -113,20 +111,20 @@ describe('Euler Path', function () { assert.deepEqual(trail, [5, 3, 1, 5, 0, 2, 4, 0]); }); - it('should return single-vertex-trail for an isolated vertex', function () { + it('should return single-vertex-trail for an isolated vertex', function() { var graph = new Graph(); graph.addVertex('loner'); var trail = eulerPath(graph); assert.deepEqual(trail, ['loner']); }); - it('should return empty trail for an empty graph', function () { + it('should return empty trail for an empty graph', function() { var graph = new Graph(); var trail = eulerPath(graph); assert.deepEqual(trail, []); }); - it('should raise an error if there is no Euler path', function () { + it('should raise an error if there is no Euler path', function() { var graph = graphFromEdges(false, [[0, 1], [2, 3]]); assert.throws(eulerPath.bind(null, graph)); diff --git a/src/test/algorithms/graph/floyd_warshall.js b/src/test/algorithms/graph/floyd_warshall.js index 39003ba..56c8c62 100644 --- a/src/test/algorithms/graph/floyd_warshall.js +++ b/src/test/algorithms/graph/floyd_warshall.js @@ -1,13 +1,12 @@ 'use strict'; -var root = require('../../../'), - floydWarshall = root.Graph.floydWarshall, - Graph = root.DataStructures.Graph, - assert = require('assert'); +var root = require('../../../'); +var floydWarshall = root.Graph.floydWarshall; +var Graph = root.DataStructures.Graph; +var assert = require('assert'); - -describe('Floyd-Warshall Algorithm', function () { - it('should compute all-pairs shortest paths in the graph', function () { +describe('Floyd-Warshall Algorithm', function() { + it('should compute all-pairs shortest paths in the graph', function() { var graph = new Graph(); graph.addEdge('a', 'b', -2); graph.addEdge('b', 'c', -1); @@ -19,42 +18,42 @@ describe('Floyd-Warshall Algorithm', function () { var result = floydWarshall(graph); - assert.deepEqual(result.distance, {'a': {'a': 0, - 'b': -2, - 'c': -3, - 'x': -1, - 'y': -6, - 'z': Infinity}, - 'b': {'a': 3, - 'b': 0, - 'c': -1, - 'x': 1, - 'y': -4, - 'z': Infinity}, - 'c': {'a': 4, - 'b': 2, - 'c': 0, - 'x': 2, - 'y': -3, - 'z': Infinity}, - 'x': {'a': Infinity, - 'b': Infinity, - 'c': Infinity, - 'x': 0, - 'y': Infinity, - 'z': Infinity}, - 'y': {'a': Infinity, - 'b': Infinity, - 'c': Infinity, - 'x': Infinity, - 'y': 0, - 'z': Infinity}, - 'z': {'a': Infinity, - 'b': Infinity, - 'c': Infinity, - 'x': 1, - 'y': -4, - 'z': 0}}); + assert.deepEqual(result.distance, {a: {a: 0, + b: -2, + c: -3, + x: -1, + y: -6, + z: Infinity}, + b: {a: 3, + b: 0, + c: -1, + x: 1, + y: -4, + z: Infinity}, + c: {a: 4, + b: 2, + c: 0, + x: 2, + y: -3, + z: Infinity}, + x: {a: Infinity, + b: Infinity, + c: Infinity, + x: 0, + y: Infinity, + z: Infinity}, + y: {a: Infinity, + b: Infinity, + c: Infinity, + x: Infinity, + y: 0, + z: Infinity}, + z: {a: Infinity, + b: Infinity, + c: Infinity, + x: 1, + y: -4, + z: 0}}); assert.equal(result.path('x', 'y'), null); assert.deepEqual(result.path('z', 'z'), ['z']); @@ -63,7 +62,7 @@ describe('Floyd-Warshall Algorithm', function () { }); it('should determine if the graph contains a negative-weighted cycle', - function () { + function() { var graph = new Graph(); graph.addEdge('a', 'b', -2); graph.addEdge('b', 'c', -1); diff --git a/src/test/algorithms/graph/minimum_spanning_tree.js b/src/test/algorithms/graph/minimum_spanning_tree.js index 1191886..21264e8 100644 --- a/src/test/algorithms/graph/minimum_spanning_tree.js +++ b/src/test/algorithms/graph/minimum_spanning_tree.js @@ -1,32 +1,30 @@ 'use strict'; -var root = require('../../../'), - kruskal = root.Graph.kruskal, - prim = root.Graph.prim, - depthFirstSearch = root.Graph.depthFirstSearch, - Graph = root.DataStructures.Graph, - assert = require('assert'); - - -describe('Minimum Spanning Tree', function () { - +var root = require('../../../'); +var kruskal = root.Graph.kruskal; +var prim = root.Graph.prim; +var depthFirstSearch = root.Graph.depthFirstSearch; +var Graph = root.DataStructures.Graph; +var assert = require('assert'); + +describe('Minimum Spanning Tree', function() { /** * @param {Graph} graph - Undirected graph. * @return {number} */ - var numberOfConnectedComponents = function (graph) { + var numberOfConnectedComponents = function(graph) { assert(!graph.directed); var seen = {}; - var coverComponent = function (origin) { + var coverComponent = function(origin) { depthFirstSearch(graph, origin, { - enterVertex: function (vertex) { + enterVertex: function(vertex) { seen[vertex] = true; } }); }; var count = 0; - graph.vertices.forEach(function (vertex) { + graph.vertices.forEach(function(vertex) { if (!seen[vertex]) { coverComponent(vertex); count++; @@ -35,7 +33,6 @@ describe('Minimum Spanning Tree', function () { return count; }; - /** * Test whether graph is a valid (undirected) forest. * In a forest #vertices = #edges + #components. @@ -44,23 +41,20 @@ describe('Minimum Spanning Tree', function () { * @param {number} connectivity * @return {boolean} */ - var isForest = function (graph, connectivity) { + var isForest = function(graph, connectivity) { if (graph.directed || numberOfConnectedComponents(graph) !== connectivity) { return false; } var numberOfEdges = 0; - graph.vertices.forEach(function (vertex) { - graph.neighbors(vertex).filter( - function (neighbor) { - if (vertex <= neighbor) { - numberOfEdges++; - } - }); + graph.vertices.forEach(function(vertex) { + numberOfEdges += graph.neighbors(vertex).filter( + function(neighbor) { + return vertex <= neighbor; + }).length; }); return graph.vertices.size === numberOfEdges + connectivity; }; - /** * Test whether two graphs share the same vertex set. * @@ -68,11 +62,11 @@ describe('Minimum Spanning Tree', function () { * @param {Graph} graph2 * @return {boolean} */ - var spans = function (graph1, graph2) { + var spans = function(graph1, graph2) { var span; if (graph1.vertices.size === graph2.vertices.size) { span = true; - graph1.vertices.forEach(function (v) { + graph1.vertices.forEach(function(v) { if (!graph2.vertices.contains(v)) { span = false; } @@ -83,26 +77,22 @@ describe('Minimum Spanning Tree', function () { return span; }; - /** * Sum up graph edge weights. * * @param {Graph} graph - * @return {?number} Null if the graph contains no edges. + * @return {number} */ - var graphCost = function (graph) { - var noEdges = true; + var graphCost = function(graph) { var total = 0; - graph.vertices.forEach(function (vertex) { - graph.neighbors(vertex).forEach(function (neighbor) { - noEdges = false; - total += graph.edge(vertex, neighbor); - }); + graph.vertices.forEach(function(vertex) { + total += graph.neighbors(vertex).reduce(function(accum, neighbor) { + return accum + graph.edge(vertex, neighbor); + }, 0); }); - return noEdges ? null : graph.directed ? total : total / 2; + return graph.directed ? total : total / 2; }; - /** * Test whether one graph is the minimum spanning forest of the other. * @@ -112,7 +102,7 @@ describe('Minimum Spanning Tree', function () { * @param {number} [connectivity=1] * @return {boolean} */ - var isMinimumSpanningForest = function (suspect, graph, + var isMinimumSpanningForest = function(suspect, graph, minimumCost, connectivity) { assert(!graph.directed); return isForest(suspect, connectivity || 1) && @@ -120,9 +110,8 @@ describe('Minimum Spanning Tree', function () { graphCost(suspect) === minimumCost; }; - - var testMstAlgorithm = function (mst) { - it('should find a minimum spanning tree', function () { + var testMstAlgorithm = function(mst) { + it('should find a minimum spanning tree', function() { var graph = new Graph(false); graph.addEdge(1, 2, 1); graph.addEdge(1, 4, 2); @@ -145,7 +134,7 @@ describe('Minimum Spanning Tree', function () { assert(isMinimumSpanningForest(mst(graph), graph, 10)); // It should find zero-cost MST. - var clear = function (a, b) { + var clear = function(a, b) { graph.addEdge(a, b, -graph.edge(a, b)); }; clear(2, 1); @@ -161,39 +150,38 @@ describe('Minimum Spanning Tree', function () { }); it('should find a minimum spaning forest if the graph is not connected', - function () { - var graph = new Graph(false); - graph.addVertex(1); - graph.addVertex(2); - graph.addVertex(3); - assert(isMinimumSpanningForest(mst(graph), graph, null, 3)); + function() { + var graph = new Graph(false); + graph.addVertex(1); + graph.addVertex(2); + graph.addVertex(3); + assert(isMinimumSpanningForest(mst(graph), graph, 0, 3)); - graph.addEdge(1, 2, 2); - assert(isMinimumSpanningForest(mst(graph), graph, 2, 2)); + graph.addEdge(1, 2, 2); + assert(isMinimumSpanningForest(mst(graph), graph, 2, 2)); - graph.addEdge(1, 3, 1); - graph.addEdge(2, 3, -1); - assert(isMinimumSpanningForest(mst(graph), graph, 0, 1)); + graph.addEdge(1, 3, 1); + graph.addEdge(2, 3, -1); + assert(isMinimumSpanningForest(mst(graph), graph, 0, 1)); - graph.addVertex(4); - assert(isMinimumSpanningForest(mst(graph), graph, 0, 2)); + graph.addVertex(4); + assert(isMinimumSpanningForest(mst(graph), graph, 0, 2)); - graph.addEdge(5, 6, 1); - assert(isMinimumSpanningForest(mst(graph), graph, 1, 3)); + graph.addEdge(5, 6, 1); + assert(isMinimumSpanningForest(mst(graph), graph, 1, 3)); - graph.addEdge(5, 4, -100); - graph.addEdge(6, 4, -100); - assert(isMinimumSpanningForest(mst(graph), graph, -200, 2)); - }); + graph.addEdge(5, 4, -100); + graph.addEdge(6, 4, -100); + assert(isMinimumSpanningForest(mst(graph), graph, -200, 2)); + }); - it('should throw an error if the graph is directed', function () { + it('should throw an error if the graph is directed', function() { var directedGraph = new Graph(true); directedGraph.addEdge('Rock', 'Hard Place'); assert.throws(mst.bind(null, directedGraph)); }); }; - describe('#Kruskal\'s Algorithm', testMstAlgorithm.bind(null, kruskal)); describe('#Prim\'s Algorithm', testMstAlgorithm.bind(null, prim)); }); diff --git a/src/test/algorithms/graph/topological_sort.js b/src/test/algorithms/graph/topological_sort.js index c8b9009..a386dd0 100644 --- a/src/test/algorithms/graph/topological_sort.js +++ b/src/test/algorithms/graph/topological_sort.js @@ -1,47 +1,46 @@ 'use strict'; -var root = require('../../../'), - topologicalSort = root.Graph.topologicalSort, - Graph = root.DataStructures.Graph, - assert = require('assert'); +var root = require('../../../'); +var topologicalSort = root.Graph.topologicalSort; +var Graph = root.DataStructures.Graph; +var assert = require('assert'); -describe('Topological Sort', function () { +describe('Topological Sort', function() { it('should return a stack with the vertices ordered' + - ' considering the dependencies', function () { - - var graph = new Graph(); - graph.addVertex('shoes'); - graph.addVertex('watch'); - graph.addVertex('underwear'); - graph.addVertex('socks'); - graph.addVertex('shirt'); - graph.addVertex('pants'); - graph.addVertex('belt'); - graph.addVertex('tie'); - graph.addVertex('jacket'); - - graph.addEdge('shirt', 'belt'); - graph.addEdge('shirt', 'tie'); - graph.addEdge('shirt', 'jacket'); - - graph.addEdge('socks', 'shoes'); - - graph.addEdge('underwear', 'pants'); - graph.addEdge('underwear', 'shoes'); - - graph.addEdge('pants', 'shoes'); - graph.addEdge('pants', 'belt'); - - graph.addEdge('belt', 'jacket'); - - graph.addEdge('tie', 'jacket'); - - var stack = topologicalSort(graph); - var a = []; - while (!stack.isEmpty()) a.push(stack.pop()); - assert.deepEqual(a, [ - 'shirt', 'socks', 'underwear', 'pants', 'shoes', - 'tie', 'watch', 'belt', 'jacket' - ]); - }); + ' considering the dependencies', function() { + var graph = new Graph(); + graph.addVertex('shoes'); + graph.addVertex('watch'); + graph.addVertex('underwear'); + graph.addVertex('socks'); + graph.addVertex('shirt'); + graph.addVertex('pants'); + graph.addVertex('belt'); + graph.addVertex('tie'); + graph.addVertex('jacket'); + + graph.addEdge('shirt', 'belt'); + graph.addEdge('shirt', 'tie'); + graph.addEdge('shirt', 'jacket'); + + graph.addEdge('socks', 'shoes'); + + graph.addEdge('underwear', 'pants'); + graph.addEdge('underwear', 'shoes'); + + graph.addEdge('pants', 'shoes'); + graph.addEdge('pants', 'belt'); + + graph.addEdge('belt', 'jacket'); + + graph.addEdge('tie', 'jacket'); + + var stack = topologicalSort(graph); + var a = []; + while (!stack.isEmpty()) a.push(stack.pop()); + assert.deepEqual(a, [ + 'shirt', 'socks', 'underwear', 'pants', 'shoes', + 'tie', 'watch', 'belt', 'jacket' + ]); + }); }); diff --git a/src/test/algorithms/math/collatz_conjecture.js b/src/test/algorithms/math/collatz_conjecture.js index bba8a45..753adcd 100644 --- a/src/test/algorithms/math/collatz_conjecture.js +++ b/src/test/algorithms/math/collatz_conjecture.js @@ -1,23 +1,23 @@ 'use strict'; -var math = require('../../..').Math, - collatzConjecture = math.collatzConjecture, - assert = require('assert'); +var math = require('../../..').Math; +var collatzConjecture = math.collatzConjecture; +var assert = require('assert'); -describe('Collatz Conjecture', function () { - it('should return odd numbers divided by two', function () { +describe('Collatz Conjecture', function() { + it('should return odd numbers divided by two', function() { assert.equal(collatzConjecture.calculate(200), 100); assert.equal(collatzConjecture.calculate(222), 111); assert.equal(collatzConjecture.calculate(444), 222); }); - it('should return even numbers multiplied by 3 + 1', function () { + it('should return even numbers multiplied by 3 + 1', function() { assert.equal(collatzConjecture.calculate(111), 334); assert.equal(collatzConjecture.calculate(333), 1000); assert.equal(collatzConjecture.calculate(555), 1666); }); - it('should return Collatz Conjecture sequence ', function () { + it('should return Collatz Conjecture sequence ', function() { assert.deepEqual(collatzConjecture.generate(10), [5, 16, 8, 4, 2, 1]); }); }); diff --git a/src/test/algorithms/math/extended_euclidean.js b/src/test/algorithms/math/extended_euclidean.js index ecd9de3..f155ae8 100644 --- a/src/test/algorithms/math/extended_euclidean.js +++ b/src/test/algorithms/math/extended_euclidean.js @@ -1,11 +1,11 @@ 'use strict'; -var math = require('../../..').Math, - extEuclid = math.extendedEuclidean, - assert = require('assert'); +var math = require('../../..').Math; +var extEuclid = math.extendedEuclidean; +var assert = require('assert'); -describe('extEuclid', function () { - it('should calculate the solve to Bézout\'s identity', function () { +describe('extEuclid', function() { + it('should calculate the solve to Bézout\'s identity', function() { var solve = extEuclid(1, 0); assert.equal(solve.x, 1); assert.equal(solve.y, 0); diff --git a/src/test/algorithms/math/fast_power.js b/src/test/algorithms/math/fast_power.js index bcad8fe..4344429 100644 --- a/src/test/algorithms/math/fast_power.js +++ b/src/test/algorithms/math/fast_power.js @@ -1,23 +1,20 @@ 'use strict'; -var math = require('../../..').Math, - power = math.fastPower, - assert = require('assert'); +var math = require('../../..').Math; +var power = math.fastPower; +var assert = require('assert'); - -var assertApproximatelyEqual = function (a, b, eps) { +var assertApproximatelyEqual = function(a, b, eps) { eps = eps || 1e-12; assert(Math.abs(a - b) < eps); }; - -var multiplyModulo = function (modulo) { - return function (a, b) { +var multiplyModulo = function(modulo) { + return function(a, b) { return (a * b) % modulo; }; }; - /** * This operation is isomorphic to addition in Z/3. * @@ -28,7 +25,7 @@ var multiplyModulo = function (modulo) { * c | c | a | b | * --------------- */ -var abcMultiply = function (a, b) { +var abcMultiply = function(a, b) { var table = { a: {a: 'a', b: 'b', c: 'c'}, b: {a: 'b', b: 'c', c: 'a'}, @@ -38,9 +35,8 @@ var abcMultiply = function (a, b) { return table[a][b]; }; - -describe('Fast Power', function () { - it('should correctly raise numbers to positive integer powers', function () { +describe('Fast Power', function() { + it('should correctly raise numbers to positive integer powers', function() { assert.equal(power(2, 5), 32); assert.equal(power(32, 1), 32); assert.equal(power(3, 7), Math.pow(3, 7)); @@ -52,15 +48,15 @@ describe('Fast Power', function () { }); it('should raise an error if the power is not a nonnegative integer', - function () { + function() { // It is not clear how to handle these cases // when custom multiplication is also supplied. - assert.throws(power.bind(null, 7, -2)); - assert.throws(power.bind(null, 5, -1)); - assert.throws(power.bind(null, Math.PI, Math.E)); - }); + assert.throws(power.bind(null, 7, -2)); + assert.throws(power.bind(null, 5, -1)); + assert.throws(power.bind(null, Math.PI, Math.E)); + }); - it('should accept custom multiplication functions', function () { + it('should accept custom multiplication functions', function() { // Math.pow is basically useless here. assert.equal(power(0, 0, multiplyModulo(5), 1), 1); @@ -77,8 +73,8 @@ describe('Fast Power', function () { }); it('should raise an error if the power is zero but no identity value given' + - ' (custom multiplication)', function () { - assert.throws(power.bind(null, 0, 0, multiplyModulo(5))); - assert.throws(power.bind(null, 'a', 0, abcMultiply)); - }); + ' (custom multiplication)', function() { + assert.throws(power.bind(null, 0, 0, multiplyModulo(5))); + assert.throws(power.bind(null, 'a', 0, abcMultiply)); + }); }); diff --git a/src/test/algorithms/math/fibonacci.js b/src/test/algorithms/math/fibonacci.js index 78043c5..129a005 100644 --- a/src/test/algorithms/math/fibonacci.js +++ b/src/test/algorithms/math/fibonacci.js @@ -1,10 +1,10 @@ 'use strict'; -var math = require('../../..').Math, - fib = math.fibonacci, - assert = require('assert'); +var math = require('../../..').Math; +var fib = math.fibonacci; +var assert = require('assert'); -var testFibonacciSequence = function (fib) { +var testFibonacciSequence = function(fib) { assert.equal(0, fib(0)); assert.equal(1, fib(1)); assert.equal(1, fib(2)); @@ -20,33 +20,33 @@ var testFibonacciSequence = function (fib) { assert.equal(144, fib(12)); }; -describe('Fibonacci', function () { - describe('#exponential()', function () { - it('should return the right value for fibonacci sequence', function () { +describe('Fibonacci', function() { + describe('#exponential()', function() { + it('should return the right value for fibonacci sequence', function() { testFibonacciSequence(fib.exponential); }); }); - describe('#linear()', function () { - it('should return the right value for fibonacci sequence', function () { + describe('#linear()', function() { + it('should return the right value for fibonacci sequence', function() { testFibonacciSequence(fib); }); }); - describe('#withMemoization()', function () { - it('should return the right value for fibonacci sequence', function () { + describe('#withMemoization()', function() { + it('should return the right value for fibonacci sequence', function() { testFibonacciSequence(fib.withMemoization); }); }); - describe('#direct()', function () { - it('should return the right value for fibonacci sequence', function () { + describe('#direct()', function() { + it('should return the right value for fibonacci sequence', function() { testFibonacciSequence(fib.direct); }); }); - describe('#logarithmic()', function () { - it('should return the right value for fibonacci sequence', function () { + describe('#logarithmic()', function() { + it('should return the right value for fibonacci sequence', function() { testFibonacciSequence(fib.logarithmic); }); }); diff --git a/src/test/algorithms/math/fisher_yates.js b/src/test/algorithms/math/fisher_yates.js index 7112538..03be860 100644 --- a/src/test/algorithms/math/fisher_yates.js +++ b/src/test/algorithms/math/fisher_yates.js @@ -1,21 +1,21 @@ 'use strict'; -var math = require('../../..').Math, - fisherYates = math.fisherYates, - assert = require('assert'); +var math = require('../../..').Math; +var fisherYates = math.fisherYates; +var assert = require('assert'); -describe('Fisher-Yates', function () { - it('should shuffle the elements in the array in-place', function () { +describe('Fisher-Yates', function() { + it('should shuffle the elements in the array in-place', function() { var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; fisherYates(a); assert.notDeepEqual(a, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); }); - describe('should be able to be used as Array.suffle', function () { + describe('should be able to be used as Array.suffle', function() { var a = [1, 2, 3, 4, 5]; assert.equal(a.shuffle, undefined); /* eslint-disable no-extend-native */ - Array.prototype.shuffle = function () { + Array.prototype.shuffle = function() { fisherYates(this); }; /* eslint-enable no-extend-native */ diff --git a/src/test/algorithms/math/gcd.js b/src/test/algorithms/math/gcd.js index 1fa476c..5966e97 100644 --- a/src/test/algorithms/math/gcd.js +++ b/src/test/algorithms/math/gcd.js @@ -1,11 +1,11 @@ 'use strict'; -var root = require('../../..'), - gcd = root.Math.gcd, - assert = require('assert'); +var root = require('../../..'); +var gcd = root.Math.gcd; +var assert = require('assert'); -describe('GCD', function () { - it('should calculate the correct GCD between two numbers', function () { +describe('GCD', function() { + it('should calculate the correct GCD between two numbers', function() { assert.equal(gcd(1, 0), 1); assert.equal(gcd(2, 2), 2); assert.equal(gcd(2, 4), 2); @@ -19,21 +19,20 @@ describe('GCD', function () { }); it('should calculate the correct GCD between two numbers using ' + - 'the binary method', function () { - var gcdb = gcd.binary; - assert.equal(gcdb(1, 0), 1); - assert.equal(gcdb(0, 1), 1); - assert.equal(gcdb(0, 0), 0); - assert.equal(gcdb(2, 2), 2); - assert.equal(gcdb(2, 4), 2); - assert.equal(gcdb(4, 2), 2); - assert.equal(gcdb(5, 2), 1); - assert.equal(gcdb(10, 100), 10); - assert.equal(gcdb(10000000, 2), 2); - assert.equal(gcdb(7, 49), 7); - assert.equal(gcdb(7, 5), 1); - assert.equal(gcdb(35, 49), 7); - }); + 'the binary method', function() { + var gcdb = gcd.binary; + assert.equal(gcdb(1, 0), 1); + assert.equal(gcdb(0, 1), 1); + assert.equal(gcdb(0, 0), 0); + assert.equal(gcdb(2, 2), 2); + assert.equal(gcdb(2, 4), 2); + assert.equal(gcdb(4, 2), 2); + assert.equal(gcdb(5, 2), 1); + assert.equal(gcdb(10, 100), 10); + assert.equal(gcdb(10000000, 2), 2); + assert.equal(gcdb(7, 49), 7); + assert.equal(gcdb(7, 5), 1); + assert.equal(gcdb(35, 49), 7); + }); }); - diff --git a/src/test/algorithms/math/greatest_difference.js b/src/test/algorithms/math/greatest_difference.js index 714be1d..1b66c6d 100644 --- a/src/test/algorithms/math/greatest_difference.js +++ b/src/test/algorithms/math/greatest_difference.js @@ -4,16 +4,16 @@ var assert = require('assert'); var math = require('../../..').Math; var greatestDifference = math.greatestDifference; -describe('Greatest Difference', function () { - it('should return 7 for [5, 8, 6, 1]', function () { +describe('Greatest Difference', function() { + it('should return 7 for [5, 8, 6, 1]', function() { assert.equal(greatestDifference([5, 8, 6, 1]), 7); }); - it('should return 4 for [7, 8, 4]', function () { + it('should return 4 for [7, 8, 4]', function() { assert.equal(greatestDifference([7, 8, 4]), 4); }); - it('should return 38 for the Lost numbers', function () { + it('should return 38 for the Lost numbers', function() { assert.equal(greatestDifference([4, 8, 15, 16, 23, 42]), 38); }); }); diff --git a/src/test/algorithms/math/lcm.js b/src/test/algorithms/math/lcm.js index 0104b33..2a3d002 100644 --- a/src/test/algorithms/math/lcm.js +++ b/src/test/algorithms/math/lcm.js @@ -1,44 +1,44 @@ 'use strict'; -var root = require('../../..'), - lcm = root.Math.lcm, - assert = require('assert'); +var root = require('../../..'); +var lcm = root.Math.lcm; +var assert = require('assert'); -describe('LCM', function () { +describe('LCM', function() { it('should calculate the correct LCM between two numbers ' + - 'using Euclidean algorithm', function () { - assert.equal(lcm(2, 3), 6); - assert.equal(lcm(0, 1), 0); - assert.equal(lcm(4, 9), 36); - assert.equal(lcm(39, 81), 1053); - assert.equal(lcm(10000000, 2), 10000000); - assert.equal(lcm(35, 49), 245); - assert.equal(lcm(7, 49), 49); - assert.equal(lcm(7, 5), 35); - assert.equal(lcm(0, 0), 0); - assert.equal(lcm(0, 9), 0); - assert.equal(lcm(0, -9), 0); - assert.equal(lcm(-9, -18), 18); - assert.equal(lcm(-7, 9), 63); - assert.equal(lcm(-7, -9), 63); - }); + 'using Euclidean algorithm', function() { + assert.equal(lcm(2, 3), 6); + assert.equal(lcm(0, 1), 0); + assert.equal(lcm(4, 9), 36); + assert.equal(lcm(39, 81), 1053); + assert.equal(lcm(10000000, 2), 10000000); + assert.equal(lcm(35, 49), 245); + assert.equal(lcm(7, 49), 49); + assert.equal(lcm(7, 5), 35); + assert.equal(lcm(0, 0), 0); + assert.equal(lcm(0, 9), 0); + assert.equal(lcm(0, -9), 0); + assert.equal(lcm(-9, -18), 18); + assert.equal(lcm(-7, 9), 63); + assert.equal(lcm(-7, -9), 63); + }); it('should calculate the correct LCM between two numbers ' + - 'using the binary method', function () { - var lcmb = lcm.binary; - assert.equal(lcmb(2, 3), 6); - assert.equal(lcmb(0, 1), 0); - assert.equal(lcmb(4, 9), 36); - assert.equal(lcmb(39, 81), 1053); - assert.equal(lcmb(10000000, 2), 10000000); - assert.equal(lcmb(35, 49), 245); - assert.equal(lcmb(7, 49), 49); - assert.equal(lcmb(7, 5), 35); - assert.equal(lcmb(0, 0), 0); - assert.equal(lcmb(0, 9), 0); - assert.equal(lcmb(0, -9), 0); - assert.equal(lcmb(-9, -18), 18); - assert.equal(lcmb(-7, 9), 63); - assert.equal(lcmb(-7, -9), 63); - }); + 'using the binary method', function() { + var lcmb = lcm.binary; + assert.equal(lcmb(2, 3), 6); + assert.equal(lcmb(0, 1), 0); + assert.equal(lcmb(4, 9), 36); + assert.equal(lcmb(39, 81), 1053); + assert.equal(lcmb(10000000, 2), 10000000); + assert.equal(lcmb(35, 49), 245); + assert.equal(lcmb(7, 49), 49); + assert.equal(lcmb(7, 5), 35); + assert.equal(lcmb(0, 0), 0); + assert.equal(lcmb(0, 9), 0); + assert.equal(lcmb(0, -9), 0); + assert.equal(lcmb(-9, -18), 18); + assert.equal(lcmb(-7, 9), 63); + assert.equal(lcmb(-7, -9), 63); + }); }); diff --git a/src/test/algorithms/math/newton_sqrt.js b/src/test/algorithms/math/newton_sqrt.js index c74ba25..00ee77c 100644 --- a/src/test/algorithms/math/newton_sqrt.js +++ b/src/test/algorithms/math/newton_sqrt.js @@ -1,11 +1,11 @@ 'use strict'; -var math = require('../../..').Math, - newtonSqrt = math.newtonSqrt, - assert = require('assert'); +var math = require('../../..').Math; +var newtonSqrt = math.newtonSqrt; +var assert = require('assert'); -describe('Newton square root', function () { - it('should calculate the exact root of square numbers', function () { +describe('Newton square root', function() { + it('should calculate the exact root of square numbers', function() { assert.strictEqual(newtonSqrt(0), 0); assert.strictEqual(newtonSqrt(1), 1); assert.strictEqual(newtonSqrt(4), 2); @@ -20,7 +20,7 @@ describe('Newton square root', function () { }); it('should calculate an approximated root for every number', - function () { + function() { for (var i = 0; i < 1000; i++) { var newton = newtonSqrt(i); var nativeJS = Math.sqrt(i); @@ -30,5 +30,4 @@ describe('Newton square root', function () { ' but got ' + newton + ' instead'); } }); - }); diff --git a/src/test/algorithms/math/next_permutation.js b/src/test/algorithms/math/next_permutation.js index 7d351ad..f3d7730 100644 --- a/src/test/algorithms/math/next_permutation.js +++ b/src/test/algorithms/math/next_permutation.js @@ -1,12 +1,11 @@ 'use strict'; -var math = require('../../..').Math, - nextPermutation = math.nextPermutation, - Comparator = require('../../../util/comparator'), - assert = require('assert'); +var math = require('../../..').Math; +var nextPermutation = math.nextPermutation; +var Comparator = require('../../../util/comparator'); +var assert = require('assert'); - -var range = function (begin, end) { +var range = function(begin, end) { if (end === undefined) { end = begin; begin = 0; @@ -14,20 +13,18 @@ var range = function (begin, end) { if (end <= begin) { return []; } - return new Array(end - begin + 1).join(0).split('').map(function (_, index) { + return new Array(end - begin + 1).join(0).split('').map(function(_, index) { return begin + index; }); }; - -var factorial = function (n) { - return range(1, n + 1).reduce(function (product, value) { +var factorial = function(n) { + return range(1, n + 1).reduce(function(product, value) { return product * value; }, 1); }; - -var permutations = function (start, compareFn) { +var permutations = function(start, compareFn) { var permutations = []; var perm = start.slice(); do { @@ -36,9 +33,8 @@ var permutations = function (start, compareFn) { return permutations; }; - -describe('Next Permutation', function () { - it('should return immediately following permutation', function () { +describe('Next Permutation', function() { + it('should return immediately following permutation', function() { assert.deepEqual(permutations([1, 2]), [[1, 2], [2, 1]]); assert.deepEqual(permutations([1, 2, 2]), [[1, 2, 2], [2, 1, 2], [2, 2, 1]]); @@ -47,18 +43,18 @@ describe('Next Permutation', function () { }); it('should generate all N! permutations if the elements are distinct', - function () { - [4, 5, 6].forEach(function (size) { - var count = 0; - var perm = range(size); - do { - count += 1; - } while (nextPermutation(perm)); - assert.equal(count, factorial(size)); - }); - }); + function() { + [4, 5, 6].forEach(function(size) { + var count = 0; + var perm = range(size); + do { + count += 1; + } while (nextPermutation(perm)); + assert.equal(count, factorial(size)); + }); + }); - it('should support custom compare functions', function () { + it('should support custom compare functions', function() { var reverseComparator = new Comparator(); reverseComparator.reverse(); var reverseCompareFn = reverseComparator.compare; diff --git a/src/test/algorithms/math/power_set.js b/src/test/algorithms/math/power_set.js index d10ce66..3ba2726 100644 --- a/src/test/algorithms/math/power_set.js +++ b/src/test/algorithms/math/power_set.js @@ -1,12 +1,15 @@ 'use strict'; -var math = require('../../..').Math, - powerSet = math.powerSet, - assert = require('assert'); +var math = require('../../..').Math; +var powerSet = math.powerSet; +var assert = require('assert'); +/** + * Deep equal for arrays + */ function testArrayEqual(a, b) { var arrayEqual = true; - a.forEach(function (elem, index) { + a.forEach(function(elem, index) { if (a[index] !== b[index]) { arrayEqual = false; } @@ -14,9 +17,12 @@ function testArrayEqual(a, b) { return arrayEqual && a.length === b.length; } +/** + * Tests if one array is an element of another + */ function testArrayInArray(a, b) { var arrayInArray = false; - b.forEach(function (array) { + b.forEach(function(array) { if (testArrayEqual(a, array)) { arrayInArray = true; } @@ -24,9 +30,9 @@ function testArrayInArray(a, b) { return arrayInArray; } -describe('Power set', function () { - describe('#iterative()', function () { - it('should return the right elements of power set', function () { +describe('Power set', function() { + describe('#iterative()', function() { + it('should return the right elements of power set', function() { var zeroElementTest = powerSet([]); assert(zeroElementTest.length === 0); @@ -72,12 +78,11 @@ describe('Power set', function () { assert(testArrayInArray([1, 2, 3], fourElementTest)); assert(testArrayInArray([0, 1, 2, 3], fourElementTest)); assert(fourElementTest.length === 16); - }); }); - describe('#recursive()', function () { - it('should return the right elements of power set', function () { + describe('#recursive()', function() { + it('should return the right elements of power set', function() { var zeroElementTest = powerSet.recursive([]); assert(zeroElementTest.length === 0); diff --git a/src/test/algorithms/math/primality_tests.js b/src/test/algorithms/math/primality_tests.js index 834d77b..ead3e4f 100644 --- a/src/test/algorithms/math/primality_tests.js +++ b/src/test/algorithms/math/primality_tests.js @@ -1,24 +1,10 @@ 'use strict'; -var root = require('../../..'), - primalityTests = root.Math.primalityTests, - assert = require('assert'), - s = 'should correctly determine whether a number is prime'; +var root = require('../../..'); +var primalityTests = root.Math.primalityTests; +var assert = require('assert'); -describe('Primality Tests', function () { - describe('#naiveTest()', function () { - it(s, function () { - f(primalityTests.naiveTest); - }); - }); - describe('#trialDivisionTest()', function () { - it(s, function () { - f(primalityTests.trialDivisionTest); - }); - }); -}); - -var f = function (primalityTest) { +var validate = function(primalityTest) { assert.equal(primalityTest(1), false); assert.equal(primalityTest(2), true); assert.equal(primalityTest(3), true); @@ -30,3 +16,17 @@ var f = function (primalityTest) { assert.equal(primalityTest(209), false); assert.equal(primalityTest(211), true); }; + +describe('Primality Tests', function() { + describe('#naiveTest()', function() { + it('should correctly determine whether a number is prime', function() { + validate(primalityTests.naiveTest); + }); + }); + describe('#trialDivisionTest()', function() { + it('should correctly determine whether a number is prime', function() { + validate(primalityTests.trialDivisionTest); + }); + }); +}); + diff --git a/src/test/algorithms/math/reservoir_sampling.js b/src/test/algorithms/math/reservoir_sampling.js index 16bc8d0..3933cb6 100644 --- a/src/test/algorithms/math/reservoir_sampling.js +++ b/src/test/algorithms/math/reservoir_sampling.js @@ -1,33 +1,32 @@ 'use strict'; -var math = require('../../..').Math, - reservoirSampling = math.reservoirSampling, - assert = require('assert'); +var math = require('../../..').Math; +var reservoirSampling = math.reservoirSampling; +var assert = require('assert'); - -describe('Reservoir Sampling', function () { +describe('Reservoir Sampling', function() { var array = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - it('should sample K distinct values from the array', function () { + it('should sample K distinct values from the array', function() { var sample = reservoirSampling(array, 5); assert.equal(sample.length, 5); var seen = {}; - array.forEach(function (value) { + array.forEach(function(value) { assert(!seen[value]); assert(array.indexOf(value) >= 0); seen[value] = true; }); }); - it('should work in corner cases', function () { + it('should work in corner cases', function() { assert.deepEqual(reservoirSampling(array, 0), []); assert.deepEqual(reservoirSampling([], 0), []); var fullSample = reservoirSampling(array, array.length); assert.deepEqual(fullSample.sort(), array); }); - it('should raise an error if asked for too many elements', function () { - assert.throws(function () { + it('should raise an error if asked for too many elements', function() { + assert.throws(function() { reservoirSampling(array, array.length + 1); }); }); diff --git a/src/test/algorithms/math/shannon_entropy.js b/src/test/algorithms/math/shannon_entropy.js index 8dcb56b..05944f1 100644 --- a/src/test/algorithms/math/shannon_entropy.js +++ b/src/test/algorithms/math/shannon_entropy.js @@ -3,8 +3,8 @@ var shannonEntropy = require('../../../').Math.shannonEntropy; var assert = require('assert'); -describe('Shannon Entropy', function () { - it('calculates shannon entropy', function () { +describe('Shannon Entropy', function() { + it('calculates shannon entropy', function() { assert.equal(shannonEntropy([]), 0); assert.equal(shannonEntropy([1]), 0); assert.equal(shannonEntropy([1, 0]), 1); diff --git a/src/test/algorithms/searching/bfs.js b/src/test/algorithms/searching/bfs.js index 5c5882e..9d44e6e 100644 --- a/src/test/algorithms/searching/bfs.js +++ b/src/test/algorithms/searching/bfs.js @@ -1,12 +1,11 @@ 'use strict'; -var root = require('../../..'), - BST = root.DataStructures.BST, - bfs = root.Search.bfs, - assert = require('assert'); - -describe('Breadth First Search', function () { +var root = require('../../..'); +var BST = root.DataStructures.BST; +var bfs = root.Search.bfs; +var assert = require('assert'); +describe('Breadth First Search', function() { var bst = new BST(); /** * 4 @@ -25,11 +24,11 @@ describe('Breadth First Search', function () { bst.insert(100); bst.insert(2.5); - var callbackGenerator = function (a) { - return function (n) { a.push(n); }; + var callbackGenerator = function(a) { + return n => a.push(n); }; - it('should return the items by level', function () { + it('should return the items by level', function() { var a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 10, 0, 2.5, 100]); diff --git a/src/test/algorithms/searching/binarysearch.js b/src/test/algorithms/searching/binarysearch.js index f2e5169..8364ead 100644 --- a/src/test/algorithms/searching/binarysearch.js +++ b/src/test/algorithms/searching/binarysearch.js @@ -1,10 +1,10 @@ 'use strict'; -var binarySearch = require('../../..').Search.binarySearch, - assert = require('assert'); +var binarySearch = require('../../..').Search.binarySearch; +var assert = require('assert'); -describe('Binary Search', function () { - it('should find elements in the sorted array', function () { +describe('Binary Search', function() { + it('should find elements in the sorted array', function() { assert.equal(binarySearch([1, 2, 3, 4, 5], 3), 2); assert.equal(binarySearch([1, 2, 3, 4, 5], 1), 0); assert.equal(binarySearch([1, 2, 3, 4, 5], 2), 1); @@ -16,4 +16,3 @@ describe('Binary Search', function () { }); }); - diff --git a/src/test/algorithms/searching/dfs.js b/src/test/algorithms/searching/dfs.js index 5a295e5..a180f33 100644 --- a/src/test/algorithms/searching/dfs.js +++ b/src/test/algorithms/searching/dfs.js @@ -1,11 +1,11 @@ 'use strict'; -var root = require('../../..'), - BST = root.DataStructures.BST, - dfs = root.Search.dfs, - assert = require('assert'); +var root = require('../../..'); +var BST = root.DataStructures.BST; +var dfs = root.Search.dfs; +var assert = require('assert'); -describe('Depth First Search', function () { +describe('Depth First Search', function() { var bst = new BST(); bst.insert(4); bst.insert(8); @@ -17,25 +17,25 @@ describe('Depth First Search', function () { bst.insert(5); bst.insert(100); - var callbackGenerator = function (a) { - return function (n) { a.push(n); }; + var callbackGenerator = function(a) { + return n => a.push(n); }; - it('should return the items sorted when retrieving in order', function () { + it('should return the items sorted when retrieving in order', function() { var a = []; dfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, [0, 1, 2, 3, 4, 5, 8, 10, 100]); }); it('should return parents before children when retrieving pre-order', - function () { + function() { var a = []; dfs.preOrder(bst.root, callbackGenerator(a)); assert.deepEqual(a, [4, 2, 1, 0, 3, 8, 5, 10, 100]); }); it('should return children before parents when retrieving post-order', - function () { + function() { var a = []; dfs.postOrder(bst.root, callbackGenerator(a)); assert.deepEqual(a, [0, 1, 3, 2, 5, 100, 10, 8, 4]); diff --git a/src/test/algorithms/searching/ternary_search.js b/src/test/algorithms/searching/ternary_search.js index b117815..61fae62 100644 --- a/src/test/algorithms/searching/ternary_search.js +++ b/src/test/algorithms/searching/ternary_search.js @@ -1,27 +1,27 @@ 'use strict'; -var ternarySearch = require('../../..').Search.ternarySearch, - assert = require('assert'), - eps = 1e-6; +var ternarySearch = require('../../..').Search.ternarySearch; +var assert = require('assert'); +var eps = 1e-6; -var fn1 = function (x) { +var fn1 = function(x) { return -Math.pow(x - 2, 2) + 4; }; -var fn2 = function (x) { +var fn2 = function(x) { return -2 * Math.cos(x); }; -var closeEnough = function (a, b, precision) { +var closeEnough = function(a, b, precision) { return Math.abs(a - b) < precision; }; -describe('Ternary search', function () { - it('should find the maximum of passed function', function () { +describe('Ternary search', function() { + it('should find the maximum of passed function', function() { assert(closeEnough(ternarySearch(fn1, 0.0, 4.0, eps), 2.0, eps)); assert(closeEnough(ternarySearch(fn1, 0.0, 1.0, eps), 1.0, eps)); assert(closeEnough(ternarySearch(fn2, -2.0, 2.0, eps), 2.0, eps)); - assert(closeEnough(ternarySearch(fn2, 0.0, 2*Math.PI, eps), Math.PI, eps)); + assert(closeEnough(ternarySearch(fn2, 0, 2 * Math.PI, eps), Math.PI, eps)); }); }); diff --git a/src/test/algorithms/sorting/bubble_sort.js b/src/test/algorithms/sorting/bubble_sort.js index 329c977..ecc75e9 100644 --- a/src/test/algorithms/sorting/bubble_sort.js +++ b/src/test/algorithms/sorting/bubble_sort.js @@ -1,14 +1,14 @@ 'use strict'; -var bubbleSort = require('../../..').Sorting.bubbleSort, - sortingTestsHelper = require('./sorting_tests_helper'); +var bubbleSort = require('../../..').Sorting.bubbleSort; +var sortingTestsHelper = require('./sorting_tests_helper'); -describe('Bubble Sort', function () { - it('should sort the given array', function () { +describe('Bubble Sort', function() { + it('should sort the given array', function() { sortingTestsHelper.testSort(bubbleSort); }); - it('should sort the array with a specific comparison function', function () { + it('should sort the array with a specific comparison function', function() { sortingTestsHelper.testSortWithComparisonFn(bubbleSort); }); }); diff --git a/src/test/algorithms/sorting/counting_sort.js b/src/test/algorithms/sorting/counting_sort.js index e47d5b0..a8da343 100644 --- a/src/test/algorithms/sorting/counting_sort.js +++ b/src/test/algorithms/sorting/counting_sort.js @@ -1,7 +1,7 @@ 'use strict'; -var countingSort = require('../../..').Sorting.countingSort, - assert = require('assert'); +var countingSort = require('../../..').Sorting.countingSort; +var assert = require('assert'); var firstObject = { someProperty: 'The', @@ -27,8 +27,8 @@ var array = [ firstObject ]; -describe('Counting Sort', function () { - it('should sort the given array', function () { +describe('Counting Sort', function() { + it('should sort the given array', function() { array = countingSort(array); // Asserts that the array is truly sorted diff --git a/src/test/algorithms/sorting/heap_sort.js b/src/test/algorithms/sorting/heap_sort.js index 5d95edc..c0db1db 100644 --- a/src/test/algorithms/sorting/heap_sort.js +++ b/src/test/algorithms/sorting/heap_sort.js @@ -1,14 +1,14 @@ 'use strict'; -var heapSort = require('../../..').Sorting.heapSort, - sortingTestsHelper = require('./sorting_tests_helper'); +var heapSort = require('../../..').Sorting.heapSort; +var sortingTestsHelper = require('./sorting_tests_helper'); -describe('Heap Sort', function () { - it('should sort the given array', function () { +describe('Heap Sort', function() { + it('should sort the given array', function() { sortingTestsHelper.testSort(heapSort); }); - it('should sort the array with a specific comparison function', function () { + it('should sort the array with a specific comparison function', function() { sortingTestsHelper.testSortWithComparisonFn(heapSort); }); }); diff --git a/src/test/algorithms/sorting/insertion_sort.js b/src/test/algorithms/sorting/insertion_sort.js index 97ab7f3..12b4cae 100644 --- a/src/test/algorithms/sorting/insertion_sort.js +++ b/src/test/algorithms/sorting/insertion_sort.js @@ -1,15 +1,14 @@ 'use strict'; -var insertionSort = require('../../..').Sorting.insertionSort, - sortingTestsHelper = require('./sorting_tests_helper'); +var insertionSort = require('../../..').Sorting.insertionSort; +var sortingTestsHelper = require('./sorting_tests_helper'); -describe('Insertion Sort', function () { - it('should sort the given array', function () { +describe('Insertion Sort', function() { + it('should sort the given array', function() { sortingTestsHelper.testSort(insertionSort); }); - - it('should sort the array with a specific comparison function', function () { + it('should sort the array with a specific comparison function', function() { sortingTestsHelper.testSortWithComparisonFn(insertionSort); }); }); diff --git a/src/test/algorithms/sorting/merge_sort.js b/src/test/algorithms/sorting/merge_sort.js index acb43b3..4c193c3 100644 --- a/src/test/algorithms/sorting/merge_sort.js +++ b/src/test/algorithms/sorting/merge_sort.js @@ -1,14 +1,14 @@ 'use strict'; -var mergeSort = require('../../..').Sorting.mergeSort, - sortingTestsHelper = require('./sorting_tests_helper'); +var mergeSort = require('../../..').Sorting.mergeSort; +var sortingTestsHelper = require('./sorting_tests_helper'); -describe('Merge Sort', function () { - it('should sort the given array', function () { +describe('Merge Sort', function() { + it('should sort the given array', function() { sortingTestsHelper.testSort(mergeSort); }); - it('should sort the array with a specific comparison function', function () { + it('should sort the array with a specific comparison function', function() { sortingTestsHelper.testSortWithComparisonFn(mergeSort); }); }); diff --git a/src/test/algorithms/sorting/quicksort.js b/src/test/algorithms/sorting/quicksort.js index c970567..c78860f 100644 --- a/src/test/algorithms/sorting/quicksort.js +++ b/src/test/algorithms/sorting/quicksort.js @@ -1,14 +1,14 @@ 'use strict'; -var quicksort = require('../../..').Sorting.quicksort, - sortingTestsHelper = require('./sorting_tests_helper'); +var quicksort = require('../../..').Sorting.quicksort; +var sortingTestsHelper = require('./sorting_tests_helper'); -describe('QuickSort', function () { - it('should sort the given array', function () { +describe('QuickSort', function() { + it('should sort the given array', function() { sortingTestsHelper.testSort(quicksort); }); - it('should sort the array with a specific comparison function', function () { + it('should sort the array with a specific comparison function', function() { sortingTestsHelper.testSortWithComparisonFn(quicksort); }); }); diff --git a/src/test/algorithms/sorting/radix_sort.js b/src/test/algorithms/sorting/radix_sort.js index 358ce93..6e3db08 100644 --- a/src/test/algorithms/sorting/radix_sort.js +++ b/src/test/algorithms/sorting/radix_sort.js @@ -1,7 +1,7 @@ 'use strict'; -var radixSort = require('../../..').Sorting.radixSort, - assert = require('assert'); +var radixSort = require('../../..').Sorting.radixSort; +var assert = require('assert'); var firstObject = { someProperty: 'The', @@ -24,8 +24,8 @@ var fourthObject = { anotherProperty: '!' }; -describe('Radix Sort', function () { - it('should sort the given array', function () { +describe('Radix Sort', function() { + it('should sort the given array', function() { var sorted = radixSort([ thirdObject, fourthObject, @@ -50,8 +50,8 @@ describe('Radix Sort', function () { ]); assert.deepEqual(radixSort([thirdObject, thirdObject]), [ - thirdObject, - thirdObject - ]); + thirdObject, + thirdObject + ]); }); }); diff --git a/src/test/algorithms/sorting/selection_sort.js b/src/test/algorithms/sorting/selection_sort.js index 0cc85cd..abe8e0a 100644 --- a/src/test/algorithms/sorting/selection_sort.js +++ b/src/test/algorithms/sorting/selection_sort.js @@ -1,14 +1,14 @@ 'use strict'; -var selectionSort = require('../../..').Sorting.selectionSort, - sortingTestsHelper = require('./sorting_tests_helper'); +var selectionSort = require('../../..').Sorting.selectionSort; +var sortingTestsHelper = require('./sorting_tests_helper'); -describe('Selection Sort', function () { - it('should sort the given array', function () { +describe('Selection Sort', function() { + it('should sort the given array', function() { sortingTestsHelper.testSort(selectionSort); }); - it('should sort the array with a specific comparison function', function () { + it('should sort the array with a specific comparison function', function() { sortingTestsHelper.testSortWithComparisonFn(selectionSort); }); }); diff --git a/src/test/algorithms/sorting/shell_sort.js b/src/test/algorithms/sorting/shell_sort.js index 97f6bc1..07f9524 100644 --- a/src/test/algorithms/sorting/shell_sort.js +++ b/src/test/algorithms/sorting/shell_sort.js @@ -1,16 +1,15 @@ 'use strict'; -var shellSort = require('../../..').Sorting.shellSort, - sortingTestsHelper = require('./sorting_tests_helper.js'); +var shellSort = require('../../..').Sorting.shellSort; +var sortingTestsHelper = require('./sorting_tests_helper.js'); -describe('ShellSort', function () { - it('should sort the given array', function () { +describe('ShellSort', function() { + it('should sort the given array', function() { sortingTestsHelper.testSort(shellSort); }); - it('should sort the array with a specific comparison function', function () { + it('should sort the array with a specific comparison function', function() { sortingTestsHelper.testSortWithComparisonFn(shellSort); }); }); - diff --git a/src/test/algorithms/sorting/short_bubble_sort.js b/src/test/algorithms/sorting/short_bubble_sort.js index 6837bb3..afe6a21 100644 --- a/src/test/algorithms/sorting/short_bubble_sort.js +++ b/src/test/algorithms/sorting/short_bubble_sort.js @@ -1,14 +1,14 @@ 'use strict'; -var shortBubbleSort = require('../../..').Sorting.shortBubbleSort, - sortingTestsHelper = require('./sorting_tests_helper'); +var shortBubbleSort = require('../../..').Sorting.shortBubbleSort; +var sortingTestsHelper = require('./sorting_tests_helper'); -describe('Short Bubble Sort', function () { - it('should sort the given array', function () { +describe('Short Bubble Sort', function() { + it('should sort the given array', function() { sortingTestsHelper.testSort(shortBubbleSort); }); - it('should sort the array with a specific comparison function', function () { + it('should sort the array with a specific comparison function', function() { sortingTestsHelper.testSortWithComparisonFn(shortBubbleSort); }); }); diff --git a/src/test/algorithms/sorting/sorting_tests_helper.js b/src/test/algorithms/sorting/sorting_tests_helper.js index 68932a9..5ca8179 100644 --- a/src/test/algorithms/sorting/sorting_tests_helper.js +++ b/src/test/algorithms/sorting/sorting_tests_helper.js @@ -3,7 +3,7 @@ var assert = require('assert'); module.exports = { - testSort: function (sortFn) { + testSort: function(sortFn) { assert.deepEqual(sortFn([]), []); assert.deepEqual(sortFn([1]), [1]); assert.deepEqual(sortFn([2, 1]), [1, 2]); @@ -15,8 +15,8 @@ module.exports = { assert.deepEqual(sortFn(['a', 'b', 'abc']), ['a', 'abc', 'b']); }, - testSortWithComparisonFn: function (sortFn) { - var compare = function (a, b) { + testSortWithComparisonFn: function(sortFn) { + var compare = function(a, b) { if (a.length === b.length) return 0; return a.length < b.length ? -1 : 1; }; @@ -29,7 +29,7 @@ module.exports = { assert.deepEqual(sortFn(['apple', 'banana', 'car', 'z'], compare), ['z', 'car', 'apple', 'banana']); - var reverseSort = function (a, b) { + var reverseSort = function(a, b) { if (a === b) return 0; return a < b ? 1 : -1; }; @@ -39,4 +39,3 @@ module.exports = { } }; - diff --git a/src/test/algorithms/string/hamming.js b/src/test/algorithms/string/hamming.js index cce683d..4870fbf 100644 --- a/src/test/algorithms/string/hamming.js +++ b/src/test/algorithms/string/hamming.js @@ -1,29 +1,27 @@ 'use strict'; -var hamming = require('../../..').String.hamming, - assert = require('assert'); +var hamming = require('../../..').String.hamming; +var assert = require('assert'); - -describe('Hamming distance', function () { - it('should raise an error if the inputs are not equal lengths', function () { - assert.throws(function () { +describe('Hamming distance', function() { + it('should raise an error if the inputs are not equal lengths', function() { + assert.throws(function() { hamming('abcde', '1234'); }); }); - it('should return the correct the correct distances', function () { + it('should return the correct the correct distances', function() { var inputs = [ - { a: 'karolin', b: 'kathrin', expected: 3 }, - { a: 'karolin', b: 'kerstin', expected: 3 }, - { a: '1011101', b: '1001001', expected: 2 }, - { a: '2173896', b: '2233796', expected: 3 }, - { a: '1111111111', b: '0000000000', expected: 10 }, - { a: '', b: '', expected: 0} + {a: 'karolin', b: 'kathrin', expected: 3}, + {a: 'karolin', b: 'kerstin', expected: 3}, + {a: '1011101', b: '1001001', expected: 2}, + {a: '2173896', b: '2233796', expected: 3}, + {a: '1111111111', b: '0000000000', expected: 10}, + {a: '', b: '', expected: 0} ]; - inputs.forEach(function (val) { + inputs.forEach(function(val) { assert.equal(hamming(val.a, val.b), val.expected); }); }); - }); diff --git a/src/test/algorithms/string/huffman.js b/src/test/algorithms/string/huffman.js index d0b7cf4..2f53d75 100644 --- a/src/test/algorithms/string/huffman.js +++ b/src/test/algorithms/string/huffman.js @@ -1,10 +1,9 @@ 'use strict'; -var huffman = require('../../..').String.huffman, - assert = require('assert'); +var huffman = require('../../..').String.huffman; +var assert = require('assert'); - -describe('Huffman', function () { +describe('Huffman', function() { var messages = ['', 'a', 'b', 'hello', 'test', 'aaaabbbccddef', 'The seething sea ceaseth and thus' + ' the seething sea sufficeth us.', @@ -20,8 +19,8 @@ describe('Huffman', function () { messages.push(characters.join('')); } - it('should decode previously encoded messages correctly', function () { - messages.forEach(function (message) { + it('should decode previously encoded messages correctly', function() { + messages.forEach(function(message) { var encoded = huffman.encode(message); var decoded = huffman.decode(encoded.encoding, encoded.value); assert.equal(message, decoded); @@ -32,18 +31,18 @@ describe('Huffman', function () { }); }); - it('should raise an error if it fails to decode', function () { + it('should raise an error if it fails to decode', function() { var badArgs = [[{}, '0'], [{}, [0]], [{a: '0', b: '10', c: '11'}, '001']]; - badArgs.forEach(function (args) { - assert.throws(function () { + badArgs.forEach(function(args) { + assert.throws(function() { huffman.decode.apply(null, args); }); }); }); - it('should encode sample strings in the expected manner', function () { + it('should encode sample strings in the expected manner', function() { assert.deepEqual(huffman.encode(''), {encoding: {}, value: ''}); assert.deepEqual(huffman.encode('a'), {encoding: {a: '0'}, value: '0'}); assert.deepEqual(huffman.encode('aaaaa'), {encoding: {a: '0'}, @@ -53,27 +52,27 @@ describe('Huffman', function () { assert.equal(result.encoding.b.length, 2); assert.equal(result.encoding.c.length, 2); result = huffman.encode('abcdabcdabcdabcd'); - Object.keys(result.encoding).forEach(function (char) { + Object.keys(result.encoding).forEach(function(char) { assert.equal(result.encoding[char].length, 2); }); assert.equal(result.value.length, 32); }); - it('should satisfy the entropy condition (H <= cost <= H+1)', function () { - messages.forEach(function (message) { - var frequencies = message.split('').reduce(function (acc, char) { + it('should satisfy the entropy condition (H <= cost <= H+1)', function() { + messages.forEach(function(message) { + var frequencies = message.split('').reduce(function(acc, char) { acc[char] = (acc[char] || 0) + 1; return acc; }, {}); - Object.keys(frequencies).forEach(function (char) { + Object.keys(frequencies).forEach(function(char) { frequencies[char] /= message.length; }); - var entropy = Object.keys(frequencies).reduce(function (partial, char) { + var entropy = Object.keys(frequencies).reduce(function(partial, char) { var freq = frequencies[char]; return partial - freq * Math.log(freq); }, 0) / Math.log(2); var encoding = huffman.encode(message).encoding; - var cost = Object.keys(encoding).reduce(function (partial, char) { + var cost = Object.keys(encoding).reduce(function(partial, char) { return partial + frequencies[char] * encoding[char].length; }, 0); assert(entropy <= cost); diff --git a/src/test/algorithms/string/knuth_morris_pratt.js b/src/test/algorithms/string/knuth_morris_pratt.js index 6cb5e34..aba77d0 100644 --- a/src/test/algorithms/string/knuth_morris_pratt.js +++ b/src/test/algorithms/string/knuth_morris_pratt.js @@ -1,11 +1,11 @@ 'use strict'; -var knuthMorrisPratt = require('../../..').String.knuthMorrisPratt, - assert = require('assert'); +var knuthMorrisPratt = require('../../..').String.knuthMorrisPratt; +var assert = require('assert'); -describe('Knuth-Morris-Pratt', function () { +describe('Knuth-Morris-Pratt', function() { it('should verify if a pattern is contained in some text (or array)', - function () { + function() { var text = 'A string matching algorithm wants to find the starting' + 'index m in string S[] that matches the search word W[].The most' + ' straightforward algorithm is to look for a character match at ' + @@ -31,7 +31,6 @@ describe('Knuth-Morris-Pratt', function () { assert.equal(knuthMorrisPratt(text, pattern), text.length); - var arrayText = [3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 4]; var arrayPattern = [8, 9, 8]; diff --git a/src/test/algorithms/string/levenshtein.js b/src/test/algorithms/string/levenshtein.js index cc94f7c..17ddac3 100644 --- a/src/test/algorithms/string/levenshtein.js +++ b/src/test/algorithms/string/levenshtein.js @@ -1,11 +1,11 @@ 'use strict'; -var levenshtein = require('../../..').String.levenshtein, - assert = require('assert'); +var levenshtein = require('../../..').String.levenshtein; +var assert = require('assert'); -describe('Levenshtein', function () { +describe('Levenshtein', function() { it('should calculate the minimal edit distance between two words', - function () { + function() { assert.equal(levenshtein('', ''), 0); assert.equal(levenshtein('a', ''), 1); assert.equal(levenshtein('', 'a'), 1); diff --git a/src/test/algorithms/string/longest_common_subsequence.js b/src/test/algorithms/string/longest_common_subsequence.js index bcf023a..1a2b3eb 100644 --- a/src/test/algorithms/string/longest_common_subsequence.js +++ b/src/test/algorithms/string/longest_common_subsequence.js @@ -2,12 +2,12 @@ var directory = '../../../algorithms/string/'; var filename = 'longest_common_subsequence'; -var longestCommonSubsequence = require(directory + filename), - assert = require('assert'); +var longestCommonSubsequence = require(directory + filename); +var assert = require('assert'); -describe('Longest common subsequence', function () { +describe('Longest common subsequence', function() { it('should return the longest common subsequence of ' + - 'two strings', function () { + 'two strings', function() { assert.equal('', longestCommonSubsequence('', '')); assert.equal('', longestCommonSubsequence('', 'aaa')); assert.equal('', longestCommonSubsequence('aaa', '')); diff --git a/src/test/algorithms/string/longest_common_substring.js b/src/test/algorithms/string/longest_common_substring.js index 2c910dc..4d256fb 100644 --- a/src/test/algorithms/string/longest_common_substring.js +++ b/src/test/algorithms/string/longest_common_substring.js @@ -2,11 +2,11 @@ var directory = '../../../algorithms/string/'; var filename = 'longest_common_substring'; -var longestCommonSubstring = require(directory + filename), - assert = require('assert'); +var longestCommonSubstring = require(directory + filename); +var assert = require('assert'); -describe('Longest common substring', function () { - it('should return the longest common substring of two strings', function () { +describe('Longest common substring', function() { + it('should return the longest common substring of two strings', function() { assert.equal('', longestCommonSubstring('', '')); assert.equal('', longestCommonSubstring('', 'aaa')); assert.equal('', longestCommonSubstring('aaa', '')); diff --git a/src/test/algorithms/string/rabin_karp.js b/src/test/algorithms/string/rabin_karp.js index 1789b1f..4abec80 100644 --- a/src/test/algorithms/string/rabin_karp.js +++ b/src/test/algorithms/string/rabin_karp.js @@ -1,15 +1,15 @@ 'use strict'; -var rabinKarp = require('../../..').String.rabinKarp, - assert = require('assert'); +var rabinKarp = require('../../..').String.rabinKarp; +var assert = require('assert'); -var rabinKarpEqualsToIndexOf = function (a, b) { +var rabinKarpEqualsToIndexOf = function(a, b) { assert.equal(rabinKarp(a, b), a.indexOf(b)); }; -describe('Karp-Rabin', function () { +describe('Karp-Rabin', function() { it('should verify if a string is contained in another string', - function () { + function() { rabinKarpEqualsToIndexOf('', ''); rabinKarpEqualsToIndexOf('a', 'b'); rabinKarpEqualsToIndexOf('b', 'a'); diff --git a/src/test/data_structures/avl-tree.js b/src/test/data_structures/avl-tree.js index f6b2724..b951258 100644 --- a/src/test/data_structures/avl-tree.js +++ b/src/test/data_structures/avl-tree.js @@ -1,15 +1,15 @@ 'use strict'; -var root = require('../..'), - AVLTree = root.DataStructures.AVLTree, - assert = require('assert'); +var root = require('../..'); +var AVLTree = root.DataStructures.AVLTree; +var assert = require('assert'); -describe('AVL Tree', function () { - it('should start with null root', function () { +describe('AVL Tree', function() { + it('should start with null root', function() { assert.equal(new AVLTree().root, null); }); - it('should insert and single rotate (leftRight) properly', function () { + it('should insert and single rotate (leftRight) properly', function() { var avlTree = new AVLTree(); avlTree.insert(9); avlTree.insert(3); @@ -24,7 +24,7 @@ describe('AVL Tree', function () { assert.equal(avlTree.root.right.height, 1); }); - it('should insert and single rotate (rightLeft) properly', function () { + it('should insert and single rotate (rightLeft) properly', function() { var avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(75); @@ -39,7 +39,7 @@ describe('AVL Tree', function () { assert.equal(avlTree.root.right.height, 1); }); - it('should insert and double rotate (leftLeft) properly', function () { + it('should insert and double rotate (leftLeft) properly', function() { var avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(25); @@ -54,7 +54,7 @@ describe('AVL Tree', function () { assert.equal(avlTree.root.right.height, 1); }); - it('should insert and double rotate (rightRight) properly', function () { + it('should insert and double rotate (rightRight) properly', function() { var avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(75); @@ -69,7 +69,7 @@ describe('AVL Tree', function () { assert.equal(avlTree.root.right.height, 1); }); - it('should insert multiple nodes and balance properly (1)', function () { + it('should insert multiple nodes and balance properly (1)', function() { var avlTree = new AVLTree(); avlTree.insert(30); avlTree.insert(15); @@ -90,7 +90,7 @@ describe('AVL Tree', function () { assert.equal(avlTree.root.right.right.height, 1); }); - it('should remove nodes and balance properly (2)', function () { + it('should remove nodes and balance properly (2)', function() { var avlTree = new AVLTree(); avlTree.insert(55); avlTree.insert(25); @@ -107,7 +107,7 @@ describe('AVL Tree', function () { assert.equal(avlTree.root.right.height, 1); }); - it('should always keep the tree balanced', function () { + it('should always keep the tree balanced', function() { var avlTree = new AVLTree(); avlTree.insert(50); @@ -195,8 +195,8 @@ describe('AVL Tree', function () { assert.equal(avlTree.root.right.right.value, 200); }); - it('should return the parents before the children when '+ - 'traversing in preorder', function () { + it('should return the parents before the children when ' + + 'traversing in preorder', function() { var avlTree = new AVLTree(); avlTree.insert(50); @@ -218,14 +218,14 @@ describe('AVL Tree', function () { var expectedPreOrder = [50, 5, 2, 1, 4, 20, 7, 6, 15, 30, 40, 100, 75, 80, 200]; var preOrder = []; - avlTree.preOrder(avlTree.root, function (n) { + avlTree.preOrder(avlTree.root, function(n) { preOrder.push(n.value); }); assert.deepEqual(expectedPreOrder, preOrder); }); - it('should return the children before the parents when '+ - 'traversing in postorder', function () { + it('should return the children before the parents when ' + + 'traversing in postorder', function() { var avlTree = new AVLTree(); avlTree.insert(50); @@ -247,14 +247,13 @@ describe('AVL Tree', function () { var expectedPostOrder = [1, 4, 2, 6, 15, 7, 40, 30, 20, 5, 80, 75, 200, 100, 50]; var postOrder = []; - avlTree.postOrder(avlTree.root, function (n) { + avlTree.postOrder(avlTree.root, function(n) { postOrder.push(n.value); }); assert.deepEqual(expectedPostOrder, postOrder); }); - - it('should return the sorted elements when traversing in order', function () { + it('should return the sorted elements when traversing in order', function() { var avlTree = new AVLTree(); var a = []; var i; @@ -263,13 +262,13 @@ describe('AVL Tree', function () { avlTree.insert(x); a.push(x); } - a.sort(function (a, b) { return a - b; }); + a.sort((a, b) => a - b); var b = []; - avlTree.inOrder(avlTree.root, function (node) { b.push(node.value); }); + avlTree.inOrder(avlTree.root, node => b.push(node.value)); assert.equal(a.length, b.length); for (i = 0; i < a.length; i++) { assert.equal(a[i], b[i]); } }); - }); +}); diff --git a/src/test/data_structures/bst.js b/src/test/data_structures/bst.js index 190e168..af507b2 100644 --- a/src/test/data_structures/bst.js +++ b/src/test/data_structures/bst.js @@ -1,12 +1,12 @@ 'use strict'; -var root = require('../..'), - BST = root.DataStructures.BST, - bfs = root.Search.bfs, - assert = require('assert'); +var root = require('../..'); +var BST = root.DataStructures.BST; +var bfs = root.Search.bfs; +var assert = require('assert'); -describe('Binary Search Tree', function () { - it('should insert elements respecting the BST restrictions', function () { +describe('Binary Search Tree', function() { + it('should insert elements respecting the BST restrictions', function() { var bst = new BST(); bst.insert(4); bst.insert(8); @@ -19,7 +19,7 @@ describe('Binary Search Tree', function () { bst.insert(100); assert.equal(bst.size, 9); }); - it('should check if an element exists (in O(lg n))', function () { + it('should check if an element exists (in O(lg n))', function() { var bst = new BST(); bst.insert(4); bst.insert(8); @@ -62,84 +62,81 @@ describe('Binary Search Tree', function () { bst.insert(100); bst.insert(2.5); - var callbackGenerator = function (a) { - return function (n) { a.push(n); }; + var callbackGenerator = function(a) { + return n => a.push(n); }; - it('should remove a leaf without altering anything else in ' + - 'the structure of the tree', function () { - - bst.remove(0); + 'the structure of the tree', function() { + bst.remove(0); /** * 4 * 2 8 * 1 3 5 10 * 2.5 100 */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 10, 2.5, 100]); - }); + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 10, 2.5, 100]); + }); it('should remove an element with just one child and substitute ' + - 'it as the root of only subtree', function () { - - bst.remove(10); + 'it as the root of only subtree', function() { + bst.remove(10); /** * 4 * 2 8 * 1 3 5 100 * 2.5 */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 100, 2.5]); - }); + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 100, 2.5]); + }); it('should substitute an element by the leftmost child in the right ' + - 'subtree and remove it as a leaf', function () { + 'subtree and remove it as a leaf', function() { /** * 4 * 2 8 * 1 3 5 100 * 2.5 */ - bst.remove(2); + bst.remove(2); /** * 4 * 2.5 8 * 1 3 5 100 * */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [4, 2.5, 8, 1, 3, 5, 100]); + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [4, 2.5, 8, 1, 3, 5, 100]); - bst.remove(4); + bst.remove(4); /** * 5 * 2.5 8 * 1 3 100 * */ - a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [5, 2.5, 8, 1, 3, 100]); + a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [5, 2.5, 8, 1, 3, 100]); - bst.remove(2.5); + bst.remove(2.5); /** * 5 * 3 8 * 1 100 * */ - a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [5, 3, 8, 1, 100]); - }); + a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [5, 3, 8, 1, 100]); + }); - it('should always return the right root and size', function () { + it('should always return the right root and size', function() { var bst = new BST(); bst.insert(5); assert.equal(bst.size, 1); @@ -159,23 +156,22 @@ describe('Binary Search Tree', function () { }); it('should throw an error when trying to remove an unexisting node', - function () { + function() { var bst = new BST(); - assert.throws(function () { bst.remove(0); }, Error); + assert.throws(() => bst.remove(0), Error); bst.insert(3); - assert.throws(function () { bst.remove(0); }, Error); + assert.throws(() => bst.remove(0), Error); }); - }); -describe('Binary Search Tree with custom comparator', function () { - var strLenCompare = function (a, b) { +describe('Binary Search Tree with custom comparator', function() { + var strLenCompare = function(a, b) { if (a.length === b.length) return 0; return a.length < b.length ? -1 : 1; }; it( - 'should insert elements respecting the BST restrictions', function () { + 'should insert elements respecting the BST restrictions', function() { var bst = new BST(strLenCompare); bst.insert('banana'); bst.insert('apple'); @@ -184,7 +180,7 @@ describe('Binary Search Tree with custom comparator', function () { assert.equal(bst.size, 4); }); - it('should check if an element exists (in O(lg n))', function () { + it('should check if an element exists (in O(lg n))', function() { var bst = new BST(strLenCompare); bst.insert('banana'); bst.insert('apple'); @@ -214,54 +210,50 @@ describe('Binary Search Tree with custom comparator', function () { bst.insert('pineapple'); bst.insert('watermelon'); - var callbackGenerator = function (a) { - return function (n) { a.push(n); }; + var callbackGenerator = function(a) { + return n => a.push(n); }; - it('should insert the items according to the comparator', function () { - + it('should insert the items according to the comparator', function() { var a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear', 'watermelon']); }); it('should remove a leaf without altering anything else in ' + - 'the structure of the tree', function () { - - bst.remove('watermelon'); + 'the structure of the tree', function() { + bst.remove('watermelon'); /** * 'banana' * 'apple' 'pineapple' * 'pear' */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear']); - }); + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear']); + }); it('should remove an element with just one child and substitute ' + - 'it as the root of only subtree', function () { - - bst.remove('apple'); + 'it as the root of only subtree', function() { + bst.remove('apple'); /** * 'banana' * 'pear' 'pineapple' */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, ['banana', 'pear', 'pineapple']); - }); + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, ['banana', 'pear', 'pineapple']); + }); it('should substitute an element by the leftmost child in the right ' + - 'subtree and remove it as a leaf', function () { - - bst.remove('banana'); + 'subtree and remove it as a leaf', function() { + bst.remove('banana'); /** * 'pineapple' * 'pear' */ - var a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, ['pineapple', 'pear']); - }); + var a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, ['pineapple', 'pear']); + }); }); diff --git a/src/test/data_structures/disjoint_set_forest.js b/src/test/data_structures/disjoint_set_forest.js index a640cdb..d14b235 100644 --- a/src/test/data_structures/disjoint_set_forest.js +++ b/src/test/data_structures/disjoint_set_forest.js @@ -1,27 +1,26 @@ 'use strict'; -var DisjointSetForest = require('../..').DataStructures.DisjointSetForest, - assert = require('assert'); +var DisjointSetForest = require('../..').DataStructures.DisjointSetForest; +var assert = require('assert'); - -describe('Disjoint Set Forest', function () { +describe('Disjoint Set Forest', function() { it('should decide if two elements belong to the same subset or not', - function () { - var forest = new DisjointSetForest(); - assert(!forest.sameSubset(1, 2)); - forest.merge(1, 2); - assert(forest.sameSubset(1, 2)); - forest.merge(3, 4); - assert(!forest.sameSubset(2, 4)); - forest.merge(1, 3); - assert(forest.sameSubset(1, 2, 3, 4)); - assert(!forest.sameSubset(1, 5)); - }); + function() { + var forest = new DisjointSetForest(); + assert(!forest.sameSubset(1, 2)); + forest.merge(1, 2); + assert(forest.sameSubset(1, 2)); + forest.merge(3, 4); + assert(!forest.sameSubset(2, 4)); + forest.merge(1, 3); + assert(forest.sameSubset(1, 2, 3, 4)); + assert(!forest.sameSubset(1, 5)); + }); - it('should maintain subset sizes', function () { + it('should maintain subset sizes', function() { var forest = new DisjointSetForest(); - var assertSizesCorrect = function (elements, size) { - elements.forEach(function (element) { + var assertSizesCorrect = function(elements, size) { + elements.forEach(function(element) { assert.equal(forest.size(element), size); }); }; @@ -38,11 +37,11 @@ describe('Disjoint Set Forest', function () { assertSizesCorrect([0, 1, 2, 3, 4], 5); }); - it('should point all elements to the same root', function () { + it('should point all elements to the same root', function() { var forest = new DisjointSetForest(); - var assertSameRoot = function (element) { + var assertSameRoot = function(element) { var root = forest.root(element); - [].slice.call(arguments, 1).forEach(function (element) { + [].slice.call(arguments, 1).forEach(function(element) { assert.equal(forest.root(element), root); }); }; @@ -56,10 +55,10 @@ describe('Disjoint Set Forest', function () { assertSameRoot(0, 1, 2, 3, 4, 5); }); - it('should not choose the root element outside the subset', function () { + it('should not choose the root element outside the subset', function() { var forest = new DisjointSetForest(); - var assertInside = function (value, set) { - return set.some(function (element) { + var assertInside = function(value, set) { + return set.some(function(element) { return element === value; }); }; diff --git a/src/test/data_structures/fenwick_tree.js b/src/test/data_structures/fenwick_tree.js index 8f99d4a..b0fe673 100644 --- a/src/test/data_structures/fenwick_tree.js +++ b/src/test/data_structures/fenwick_tree.js @@ -1,16 +1,15 @@ 'use strict'; -var FenwickTree = require('../..').DataStructures.FenwickTree, - assert = require('assert'); +var FenwickTree = require('../..').DataStructures.FenwickTree; +var assert = require('assert'); -describe('FenwickTree', function () { - it('should allow prefix queries', function () { +describe('FenwickTree', function() { + it('should allow prefix queries', function() { var tree = new FenwickTree(10); tree.adjust(5, 42); tree.adjust(7, 43); tree.adjust(9, 44); - assert.equal(tree.prefixSum(0), 0); assert.equal(tree.prefixSum(1), 0); assert.equal(tree.prefixSum(2), 0); @@ -24,13 +23,12 @@ describe('FenwickTree', function () { assert.equal(tree.prefixSum(10), 42 + 43 + 44); }); - it('should allow range queries', function () { + it('should allow range queries', function() { var tree = new FenwickTree(10); tree.adjust(5, 42); tree.adjust(7, 43); tree.adjust(9, 44); - assert.equal(tree.rangeSum(6, 10), 43 + 44); assert.equal(tree.rangeSum(5, 7), 42 + 43); }); diff --git a/src/test/data_structures/graph.js b/src/test/data_structures/graph.js index fcecbbd..9d4e38c 100644 --- a/src/test/data_structures/graph.js +++ b/src/test/data_structures/graph.js @@ -1,10 +1,10 @@ 'use strict'; -var Graph = require('../..').DataStructures.Graph, - assert = require('assert'); +var Graph = require('../..').DataStructures.Graph; +var assert = require('assert'); -describe('Graph - Adjacency list', function () { - it('should be directed by default', function () { +describe('Graph - Adjacency list', function() { + it('should be directed by default', function() { var g = new Graph(); assert(g.directed); @@ -15,7 +15,7 @@ describe('Graph - Adjacency list', function () { assert(g.directed); }); - it('should default weight 1 for edges', function () { + it('should default weight 1 for edges', function() { var g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -24,7 +24,7 @@ describe('Graph - Adjacency list', function () { }); it('should create the vertex if an edge is inserted and vertex doesnt exist', - function () { + function() { var g = new Graph(); g.addEdge('a', 'b'); assert.equal(g.vertices.size, 2); @@ -32,7 +32,7 @@ describe('Graph - Adjacency list', function () { assert(g.vertices.contains('b')); }); - it('should sum multiple edges between the same vertices', function () { + it('should sum multiple edges between the same vertices', function() { var g = new Graph(); g.addEdge('a', 'b', 10); assert.equal(g.edge('a', 'b'), 10); @@ -40,7 +40,7 @@ describe('Graph - Adjacency list', function () { assert.equal(g.edge('a', 'b'), 14); }); - it('should have edges in both directions if undirected', function () { + it('should have edges in both directions if undirected', function() { var g = new Graph(false); g.addVertex('a'); g.addVertex('b'); @@ -63,7 +63,7 @@ describe('Graph - Adjacency list', function () { assert.equal(g.edge('b', 'a'), 12); }); - it('should respect direction of the edges in directed graphs', function () { + it('should respect direction of the edges in directed graphs', function() { var g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -86,7 +86,7 @@ describe('Graph - Adjacency list', function () { assert.equal(g.edge('b', 'a'), 2); }); - it('should have a list of vertices', function () { + it('should have a list of vertices', function() { var g = new Graph(); assert.equal(g.vertices.size, 0); g.addVertex('a'); @@ -98,15 +98,15 @@ describe('Graph - Adjacency list', function () { assert(g.vertices.contains('c')); }); - it('should not allow repeated vertices', function () { + it('should not allow repeated vertices', function() { var g = new Graph(); g.addVertex('a'); - assert.throws(function () { + assert.throws(function() { g.addVertex('a'); }); }); - it('should return a list of neighbors of a vertex', function () { + it('should return a list of neighbors of a vertex', function() { var g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -121,7 +121,7 @@ describe('Graph - Adjacency list', function () { assert.deepEqual(g.neighbors('c'), ['d']); }); - it('should return the weight of the edge', function () { + it('should return the weight of the edge', function() { var g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -136,7 +136,7 @@ describe('Graph - Adjacency list', function () { assert.equal(g.edge('c', 'd'), 2); }); - it('should not "inherit" edges from Object.prototype', function () { + it('should not "inherit" edges from Object.prototype', function() { var g = new Graph(); g.addEdge('a', 'b'); diff --git a/src/test/data_structures/hash_table.js b/src/test/data_structures/hash_table.js index 86ede97..bda8cde 100644 --- a/src/test/data_structures/hash_table.js +++ b/src/test/data_structures/hash_table.js @@ -1,18 +1,18 @@ 'use strict'; -var HashTable = require('../..').DataStructures.HashTable, - assert = require('assert'); +var HashTable = require('../..').DataStructures.HashTable; +var assert = require('assert'); -describe('Hash Table', function () { +describe('Hash Table', function() { it('should calculate hashes using the same algorithm as ' + - 'Java\'s String.hashCode', function () { - var h = new HashTable(); - assert.equal(h.hash('The quick brown fox jumps over the lazy dog'), + 'Java\'s String.hashCode', function() { + var h = new HashTable(); + assert.equal(h.hash('The quick brown fox jumps over the lazy dog'), -609428141); - assert.equal(h.hash('Testing the hashCode function'), 1538083358); - assert.equal(h.hash(''), 0); - assert.equal(h.hash('a'), 97); - var longString = + assert.equal(h.hash('Testing the hashCode function'), 1538083358); + assert.equal(h.hash(''), 0); + assert.equal(h.hash('a'), 97); + var longString = 'k"hg3q#+~/l2Eljan;DB x.P%-:iA' + '/b/hG($8-SZcZX871&;fDEWthw.b5agzov],X00--O:mcQ$JFi-4uIo"D:(r(yvs' + @@ -29,11 +29,11 @@ describe('Hash Table', function () { 'fE$O[YV8X3PV6TR(*Ed4|y[8tG~K=[MxgLI%yx]16Kg3YSHE{2^1TOAnf`EsKWm,' + 'WGD)s;Zs<8K6(K_kVko"mV82Pcl)0Rx}jfq3VBm:MOX/gLfSPvLx~%(3jHh5gG2e' + 'JaQ|nW}ekR_W5Ldv`@j^hd%Wiw6moGekrS>k7gRR|dd?7Pi:`0; r_wq=-F-e(iY'; - assert.equal(h.hash(longString), -998071508); - }); + assert.equal(h.hash(longString), -998071508); + }); it('should initialize the table with the given capacity', - function () { + function() { var h = new HashTable(); assert.equal(h.capacity, 64); // default initial capacity; assert.equal(h.size, 0); @@ -42,7 +42,7 @@ describe('Hash Table', function () { assert.equal(h.capacity, 2); }); - it('should allow putting and getting elements from the table', function () { + it('should allow putting and getting elements from the table', function() { var h = new HashTable(16); var a = {a: 'foo', b: 'bar'}; h.put('foo', a); @@ -57,7 +57,7 @@ describe('Hash Table', function () { assert.strictEqual(h.get('bar'), b); }); - it('should replace items if the same key is reused', function () { + it('should replace items if the same key is reused', function() { var h = new HashTable(16); var a = {a: 'foo', b: 'bar'}; h.put('foo', a); @@ -68,13 +68,13 @@ describe('Hash Table', function () { assert.strictEqual(h.get('foo'), b); }); - it('should return undefined if there\'s no element', function () { + it('should return undefined if there\'s no element', function() { var h = new HashTable(8); assert.equal(h.get('foo'), undefined); assert.equal(h.get('bar'), undefined); }); - it('should handle hash conflicts', function () { + it('should handle hash conflicts', function() { var h = new HashTable(4); // Both keys are supposed to be pushed to the same position assert.equal(h._position('a'), h._position('e')); @@ -88,7 +88,7 @@ describe('Hash Table', function () { assert.equal(h.get('e'), 'bar'); }); - it('should increase capacity if needed', function () { + it('should increase capacity if needed', function() { var h = new HashTable(2); assert.equal(h.capacity, 2); @@ -99,7 +99,7 @@ describe('Hash Table', function () { assert.equal(h.capacity, 4); }); - it('should allow removing items', function () { + it('should allow removing items', function() { var h = new HashTable(); assert.equal(h.get('foo'), undefined); @@ -114,7 +114,7 @@ describe('Hash Table', function () { assert.equal(h.get('foo'), undefined); }); - it('should allow non-string keys', function () { + it('should allow non-string keys', function() { var h = new HashTable(); h.put(10, 5); assert.equal(h.get(10), 5); @@ -124,7 +124,7 @@ describe('Hash Table', function () { assert.equal(h.get(o), 'foo'); }); - it('should perform a function to all keys with forEach', function () { + it('should perform a function to all keys with forEach', function() { var h = new HashTable(); h.put(1, 10); h.put(2, 20); @@ -132,7 +132,7 @@ describe('Hash Table', function () { var totalKeys = 0; var totalValues = 0; - h.forEach(function (k, v) { + h.forEach(function(k, v) { totalKeys += k; totalValues += v; }); diff --git a/src/test/data_structures/heap.js b/src/test/data_structures/heap.js index 7772d9a..e95aecb 100644 --- a/src/test/data_structures/heap.js +++ b/src/test/data_structures/heap.js @@ -1,10 +1,10 @@ 'use strict'; -var heap = require('../..').DataStructures.Heap, - assert = require('assert'); +var heap = require('../..').DataStructures.Heap; +var assert = require('assert'); -describe('Min Heap', function () { - it('should always return the lowest element', function () { +describe('Min Heap', function() { + it('should always return the lowest element', function() { var h = new heap.MinHeap(); assert(h.isEmpty()); h.insert(10); @@ -35,7 +35,7 @@ describe('Min Heap', function () { assert(h.isEmpty()); }); - it('should heapify an unordered array', function () { + it('should heapify an unordered array', function() { var h = new heap.MinHeap(); h.heapify([10, 2091, 4, 1, 5, 500, 0, 18, 3, 22, 20]); @@ -55,12 +55,12 @@ describe('Min Heap', function () { }); it('should perform a function to all elements from smallest to largest' + - ' with forEach', function () { + ' with forEach', function() { var h = new heap.MinHeap(); h.heapify([3, 10, 1000, 0, 2, 1]); var output = []; - h.forEach(function (n) { + h.forEach(function(n) { output.push(n); }); @@ -71,8 +71,8 @@ describe('Min Heap', function () { }); }); -describe('Max Heap', function () { - it('should always return the greatest element', function () { +describe('Max Heap', function() { + it('should always return the greatest element', function() { var h = new heap.MaxHeap(); assert(h.isEmpty()); h.insert(10); @@ -103,7 +103,7 @@ describe('Max Heap', function () { assert(h.isEmpty()); }); - it('should heapify an unordered array', function () { + it('should heapify an unordered array', function() { var h = new heap.MaxHeap(); h.heapify([10, 2091, 4, 1, 5, 500, 0, 18, 3, 22, 20]); @@ -123,12 +123,12 @@ describe('Max Heap', function () { }); it('should perform a function to all elements from largest to smallest' + - ' with forEach', function () { + ' with forEach', function() { var h = new heap.MaxHeap(); h.heapify([3, 10, 1000, 0, 2, 1]); var output = []; - h.forEach(function (n) { + h.forEach(function(n) { output.push(n); }); diff --git a/src/test/data_structures/linked_list.js b/src/test/data_structures/linked_list.js index 5eadd60..dd946c6 100644 --- a/src/test/data_structures/linked_list.js +++ b/src/test/data_structures/linked_list.js @@ -1,17 +1,16 @@ 'use strict'; -var LinkedList = require('../..').DataStructures.LinkedList, - assert = require('assert'); +var LinkedList = require('../..').DataStructures.LinkedList; +var assert = require('assert'); -describe('LinkedList', function () { - - it('should start empty', function () { +describe('LinkedList', function() { + it('should start empty', function() { var l = new LinkedList(); assert(l.isEmpty()); assert.equal(l.length, 0); }); - it('should increment length when an item is added', function () { + it('should increment length when an item is added', function() { var l = new LinkedList(); l.add(1); assert.equal(l.length, 1); @@ -22,7 +21,7 @@ describe('LinkedList', function () { }); it('should return the items from the positions they were inserted', - function () { + function() { var l = new LinkedList(); l.add(1); l.add(2); @@ -63,30 +62,30 @@ describe('LinkedList', function () { }); it('should throw errors when trying to access indexes out of bounds', - function () { + function() { var l = new LinkedList(); - assert.throws(function () { l.get(0); }, Error); - assert.throws(function () { l.get(1); }, Error); - assert.throws(function () { l.get(10); }, Error); - assert.throws(function () { l.add(10, 1); }, Error); - assert.throws(function () { l.add(10, 10); }, Error); + assert.throws(() => l.get(0), Error); + assert.throws(() => l.get(1), Error); + assert.throws(() => l.get(10), Error); + assert.throws(() => l.add(10, 1), Error); + assert.throws(() => l.add(10, 10), Error); l.add(1); l.add(2); // length = 2 - assert.doesNotThrow(function () { l.get(0); }); - assert.doesNotThrow(function () { l.get(1); }); - assert.doesNotThrow(function () { l.add(3, 2); }); // length = 3 - assert.doesNotThrow(function () { l.add(3, 0); }); // length =4 - assert.doesNotThrow(function () { l.add(4, 1); }); // length = 5 - assert.doesNotThrow(function () { l.add(5, 5); }); // length = 6 - - assert.throws(function () { l.add(10, 10); }, Error); - assert.throws(function () { l.add(10, 7); }, Error); - assert.throws(function () { l.get(10); }, Error); + assert.doesNotThrow(() => l.get(0)); + assert.doesNotThrow(() => l.get(1)); + assert.doesNotThrow(() => l.add(3, 2)); // length = 3 + assert.doesNotThrow(() => l.add(3, 0)); // length =4 + assert.doesNotThrow(() => l.add(4, 1)); // length = 5 + assert.doesNotThrow(() => l.add(5, 5)); // length = 6 + + assert.throws(() => l.add(10, 10), Error); + assert.throws(() => l.add(10, 7), Error); + assert.throws(() => l.get(10), Error); }); - it('should be able to delete elements', function () { + it('should be able to delete elements', function() { var l = new LinkedList(); l.add(1); @@ -106,7 +105,7 @@ describe('LinkedList', function () { l.del(7); assert.equal(l.length, 7); assert.equal(l.tail.value, 7); - assert.throws(function () { l.get(7); }, Error); + assert.throws(() => l.get(7), Error); l.del(0); assert.equal(l.length, 6); @@ -133,7 +132,7 @@ describe('LinkedList', function () { assert.equal(l.length, 0); }); - it('should perform a function to all elements with forEach', function () { + it('should perform a function to all elements with forEach', function() { var l = new LinkedList(); l.add(5); l.add(1); @@ -142,7 +141,7 @@ describe('LinkedList', function () { l.add(1000); var a = []; - l.forEach(function (e) { + l.forEach(function(e) { a.push(e); }); @@ -150,8 +149,8 @@ describe('LinkedList', function () { }); it('should throw an error when trying to delete from an empty list', - function () { + function() { var l = new LinkedList(); - assert.throws(function () { l.del(0); }, Error); + assert.throws(() => l.del(0), Error); }); }); diff --git a/src/test/data_structures/priority_queue.js b/src/test/data_structures/priority_queue.js index 33728ef..5ef9a83 100644 --- a/src/test/data_structures/priority_queue.js +++ b/src/test/data_structures/priority_queue.js @@ -1,10 +1,10 @@ 'use strict'; -var PriorityQueue = require('../..').DataStructures.PriorityQueue, - assert = require('assert'); +var PriorityQueue = require('../..').DataStructures.PriorityQueue; +var assert = require('assert'); -describe('Min Priority Queue', function () { - it('should always return the element with the lowest priority', function () { +describe('Min Priority Queue', function() { + it('should always return the element with the lowest priority', function() { var q = new PriorityQueue(); assert(q.isEmpty()); q.insert('a', 10); @@ -36,7 +36,7 @@ describe('Min Priority Queue', function () { }); it('can receive a dictionary with item => priority in construction', - function () { + function() { var q = new PriorityQueue({ a: 10, b: 2091, @@ -53,7 +53,7 @@ describe('Min Priority Queue', function () { assert.equal(q.extract(), 'b'); }); - it('should be possible to change the priority of an item', function () { + it('should be possible to change the priority of an item', function() { var q = new PriorityQueue({ a: 10, b: 2091, @@ -79,7 +79,7 @@ describe('Min Priority Queue', function () { }); it('should just update the priority when trying to insert an element that ' + - ' already exists', function () { + ' already exists', function() { var q = new PriorityQueue({ a: 10, b: 2091, @@ -103,7 +103,5 @@ describe('Min Priority Queue', function () { assert.equal(q.extract(), 'd'); assert(q.isEmpty()); }); - }); - diff --git a/src/test/data_structures/queue.js b/src/test/data_structures/queue.js index 1915cca..aa7674b 100644 --- a/src/test/data_structures/queue.js +++ b/src/test/data_structures/queue.js @@ -1,16 +1,16 @@ 'use strict'; -var Queue = require('../..').DataStructures.Queue, - assert = require('assert'); +var Queue = require('../..').DataStructures.Queue; +var assert = require('assert'); -describe('Queue', function () { - it('should start empty', function () { +describe('Queue', function() { + it('should start empty', function() { var q = new Queue(); assert(q.isEmpty()); assert.equal(q.length, 0); }); - it('should implement a FIFO logic', function () { + it('should implement a FIFO logic', function() { var q = new Queue(); q.push(1); q.push(2); @@ -20,30 +20,30 @@ describe('Queue', function () { assert.equal(q.pop(), 2); assert.equal(q.pop(), 3); assert(q.isEmpty()); - assert.throws(function () { q.pop(); }, Error); + assert.throws(() => q.pop(), Error); }); it('should allow me to peek at the first element in' + - ' line without popping it', function () { - var q = new Queue(); - assert.throws(function () { q.peek(); }, Error); //Empty list - q.push(1); - q.push(2); - q.push(3); - assert.equal(q.peek(), 1); - assert.equal(q.peek(), 1); - q.pop(); - assert.equal(q.peek(), 2); - }); + ' line without popping it', function() { + var q = new Queue(); + assert.throws(() => q.peek(), Error); // Empty list + q.push(1); + q.push(2); + q.push(3); + assert.equal(q.peek(), 1); + assert.equal(q.peek(), 1); + q.pop(); + assert.equal(q.peek(), 2); + }); - it('should perform a function to all elements with forEach', function () { + it('should perform a function to all elements with forEach', function() { var q = new Queue(); q.push(1); q.push(2); q.push(3); var total = 0; - q.forEach(function (elem) { + q.forEach(function(elem) { total += elem; }); @@ -51,4 +51,3 @@ describe('Queue', function () { }); }); - diff --git a/src/test/data_structures/set.js b/src/test/data_structures/set.js index ab604c3..7cc088e 100644 --- a/src/test/data_structures/set.js +++ b/src/test/data_structures/set.js @@ -1,24 +1,23 @@ 'use strict'; -var HashSet = require('../..').DataStructures.Set, - assert = require('assert'); +var HashSet = require('../..').DataStructures.Set; +var assert = require('assert'); -describe('HashSet', function () { - it('should start empty', function () { +describe('HashSet', function() { + it('should start empty', function() { var s = new HashSet(); assert.equal(s.size, 0); }); - it('should add all initial arguments', function () { + it('should add all initial arguments', function() { var s = new HashSet(1, 2, 3); assert.equal(s.size, 3); assert(s.contains(1)); assert(s.contains(2)); assert(s.contains(3)); - }); - it('should add all arguments', function () { + it('should add all arguments', function() { var s = new HashSet(1, 2, 3); assert.equal(s.size, 3); s.add(4, 5, 6); @@ -31,7 +30,7 @@ describe('HashSet', function () { assert(s.contains(6)); }); - it('should remove all arguments', function () { + it('should remove all arguments', function() { var s = new HashSet(1, 2, 3); assert.equal(s.size, 3); s.remove(1, 3); @@ -42,7 +41,7 @@ describe('HashSet', function () { }); it('should do nothing when trying to remove an element that doesn\'t exist', - function () { + function() { var s = new HashSet(1, 2, 3); assert.equal(s.size, 3); s.remove(4); @@ -52,18 +51,18 @@ describe('HashSet', function () { assert(s.contains(3)); }); - it('should only contain its elements', function () { + it('should only contain its elements', function() { var s = new HashSet(1, 2, 3); assert(s.contains(1)); assert(!s.contains(4)); }); - it('should perform a function to all elements with forEach', function () { + it('should perform a function to all elements with forEach', function() { var s = new HashSet(); s.add(1, 2, 3); var total = 0; - s.forEach(function (elem) { + s.forEach(function(elem) { total += elem; }); @@ -71,4 +70,3 @@ describe('HashSet', function () { }); }); - diff --git a/src/test/data_structures/stack.js b/src/test/data_structures/stack.js index 2fa5fd9..dcf6527 100644 --- a/src/test/data_structures/stack.js +++ b/src/test/data_structures/stack.js @@ -1,16 +1,16 @@ 'use strict'; -var Stack = require('../..').DataStructures.Stack, - assert = require('assert'); +var Stack = require('../..').DataStructures.Stack; +var assert = require('assert'); -describe('Stack', function () { - it('should start empty', function () { +describe('Stack', function() { + it('should start empty', function() { var s = new Stack(); assert(s.isEmpty()); assert.equal(s.length, 0); }); - it('should implement a LIFO logic', function () { + it('should implement a LIFO logic', function() { var s = new Stack(); s.push(1); s.push(2); @@ -20,21 +20,19 @@ describe('Stack', function () { assert.equal(s.pop(), 2); assert.equal(s.pop(), 1); assert(s.isEmpty()); - assert.throws(function () { s.pop(); }, Error); + assert.throws(() => s.pop(), Error); }); it('should allow me to peek at the top element in' + - ' the stack without popping it', function () { - var s = new Stack(); - s.push(1); - s.push(2); - s.push(3); - assert.equal(s.peek(), 3); - assert.equal(s.peek(), 3); - s.pop(); - assert.equal(s.peek(), 2); - }); - + ' the stack without popping it', function() { + var s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + assert.equal(s.peek(), 3); + assert.equal(s.peek(), 3); + s.pop(); + assert.equal(s.peek(), 2); + }); }); - diff --git a/src/test/data_structures/treap.js b/src/test/data_structures/treap.js index 55c991d..ed9d852 100644 --- a/src/test/data_structures/treap.js +++ b/src/test/data_structures/treap.js @@ -1,16 +1,16 @@ 'use strict'; -var root = require('../..'), - Treap = root.DataStructures.Treap, - assert = require('assert'); +var root = require('../..'); +var Treap = root.DataStructures.Treap; +var assert = require('assert'); -describe('Treap', function () { +describe('Treap', function() { var treap; - before(function () { + before(function() { treap = new Treap(); }); - it('should insert elements', function () { + it('should insert elements', function() { treap.insert(3); treap.insert(2); treap.insert(10); @@ -23,7 +23,7 @@ describe('Treap', function () { assert.equal(treap.root.size, 8); }); - it('should remove elements correctly', function () { + it('should remove elements correctly', function() { // Value that not exist treap.remove(200); assert.equal(treap.root.size, 8); @@ -36,7 +36,7 @@ describe('Treap', function () { assert.equal(treap.root.size, 4); }); - it('should insert and remove elements', function () { + it('should insert and remove elements', function() { // [-100, 2, 3, 10] treap.insert(200); // [-100, 2, 3, 10, 200] @@ -54,7 +54,7 @@ describe('Treap', function () { assert.equal(treap.root.size, 5); }); - it('should check if an element exists', function () { + it('should check if an element exists', function() { // [1, 2, 3, 10, 100] assert.equal(treap.find(1), true); assert.equal(treap.find(2), true); @@ -67,7 +67,7 @@ describe('Treap', function () { assert.equal(treap.find(101), false); }); - it('should get minimum element', function () { + it('should get minimum element', function() { // [1, 2, 3, 10, 100] assert.equal(treap.minimum(), 1); treap.remove(1); @@ -81,7 +81,7 @@ describe('Treap', function () { assert.equal(treap.minimum(), 2); }); - it('should get maximum element', function () { + it('should get maximum element', function() { // [2, 3, 10, 100] assert.equal(treap.maximum(), 100); treap.remove(100); @@ -100,43 +100,43 @@ describe('Treap', function () { // [1] assert.equal(treap.maximum(), 1); }); - - it('should handle dumplicated elements', function () { - treap.insert(1); - // [1, 1] - assert.equal(treap.size(), 2); - treap.insert(-1); - // [-1, 1, 1] - assert.equal(treap.size(), 3); - treap.remove(1); - // [-1, 1] - assert.equal(treap.size(), 2); - treap.insert(-1); - treap.insert(-1); - treap.insert(-1); - // [-1, -1, -1, -1, 1] - assert.equal(treap.size(), 5); - treap.remove(-1); - treap.remove(1); - treap.remove(-1); - treap.remove(-1); - treap.remove(-1); - assert.equal(treap.size(), 0); + + it('should handle dumplicated elements', function() { + treap.insert(1); + // [1, 1] + assert.equal(treap.size(), 2); + treap.insert(-1); + // [-1, 1, 1] + assert.equal(treap.size(), 3); + treap.remove(1); + // [-1, 1] + assert.equal(treap.size(), 2); + treap.insert(-1); + treap.insert(-1); + treap.insert(-1); + // [-1, -1, -1, -1, 1] + assert.equal(treap.size(), 5); + treap.remove(-1); + treap.remove(1); + treap.remove(-1); + treap.remove(-1); + treap.remove(-1); + assert.equal(treap.size(), 0); }); - it('should keep balance', function () { - // Insert 1023 elements randomly - for (var i = 0; i < 1023; ++i) { - treap.insert(Math.random()); - } - assert.equal(treap.size(), 1023); - // The averange height should be 23 (with an error of 5) - assert(Math.abs(treap.height() - 23) < 5); + it('should keep balance', function() { + // Insert 1023 elements randomly + for (var i = 0; i < 1023; ++i) { + treap.insert(Math.random()); + } + assert.equal(treap.size(), 1023); + // The averange height should be 23 (with an error of 5) + assert(Math.abs(treap.height() - 23) < 5); }); - it('should rotate correctly', function () { - // Force clear the tree - treap.root = null; + it('should rotate correctly', function() { + // Force clear the tree + treap.root = null; treap.insert(1); // 1 assert.equal(treap.height(), 1); @@ -149,10 +149,10 @@ describe('Treap', function () { * / * 1 * - */ + */ assert.equal(treap.height(), 2); - treap.root.key = 1; + treap.root.key = 1; treap.insert(3); /** * 3 @@ -161,7 +161,7 @@ describe('Treap', function () { * / * 1 * - */ + */ assert.equal(treap.height(), 3); assert.equal(treap.root.value, 3); @@ -171,7 +171,7 @@ describe('Treap', function () { * / \ * 1 3 * - */ + */ assert.equal(treap.height(), 2); assert.equal(treap.root.value, 2); @@ -183,8 +183,8 @@ describe('Treap', function () { * \ * 3 * - */ + */ assert.equal(treap.height(), 3); assert.equal(treap.root.value, 1); }); -}); \ No newline at end of file +}); diff --git a/src/test/util/comparator.js b/src/test/util/comparator.js index 62bd2a6..41eea91 100644 --- a/src/test/util/comparator.js +++ b/src/test/util/comparator.js @@ -1,11 +1,11 @@ 'use strict'; -var Comparator = require('../../util/comparator'), - assert = require('assert'); +var Comparator = require('../../util/comparator'); +var assert = require('assert'); -describe('Comparator', function () { +describe('Comparator', function() { it('Should use a default arithmetic comparison if no function is passed', - function () { + function() { var c = new Comparator(); assert.equal(c.compare(1, 1), 0); assert.equal(c.compare(1, 2), -1); @@ -25,8 +25,8 @@ describe('Comparator', function () { assert(!c.equal(0, 1)); }); - it('should allow comparison function to be defined by user', function () { - var compareFn = function () { + it('should allow comparison function to be defined by user', function() { + var compareFn = function() { return 0; }; var c = new Comparator(compareFn); @@ -48,7 +48,7 @@ describe('Comparator', function () { assert(c.equal(0, 1)); }); - it('Should allow reversing the comparisons', function () { + it('Should allow reversing the comparisons', function() { var c = new Comparator(); c.reverse(); assert.equal(c.compare(1, 1), 0); diff --git a/src/util/comparator.js b/src/util/comparator.js index e35578d..75f9e6c 100644 --- a/src/util/comparator.js +++ b/src/util/comparator.js @@ -17,28 +17,28 @@ function Comparator(compareFn) { /** * Default implementation for the compare function */ -Comparator.prototype.compare = function (a, b) { +Comparator.prototype.compare = function(a, b) { if (a === b) return 0; return a < b ? -1 : 1; }; -Comparator.prototype.lessThan = function (a, b) { +Comparator.prototype.lessThan = function(a, b) { return this.compare(a, b) < 0; }; -Comparator.prototype.lessThanOrEqual = function (a, b) { +Comparator.prototype.lessThanOrEqual = function(a, b) { return this.lessThan(a, b) || this.equal(a, b); }; -Comparator.prototype.greaterThan = function (a, b) { +Comparator.prototype.greaterThan = function(a, b) { return this.compare(a, b) > 0; }; -Comparator.prototype.greaterThanOrEqual = function (a, b) { +Comparator.prototype.greaterThanOrEqual = function(a, b) { return this.greaterThan(a, b) || this.equal(a, b); }; -Comparator.prototype.equal = function (a, b) { +Comparator.prototype.equal = function(a, b) { return this.compare(a, b) === 0; }; @@ -48,9 +48,9 @@ Comparator.prototype.equal = function (a, b) { * this.reverse(); * this.compare(a, b) => -1 */ -Comparator.prototype.reverse = function () { +Comparator.prototype.reverse = function() { var originalCompareFn = this.compare; - this.compare = function (a, b) { + this.compare = function(a, b) { return originalCompareFn(b, a); }; }; From dec8937fa3695c5b40e37616dcf6ecad19e645af Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 21 Jun 2016 22:43:31 +0200 Subject: [PATCH 232/280] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc8d7cb..8749aef 100644 --- a/README.md +++ b/README.md @@ -151,4 +151,4 @@ require('algorithms').String; ### Contributing -This project uses [Google JavaScript Style Guide](https://google.github.io/styleguide/javascriptguide.xml) which can be a bit strict, but is really helpful to have more readable and less error-prone code +This project uses [Google JavaScript Style Guide](https://google.github.io/styleguide/javascriptguide.xml) which can be a bit strict, but is really helpful in order to have more readable and less error-prone code From 3f4e7e0365a57d20b768a1f41983db3b65592c0a Mon Sep 17 00:00:00 2001 From: Venkata krishna Date: Sat, 27 Aug 2016 22:59:33 -0700 Subject: [PATCH 233/280] Added findDivisors Added findDivisors to find all the divisors of a natural number. Implemented three versions. 1) findDivisorsGeneric 2) findDivisorsByPairingUnsorted 3) findDivisorsByPairingSorted Signed-off-by: Venkata krishna --- README.md | 1 + src/algorithms/math/find_divisors.js | 91 +++++++++++++++++++++++ src/math.js | 3 +- src/test/algorithms/math/find_divisors.js | 52 +++++++++++++ 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/algorithms/math/find_divisors.js create mode 100644 src/test/algorithms/math/find_divisors.js diff --git a/README.md b/README.md index 8749aef..711d5ca 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ require('algorithms').Math; * extendedEuclidean * fastPower * fibonacci +* findDivisors * fisherYates * gcd (Greatest common divisor) * greatestDifference diff --git a/src/algorithms/math/find_divisors.js b/src/algorithms/math/find_divisors.js new file mode 100644 index 0000000..463d326 --- /dev/null +++ b/src/algorithms/math/find_divisors.js @@ -0,0 +1,91 @@ +'use strict'; + +/** + * Different implementations for finding the divisors + */ + +/** + * Find all the divisors of a natural number + * This solution has a cost of O(n) + * This solution uses the naive method to print all divisors + * + * @param {number} + * @returns {number[]} - returns the divisors + */ + +var findDivisorsGeneric = function(number) { + var index = 1; + var divisors = []; + + for (index; index <= number; index++) { + if (number % index === 0) { + divisors.push(index); + } + } + return divisors; +}; + +/** + * Find all the divisors of a natural number + * This solution has a cost of O(sqrt(n)) + * This method returns the divisors in an unsorted manner. + * All divisors of a number are present in pairs. + * Eg : For n=16: (1, 16), (2, 8), (4, 4). Include only one of the repeated divisors if any. + * + * @param {number} + * @returns {number[]} - returns the divisors + */ + +var findDivisorsByPairingUnsorted = function(number) { + var index = 1; + var divisors = []; + + for (index; index <= Math.sqrt(number); index++) { + if (number % index === 0) { + if (number / index === index) + divisors.push(index); + else { + divisors.push(index); + divisors.push(number / index); + } + } + } + return divisors; +}; + +/** + * Find all the divisors of a natural number + * This solution has a cost of O(sqrt(n)) + * This method returns the array in a sorted manner + * All divisors of a number are present in pairs (divisorLessThanSqrt, divisorGreaterThanSqrt) + * Reverse the divisorGreaterThanSqrt array and append to divisorLessThanSqrt to sort the result + * Eg : For n=16: (1, 16), (2, 8), (4, 4). Include only one of the repeated divisors if any + * + * @param {number} + * @returns {number[]} - returns the divisors + */ + +var findDivisorsByPairingSorted = function(number) { + var index = 1; + var divisors = []; + var divisorsLessThanSqrt = []; + var divisorsMoreThanSqrt = []; + + for (index; index <= Math.sqrt(number); index++) { + if (number % index === 0) { + if (number / index === index) + divisorsLessThanSqrt.push(index); + else { + divisorsLessThanSqrt.push(index); + divisorsMoreThanSqrt.push(number / index); + } + } + } + divisors = divisorsLessThanSqrt.concat(divisorsMoreThanSqrt.reverse()); + return divisors; +}; + +// Use findDivisorsGeneric as the default implementation +findDivisorsGeneric.pairingUnsorted = findDivisorsByPairingUnsorted; +findDivisorsGeneric.pairingSorted = findDivisorsByPairingSorted; +module.exports = findDivisorsGeneric; diff --git a/src/math.js b/src/math.js index 3276a7e..af22fe1 100644 --- a/src/math.js +++ b/src/math.js @@ -15,5 +15,6 @@ module.exports = { powerSet: require('./algorithms/math/power_set'), shannonEntropy: require('./algorithms/math/shannon_entropy'), collatzConjecture: require('./algorithms/math/collatz_conjecture'), - greatestDifference: require('./algorithms/math/greatest_difference') + greatestDifference: require('./algorithms/math/greatest_difference'), + findDivisors: require('./algorithms/math/find_divisors') }; diff --git a/src/test/algorithms/math/find_divisors.js b/src/test/algorithms/math/find_divisors.js new file mode 100644 index 0000000..08aa010 --- /dev/null +++ b/src/test/algorithms/math/find_divisors.js @@ -0,0 +1,52 @@ +'use strict'; + +var math = require('../../..').Math; +var findDivisors = math.findDivisors; +var assert = require('assert'); + +/** + * Deep equal for arrays + */ +function testArrayEqual(a, b) { + var arrayEqual = true; + a.sort(); + b.sort(); + a.forEach(function(elem, index) { + if (a[index] !== b[index]) { + arrayEqual = false; + } + }); + return arrayEqual && a.length === b.length; +} + +var testFindDivisors = function(findDivisors) { + assert(testArrayEqual([], findDivisors(-2))); + assert(testArrayEqual([], findDivisors(0))); + assert(testArrayEqual([1], findDivisors(1))); + assert(testArrayEqual([1, 2], findDivisors(2))); + assert(testArrayEqual([1, 3], findDivisors(3))); + assert(testArrayEqual([1, 2, 4], findDivisors(4))); + assert(testArrayEqual([1, 5], findDivisors(5))); + assert(testArrayEqual([1, 2, 4, 5, 10, 20, 25, 50, 100], findDivisors(100))); + assert(testArrayEqual([1, 2, 7, 13, 14, 26, 91, 182], findDivisors(182))); +}; + +describe('Find divisors', function() { + describe('#Generic()', function() { + it('should return the divisors of the number', function() { + testFindDivisors(findDivisors); + }); + }); + + describe('#PairingUnsorted()', function() { + it('should return the divisors of the number', function() { + testFindDivisors(findDivisors.pairingUnsorted); + }); + }); + + describe('#PairingSorted()', function() { + it('should return the divisors of the number', function() { + testFindDivisors(findDivisors.pairingSorted); + }); + }); +}); From 8e71c15b6352cb89fb1e98fb03d75cdfbec39328 Mon Sep 17 00:00:00 2001 From: Xuefeng Zhu Date: Fri, 4 Nov 2016 23:36:48 -0500 Subject: [PATCH 234/280] minor simplify to shell_sort.js --- src/algorithms/sorting/shell_sort.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/sorting/shell_sort.js b/src/algorithms/sorting/shell_sort.js index bdd7c11..312b394 100644 --- a/src/algorithms/sorting/shell_sort.js +++ b/src/algorithms/sorting/shell_sort.js @@ -7,7 +7,7 @@ var shellSort = function(array, comparatorFn) { var comparator = new Comparator(comparatorFn); var begin = 0; var end = array.length - 1; - var gap = parseInt((end - begin + 1) / 2, 10); + var gap = parseInt((array.length) / 2, 10); var i = 0; var j = 0; var temp = 0; From 97cb74078ba090d2c9b715285a1c9af9e97de972 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Sat, 5 Nov 2016 13:44:56 +0100 Subject: [PATCH 235/280] Simplify shellSort code --- src/algorithms/sorting/shell_sort.js | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/algorithms/sorting/shell_sort.js b/src/algorithms/sorting/shell_sort.js index 312b394..135b8b1 100644 --- a/src/algorithms/sorting/shell_sort.js +++ b/src/algorithms/sorting/shell_sort.js @@ -5,24 +5,19 @@ var Comparator = require('../../util/comparator'); */ var shellSort = function(array, comparatorFn) { var comparator = new Comparator(comparatorFn); - var begin = 0; - var end = array.length - 1; - var gap = parseInt((array.length) / 2, 10); - var i = 0; - var j = 0; - var temp = 0; + var gap = Math.floor(array.length / 2); - while (gap >= 1) { - for (i = begin + gap; i <= end; i += 1) { - temp = array[i]; - j = i - gap; - while (j >= begin && comparator.greaterThan(array[j], temp)) { + while (gap > 0) { + for (var i = gap; i < array.length; i++) { + var temp = array[i]; + var j = i - gap; + while (j >= 0 && comparator.greaterThan(array[j], temp)) { array[j + gap] = array[j]; j -= gap; } array[j + gap] = temp; } - gap = parseInt(gap / 2, 10); + gap = Math.floor(gap / 2); } return array; From fea6b652948da229518cdcad83edda2dbdfcdcac Mon Sep 17 00:00:00 2001 From: Xuefeng Zhu Date: Fri, 18 Nov 2016 22:12:05 -0600 Subject: [PATCH 236/280] remove unused code in longest_common_substring --- src/algorithms/string/longest_common_substring.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/algorithms/string/longest_common_substring.js b/src/algorithms/string/longest_common_substring.js index e093e3e..060ddf8 100644 --- a/src/algorithms/string/longest_common_substring.js +++ b/src/algorithms/string/longest_common_substring.js @@ -28,7 +28,6 @@ var longestCommonSubstring = function(s1, s2) { cache[i][j] = cache[i - 1][j - 1] + 1; if (cache[i][j] > lcsLength) { lcsPosition.i = i; - lcsPosition.j = j; lcsLength = cache[i][j]; } } else { From 0e1766f1f9b7fccdb2c44deca4f6bdf8fc7809ca Mon Sep 17 00:00:00 2001 From: Hart Chu Date: Sun, 12 Feb 2017 02:54:22 -0600 Subject: [PATCH 237/280] Strongly Connected Component (#121) * Added reverseGraph method to Graph (and its test) * Added Strongly Connected Component Algorithm (and its test) * Fix code style problems * Fix code style problems * Fix code style problems * Improved documentation * Use addEdge method instead of hard coding * Use stack more properly * Move function creation out of loop * Fix style problem --- .../graph/strongly_connected_component.js | 72 +++++++++++++++++ src/data_structures/graph.js | 17 ++++ src/graph.js | 4 +- .../graph/strongly_connected_component.js | 81 +++++++++++++++++++ src/test/data_structures/graph.js | 26 ++++++ 5 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 src/algorithms/graph/strongly_connected_component.js create mode 100644 src/test/algorithms/graph/strongly_connected_component.js diff --git a/src/algorithms/graph/strongly_connected_component.js b/src/algorithms/graph/strongly_connected_component.js new file mode 100644 index 0000000..e2bbef2 --- /dev/null +++ b/src/algorithms/graph/strongly_connected_component.js @@ -0,0 +1,72 @@ +'use strict'; + +var Stack = require('../../data_structures/stack'); +var depthFirstSearch = require('../../algorithms/graph/depth_first_search'); + +/** + * Kosaraju's Strongly Connected Component algorithm, https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm + * Complexity: O(V + E). + * + * @param {Graph} graph + * @return {{count: number, id: Object.}} + * count is the number of strongly connected components in the graph + * id is a Object, receives a vertex and returns id of the strongly + * connected component vertex belongs to, ranges from 0 to count - 1. + * note: 1.if v and w are in same scc, then id[v] == id[w] + * 2.if v and w are in different scc and there is a path from v to w, then id[v] > id[w]. + * + * Usage: + * var scc = stronglyConnectedComponent(g); + * scc.count; // count of strongly connected components + * scc.id[v]; // id of the strongly connected component which v belongs to + */ +var stronglyConnectedComponent = function(graph) { + var reverse = graph.reverse(); + var stack = new Stack(); + var visited = {}; + var count = 0; + var id = Object.create(null); + + reverse.vertices.forEach(function(node) { + if (!visited[node]) { + depthFirstSearch(reverse, node, { + allowTraversal: function(node, neighbor) { + return !visited[neighbor]; + }, + enterVertex: function(node) { + visited[node] = true; + }, + leaveVertex: function(node) { + stack.push(node); + } + }); + } + }); + + visited = {}; + var allowTraversal = function(node, neighbor) { + return !visited[neighbor]; + }; + var enterVertex = function(node) { + visited[node] = true; + id[node] = count; + }; + + while (!stack.isEmpty()) { + var node = stack.pop(); + if (!visited[node]) { + depthFirstSearch(graph, node, { + allowTraversal: allowTraversal, + enterVertex: enterVertex + }); + ++count; + } + } + + return { + count: count, + id: id + }; +}; + +module.exports = stronglyConnectedComponent; diff --git a/src/data_structures/graph.js b/src/data_structures/graph.js index a88303d..39019bf 100644 --- a/src/data_structures/graph.js +++ b/src/data_structures/graph.js @@ -53,4 +53,21 @@ Graph.prototype.edge = function(a, b) { return this.adjList[_(a)][_(b)]; }; +Graph.prototype.reverse = function() { + var self = this; + var r = new Graph(this.directed); + + self.vertices.forEach(function(v) { + r.addVertex(v); + }); + + self.vertices.forEach(function(a) { + self.neighbors(a).forEach(function(b) { + r.addEdge(b, a, self.edge(a, b)); + }); + }); + + return r; +}; + module.exports = Graph; diff --git a/src/graph.js b/src/graph.js index 2fbbde5..29a5c61 100644 --- a/src/graph.js +++ b/src/graph.js @@ -12,5 +12,7 @@ module.exports = { breadthFirstSearch: require('./algorithms/graph/breadth_first_search'), bfsShortestPath: require('./algorithms/graph/bfs_shortest_path'), prim: require('./algorithms/graph/prim'), - floydWarshall: require('./algorithms/graph/floyd_warshall') + floydWarshall: require('./algorithms/graph/floyd_warshall'), + strongConnectedComponent: require('./algorithms/graph/' + + 'strongly_connected_component') }; diff --git a/src/test/algorithms/graph/strongly_connected_component.js b/src/test/algorithms/graph/strongly_connected_component.js new file mode 100644 index 0000000..f879b3c --- /dev/null +++ b/src/test/algorithms/graph/strongly_connected_component.js @@ -0,0 +1,81 @@ +'use strict'; + +var root = require('../../../'); +var Graph = root.DataStructures.Graph; +var stronglyConnectedComponent = root.Graph.strongConnectedComponent; +var assert = require('assert'); + +describe('Strongly Connected Component', function() { + it('should correctly compute strongly connected components', function() { + // graph: 0 -> 1 -> 2 + var graph = new Graph(); + graph.addEdge(0, 1); + graph.addEdge(1, 2); + + var scc = stronglyConnectedComponent(graph); + assert.equal(scc.count, 3); + assert(scc.id[0] > scc.id[1]); + assert(scc.id[1] > scc.id[2]); + + // graph: 0 <-> 1 -> 2 + graph = new Graph(); + graph.addEdge(0, 1); + graph.addEdge(1, 0); + graph.addEdge(1, 2); + + scc = stronglyConnectedComponent(graph); + assert.equal(scc.count, 2); + assert.equal(scc.id[0], scc.id[1]); + assert(scc.id[1] > scc.id[2]); + + // graph: http://algs4.cs.princeton.edu/42digraph/images/transitive-closure.png + graph = new Graph(); + graph.addEdge(0, 1); + graph.addEdge(0, 5); + graph.addEdge(2, 0); + graph.addEdge(2, 3); + graph.addEdge(3, 2); + graph.addEdge(3, 5); + graph.addEdge(4, 2); + graph.addEdge(4, 3); + graph.addEdge(5, 4); + graph.addEdge(6, 0); + graph.addEdge(6, 4); + graph.addEdge(6, 9); + graph.addEdge(7, 6); + graph.addEdge(7, 8); + graph.addEdge(8, 7); + graph.addEdge(8, 9); + graph.addEdge(9, 10); + graph.addEdge(9, 11); + graph.addEdge(10, 12); + graph.addEdge(11, 4); + graph.addEdge(11, 12); + graph.addEdge(12, 9); + + scc = stronglyConnectedComponent(graph); + assert.equal(scc.count, 5); + + // scc no.0 + assert(scc.id[0] > scc.id[1]); + + // scc no.1 + assert.equal(scc.id[0], scc.id[2]); + assert.equal(scc.id[0], scc.id[3]); + assert.equal(scc.id[0], scc.id[4]); + assert.equal(scc.id[0], scc.id[5]); + + // scc no.2 + assert(scc.id[9] > scc.id[0]); + assert.equal(scc.id[9], scc.id[10]); + assert.equal(scc.id[9], scc.id[11]); + assert.equal(scc.id[9], scc.id[12]); + + // scc no.3 + assert(scc.id[6] > scc.id[9]); + + // scc no.4 + assert(scc.id[7] > scc.id[6]); + assert.equal(scc.id[7], scc.id[8]); + }); +}); diff --git a/src/test/data_structures/graph.js b/src/test/data_structures/graph.js index 9d4e38c..1ee4408 100644 --- a/src/test/data_structures/graph.js +++ b/src/test/data_structures/graph.js @@ -86,6 +86,32 @@ describe('Graph - Adjacency list', function() { assert.equal(g.edge('b', 'a'), 2); }); + it('should have reversed edges with same weight for a reverse directed graph', + function() { + var g = new Graph(); + g.addVertex('a'); + g.addVertex('b'); + g.addVertex('c'); + g.addVertex('d'); + g.addEdge('a', 'b', 10); + g.addEdge('a', 'c', 5); + g.addEdge('c', 'd', 2); + + var r = g.reverse(); + assert(r.directed); + assert.equal(r.edge('a', 'b'), undefined); + assert.equal(r.edge('b', 'a'), 10); + assert.equal(r.edge('a', 'c'), undefined); + assert.equal(r.edge('c', 'a'), 5); + assert.equal(r.edge('c', 'd'), undefined); + assert.equal(r.edge('d', 'c'), 2); + + assert.equal(r.edge('a', 'd'), undefined); + r.addEdge('a', 'b', 2); + assert.equal(r.edge('a', 'b'), 2); + assert.equal(r.edge('b', 'a'), 10); + }); + it('should have a list of vertices', function() { var g = new Graph(); assert.equal(g.vertices.size, 0); From 945aaab486173c198335e51a1a3b96051c2c1e5f Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Mon, 13 Feb 2017 14:19:19 +0100 Subject: [PATCH 238/280] Stop using inheritance wrongly --- src/data_structures/stack.js | 47 ++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/src/data_structures/stack.js b/src/data_structures/stack.js index de5f4ee..2857189 100644 --- a/src/data_structures/stack.js +++ b/src/data_structures/stack.js @@ -1,26 +1,53 @@ 'use strict'; - -var Queue = require('./queue'); +var LinkedList = require('./linked_list'); /** * Stack (LIFO) using a Linked List as basis */ function Stack() { - Queue.call(this); + this._elements = new LinkedList(); + + Object.defineProperty(this, 'length', { + get: (function() { + return this._elements.length; + }).bind(this) + }); } +Stack.prototype.isEmpty = function() { + return this._elements.isEmpty(); +}; + /** - * Use a Queue as prototype and just overwrite - * the push method to insert at the 0 position - * instead of the end of the queue + * Adds element to the end of the stack */ -Stack.prototype = new Queue(); +Stack.prototype.push = function(e) { + this._elements.add(e); +}; /** - * Adds element to the top of the stack + * Pops the element from the end of the stack */ -Stack.prototype.push = function(e) { - this._elements.add(e, 0); +Stack.prototype.pop = function() { + if (this.isEmpty()) { + throw new Error('Empty queue'); + } + + var e = this._elements.tail; + this._elements.delNode(e); + return e.value; +}; + +Stack.prototype.peek = function() { + if (this.isEmpty()) { + throw new Error('Empty queue'); + } + + return this._elements.tail.value; +}; + +Stack.prototype.forEach = function(fn) { + this._elements.forEach(fn); }; module.exports = Stack; From e9cbb710488f288ab91495c7ff6a7b2d9f0f1135 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Mon, 13 Feb 2017 14:27:14 +0100 Subject: [PATCH 239/280] Remove forEach from Stack and Queue --- src/data_structures/queue.js | 10 +++------- src/data_structures/stack.js | 4 ---- src/test/data_structures/queue.js | 15 --------------- 3 files changed, 3 insertions(+), 26 deletions(-) diff --git a/src/data_structures/queue.js b/src/data_structures/queue.js index e625bef..725fc4e 100644 --- a/src/data_structures/queue.js +++ b/src/data_structures/queue.js @@ -33,9 +33,9 @@ Queue.prototype.pop = function() { if (this.isEmpty()) { throw new Error('Empty queue'); } - var e = this._elements.get(0); - this._elements.del(0); - return e; + var e = this._elements.head; + this._elements.delNode(e); + return e.value; }; Queue.prototype.peek = function() { @@ -46,8 +46,4 @@ Queue.prototype.peek = function() { return this._elements.get(0); }; -Queue.prototype.forEach = function(fn) { - this._elements.forEach(fn); -}; - module.exports = Queue; diff --git a/src/data_structures/stack.js b/src/data_structures/stack.js index 2857189..19cf18b 100644 --- a/src/data_structures/stack.js +++ b/src/data_structures/stack.js @@ -46,8 +46,4 @@ Stack.prototype.peek = function() { return this._elements.tail.value; }; -Stack.prototype.forEach = function(fn) { - this._elements.forEach(fn); -}; - module.exports = Stack; diff --git a/src/test/data_structures/queue.js b/src/test/data_structures/queue.js index aa7674b..3ec85ee 100644 --- a/src/test/data_structures/queue.js +++ b/src/test/data_structures/queue.js @@ -35,19 +35,4 @@ describe('Queue', function() { q.pop(); assert.equal(q.peek(), 2); }); - - it('should perform a function to all elements with forEach', function() { - var q = new Queue(); - q.push(1); - q.push(2); - q.push(3); - - var total = 0; - q.forEach(function(elem) { - total += elem; - }); - - assert.equal(total, 6); - }); }); - From dea1078c5eb08fb54fba9947930fa80ba682f2f0 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Mon, 13 Feb 2017 17:13:34 +0100 Subject: [PATCH 240/280] Fix comments --- src/data_structures/stack.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data_structures/stack.js b/src/data_structures/stack.js index 19cf18b..4c7b982 100644 --- a/src/data_structures/stack.js +++ b/src/data_structures/stack.js @@ -19,14 +19,14 @@ Stack.prototype.isEmpty = function() { }; /** - * Adds element to the end of the stack + * Adds element to the top of the stack */ Stack.prototype.push = function(e) { this._elements.add(e); }; /** - * Pops the element from the end of the stack + * Pops the element from the top of the stack */ Stack.prototype.pop = function() { if (this.isEmpty()) { From 303643a130cdf1852f5e3c0fb39f82f4579bd014 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 14 Jun 2017 16:46:30 +0200 Subject: [PATCH 241/280] [es6] Use let/const instead of var --- src/algorithms/geometry/bezier_curve.js | 18 +++--- src/algorithms/graph/SPFA.js | 24 +++---- src/algorithms/graph/bellman_ford.js | 22 +++---- src/algorithms/graph/bfs_shortest_path.js | 8 +-- src/algorithms/graph/breadth_first_search.js | 16 ++--- src/algorithms/graph/depth_first_search.js | 10 +-- src/algorithms/graph/dijkstra.js | 14 ++-- src/algorithms/graph/euler_path.js | 24 +++---- src/algorithms/graph/floyd_warshall.js | 14 ++-- src/algorithms/graph/kruskal.js | 12 ++-- src/algorithms/graph/prim.js | 22 +++---- .../graph/strongly_connected_component.js | 22 +++---- src/algorithms/graph/topological_sort.js | 12 ++-- src/algorithms/math/collatz_conjecture.js | 4 +- src/algorithms/math/extended_euclidean.js | 18 +++--- src/algorithms/math/fast_power.js | 10 +-- src/algorithms/math/fibonacci.js | 32 +++++----- src/algorithms/math/find_divisors.js | 22 +++---- src/algorithms/math/fisher_yates.js | 8 +-- src/algorithms/math/gcd.js | 10 +-- src/algorithms/math/greatest_difference.js | 12 ++-- src/algorithms/math/lcm.js | 10 +-- src/algorithms/math/newton_sqrt.js | 14 ++-- src/algorithms/math/next_permutation.js | 16 ++--- src/algorithms/math/power_set.js | 20 +++--- src/algorithms/math/primality_tests.js | 12 ++-- src/algorithms/math/reservoir_sampling.js | 8 +-- src/algorithms/math/shannon_entropy.js | 6 +- src/algorithms/search/bfs.js | 8 +-- src/algorithms/search/binarysearch.js | 8 +-- src/algorithms/search/dfs.js | 6 +- src/algorithms/search/ternary_search.js | 6 +- src/algorithms/sorting/bubble_sort.js | 20 +++--- src/algorithms/sorting/counting_sort.js | 26 ++++---- src/algorithms/sorting/heap_sort.js | 8 +-- src/algorithms/sorting/insertion_sort.js | 12 ++-- src/algorithms/sorting/merge_sort.js | 20 +++--- src/algorithms/sorting/quicksort.js | 20 +++--- src/algorithms/sorting/radix_sort.js | 30 ++++----- src/algorithms/sorting/selection_sort.js | 16 ++--- src/algorithms/sorting/shell_sort.js | 14 ++-- src/algorithms/sorting/short_bubble_sort.js | 12 ++-- src/algorithms/string/hamming.js | 6 +- src/algorithms/string/huffman.js | 64 +++++++++---------- src/algorithms/string/knuth_morris_pratt.js | 22 +++---- src/algorithms/string/levenshtein.js | 8 +-- .../string/longest_common_subsequence.js | 10 +-- .../string/longest_common_substring.js | 14 ++-- src/algorithms/string/rabin_karp.js | 18 +++--- src/data_structures/avl_tree.js | 58 ++++++++--------- src/data_structures/bst.js | 12 ++-- src/data_structures/disjoint_set_forest.js | 6 +- src/data_structures/fenwick_tree.js | 4 +- src/data_structures/graph.js | 8 +-- src/data_structures/hash_table.js | 32 +++++----- src/data_structures/heap.js | 20 +++--- src/data_structures/linked_list.js | 12 ++-- src/data_structures/priority_queue.js | 6 +- src/data_structures/queue.js | 4 +- src/data_structures/set.js | 8 +-- src/data_structures/stack.js | 4 +- src/data_structures/treap.js | 8 +-- src/index.js | 2 +- src/test/algorithms/geometry/bezier_curve.js | 12 ++-- src/test/algorithms/graph/SPFA.js | 12 ++-- src/test/algorithms/graph/bellman_ford.js | 12 ++-- .../algorithms/graph/bfs_shortest_path.js | 12 ++-- .../algorithms/graph/breadth_first_search.js | 26 ++++---- .../algorithms/graph/depth_first_search.js | 24 +++---- src/test/algorithms/graph/dijkstra.js | 12 ++-- src/test/algorithms/graph/euler_path.js | 44 ++++++------- src/test/algorithms/graph/floyd_warshall.js | 14 ++-- .../algorithms/graph/minimum_spanning_tree.js | 44 ++++++------- .../graph/strongly_connected_component.js | 12 ++-- src/test/algorithms/graph/topological_sort.js | 14 ++-- .../algorithms/math/collatz_conjecture.js | 6 +- .../algorithms/math/extended_euclidean.js | 8 +-- src/test/algorithms/math/fast_power.js | 14 ++-- src/test/algorithms/math/fibonacci.js | 8 +-- src/test/algorithms/math/find_divisors.js | 10 +-- src/test/algorithms/math/fisher_yates.js | 10 +-- src/test/algorithms/math/gcd.js | 8 +-- .../algorithms/math/greatest_difference.js | 6 +- src/test/algorithms/math/lcm.js | 8 +-- src/test/algorithms/math/newton_sqrt.js | 14 ++-- src/test/algorithms/math/next_permutation.js | 26 ++++---- src/test/algorithms/math/power_set.js | 30 ++++----- src/test/algorithms/math/primality_tests.js | 8 +-- .../algorithms/math/reservoir_sampling.js | 14 ++-- src/test/algorithms/math/shannon_entropy.js | 4 +- src/test/algorithms/searching/bfs.js | 14 ++-- src/test/algorithms/searching/binarysearch.js | 4 +- src/test/algorithms/searching/dfs.js | 18 +++--- .../algorithms/searching/ternary_search.js | 12 ++-- src/test/algorithms/sorting/bubble_sort.js | 4 +- src/test/algorithms/sorting/counting_sort.js | 12 ++-- src/test/algorithms/sorting/heap_sort.js | 4 +- src/test/algorithms/sorting/insertion_sort.js | 4 +- src/test/algorithms/sorting/merge_sort.js | 4 +- src/test/algorithms/sorting/quicksort.js | 4 +- src/test/algorithms/sorting/radix_sort.js | 14 ++-- src/test/algorithms/sorting/selection_sort.js | 4 +- src/test/algorithms/sorting/shell_sort.js | 4 +- .../algorithms/sorting/short_bubble_sort.js | 4 +- .../sorting/sorting_tests_helper.js | 6 +- src/test/algorithms/string/hamming.js | 6 +- src/test/algorithms/string/huffman.js | 38 +++++------ .../algorithms/string/knuth_morris_pratt.js | 12 ++-- src/test/algorithms/string/levenshtein.js | 4 +- .../string/longest_common_subsequence.js | 8 +-- .../string/longest_common_substring.js | 8 +-- src/test/algorithms/string/rabin_karp.js | 6 +- src/test/data_structures/avl-tree.js | 42 ++++++------ src/test/data_structures/bst.js | 44 ++++++------- .../data_structures/disjoint_set_forest.js | 20 +++--- src/test/data_structures/fenwick_tree.js | 8 +-- src/test/data_structures/graph.js | 30 ++++----- src/test/data_structures/hash_table.js | 40 ++++++------ src/test/data_structures/heap.js | 20 +++--- src/test/data_structures/linked_list.js | 22 +++---- src/test/data_structures/priority_queue.js | 12 ++-- src/test/data_structures/queue.js | 10 +-- src/test/data_structures/set.js | 20 +++--- src/test/data_structures/stack.js | 10 +-- src/test/data_structures/treap.js | 10 +-- src/test/util/comparator.js | 12 ++-- src/util/comparator.js | 2 +- 127 files changed, 930 insertions(+), 930 deletions(-) diff --git a/src/algorithms/geometry/bezier_curve.js b/src/algorithms/geometry/bezier_curve.js index 7ce28c5..b5a88df 100644 --- a/src/algorithms/geometry/bezier_curve.js +++ b/src/algorithms/geometry/bezier_curve.js @@ -11,14 +11,14 @@ * Generates a bezier-curve from a series of points * @param Array array of control points ([{x: x0, y: y0}, {x: x1, y: y1}]) */ -var BezierCurve = function(points) { +const BezierCurve = function(points) { this.n = points.length; this.p = []; // The binomial coefficient - var c = [1]; - var i; - var j; + const c = [1]; + let i; + let j; for (i = 1; i < this.n; ++i) { c.push(0); for (j = i; j >= 1; --j) { @@ -36,13 +36,13 @@ var BezierCurve = function(points) { * @param Number float variable from 0 to 1 */ BezierCurve.prototype.get = function(t) { - var res = {x: 0, y: 0}; - var i; - var a = 1; - var b = 1; + const res = {x: 0, y: 0}; + let i; + let a = 1; + let b = 1; // The coefficient - var c = []; + const c = []; for (i = 0; i < this.n; ++i) { c.push(a); a *= t; diff --git a/src/algorithms/graph/SPFA.js b/src/algorithms/graph/SPFA.js index 9c8c412..fe0f0c6 100644 --- a/src/algorithms/graph/SPFA.js +++ b/src/algorithms/graph/SPFA.js @@ -9,13 +9,13 @@ * */ function spfa(graph, s) { - var distance = {}; - var previous = {}; - var queue = {}; - var isInQue = {}; - var cnt = {}; - var head = 0; - var tail = 1; + const distance = {}; + const previous = {}; + const queue = {}; + const isInQue = {}; + const cnt = {}; + let head = 0; + let tail = 1; // initialize distance[s] = 0; queue[0] = s; @@ -29,15 +29,15 @@ function spfa(graph, s) { } }); - var currNode; + let currNode; while (head !== tail) { currNode = queue[head++]; isInQue[currNode] = false; - var neighbors = graph.neighbors(currNode); - for (var i = 0; i < neighbors.length; i++) { - var v = neighbors[i]; + const neighbors = graph.neighbors(currNode); + for (let i = 0; i < neighbors.length; i++) { + const v = neighbors[i]; // relaxation - var newDistance = distance[currNode] + graph.edge(currNode, v); + const newDistance = distance[currNode] + graph.edge(currNode, v); if (newDistance < distance[v]) { distance[v] = newDistance; previous[v] = currNode; diff --git a/src/algorithms/graph/bellman_ford.js b/src/algorithms/graph/bellman_ford.js index f727d4c..b81565b 100644 --- a/src/algorithms/graph/bellman_ford.js +++ b/src/algorithms/graph/bellman_ford.js @@ -13,11 +13,11 @@ * the graph starting in 'startNode', or an empty object if there * exists a Negative-Weighted Cycle in the graph */ -var bellmanFord = function(graph, startNode) { - var minDistance = {}; - var previousVertex = {}; - var edges = []; - var adjacencyListSize = 0; +const bellmanFord = function(graph, startNode) { + const minDistance = {}; + const previousVertex = {}; + const edges = []; + let adjacencyListSize = 0; // Add all the edges from the graph to the 'edges' array graph.vertices.forEach(function(s) { @@ -35,15 +35,15 @@ var bellmanFord = function(graph, startNode) { minDistance[startNode] = 0; - var edgesSize = edges.length; - var sourceDistance; - var targetDistance; + const edgesSize = edges.length; + let sourceDistance; + let targetDistance; - var iteration; + let iteration; for (iteration = 0; iteration < adjacencyListSize; ++iteration) { - var somethingChanged = false; + let somethingChanged = false; - for (var j = 0; j < edgesSize; j++) { + for (let j = 0; j < edgesSize; j++) { sourceDistance = minDistance[edges[j].source] + edges[j].weight; targetDistance = minDistance[edges[j].target]; diff --git a/src/algorithms/graph/bfs_shortest_path.js b/src/algorithms/graph/bfs_shortest_path.js index 1d5c9d5..e466c3c 100644 --- a/src/algorithms/graph/bfs_shortest_path.js +++ b/src/algorithms/graph/bfs_shortest_path.js @@ -1,6 +1,6 @@ 'use strict'; -var breadthFirstSearch = require('./breadth_first_search'); +const breadthFirstSearch = require('./breadth_first_search'); /** * Shortest-path algorithm based on Breadth-First Search. @@ -12,9 +12,9 @@ var breadthFirstSearch = require('./breadth_first_search'); * @return {{distance: Object., * previous: Object.}} */ -var bfsShortestPath = function(graph, source) { - var distance = {}; - var previous = {}; +const bfsShortestPath = function(graph, source) { + const distance = {}; + const previous = {}; distance[source] = 0; breadthFirstSearch(graph, source, { diff --git a/src/algorithms/graph/breadth_first_search.js b/src/algorithms/graph/breadth_first_search.js index 3fc5658..08c58df 100644 --- a/src/algorithms/graph/breadth_first_search.js +++ b/src/algorithms/graph/breadth_first_search.js @@ -1,6 +1,6 @@ 'use strict'; -var Queue = require('../../data_structures/queue'); +const Queue = require('../../data_structures/queue'); /** * @typedef {Object} Callbacks @@ -21,11 +21,11 @@ var Queue = require('../../data_structures/queue'); * used by default allowTraversal implementation. * @return {Callbacks} The same object or new one (if null passed). */ -var normalizeCallbacks = function(callbacks, seenVertices) { +const normalizeCallbacks = function(callbacks, seenVertices) { callbacks = callbacks || {}; callbacks.allowTraversal = callbacks.allowTraversal || (function() { - var seen = seenVertices.reduce(function(seen, vertex) { + const seen = seenVertices.reduce(function(seen, vertex) { seen[vertex] = true; return seen; }, {}); @@ -39,7 +39,7 @@ var normalizeCallbacks = function(callbacks, seenVertices) { }; })(); - var noop = function() {}; + const noop = function() {}; callbacks.onTraversal = callbacks.onTraversal || noop; callbacks.enterVertex = callbacks.enterVertex || noop; callbacks.leaveVertex = callbacks.leaveVertex || noop; @@ -55,13 +55,13 @@ var normalizeCallbacks = function(callbacks, seenVertices) { * @param {*} startVertex * @param {Callbacks} [callbacks] */ -var breadthFirstSearch = function(graph, startVertex, callbacks) { - var vertexQueue = new Queue(); +const breadthFirstSearch = function(graph, startVertex, callbacks) { + const vertexQueue = new Queue(); vertexQueue.push(startVertex); callbacks = normalizeCallbacks(callbacks, [startVertex]); - var vertex; - var enqueue = function(neighbor) { + let vertex; + const enqueue = function(neighbor) { if (callbacks.allowTraversal(vertex, neighbor)) { callbacks.onTraversal(vertex, neighbor); vertexQueue.push(neighbor); diff --git a/src/algorithms/graph/depth_first_search.js b/src/algorithms/graph/depth_first_search.js index 8ebd242..901d7ed 100644 --- a/src/algorithms/graph/depth_first_search.js +++ b/src/algorithms/graph/depth_first_search.js @@ -20,11 +20,11 @@ * used by default allowTraversal implementation. * @return {Callbacks} The same object or new one (if null passed). */ -var normalizeCallbacks = function(callbacks, seenVertices) { +const normalizeCallbacks = function(callbacks, seenVertices) { callbacks = callbacks || {}; callbacks.allowTraversal = callbacks.allowTraversal || (function() { - var seen = {}; + const seen = {}; seenVertices.forEach(function(vertex) { seen[vertex] = true; }); @@ -41,7 +41,7 @@ var normalizeCallbacks = function(callbacks, seenVertices) { }; })(); - var noop = function() {}; + const noop = function() {}; callbacks.beforeTraversal = callbacks.beforeTraversal || noop; callbacks.afterTraversal = callbacks.afterTraversal || noop; callbacks.enterVertex = callbacks.enterVertex || noop; @@ -50,7 +50,7 @@ var normalizeCallbacks = function(callbacks, seenVertices) { return callbacks; }; -var dfsLoop = function dfsLoop(graph, vertex, callbacks) { +const dfsLoop = function dfsLoop(graph, vertex, callbacks) { callbacks.enterVertex(vertex); graph.neighbors(vertex).forEach(function(neighbor) { @@ -72,7 +72,7 @@ var dfsLoop = function dfsLoop(graph, vertex, callbacks) { * @param {*} startVertex * @param {Callbacks} [callbacks] */ -var depthFirstSearch = function(graph, startVertex, callbacks) { +const depthFirstSearch = function(graph, startVertex, callbacks) { dfsLoop(graph, startVertex, normalizeCallbacks(callbacks, [startVertex])); }; diff --git a/src/algorithms/graph/dijkstra.js b/src/algorithms/graph/dijkstra.js index 845c3e7..0d3f6b9 100644 --- a/src/algorithms/graph/dijkstra.js +++ b/src/algorithms/graph/dijkstra.js @@ -1,6 +1,6 @@ 'use strict'; -var PriorityQueue = require('../../data_structures/priority_queue'); +const PriorityQueue = require('../../data_structures/priority_queue'); /** * Calculates the shortest paths in a graph to every node from the node s @@ -11,9 +11,9 @@ var PriorityQueue = require('../../data_structures/priority_queue'); * */ function dijkstra(graph, s) { - var distance = {}; - var previous = {}; - var q = new PriorityQueue(); + const distance = {}; + const previous = {}; + const q = new PriorityQueue(); // Initialize distance[s] = 0; graph.vertices.forEach(function(v) { @@ -23,9 +23,9 @@ function dijkstra(graph, s) { q.insert(v, distance[v]); }); - var currNode; - var relax = function(v) { - var newDistance = distance[currNode] + graph.edge(currNode, v); + let currNode; + const relax = function(v) { + const newDistance = distance[currNode] + graph.edge(currNode, v); if (newDistance < distance[v]) { distance[v] = newDistance; previous[v] = currNode; diff --git a/src/algorithms/graph/euler_path.js b/src/algorithms/graph/euler_path.js index 75bdd40..578fa69 100644 --- a/src/algorithms/graph/euler_path.js +++ b/src/algorithms/graph/euler_path.js @@ -1,7 +1,7 @@ 'use strict'; -var Graph = require('../../data_structures/graph'); -var depthFirstSearch = require('../../algorithms/graph/depth_first_search'); +const Graph = require('../../data_structures/graph'); +const depthFirstSearch = require('../../algorithms/graph/depth_first_search'); /** Examine a graph and compute pair of end vertices of the existing Euler path. * Return pair of undefined values if there is no specific choice of end points. @@ -10,8 +10,8 @@ var depthFirstSearch = require('../../algorithms/graph/depth_first_search'); * @param {Graph} Graph, must be connected and contain at least one vertex. * @return Object */ -var eulerEndpoints = function(graph) { - var rank = {}; +const eulerEndpoints = function(graph) { + const rank = {}; // start -> rank = +1 // middle points -> rank = 0 // finish -> rank = -1 @@ -30,7 +30,7 @@ var eulerEndpoints = function(graph) { }); } else { // Compute ranks from vertex degree parity values. - var startChosen = false; + let startChosen = false; graph.vertices.forEach(function(vertex) { rank[vertex] %= 2; if (rank[vertex]) { @@ -42,9 +42,9 @@ var eulerEndpoints = function(graph) { }); } - var start; - var finish; - var v; + let start; + let finish; + let v; graph.vertices.forEach(function(vertex) { if (rank[vertex] === 1) { @@ -82,15 +82,15 @@ var eulerEndpoints = function(graph) { * @param {Graph} * @return Array */ -var eulerPath = function(graph) { +const eulerPath = function(graph) { if (!graph.vertices.size) { return []; } - var endpoints = eulerEndpoints(graph); - var route = [endpoints.finish]; + const endpoints = eulerEndpoints(graph); + const route = [endpoints.finish]; - var seen = new Graph(graph.directed); + const seen = new Graph(graph.directed); graph.vertices.forEach(seen.addVertex.bind(seen)); depthFirstSearch(graph, endpoints.start, { diff --git a/src/algorithms/graph/floyd_warshall.js b/src/algorithms/graph/floyd_warshall.js index 681e0f6..2f3d6d7 100644 --- a/src/algorithms/graph/floyd_warshall.js +++ b/src/algorithms/graph/floyd_warshall.js @@ -8,12 +8,12 @@ * @param {Graph} graph * @return {{distance, path}} */ -var floydWarshall = function(graph) { +const floydWarshall = function(graph) { // Fill in the distances with initial values: // - 0 if source == destination; // - edge(source, destination) if there is a direct edge; // - +inf otherwise. - var distance = Object.create(null); + const distance = Object.create(null); graph.vertices.forEach(function(src) { distance[src] = Object.create(null); graph.vertices.forEach(function(dest) { @@ -29,7 +29,7 @@ var floydWarshall = function(graph) { // Internal vertex with the largest index along the shortest path. // Needed for path reconstruction. - var middleVertex = Object.create(null); + const middleVertex = Object.create(null); graph.vertices.forEach(function(vertex) { middleVertex[vertex] = Object.create(null); }); @@ -37,7 +37,7 @@ var floydWarshall = function(graph) { graph.vertices.forEach(function(middle) { graph.vertices.forEach(function(src) { graph.vertices.forEach(function(dest) { - var dist = distance[src][middle] + distance[middle][dest]; + const dist = distance[src][middle] + distance[middle][dest]; if (dist < distance[src][dest]) { distance[src][dest] = dist; middleVertex[src][dest] = middle; @@ -62,20 +62,20 @@ var floydWarshall = function(graph) { * @param {string} dest * @return {?string[]} Null if destination is unreachable. */ - var path = function(src, dest) { + const path = function(src, dest) { if (!Number.isFinite(distance[src][dest])) { // dest unreachable. return null; } - var path = [src]; + const path = [src]; if (src !== dest) { (function pushInOrder(src, dest) { if (middleVertex[src][dest] === undefined) { path.push(dest); } else { - var middle = middleVertex[src][dest]; + const middle = middleVertex[src][dest]; pushInOrder(src, middle); pushInOrder(middle, dest); } diff --git a/src/algorithms/graph/kruskal.js b/src/algorithms/graph/kruskal.js index fffca9d..0f9f949 100644 --- a/src/algorithms/graph/kruskal.js +++ b/src/algorithms/graph/kruskal.js @@ -1,7 +1,7 @@ 'use strict'; -var DisjointSetForest = require('../../data_structures/disjoint_set_forest'); -var Graph = require('../../data_structures/graph'); +const DisjointSetForest = require('../../data_structures/disjoint_set_forest'); +const Graph = require('../../data_structures/graph'); /** * Kruskal's minimum spanning tree (forest) algorithm. @@ -11,16 +11,16 @@ var Graph = require('../../data_structures/graph'); * @return {Graph} Minimum spanning tree or forest * (depending on whether input graph is connected itself). */ -var kruskal = function(graph) { +const kruskal = function(graph) { if (graph.directed) { throw new Error('Can\'t build MST of a directed graph.'); } - var connectedComponents = new DisjointSetForest(); - var mst = new Graph(false); + const connectedComponents = new DisjointSetForest(); + const mst = new Graph(false); graph.vertices.forEach(mst.addVertex.bind(mst)); - var edges = []; + const edges = []; graph.vertices.forEach(function(vertex) { graph.neighbors(vertex).forEach(function(neighbor) { // Compared as strings, loops intentionally omitted. diff --git a/src/algorithms/graph/prim.js b/src/algorithms/graph/prim.js index 26c2386..10d2e30 100644 --- a/src/algorithms/graph/prim.js +++ b/src/algorithms/graph/prim.js @@ -1,7 +1,7 @@ 'use strict'; -var PriorityQueue = require('../../data_structures/priority_queue'); -var Graph = require('../../data_structures/graph'); +const PriorityQueue = require('../../data_structures/priority_queue'); +const Graph = require('../../data_structures/graph'); /** * Prim's minimum spanning tree (forest) algorithm. @@ -11,21 +11,21 @@ var Graph = require('../../data_structures/graph'); * @return {Graph} Minimum spanning tree or forest * (depending on whether input graph is connected itself). */ -var prim = function(graph) { +const prim = function(graph) { if (graph.directed) { throw new Error('Can\'t build MST of a directed graph.'); } - var mst = new Graph(false); - var parent = Object.create(null); + const mst = new Graph(false); + const parent = Object.create(null); - var q = new PriorityQueue(); + const q = new PriorityQueue(); graph.vertices.forEach(function(vertex) { q.insert(vertex, Infinity); }); - var relax = function(vertex, neighbor) { - var weight = graph.edge(vertex, neighbor); + const relax = function(vertex, neighbor) { + const weight = graph.edge(vertex, neighbor); if (weight < q.priority(neighbor)) { q.changePriority(neighbor, weight); parent[neighbor] = vertex; @@ -33,9 +33,9 @@ var prim = function(graph) { }; while (!q.isEmpty()) { - var top = q.extract(true); - var vertex = top.item; - var weight = top.priority; + const top = q.extract(true); + const vertex = top.item; + const weight = top.priority; if (parent[vertex]) { mst.addEdge(parent[vertex], vertex, weight); diff --git a/src/algorithms/graph/strongly_connected_component.js b/src/algorithms/graph/strongly_connected_component.js index e2bbef2..6974515 100644 --- a/src/algorithms/graph/strongly_connected_component.js +++ b/src/algorithms/graph/strongly_connected_component.js @@ -1,7 +1,7 @@ 'use strict'; -var Stack = require('../../data_structures/stack'); -var depthFirstSearch = require('../../algorithms/graph/depth_first_search'); +const Stack = require('../../data_structures/stack'); +const depthFirstSearch = require('../../algorithms/graph/depth_first_search'); /** * Kosaraju's Strongly Connected Component algorithm, https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm @@ -20,12 +20,12 @@ var depthFirstSearch = require('../../algorithms/graph/depth_first_search'); * scc.count; // count of strongly connected components * scc.id[v]; // id of the strongly connected component which v belongs to */ -var stronglyConnectedComponent = function(graph) { - var reverse = graph.reverse(); - var stack = new Stack(); - var visited = {}; - var count = 0; - var id = Object.create(null); +const stronglyConnectedComponent = function(graph) { + const reverse = graph.reverse(); + const stack = new Stack(); + let visited = {}; + let count = 0; + const id = Object.create(null); reverse.vertices.forEach(function(node) { if (!visited[node]) { @@ -44,16 +44,16 @@ var stronglyConnectedComponent = function(graph) { }); visited = {}; - var allowTraversal = function(node, neighbor) { + const allowTraversal = function(node, neighbor) { return !visited[neighbor]; }; - var enterVertex = function(node) { + const enterVertex = function(node) { visited[node] = true; id[node] = count; }; while (!stack.isEmpty()) { - var node = stack.pop(); + const node = stack.pop(); if (!visited[node]) { depthFirstSearch(graph, node, { allowTraversal: allowTraversal, diff --git a/src/algorithms/graph/topological_sort.js b/src/algorithms/graph/topological_sort.js index 588f8d8..142f1af 100644 --- a/src/algorithms/graph/topological_sort.js +++ b/src/algorithms/graph/topological_sort.js @@ -1,7 +1,7 @@ 'use strict'; -var Stack = require('../../data_structures/stack'); -var depthFirstSearch = require('../../algorithms/graph/depth_first_search'); +const Stack = require('../../data_structures/stack'); +const depthFirstSearch = require('../../algorithms/graph/depth_first_search'); /** * Sorts the edges of the DAG topologically @@ -17,10 +17,10 @@ var depthFirstSearch = require('../../algorithms/graph/depth_first_search'); * @param {Graph} * @return Stack */ -var topologicalSort = function(graph) { - var stack = new Stack(); - var firstHit = {}; - var time = 0; +const topologicalSort = function(graph) { + const stack = new Stack(); + const firstHit = {}; + let time = 0; graph.vertices.forEach(function(node) { if (!firstHit[node]) { diff --git a/src/algorithms/math/collatz_conjecture.js b/src/algorithms/math/collatz_conjecture.js index 4391f10..85b3a2e 100644 --- a/src/algorithms/math/collatz_conjecture.js +++ b/src/algorithms/math/collatz_conjecture.js @@ -1,7 +1,7 @@ 'use strict'; // cache algorithm results -var cache = {1: 1}; +const cache = {1: 1}; /** * Collatz Conjecture algorithm @@ -25,7 +25,7 @@ function calculateCollatzConjecture(number) { * @return Array */ function generateCollatzConjecture(number) { - var collatzConjecture = []; + const collatzConjecture = []; do { number = calculateCollatzConjecture(number); diff --git a/src/algorithms/math/extended_euclidean.js b/src/algorithms/math/extended_euclidean.js index 1b1f1ff..5214288 100644 --- a/src/algorithms/math/extended_euclidean.js +++ b/src/algorithms/math/extended_euclidean.js @@ -10,15 +10,15 @@ * * @return {Number, Number} */ -var extEuclid = function(a, b) { - var s = 0; - var oldS = 1; - var t = 1; - var oldT = 0; - var r = b; - var oldR = a; - var quotient; - var temp; +const extEuclid = function(a, b) { + let s = 0; + let oldS = 1; + let t = 1; + let oldT = 0; + let r = b; + let oldR = a; + let quotient; + let temp; while (r !== 0) { quotient = Math.floor(oldR / r); diff --git a/src/algorithms/math/fast_power.js b/src/algorithms/math/fast_power.js index f5c3454..1cb8a81 100644 --- a/src/algorithms/math/fast_power.js +++ b/src/algorithms/math/fast_power.js @@ -1,6 +1,6 @@ 'use strict'; -var multiplicationOperator = function(a, b) { +const multiplicationOperator = function(a, b) { return a * b; }; @@ -15,7 +15,7 @@ var multiplicationOperator = function(a, b) { * If mul is not set, defaults to 1. * @return {*} */ -var fastPower = function(base, power, mul, identity) { +const fastPower = function(base, power, mul, identity) { if (mul === undefined) { mul = multiplicationOperator; identity = 1; @@ -33,11 +33,11 @@ var fastPower = function(base, power, mul, identity) { } // Iterative form of the algorithm avoids checking the same thing twice. - var result; - var multiplyBy = function(value) { + let result; + const multiplyBy = function(value) { result = (result === undefined) ? value : mul(result, value); }; - for (var factor = base; power; power >>>= 1, factor = mul(factor, factor)) { + for (let factor = base; power; power >>>= 1, factor = mul(factor, factor)) { if (power & 1) { multiplyBy(factor); } diff --git a/src/algorithms/math/fibonacci.js b/src/algorithms/math/fibonacci.js index 06485f8..149994a 100644 --- a/src/algorithms/math/fibonacci.js +++ b/src/algorithms/math/fibonacci.js @@ -4,7 +4,7 @@ * Different implementations of the Fibonacci sequence */ -var power = require('./fast_power'); +const power = require('./fast_power'); /** * Regular fibonacci implementation following the definition: @@ -15,7 +15,7 @@ var power = require('./fast_power'); * @param Number * @return Number */ -var fibExponential = function(n) { +const fibExponential = function(n) { return n < 2 ? n : fibExponential(n - 1) + fibExponential(n - 2); }; @@ -25,11 +25,11 @@ var fibExponential = function(n) { * @param Number * @return Number */ -var fibLinear = function(n) { - var fibNMinus2 = 0; - var fibNMinus1 = 1; - var fib = n; - for (var i = 1; i < n; i++) { +const fibLinear = function(n) { + let fibNMinus2 = 0; + let fibNMinus1 = 1; + let fib = n; + for (let i = 1; i < n; i++) { fib = fibNMinus1 + fibNMinus2; fibNMinus2 = fibNMinus1; fibNMinus1 = fib; @@ -43,10 +43,10 @@ var fibLinear = function(n) { * @param Number * @return Number */ -var fibWithMemoization = (function() { - var cache = [0, 1]; +const fibWithMemoization = (function() { + const cache = [0, 1]; - var fib = function(n) { + const fib = function(n) { if (cache[n] === undefined) { cache[n] = fib(n - 1) + fib(n - 2); } @@ -63,8 +63,8 @@ var fibWithMemoization = (function() { * @param Number * @return Number */ -var fibDirect = function(number) { - var phi = (1 + Math.sqrt(5)) / 2; +const fibDirect = function(number) { + const phi = (1 + Math.sqrt(5)) / 2; return Math.floor(Math.pow(phi, number) / Math.sqrt(5) + 0.5); }; @@ -75,18 +75,18 @@ var fibDirect = function(number) { * @param Number * @return Number */ -var fibLogarithmic = function(number) { +const fibLogarithmic = function(number) { // Transforms [f_1, f_0] to [f_2, f_1] and so on. - var nextFib = [[1, 1], [1, 0]]; + const nextFib = [[1, 1], [1, 0]]; - var matrixMultiply = function(a, b) { + const matrixMultiply = function(a, b) { return [[a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1]], [a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1]]]; }; - var transform = power(nextFib, number, matrixMultiply, [[1, 0], [0, 1]]); + const transform = power(nextFib, number, matrixMultiply, [[1, 0], [0, 1]]); // [f_n, f_{n-1}] = Transform * [f_0, f_{-1}] = Transform * [0, 1] // Hence the result is the first row of Transform multiplied by [0, 1], diff --git a/src/algorithms/math/find_divisors.js b/src/algorithms/math/find_divisors.js index 463d326..f7f8230 100644 --- a/src/algorithms/math/find_divisors.js +++ b/src/algorithms/math/find_divisors.js @@ -13,9 +13,9 @@ * @returns {number[]} - returns the divisors */ -var findDivisorsGeneric = function(number) { - var index = 1; - var divisors = []; +const findDivisorsGeneric = function(number) { + let index = 1; + const divisors = []; for (index; index <= number; index++) { if (number % index === 0) { @@ -36,9 +36,9 @@ var findDivisorsGeneric = function(number) { * @returns {number[]} - returns the divisors */ -var findDivisorsByPairingUnsorted = function(number) { - var index = 1; - var divisors = []; +const findDivisorsByPairingUnsorted = function(number) { + let index = 1; + const divisors = []; for (index; index <= Math.sqrt(number); index++) { if (number % index === 0) { @@ -65,11 +65,11 @@ var findDivisorsByPairingUnsorted = function(number) { * @returns {number[]} - returns the divisors */ -var findDivisorsByPairingSorted = function(number) { - var index = 1; - var divisors = []; - var divisorsLessThanSqrt = []; - var divisorsMoreThanSqrt = []; +const findDivisorsByPairingSorted = function(number) { + let index = 1; + let divisors = []; + const divisorsLessThanSqrt = []; + const divisorsMoreThanSqrt = []; for (index; index <= Math.sqrt(number); index++) { if (number % index === 0) { diff --git a/src/algorithms/math/fisher_yates.js b/src/algorithms/math/fisher_yates.js index 5cf4122..0318675 100644 --- a/src/algorithms/math/fisher_yates.js +++ b/src/algorithms/math/fisher_yates.js @@ -4,10 +4,10 @@ * Fisher-Yates shuffles the elements in an array * in O(n) */ -var fisherYates = function(a) { - for (var i = a.length - 1; i > 0; i--) { - var j = Math.floor(Math.random() * (i + 1)); - var tmp = a[i]; +const fisherYates = function(a) { + for (let i = a.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + const tmp = a[i]; a[i] = a[j]; a[j] = tmp; } diff --git a/src/algorithms/math/gcd.js b/src/algorithms/math/gcd.js index 08c590e..e140a88 100644 --- a/src/algorithms/math/gcd.js +++ b/src/algorithms/math/gcd.js @@ -8,8 +8,8 @@ * * @return Number */ -var gcdDivisionBased = function(a, b) { - var tmp = a; +const gcdDivisionBased = function(a, b) { + let tmp = a; a = Math.max(a, b); b = Math.min(tmp, b); while (b !== 0) { @@ -32,7 +32,7 @@ var gcdDivisionBased = function(a, b) { * * @return Number */ -var gcdBinaryIterative = function(a, b) { +const gcdBinaryIterative = function(a, b) { // GCD(0,b) == b; GCD(a,0) == a, GCD(0,0) == 0 if (a === 0) { return b; @@ -42,7 +42,7 @@ var gcdBinaryIterative = function(a, b) { return a; } - var shift; + let shift; // Let shift = log(K), where K is the greatest power of 2 // dividing both a and b for (shift = 0; ((a | b) & 1) === 0; ++shift) { @@ -56,7 +56,7 @@ var gcdBinaryIterative = function(a, b) { a >>= 1; } - var tmp; + let tmp; // From here on, a is always odd do { diff --git a/src/algorithms/math/greatest_difference.js b/src/algorithms/math/greatest_difference.js index edbf53a..4eec3b9 100644 --- a/src/algorithms/math/greatest_difference.js +++ b/src/algorithms/math/greatest_difference.js @@ -8,12 +8,12 @@ * @returns {number} */ -var greatestDifference = function(numbers) { - var index = 0; - var largest = numbers[0]; - var length = numbers.length; - var number; - var smallest = numbers[0]; +const greatestDifference = function(numbers) { + let index = 0; + let largest = numbers[0]; + const length = numbers.length; + let number; + let smallest = numbers[0]; for (index; index < length; index++) { number = numbers[index]; diff --git a/src/algorithms/math/lcm.js b/src/algorithms/math/lcm.js index 705330c..ad2829a 100644 --- a/src/algorithms/math/lcm.js +++ b/src/algorithms/math/lcm.js @@ -1,6 +1,6 @@ 'use strict'; -var gcd = require('./gcd.js'); +const gcd = require('./gcd.js'); /** * Calcule the Least Common Multiple with a given Greatest Common Denominator @@ -12,7 +12,7 @@ var gcd = require('./gcd.js'); * * @return Number */ -var genericLCM = function(gcdFunction, a, b) { +const genericLCM = function(gcdFunction, a, b) { if (a === 0 || b === 0) { return 0; } @@ -30,7 +30,7 @@ var genericLCM = function(gcdFunction, a, b) { * * @return Number */ -var lcmDivisionBased = genericLCM.bind(null, gcd); +const lcmDivisionBased = genericLCM.bind(null, gcd); /** * Algorithm to calculate Least Common Multiple based on Stein's Algorithm @@ -41,8 +41,8 @@ var lcmDivisionBased = genericLCM.bind(null, gcd); * * @return Number */ -var lcmBinaryIterative = genericLCM.bind(null, gcd.binary); +const lcmBinaryIterative = genericLCM.bind(null, gcd.binary); -var lcm = lcmDivisionBased; +const lcm = lcmDivisionBased; lcm.binary = lcmBinaryIterative; module.exports = lcm; diff --git a/src/algorithms/math/newton_sqrt.js b/src/algorithms/math/newton_sqrt.js index c0a8612..5305787 100644 --- a/src/algorithms/math/newton_sqrt.js +++ b/src/algorithms/math/newton_sqrt.js @@ -7,16 +7,16 @@ * @param Number tolerance - The error margin accepted (Default 1e-7) * @param Number maxIterations - The max number of iterations (Default 1e7) */ -var sqrt = function(n, tolerance, maxIterations) { +const sqrt = function(n, tolerance, maxIterations) { tolerance = tolerance || 1e-7; maxIterations = maxIterations || 1e7; - var upperBound = n; - var lowerBound = 0; + let upperBound = n; + let lowerBound = 0; - var i = 0; - var square; - var x; + let i = 0; + let square; + let x; do { i++; x = (upperBound - lowerBound) / 2 + lowerBound; @@ -26,7 +26,7 @@ var sqrt = function(n, tolerance, maxIterations) { } while (Math.abs(square - n) > tolerance && i < maxIterations); // Checks if the number is a perfect square to return the exact root - var roundX = Math.round(x); + const roundX = Math.round(x); if (roundX * roundX === n) x = roundX; return x; diff --git a/src/algorithms/math/next_permutation.js b/src/algorithms/math/next_permutation.js index be44b38..359f97c 100644 --- a/src/algorithms/math/next_permutation.js +++ b/src/algorithms/math/next_permutation.js @@ -1,6 +1,6 @@ 'use strict'; -var Comparator = require('../../util/comparator'); +const Comparator = require('../../util/comparator'); /** * Narayana's algorithm computes the subsequent permutation @@ -12,14 +12,14 @@ var Comparator = require('../../util/comparator'); * @return {boolean} Boolean flag indicating whether the algorithm succeeded, * true unless the input permutation is lexicographically the last one. */ -var nextPermutation = function(array, compareFn) { +const nextPermutation = function(array, compareFn) { if (!array.length) { return false; } - var cmp = new Comparator(compareFn); + const cmp = new Comparator(compareFn); // Find pivot and successor indices. - var pivot = array.length - 1; + let pivot = array.length - 1; while (pivot && cmp.greaterThanOrEqual(array[pivot - 1], array[pivot])) { pivot -= 1; } @@ -27,8 +27,8 @@ var nextPermutation = function(array, compareFn) { // Permutation is sorted in descending order. return false; } - var pivotValue = array[--pivot]; - var successor = array.length - 1; + const pivotValue = array[--pivot]; + let successor = array.length - 1; while (cmp.lessThanOrEqual(array[successor], pivotValue)) { successor -= 1; } @@ -38,8 +38,8 @@ var nextPermutation = function(array, compareFn) { array[successor] = pivotValue; // Reverse the descending part. - for (var left = pivot, right = array.length; ++left < --right;) { - var temp = array[left]; + for (let left = pivot, right = array.length; ++left < --right;) { + const temp = array[left]; array[left] = array[right]; array[right] = temp; } diff --git a/src/algorithms/math/power_set.js b/src/algorithms/math/power_set.js index b0b7d60..14102c4 100644 --- a/src/algorithms/math/power_set.js +++ b/src/algorithms/math/power_set.js @@ -7,14 +7,14 @@ /** * Iterative power set calculation */ -var powerSetIterative = function(array) { +const powerSetIterative = function(array) { if (array.length === 0) { return []; } - var powerSet = []; - var cache = []; - var i; + const powerSet = []; + const cache = []; + let i; for (i = 0; i < array.length; i++) { cache[i] = true; @@ -23,7 +23,7 @@ var powerSetIterative = function(array) { for (i = 0; i < Math.pow(2, array.length); i++) { powerSet.push([]); - for (var j = 0; j < array.length; j++) { + for (let j = 0; j < array.length; j++) { if (i % Math.pow(2, j) === 0) { cache[j] = !cache[j]; } @@ -40,20 +40,20 @@ var powerSetIterative = function(array) { /** * Recursive power set calculation */ -var powerSetRecursive = function(array) { +const powerSetRecursive = function(array) { if (array.length === 0) { return []; } else if (array.length === 1) { return [[], [array[0]]]; } - var powerSet = []; - var firstElem = array[0]; + const powerSet = []; + const firstElem = array[0]; array.splice(0, 1); powerSetRecursive(array).forEach(function(elem) { powerSet.push(elem); - var withFirstElem = [firstElem]; + const withFirstElem = [firstElem]; withFirstElem.push.apply(withFirstElem, elem); powerSet.push(withFirstElem); }); @@ -62,6 +62,6 @@ var powerSetRecursive = function(array) { }; // Use powerSetIterative as the default implementation -var powerSet = powerSetIterative; +const powerSet = powerSetIterative; powerSet.recursive = powerSetRecursive; module.exports = powerSet; diff --git a/src/algorithms/math/primality_tests.js b/src/algorithms/math/primality_tests.js index 4357f5c..6e213ec 100644 --- a/src/algorithms/math/primality_tests.js +++ b/src/algorithms/math/primality_tests.js @@ -8,7 +8,7 @@ * * @return Boolean */ -var genericPrimalityTest = function(primalityTest, n) { +const genericPrimalityTest = function(primalityTest, n) { if (n <= 1) { return false; } @@ -22,8 +22,8 @@ var genericPrimalityTest = function(primalityTest, n) { * * @return Boolean */ -var naiveTest = function(n) { - for (var i = 2; i < n; ++i) { +const naiveTest = function(n) { + for (let i = 2; i < n; ++i) { if (n % i === 0) { return false; } @@ -38,9 +38,9 @@ var naiveTest = function(n) { * * @return Boolean */ -var trialDivisionTest = function(n) { - var sqrt = Math.sqrt(n); - for (var i = 2; i <= sqrt; ++i) { +const trialDivisionTest = function(n) { + const sqrt = Math.sqrt(n); + for (let i = 2; i <= sqrt; ++i) { if (n % i === 0) { return false; } diff --git a/src/algorithms/math/reservoir_sampling.js b/src/algorithms/math/reservoir_sampling.js index b1cf343..e3f59aa 100644 --- a/src/algorithms/math/reservoir_sampling.js +++ b/src/algorithms/math/reservoir_sampling.js @@ -7,13 +7,13 @@ * @param {number} sampleSize * @return {Array} */ -var reservoirSampling = function(array, sampleSize) { +const reservoirSampling = function(array, sampleSize) { if (sampleSize > array.length) { throw new Error('Sample size exceeds the total number of elements.'); } - var reservoir = array.slice(0, sampleSize); - for (var i = sampleSize; i < array.length; ++i) { - var j = Math.floor(Math.random() * (i + 1)); + const reservoir = array.slice(0, sampleSize); + for (let i = sampleSize; i < array.length; ++i) { + const j = Math.floor(Math.random() * (i + 1)); if (j < sampleSize) { reservoir[j] = array[i]; } diff --git a/src/algorithms/math/shannon_entropy.js b/src/algorithms/math/shannon_entropy.js index 20dabd2..96bb719 100644 --- a/src/algorithms/math/shannon_entropy.js +++ b/src/algorithms/math/shannon_entropy.js @@ -6,15 +6,15 @@ * @param {Array} arr - An array of values. * @return Number */ -var shannonEntropy = function(arr) { +const shannonEntropy = function(arr) { // find the frequency of each value - var freqs = arr.reduce(function(acc, item) { + const freqs = arr.reduce(function(acc, item) { acc[item] = acc[item] + 1 || 1; return acc; }, {}); // find the probability of each value - var probs = Object.keys(freqs).map(function(key) { + const probs = Object.keys(freqs).map(function(key) { return freqs[key] / arr.length; }); diff --git a/src/algorithms/search/bfs.js b/src/algorithms/search/bfs.js index 739d8d8..a261625 100644 --- a/src/algorithms/search/bfs.js +++ b/src/algorithms/search/bfs.js @@ -1,13 +1,13 @@ 'use strict'; -var Queue = require('../../data_structures/queue.js'); +const Queue = require('../../data_structures/queue.js'); /** * Breadth-first search for binary trees */ -var bfs = function(root, callback) { - var q = new Queue(); +const bfs = function(root, callback) { + const q = new Queue(); q.push(root); - var node; + let node; while (!q.isEmpty()) { node = q.pop(); callback(node.value); diff --git a/src/algorithms/search/binarysearch.js b/src/algorithms/search/binarysearch.js index 701ca65..550a690 100644 --- a/src/algorithms/search/binarysearch.js +++ b/src/algorithms/search/binarysearch.js @@ -9,12 +9,12 @@ * * @return Boolean */ -var binarySearch = function(sortedArray, element) { - var init = 0; - var end = sortedArray.length - 1; +const binarySearch = function(sortedArray, element) { + let init = 0; + let end = sortedArray.length - 1; while (end >= init) { - var m = ((end - init) >> 1) + init; + const m = ((end - init) >> 1) + init; if (sortedArray[m] === element) return m; if (sortedArray[m] < element) init = m + 1; diff --git a/src/algorithms/search/dfs.js b/src/algorithms/search/dfs.js index 54e78d6..75d46de 100644 --- a/src/algorithms/search/dfs.js +++ b/src/algorithms/search/dfs.js @@ -4,7 +4,7 @@ * Depth first search for trees * (in order) */ -var inOrder = function(node, callback) { +const inOrder = function(node, callback) { if (node) { inOrder(node.left, callback); callback(node.value); @@ -15,7 +15,7 @@ var inOrder = function(node, callback) { /** * Pre order */ -var preOrder = function(node, callback) { +const preOrder = function(node, callback) { if (node) { callback(node.value); preOrder(node.left, callback); @@ -26,7 +26,7 @@ var preOrder = function(node, callback) { /** * Post order */ -var postOrder = function(node, callback) { +const postOrder = function(node, callback) { if (node) { postOrder(node.left, callback); postOrder(node.right, callback); diff --git a/src/algorithms/search/ternary_search.js b/src/algorithms/search/ternary_search.js index d9082d3..64ec585 100644 --- a/src/algorithms/search/ternary_search.js +++ b/src/algorithms/search/ternary_search.js @@ -6,10 +6,10 @@ * Time complexity: O(log(n)) */ -var ternarySearch = function(fn, left, right, precision) { +const ternarySearch = function(fn, left, right, precision) { while (Math.abs(right - left) > precision) { - var leftThird = left + (right - left) / 3; - var rightThird = right - (right - left) / 3; + const leftThird = left + (right - left) / 3; + const rightThird = right - (right - left) / 3; if (fn(leftThird) < fn(rightThird)) left = leftThird; else diff --git a/src/algorithms/sorting/bubble_sort.js b/src/algorithms/sorting/bubble_sort.js index 739b042..d809049 100644 --- a/src/algorithms/sorting/bubble_sort.js +++ b/src/algorithms/sorting/bubble_sort.js @@ -1,19 +1,19 @@ 'use strict'; -var Comparator = require('../../util/comparator'); +const Comparator = require('../../util/comparator'); /** * Bubble sort algorithm O(n^2) */ -var bubbleSort = function(a, comparatorFn) { - var comparator = new Comparator(comparatorFn); - var n = a.length; - var bound = n - 1; - var check = false; - for (var i = 0; i < n - 1; i++) { - var newbound = 0; - for (var j = 0; j < bound; j++) { +const bubbleSort = function(a, comparatorFn) { + const comparator = new Comparator(comparatorFn); + const n = a.length; + let bound = n - 1; + let check = false; + for (let i = 0; i < n - 1; i++) { + let newbound = 0; + for (let j = 0; j < bound; j++) { if (comparator.greaterThan(a[j], a[j + 1])) { - var tmp = a[j]; + const tmp = a[j]; a[j] = a[j + 1]; a[j + 1] = tmp; newbound = j; diff --git a/src/algorithms/sorting/counting_sort.js b/src/algorithms/sorting/counting_sort.js index fac8de0..97ebded 100644 --- a/src/algorithms/sorting/counting_sort.js +++ b/src/algorithms/sorting/counting_sort.js @@ -8,11 +8,11 @@ * @param Array * @return Integer */ -var maximumKey = function(array) { - var max = array[0].key; - var length = array.length; +const maximumKey = function(array) { + let max = array[0].key; + const length = array.length; - for (var i = 1; i < length; i++) { + for (let i = 1; i < length; i++) { if (array[i].key > max) { max = array[i].key; } @@ -32,14 +32,14 @@ var maximumKey = function(array) { * @param Array * @return Array */ -var countingSort = function(array) { - var max = maximumKey(array); - var auxiliaryArray = []; - var length = array.length; - var i; +const countingSort = function(array) { + const max = maximumKey(array); + const auxiliaryArray = []; + const length = array.length; + let i; for (i = 0; i < length; i++) { - var position = array[i].key; + const position = array[i].key; if (auxiliaryArray[position] === undefined) { auxiliaryArray[position] = []; @@ -49,13 +49,13 @@ var countingSort = function(array) { } array = []; - var pointer = 0; + let pointer = 0; for (i = 0; i <= max; i++) { if (auxiliaryArray[i] !== undefined) { - var localLength = auxiliaryArray[i].length; + const localLength = auxiliaryArray[i].length; - for (var j = 0; j < localLength; j++) { + for (let j = 0; j < localLength; j++) { array[pointer++] = auxiliaryArray[i][j]; } } diff --git a/src/algorithms/sorting/heap_sort.js b/src/algorithms/sorting/heap_sort.js index ace35e0..227b47b 100644 --- a/src/algorithms/sorting/heap_sort.js +++ b/src/algorithms/sorting/heap_sort.js @@ -1,16 +1,16 @@ 'use strict'; -var MinHeap = require('../../data_structures/heap').MinHeap; +const MinHeap = require('../../data_structures/heap').MinHeap; /** * Heap sort first creates a valid heap data structure. Next it * iteratively removes the smallest element of the heap until it's * empty. The time complexity of the algorithm is O(n.lg n) */ -var heapsort = function(array, comparatorFn) { - var minHeap = new MinHeap(comparatorFn); +const heapsort = function(array, comparatorFn) { + const minHeap = new MinHeap(comparatorFn); minHeap.heapify(array); - var result = []; + const result = []; while (!minHeap.isEmpty()) result.push(minHeap.extract()); diff --git a/src/algorithms/sorting/insertion_sort.js b/src/algorithms/sorting/insertion_sort.js index 26af300..e91e909 100644 --- a/src/algorithms/sorting/insertion_sort.js +++ b/src/algorithms/sorting/insertion_sort.js @@ -1,15 +1,15 @@ 'use strict'; -var Comparator = require('../../util/comparator'); +const Comparator = require('../../util/comparator'); /** * Insertion sort algorithm O(n + d) */ -var insertionSort = function(vector, comparatorFn) { - var comparator = new Comparator(comparatorFn); +const insertionSort = function(vector, comparatorFn) { + const comparator = new Comparator(comparatorFn); - for (var i = 1, len = vector.length; i < len; i++) { - var aux = vector[i]; - var j = i; + for (let i = 1, len = vector.length; i < len; i++) { + const aux = vector[i]; + let j = i; while (j > 0 && comparator.lessThan(aux, vector[j - 1])) { vector[j] = vector[j - 1]; diff --git a/src/algorithms/sorting/merge_sort.js b/src/algorithms/sorting/merge_sort.js index 89a4dc0..ebed429 100644 --- a/src/algorithms/sorting/merge_sort.js +++ b/src/algorithms/sorting/merge_sort.js @@ -1,10 +1,10 @@ 'use strict'; -var Comparator = require('../../util/comparator'); +const Comparator = require('../../util/comparator'); -var merge = function(a, b, comparator) { - var i = 0; - var j = 0; - var result = []; +const merge = function(a, b, comparator) { + let i = 0; + let j = 0; + const result = []; while (i < a.length && j < b.length) { result.push(comparator.lessThan(a[i], b[j]) ? a[i++] : b[j++]); @@ -19,14 +19,14 @@ var merge = function(a, b, comparator) { * Merge sort * O(n.lgn) */ -var mergeSortInit = function(a, compareFn) { - var comparator = new Comparator(compareFn); +const mergeSortInit = function(a, compareFn) { + const comparator = new Comparator(compareFn); return (function mergeSort(a) { if (a.length > 1) { - var middle = a.length >> 1; - var left = mergeSort(a.slice(0, middle)); - var right = mergeSort(a.slice(middle)); + const middle = a.length >> 1; + const left = mergeSort(a.slice(0, middle)); + const right = mergeSort(a.slice(middle)); a = merge(left, right, comparator); } diff --git a/src/algorithms/sorting/quicksort.js b/src/algorithms/sorting/quicksort.js index ceff08a..b1a0648 100644 --- a/src/algorithms/sorting/quicksort.js +++ b/src/algorithms/sorting/quicksort.js @@ -1,11 +1,11 @@ 'use strict'; -var Comparator = require('../../util/comparator'); +const Comparator = require('../../util/comparator'); /** * Swaps two elements in the array */ -var swap = function(array, x, y) { - var tmp = array[y]; +const swap = function(array, x, y) { + const tmp = array[y]; array[y] = array[x]; array[x] = tmp; }; @@ -17,17 +17,17 @@ var swap = function(array, x, y) { * * @return Number the positon of the pivot */ -var partition = function(a, comparator, lo, hi) { +const partition = function(a, comparator, lo, hi) { // pick a random element, swap with the rightmost and // use it as pivot swap(a, Math.floor(Math.random() * (hi - lo)) + lo, hi); - var pivot = hi; + const pivot = hi; // dividerPosition keeps track of the position // where the pivot should be inserted - var dividerPosition = lo; + let dividerPosition = lo; - for (var i = lo; i < hi; i++) { + for (let i = lo; i < hi; i++) { if (comparator.lessThan(a[i], a[pivot])) { swap(a, i, dividerPosition); dividerPosition++; @@ -41,12 +41,12 @@ var partition = function(a, comparator, lo, hi) { * Quicksort recursively sorts parts of the array in * O(n.lg n) */ -var quicksortInit = function(array, comparatorFn) { - var comparator = new Comparator(comparatorFn); +const quicksortInit = function(array, comparatorFn) { + const comparator = new Comparator(comparatorFn); return (function quicksort(array, lo, hi) { while (lo < hi) { - var p = partition(array, comparator, lo, hi); + const p = partition(array, comparator, lo, hi); // Chooses only the smallest partition to use recursion on and // tail-optimize the other. This guarantees O(log n) space in worst case. if (p - lo < hi - p) { diff --git a/src/algorithms/sorting/radix_sort.js b/src/algorithms/sorting/radix_sort.js index 126766d..c51b1e3 100644 --- a/src/algorithms/sorting/radix_sort.js +++ b/src/algorithms/sorting/radix_sort.js @@ -13,27 +13,27 @@ * @param Array * @return Array */ -var auxiliaryCountingSort = function(array, mod) { - var length = array.length; - var bucket = []; - var i; +const auxiliaryCountingSort = function(array, mod) { + const length = array.length; + const bucket = []; + let i; for (i = 0; i < 10; i++) { bucket[i] = []; } for (i = 0; i < length; i++) { - var digit = parseInt((array[i].key / Math.pow(10, mod)) + const digit = parseInt((array[i].key / Math.pow(10, mod)) .toFixed(mod), 10) % 10; bucket[digit].push(array[i]); } - var pointer = 0; + let pointer = 0; for (i = 0; i < 10; i++) { - var localLength = bucket[i].length; + const localLength = bucket[i].length; - for (var j = 0; j < localLength; j++) { + for (let j = 0; j < localLength; j++) { array[pointer++] = bucket[i][j]; } } @@ -50,9 +50,9 @@ var auxiliaryCountingSort = function(array, mod) { * @return Integer if array non-empty * Undefined otherwise */ -var maximumKey = function(a) { - var max; - for (var i = 1; i < a.length; i++) { +const maximumKey = function(a) { + let max; + for (let i = 1; i < a.length; i++) { if (max === undefined || a[i].key > max) { max = a[i].key; } @@ -71,12 +71,12 @@ var maximumKey = function(a) { * @param Array * @return Array */ -var radixSort = function(array) { - var max = maximumKey(array); - var digitsMax = (max === 0 ? 1 : +const radixSort = function(array) { + const max = maximumKey(array); + const digitsMax = (max === 0 ? 1 : 1 + Math.floor(Math.log(max) / Math.log(10))); // log base 10 - for (var i = 0; i < digitsMax; i++) { + for (let i = 0; i < digitsMax; i++) { array = auxiliaryCountingSort(array, i); } diff --git a/src/algorithms/sorting/selection_sort.js b/src/algorithms/sorting/selection_sort.js index 5636468..de73d42 100644 --- a/src/algorithms/sorting/selection_sort.js +++ b/src/algorithms/sorting/selection_sort.js @@ -1,20 +1,20 @@ 'use strict'; -var Comparator = require('../../util/comparator'); +const Comparator = require('../../util/comparator'); /** * Selection sort algorithm O(n^2) */ -var selectionSort = function(a, comparatorFn) { - var comparator = new Comparator(comparatorFn); - var n = a.length; - for (var i = 0; i < n - 1; i++) { - var min = i; - for (var j = i + 1; j < n; j++) { +const selectionSort = function(a, comparatorFn) { + const comparator = new Comparator(comparatorFn); + const n = a.length; + for (let i = 0; i < n - 1; i++) { + let min = i; + for (let j = i + 1; j < n; j++) { if (comparator.greaterThan(a[min], a[j])) { min = j; } } if (min !== i) { - var tmp = a[i]; + const tmp = a[i]; a[i] = a[min]; a[min] = tmp; } diff --git a/src/algorithms/sorting/shell_sort.js b/src/algorithms/sorting/shell_sort.js index 135b8b1..836f040 100644 --- a/src/algorithms/sorting/shell_sort.js +++ b/src/algorithms/sorting/shell_sort.js @@ -1,16 +1,16 @@ 'use strict'; -var Comparator = require('../../util/comparator'); +const Comparator = require('../../util/comparator'); /** * shell sort worst:O(n lg n) best:O(n) */ -var shellSort = function(array, comparatorFn) { - var comparator = new Comparator(comparatorFn); - var gap = Math.floor(array.length / 2); +const shellSort = function(array, comparatorFn) { + const comparator = new Comparator(comparatorFn); + let gap = Math.floor(array.length / 2); while (gap > 0) { - for (var i = gap; i < array.length; i++) { - var temp = array[i]; - var j = i - gap; + for (let i = gap; i < array.length; i++) { + const temp = array[i]; + let j = i - gap; while (j >= 0 && comparator.greaterThan(array[j], temp)) { array[j + gap] = array[j]; j -= gap; diff --git a/src/algorithms/sorting/short_bubble_sort.js b/src/algorithms/sorting/short_bubble_sort.js index 459fa65..e17b785 100644 --- a/src/algorithms/sorting/short_bubble_sort.js +++ b/src/algorithms/sorting/short_bubble_sort.js @@ -1,19 +1,19 @@ 'use strict'; -var Comparator = require('../../util/comparator'); +const Comparator = require('../../util/comparator'); /** * short bubble sort algorithm * worst: O(n^2) best: O(n) */ function shortBubbleSort(array, comparatorFn) { - var comparator = new Comparator(comparatorFn); - var length = array.length - 1; - var i = 0; + const comparator = new Comparator(comparatorFn); + const length = array.length - 1; + let i = 0; for (i; i < length; i++) { - var current = array[i]; - var next = array[i + 1]; + const current = array[i]; + const next = array[i + 1]; /** * If the current value if greater than the next: diff --git a/src/algorithms/string/hamming.js b/src/algorithms/string/hamming.js index 2cfba70..feabdea 100644 --- a/src/algorithms/string/hamming.js +++ b/src/algorithms/string/hamming.js @@ -8,14 +8,14 @@ */ 'use strict'; -var hamming = function(a, b) { +const hamming = function(a, b) { if (a.length !== b.length) { throw new Error('Strings must be equal in length'); } - var dist = 0; + let dist = 0; - for (var i = 0; i < a.length; i++) { + for (let i = 0; i < a.length; i++) { if (a[i] !== b[i]) { dist++; } diff --git a/src/algorithms/string/huffman.js b/src/algorithms/string/huffman.js index 8ff4e42..e35b43e 100644 --- a/src/algorithms/string/huffman.js +++ b/src/algorithms/string/huffman.js @@ -1,13 +1,13 @@ 'use strict'; -var huffman = {}; +const huffman = {}; /** * Maximum block size used by functions "compress", "decompress". * * @const */ -var MAX_BLOCK_SIZE = (-1 >>> 0).toString(2).length; +const MAX_BLOCK_SIZE = (-1 >>> 0).toString(2).length; /** * Compress 0-1 string to int32 array. @@ -15,10 +15,10 @@ var MAX_BLOCK_SIZE = (-1 >>> 0).toString(2).length; * @param {string} string * @return {number[]} */ -var compress = function(string) { - var blocks = []; - var currentBlock = 0; - var currentBlockSize = 0; +const compress = function(string) { + const blocks = []; + let currentBlock = 0; + let currentBlockSize = 0; string.split('').forEach(function(char) { currentBlock = (currentBlock << 1) | char; @@ -46,7 +46,7 @@ var compress = function(string) { * @param {number[]} array * @return {string} */ -var decompress = function(array) { +const decompress = function(array) { if (!array.length) { return ''; } else if (array.length === 1) { @@ -54,15 +54,15 @@ var decompress = function(array) { 'or at least 2 blocks big.'); } - var padding = new Array(MAX_BLOCK_SIZE + 1).join(0); + const padding = new Array(MAX_BLOCK_SIZE + 1).join(0); - var string = array.slice(0, -2).map(function(block) { + let string = array.slice(0, -2).map(function(block) { return (padding + (block >>> 0).toString(2)).slice(-padding.length); }).join(''); // Append the last block. - var lastBlockSize = array.slice(-1)[0]; - var lastBlock = array.slice(-2)[0]; + const lastBlockSize = array.slice(-1)[0]; + const lastBlock = array.slice(-2)[0]; string += (padding + (lastBlock >>> 0).toString(2)).slice(-lastBlockSize); return string; @@ -83,22 +83,22 @@ huffman.encode = function(string, compressed) { }; } - var counter = {}; + const counter = {}; string.split('').forEach(function(char) { counter[char] = (counter[char] || 0) + 1; }); - var letters = Object.keys(counter).map(function(char) { + const letters = Object.keys(counter).map(function(char) { return { char: char, count: counter[char] }; }); - var compare = function(a, b) { + const compare = function(a, b) { return a.count - b.count; }; - var less = function(a, b) { + const less = function(a, b) { return a && (b && (a.count < b.count) || !b); }; @@ -107,21 +107,21 @@ huffman.encode = function(string, compressed) { // Each time two least letters are merged into one, the result is pushing into // this buffer. Since the letters are pushing in ascending order of frequency, // no more sorting is ever required. - var buffer = []; - var lettersIndex = 0; - var bufferIndex = 0; + const buffer = []; + let lettersIndex = 0; + let bufferIndex = 0; - var extractMinimum = function() { + const extractMinimum = function() { return less(letters[lettersIndex], buffer[bufferIndex]) ? letters[lettersIndex++] : buffer[bufferIndex++]; }; - for (var numLetters = letters.length; numLetters > 1; --numLetters) { - var a = extractMinimum(); - var b = extractMinimum(); + for (let numLetters = letters.length; numLetters > 1; --numLetters) { + const a = extractMinimum(); + const b = extractMinimum(); a.code = '0'; b.code = '1'; - var union = { + const union = { count: a.count + b.count, parts: [a, b] }; @@ -129,14 +129,14 @@ huffman.encode = function(string, compressed) { } // At this point there is a single letter left. - var root = extractMinimum(); + const root = extractMinimum(); root.code = (letters.length > 1) ? '' : '0'; // Unroll the code recursively in reverse. (function unroll(parent) { if (parent.parts) { - var a = parent.parts[0]; - var b = parent.parts[1]; + const a = parent.parts[0]; + const b = parent.parts[1]; a.code += parent.code; b.code += parent.code; unroll(a); @@ -144,13 +144,13 @@ huffman.encode = function(string, compressed) { } })(root); - var encoding = letters.reduce(function(acc, letter) { + const encoding = letters.reduce(function(acc, letter) { acc[letter.char] = letter.code.split('').reverse().join(''); return acc; }, {}); // Finally, apply the encoding to the given string. - var result = string.split('').map(function(char) { + const result = string.split('').map(function(char) { return encoding[char]; }).join(''); @@ -174,16 +174,16 @@ huffman.decode = function(encoding, encodedString) { // We can make use of the fact that encoding mapping is always one-to-one // and rely on the power of JS hashes instead of building hand-made FSMs. - var letterByCode = Object.keys(encoding).reduce(function(acc, letter) { + const letterByCode = Object.keys(encoding).reduce(function(acc, letter) { acc[encoding[letter]] = letter; return acc; }, {}); - var decodedLetters = []; + const decodedLetters = []; - var unresolved = encodedString.split('').reduce(function(code, char) { + const unresolved = encodedString.split('').reduce(function(code, char) { code += char; - var letter = letterByCode[code]; + const letter = letterByCode[code]; if (letter) { decodedLetters.push(letter); code = ''; diff --git a/src/algorithms/string/knuth_morris_pratt.js b/src/algorithms/string/knuth_morris_pratt.js index d5c5d1f..e84ed12 100644 --- a/src/algorithms/string/knuth_morris_pratt.js +++ b/src/algorithms/string/knuth_morris_pratt.js @@ -10,11 +10,11 @@ * or {String} * @return {Array} of Integers */ -var buildTable = function(pattern) { - var length = pattern.length; - var table = []; - var position = 2; - var cnd = 0; +const buildTable = function(pattern) { + const length = pattern.length; + const table = []; + let position = 2; + let cnd = 0; table[0] = -1; table[1] = 0; @@ -50,12 +50,12 @@ var buildTable = function(pattern) { * or {String} * @return {Number} */ -var knuthMorrisPratt = function(text, pattern) { - var textLength = text.length; - var patternLength = pattern.length; - var m = 0; - var i = 0; - var table = buildTable(pattern); +const knuthMorrisPratt = function(text, pattern) { + const textLength = text.length; + const patternLength = pattern.length; + let m = 0; + let i = 0; + const table = buildTable(pattern); while (m + i < textLength) { if (pattern[i] === text[m + i]) { diff --git a/src/algorithms/string/levenshtein.js b/src/algorithms/string/levenshtein.js index a083abd..b495211 100644 --- a/src/algorithms/string/levenshtein.js +++ b/src/algorithms/string/levenshtein.js @@ -15,10 +15,10 @@ * @param String * @return Number */ -var levenshtein = function(a, b) { - var editDistance = []; - var i; - var j; +const levenshtein = function(a, b) { + const editDistance = []; + let i; + let j; // Initialize the edit distance matrix. The first collumn contains // the values comparing the string a to an empty string b diff --git a/src/algorithms/string/longest_common_subsequence.js b/src/algorithms/string/longest_common_subsequence.js index 5b8200b..60c6d80 100644 --- a/src/algorithms/string/longest_common_subsequence.js +++ b/src/algorithms/string/longest_common_subsequence.js @@ -7,12 +7,12 @@ /** * Implementation via dynamic programming */ -var longestCommonSubsequence = function(s1, s2) { +const longestCommonSubsequence = function(s1, s2) { // Multidimensional array for dynamic programming algorithm - var cache = new Array(s1.length + 1); + const cache = new Array(s1.length + 1); - var i; - var j; + let i; + let j; for (i = 0; i <= s1.length; i++) { cache[i] = new Int32Array(s2.length + 1); @@ -32,7 +32,7 @@ var longestCommonSubsequence = function(s1, s2) { // Build LCS from cache i = s1.length; j = s2.length; - var lcs = ''; + let lcs = ''; while (cache[i][j] !== 0) { if (s1[i - 1] === s2[j - 1]) { diff --git a/src/algorithms/string/longest_common_substring.js b/src/algorithms/string/longest_common_substring.js index 060ddf8..020e92e 100644 --- a/src/algorithms/string/longest_common_substring.js +++ b/src/algorithms/string/longest_common_substring.js @@ -7,19 +7,19 @@ /** * Implementation via dynamic programming */ -var longestCommonSubstring = function(s1, s2) { +const longestCommonSubstring = function(s1, s2) { // Multidimensional array for dynamic programming algorithm - var cache = new Array(s1.length + 1); + const cache = new Array(s1.length + 1); - var i; - var j; + let i; + let j; for (i = 0; i <= s1.length + 1; i++) { cache[i] = new Int32Array(s2.length + 1); } - var lcsPosition = {}; - var lcsLength = 0; + const lcsPosition = {}; + let lcsLength = 0; // Fill in the cache for (i = 1; i <= s1.length; i++) { @@ -36,7 +36,7 @@ var longestCommonSubstring = function(s1, s2) { } } - var lcs = ''; + let lcs = ''; if (lcsLength) { lcs = s1.substring(lcsPosition.i - lcsLength, lcsPosition.i); } diff --git a/src/algorithms/string/rabin_karp.js b/src/algorithms/string/rabin_karp.js index ad41018..c998d67 100644 --- a/src/algorithms/string/rabin_karp.js +++ b/src/algorithms/string/rabin_karp.js @@ -7,7 +7,7 @@ * Bigger the prime number, * bigger the hash value */ -var base = 997; +const base = 997; /** * Creates the hash representation of 'word' @@ -15,10 +15,10 @@ var base = 997; * @param String * @return Number */ -var hash = function(word) { - var h = 0; +const hash = function(word) { + let h = 0; - for (var i = 0; i < word.length; i++) { + for (let i = 0; i < word.length; i++) { h += word.charCodeAt(i) * Math.pow(base, word.length - i - 1); } @@ -36,14 +36,14 @@ var hash = function(word) { * @param String * @return Integer */ -var rabinKarp = function(s, pattern) { +const rabinKarp = function(s, pattern) { if (pattern.length === 0) return 0; - var hashPattern = hash(pattern); - var currentSubstring = s.substring(0, pattern.length); - var hashCurrentSubstring; + const hashPattern = hash(pattern); + let currentSubstring = s.substring(0, pattern.length); + let hashCurrentSubstring; - for (var i = pattern.length; i <= s.length; i++) { + for (let i = pattern.length; i <= s.length; i++) { if (hashCurrentSubstring === undefined) { hashCurrentSubstring = hash(currentSubstring); } else { diff --git a/src/data_structures/avl_tree.js b/src/data_structures/avl_tree.js index 471a0a6..077f6dc 100644 --- a/src/data_structures/avl_tree.js +++ b/src/data_structures/avl_tree.js @@ -23,7 +23,7 @@ function Node(value, left, right, parent, height) { * property of all his children. */ AVLTree.prototype.getNodeHeight = function(node) { - var height = 1; + let height = 1; if (node.left !== null && node.right !== null) { height = Math.max(node.left.height, node.right.height) + 1; } else if (node.left !== null) { @@ -38,7 +38,7 @@ AVLTree.prototype.getNodeHeight = function(node) { * Verifies if the given node is balanced. */ AVLTree.prototype.isNodeBalanced = function(node) { - var isBalanced = true; + let isBalanced = true; if (node.left !== null && node.right !== null) { isBalanced = (Math.abs(node.left.height - node.right.height) <= 1); @@ -56,12 +56,12 @@ AVLTree.prototype.isNodeBalanced = function(node) { */ AVLTree.prototype.getNodesToRestructureAfterRemove = function(traveledNodes) { // z is last traveled node - imbalance found at z - var zIndex = traveledNodes.length - 1; - var z = traveledNodes[zIndex]; + const zIndex = traveledNodes.length - 1; + const z = traveledNodes[zIndex]; // y should be child of z with larger height // (cannot be ancestor of removed node) - var y; + let y; if (z.left !== null && z.right !== null) { y = (z.left === y) ? z.right : z.left; } else if (z.left !== null && z.right === null) { @@ -73,7 +73,7 @@ AVLTree.prototype.getNodesToRestructureAfterRemove = function(traveledNodes) { // x should be tallest child of y // If children same height, x should be child of y // that has same orientation as z to y - var x; + let x; if (y.left !== null && y.right !== null) { if (y.left.height > y.right.height) { x = y.left; @@ -96,26 +96,26 @@ AVLTree.prototype.getNodesToRestructureAfterRemove = function(traveledNodes) { */ AVLTree.prototype.getNodesToRestructureAfterInsert = function(traveledNodes) { // z is last traveled node - imbalance found at z - var zIndex = traveledNodes.length - 1; - var z = traveledNodes[zIndex]; + const zIndex = traveledNodes.length - 1; + const z = traveledNodes[zIndex]; // y should be child of z with larger height // (must be ancestor of inserted node) // therefore, last traveled node is correct. - var yIndex = traveledNodes.length - 2; - var y = traveledNodes[yIndex]; + const yIndex = traveledNodes.length - 2; + const y = traveledNodes[yIndex]; // x should be tallest child of y // If children same height, x should be ancestor // of inserted node (in traveled path) - var x; + let x; if (y.left !== null && y.right !== null) { if (y.left.height > y.right.height) { x = y.left; } else if (y.left.height < y.right.height) { x = y.right; } else if (y.left.height === y.right.height) { - var xIndex = traveledNodes.length - 3; + const xIndex = traveledNodes.length - 3; x = traveledNodes[xIndex]; } } else if (y.left !== null && y.right === null) { @@ -131,13 +131,13 @@ AVLTree.prototype.getNodesToRestructureAfterInsert = function(traveledNodes) { * root and checking for invalid heights. */ AVLTree.prototype.keepHeightBalance = function(node, afterRemove) { - var current = node; - var traveledNodes = []; + let current = node; + const traveledNodes = []; while (current !== null) { traveledNodes.push(current); current.height = this.getNodeHeight(current); if (!this.isNodeBalanced(current)) { - var nodesToBeRestructured = (afterRemove) ? + const nodesToBeRestructured = (afterRemove) ? this.getNodesToRestructureAfterRemove(traveledNodes) : this.getNodesToRestructureAfterInsert(traveledNodes); this.restructure(nodesToBeRestructured); @@ -151,9 +151,9 @@ AVLTree.prototype.keepHeightBalance = function(node, afterRemove) { * rotator. */ AVLTree.prototype.restructure = function(nodesToRestructure) { - var x = nodesToRestructure[0]; - var y = nodesToRestructure[1]; - var z = nodesToRestructure[2]; + const x = nodesToRestructure[0]; + const y = nodesToRestructure[1]; + const z = nodesToRestructure[2]; // Determine Rotation Pattern if (z.right === y && y.right === x) { @@ -173,7 +173,7 @@ AVLTree.prototype.restructure = function(nodesToRestructure) { AVLTree.prototype.rightRight = function(x, y, z) { // pass z parent to y and move y's left to z's right if (z.parent) { - var orientation = (z.parent.left === z) ? 'left' : 'right'; + const orientation = (z.parent.left === z) ? 'left' : 'right'; z.parent[orientation] = y; y.parent = z.parent; } else { @@ -202,7 +202,7 @@ AVLTree.prototype.rightRight = function(x, y, z) { AVLTree.prototype.leftLeft = function(x, y, z) { // pass z parent to y and move y's right to z's left if (z.parent) { - var orientation = (z.parent.left === z) ? 'left' : 'right'; + const orientation = (z.parent.left === z) ? 'left' : 'right'; z.parent[orientation] = y; y.parent = z.parent; } else { @@ -230,7 +230,7 @@ AVLTree.prototype.leftLeft = function(x, y, z) { AVLTree.prototype.rightLeft = function(x, y, z) { // pass z parent to x if (z.parent) { - var orientation = (z.parent.left === z) ? 'left' : 'right'; + const orientation = (z.parent.left === z) ? 'left' : 'right'; z.parent[orientation] = x; x.parent = z.parent; } else { @@ -266,7 +266,7 @@ AVLTree.prototype.rightLeft = function(x, y, z) { AVLTree.prototype.leftRight = function(x, y, z) { // pass z parent to x if (z.parent) { - var orientation = (z.parent.left === z) ? 'left' : 'right'; + const orientation = (z.parent.left === z) ? 'left' : 'right'; z.parent[orientation] = x; x.parent = z.parent; } else { @@ -306,7 +306,7 @@ AVLTree.prototype.insert = function(value, current) { return; } - var insertKey; + let insertKey; current = current || this.root; if (current.value > value) { insertKey = 'left'; @@ -380,7 +380,7 @@ AVLTree.prototype._find = function(value, current) { return null; } - var node; + let node; if (current.value === value) { node = current; } else if (current.value > value) { @@ -418,14 +418,14 @@ AVLTree.prototype.replaceChild = function(parent, oldChild, newChild) { * Removes a node by its value. */ AVLTree.prototype.remove = function(value) { - var node = this.find(value); + const node = this.find(value); if (!node) { return false; } if (node.left && node.right) { - var min = this.findMin(node.right); - var temp = node.value; + const min = this.findMin(node.right); + const temp = node.value; node.value = min.value; min.value = temp; return this.remove(min); @@ -494,7 +494,7 @@ AVLTree.prototype.findMax = function() { * Verifies if the tree is balanced. */ AVLTree.prototype.isTreeBalanced = function() { - var current = this.root; + const current = this.root; if (!current) { return true; @@ -510,7 +510,7 @@ AVLTree.prototype.isTreeBalanced = function() { * property. */ AVLTree.prototype.getTreeHeight = function() { - var current = this.root; + const current = this.root; if (!current) { return 0; diff --git a/src/data_structures/bst.js b/src/data_structures/bst.js index 844b650..f546dbc 100644 --- a/src/data_structures/bst.js +++ b/src/data_structures/bst.js @@ -1,5 +1,5 @@ 'use strict'; -var Comparator = require('../util/comparator'); +const Comparator = require('../util/comparator'); /** * Binary Search Tree @@ -47,7 +47,7 @@ BST.prototype.insert = function(value, parent) { parent = this.root; } - var child = this._comparator.lessThan(value, parent.value) ? 'left' : 'right'; + const child = this._comparator.lessThan(value, parent.value) ? 'left' : 'right'; if (parent[child]) { this.insert(value, parent[child]); } else { @@ -83,7 +83,7 @@ BST.prototype._find = function(e, root) { * Substitute two nodes */ BST.prototype._replaceNodeInParent = function(currNode, newNode) { - var parent = currNode.parent; + const parent = currNode.parent; if (parent) { parent[currNode === parent.left ? 'left' : 'right'] = newNode; if (newNode) @@ -97,7 +97,7 @@ BST.prototype._replaceNodeInParent = function(currNode, newNode) { * Find the minimum value in a tree */ BST.prototype._findMin = function(root) { - var minNode = root; + let minNode = root; while (minNode.left) { minNode = minNode.left; } @@ -108,7 +108,7 @@ BST.prototype._findMin = function(root) { * Remove an element from the BST */ BST.prototype.remove = function(e) { - var node = this._find(e); + const node = this._find(e); if (!node) { throw new Error('Item not found in the tree'); } @@ -119,7 +119,7 @@ BST.prototype.remove = function(e) { * replace the node's value by the minimum value of the right * sub-tree, and remove the leave containing the value */ - var successor = this._findMin(node.right); + const successor = this._findMin(node.right); this.remove(successor.value); node.value = successor.value; } else { diff --git a/src/data_structures/disjoint_set_forest.js b/src/data_structures/disjoint_set_forest.js index 743c947..cb53631 100644 --- a/src/data_structures/disjoint_set_forest.js +++ b/src/data_structures/disjoint_set_forest.js @@ -30,7 +30,7 @@ DisjointSetForest.prototype._introduce = function(element) { */ DisjointSetForest.prototype.sameSubset = function(element) { this._introduce(element); - var root = this.root(element); + const root = this.root(element); return [].slice.call(arguments, 1).every(function(element) { this._introduce(element); return this.root(element) === root; @@ -82,8 +82,8 @@ DisjointSetForest.prototype.merge = function merge(element1, element2) { this._introduce(element1); this._introduce(element2); - var root1 = this.root(element1); - var root2 = this.root(element2); + const root1 = this.root(element1); + const root2 = this.root(element2); if (this._ranks[root1] < this._ranks[root2]) { this._parents[root1] = root2; diff --git a/src/data_structures/fenwick_tree.js b/src/data_structures/fenwick_tree.js index 68d2936..a5f4843 100644 --- a/src/data_structures/fenwick_tree.js +++ b/src/data_structures/fenwick_tree.js @@ -24,7 +24,7 @@ */ function FenwickTree(length) { this._elements = new Array(length + 1); - for (var i = 0; i < this._elements.length; i++) + for (let i = 0; i < this._elements.length; i++) this._elements[i] = 0; } @@ -71,7 +71,7 @@ FenwickTree.prototype.prefixSum = function(index) { Note: (index&-index) finds the rightmost bit in index. */ - var sum = 0; + let sum = 0; for (; index > 0; index -= (index & -index)) sum += this._elements[index]; return sum; diff --git a/src/data_structures/graph.js b/src/data_structures/graph.js index 39019bf..8df2ae0 100644 --- a/src/data_structures/graph.js +++ b/src/data_structures/graph.js @@ -1,6 +1,6 @@ 'use strict'; -var HashSet = require('./set'); +const HashSet = require('./set'); /** * Adjacency list representation of a graph @@ -13,7 +13,7 @@ function Graph(directed) { } // Normalize vertex labels as strings -var _ = function(v) { +const _ = function(v) { return String(v); }; @@ -54,8 +54,8 @@ Graph.prototype.edge = function(a, b) { }; Graph.prototype.reverse = function() { - var self = this; - var r = new Graph(this.directed); + const self = this; + const r = new Graph(this.directed); self.vertices.forEach(function(v) { r.addVertex(v); diff --git a/src/data_structures/hash_table.js b/src/data_structures/hash_table.js index 9742346..e625882 100644 --- a/src/data_structures/hash_table.js +++ b/src/data_structures/hash_table.js @@ -1,6 +1,6 @@ 'use strict'; -var LinkedList = require('./linked_list'); +const LinkedList = require('./linked_list'); /** * HashTable constructor @@ -33,8 +33,8 @@ function HashTable(initialCapacity) { */ HashTable.prototype.hash = function(s) { if (typeof s !== 'string') s = JSON.stringify(s); - var hash = 0; - for (var i = 0; i < s.length; i++) { + let hash = 0; + for (let i = 0; i < s.length; i++) { hash = ((hash << 5) - hash) + s.charCodeAt(i); hash &= hash; // Keep it a 32bit int } @@ -42,8 +42,8 @@ HashTable.prototype.hash = function(s) { }; HashTable.prototype.get = function(key) { - var i = this._position(key); - var node; + const i = this._position(key); + let node; if ((node = this._findInList(this._table[i], key))) { return node.value.v; } @@ -51,14 +51,14 @@ HashTable.prototype.get = function(key) { }; HashTable.prototype.put = function(key, value) { - var i = this._position(key); + const i = this._position(key); if (!this._table[i]) { // Hashing with chaining this._table[i] = new LinkedList(); } - var item = {k: key, v: value}; + const item = {k: key, v: value}; - var node = this._findInList(this._table[i], key); + const node = this._findInList(this._table[i], key); if (node) { // if the key already exists in the list, replace // by the current item @@ -72,8 +72,8 @@ HashTable.prototype.put = function(key, value) { }; HashTable.prototype.del = function(key) { - var i = this._position(key); - var node; + const i = this._position(key); + let node; if ((node = this._findInList(this._table[i], key))) { this._table[i].delNode(node); @@ -86,7 +86,7 @@ HashTable.prototype._position = function(key) { }; HashTable.prototype._findInList = function(list, key) { - var node = list && list.head; + let node = list && list.head; while (node) { if (node.value.k === key) return node; node = node.next; @@ -94,12 +94,12 @@ HashTable.prototype._findInList = function(list, key) { }; HashTable.prototype._increaseCapacity = function() { - var oldTable = this._table; + const oldTable = this._table; this._table = new Array(2 * this.capacity); this._items = 0; - for (var i = 0; i < oldTable.length; i++) { - var node = oldTable[i] && oldTable[i].head; + for (let i = 0; i < oldTable.length; i++) { + let node = oldTable[i] && oldTable[i].head; while (node) { this.put(node.value.k, node.value.v); node = node.next; @@ -108,13 +108,13 @@ HashTable.prototype._increaseCapacity = function() { }; HashTable.prototype.forEach = function(fn) { - var applyFunction = function(linkedList) { + const applyFunction = function(linkedList) { linkedList.forEach(function(elem) { fn(elem.k, elem.v); }); }; - for (var i = 0; i < this._table.length; i++) { + for (let i = 0; i < this._table.length; i++) { if (this._table[i]) { applyFunction(this._table[i]); } diff --git a/src/data_structures/heap.js b/src/data_structures/heap.js index 105ba35..11c9857 100644 --- a/src/data_structures/heap.js +++ b/src/data_structures/heap.js @@ -1,5 +1,5 @@ 'use strict'; -var Comparator = require('../util/comparator'); +const Comparator = require('../util/comparator'); /** * Basic Heap structure @@ -16,7 +16,7 @@ function MinHeap(compareFn) { } MinHeap.prototype._swap = function(a, b) { - var tmp = this._elements[a]; + const tmp = this._elements[a]; this._elements[a] = this._elements[b]; this._elements[b] = tmp; }; @@ -31,11 +31,11 @@ MinHeap.prototype.insert = function(e) { }; MinHeap.prototype.extract = function() { - var element = this._elements[1]; + const element = this._elements[1]; // Get the one from the bottom in insert it on top // If this isn't already the last element - var last = this._elements.pop(); + const last = this._elements.pop(); if (this.n) { this._elements[1] = last; this._siftDown(); @@ -49,8 +49,8 @@ MinHeap.prototype.extract = function() { * O(lg n) */ MinHeap.prototype._siftUp = function() { - var i; - var parent; + let i; + let parent; for (i = this.n; i > 1 && (parent = i >> 1) && this._comparator.greaterThan( @@ -65,7 +65,7 @@ MinHeap.prototype._siftUp = function() { * O(lg n) */ MinHeap.prototype._siftDown = function(i) { - var c; + let c; for (i = i || 1; (c = i << 1) <= this.n; i = c) { // checks which is the smaller child to compare with if (c + 1 <= this.n && this._comparator.lessThan( @@ -85,7 +85,7 @@ MinHeap.prototype.heapify = function(a) { this._elements.unshift(null); } - for (var i = this.n >> 1; i > 0; i--) { + for (let i = this.n >> 1; i > 0; i--) { this._siftDown(i); } }; @@ -94,8 +94,8 @@ MinHeap.prototype.forEach = function(fn) { // A copy is necessary in order to perform extract(), // get the items in sorted order and then restore the original // this._elements array - var elementsCopy = []; - var i; + const elementsCopy = []; + let i; for (i = 0; i < this._elements.length; i++) { elementsCopy.push(this._elements[i]); diff --git a/src/data_structures/linked_list.js b/src/data_structures/linked_list.js index c556904..82966d5 100644 --- a/src/data_structures/linked_list.js +++ b/src/data_structures/linked_list.js @@ -45,11 +45,11 @@ LinkedList.prototype.add = function(n, index) { throw new Error('Index out of bounds'); } - var node = new Node(n); + const node = new Node(n); if (index !== undefined && index < this.length) { - var prevNode; - var nextNode; + let prevNode; + let nextNode; if (index === 0) { // Insert in the beginning @@ -98,8 +98,8 @@ LinkedList.prototype.getNode = function(index) { throw new Error('Index out of bounds'); } - var node = this.head; - for (var i = 1; i <= index; i++) { + let node = this.head; + for (let i = 1; i <= index; i++) { node = node.next; } @@ -140,7 +140,7 @@ LinkedList.prototype.delNode = function(node) { * Performs the fn function with each element in the list */ LinkedList.prototype.forEach = function(fn) { - var node = this.head; + let node = this.head; while (node) { fn(node.value); node = node.next; diff --git a/src/data_structures/priority_queue.js b/src/data_structures/priority_queue.js index 6b394d7..df383e7 100644 --- a/src/data_structures/priority_queue.js +++ b/src/data_structures/priority_queue.js @@ -1,6 +1,6 @@ 'use strict'; -var MinHeap = require('./heap').MinHeap; +const MinHeap = require('./heap').MinHeap; /** * Extends the MinHeap with the only difference that @@ -8,7 +8,7 @@ var MinHeap = require('./heap').MinHeap; * and not on the element itself */ function PriorityQueue(initialItems) { - var self = this; + const self = this; MinHeap.call(this, function(a, b) { return self.priority(a) < self.priority(b) ? -1 : 1; }); @@ -32,7 +32,7 @@ PriorityQueue.prototype.insert = function(item, priority) { }; PriorityQueue.prototype.extract = function(withPriority) { - var min = MinHeap.prototype.extract.call(this); + const min = MinHeap.prototype.extract.call(this); return withPriority ? min && {item: min, priority: this._priority[min]} : min; diff --git a/src/data_structures/queue.js b/src/data_structures/queue.js index 725fc4e..1f3d381 100644 --- a/src/data_structures/queue.js +++ b/src/data_structures/queue.js @@ -1,6 +1,6 @@ 'use strict'; -var LinkedList = require('./linked_list'); +const LinkedList = require('./linked_list'); /** * Queue (FIFO) using a Linked List as basis @@ -33,7 +33,7 @@ Queue.prototype.pop = function() { if (this.isEmpty()) { throw new Error('Empty queue'); } - var e = this._elements.head; + const e = this._elements.head; this._elements.delNode(e); return e.value; }; diff --git a/src/data_structures/set.js b/src/data_structures/set.js index e3f0fe0..e4f343c 100644 --- a/src/data_structures/set.js +++ b/src/data_structures/set.js @@ -1,13 +1,13 @@ 'use strict'; -var HashTable = require('./hash_table'); +const HashTable = require('./hash_table'); /** * Typical representation of a mathematical set * No restriction on element types * i.e. set.add(1,'a', "b", { "foo" : "bar" }) */ -var HashSet = function() { +const HashSet = function() { this._elements = new HashTable(arguments.length); this.add.apply(this, arguments); @@ -19,14 +19,14 @@ var HashSet = function() { }; HashSet.prototype.add = function() { - for (var i = 0; i < arguments.length; i++) { + for (let i = 0; i < arguments.length; i++) { this._elements.put(arguments[i], true); } return this; }; HashSet.prototype.remove = function() { - for (var i = 0; i < arguments.length; i++) { + for (let i = 0; i < arguments.length; i++) { this._elements.del(arguments[i]); } return this; diff --git a/src/data_structures/stack.js b/src/data_structures/stack.js index 4c7b982..e29fc14 100644 --- a/src/data_structures/stack.js +++ b/src/data_structures/stack.js @@ -1,5 +1,5 @@ 'use strict'; -var LinkedList = require('./linked_list'); +const LinkedList = require('./linked_list'); /** * Stack (LIFO) using a Linked List as basis @@ -33,7 +33,7 @@ Stack.prototype.pop = function() { throw new Error('Empty queue'); } - var e = this._elements.tail; + const e = this._elements.tail; this._elements.delNode(e); return e.value; }; diff --git a/src/data_structures/treap.js b/src/data_structures/treap.js index 4949e56..4170f5f 100644 --- a/src/data_structures/treap.js +++ b/src/data_structures/treap.js @@ -26,7 +26,7 @@ Node.prototype.resize = function() { * Zigzag rotate of tree nodes */ Node.prototype.rotate = function(side) { - var temp = this.children[side]; + const temp = this.children[side]; // Rotate this.children[side] = temp.children[1 - side]; @@ -54,7 +54,7 @@ Treap.prototype._insert = function(node, value) { } // Passing to childnodes and update - var side = ~~(value > node.value); + const side = ~~(value > node.value); node.children[side] = this._insert(node.children[side], value); // Keep it balance @@ -75,7 +75,7 @@ Treap.prototype._find = function(node, value) { } // Search within childnodes - var side = ~~(value > node.value); + const side = ~~(value > node.value); return this._find(node.children[side], value); }; @@ -103,7 +103,7 @@ Treap.prototype._remove = function(node, value) { return null; } - var side; + let side; if (node.value === value) { if (node.children[0] === null && node.children[1] === null) { diff --git a/src/index.js b/src/index.js index 15f7bb5..0807726 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ 'use strict'; -var lib = { +const lib = { DataStructures: require('./data_structures'), Graph: require('./graph'), Geometry: require('./geometry'), diff --git a/src/test/algorithms/geometry/bezier_curve.js b/src/test/algorithms/geometry/bezier_curve.js index 9d09692..fb49872 100644 --- a/src/test/algorithms/geometry/bezier_curve.js +++ b/src/test/algorithms/geometry/bezier_curve.js @@ -1,14 +1,14 @@ 'use strict'; -var root = require('../../../'); -var BezierCurve = root.Geometry.BezierCurve; -var assert = require('assert'); +const root = require('../../../'); +const BezierCurve = root.Geometry.BezierCurve; +const assert = require('assert'); // Testing with http://pomax.github.io/bezierjs/ describe('Bézier-Curve Algorithm', function() { it('should get a linear Bézier-curve', function() { - var b = new BezierCurve([{x: 0, y: 0}, {x: 10, y: 3}]); + const b = new BezierCurve([{x: 0, y: 0}, {x: 10, y: 3}]); // Ends assert.deepEqual(b.get(0), {x: 0, y: 0}); @@ -22,7 +22,7 @@ describe('Bézier-Curve Algorithm', function() { assert.deepEqual(b.get(0.75), {x: 7.5, y: 2.25}); }); it('should get a quadratic Bézier-curve', function() { - var b = new BezierCurve([{x: 150, y: 40}, + const b = new BezierCurve([{x: 150, y: 40}, {x: 80, y: 30}, {x: 105, y: 150}]); @@ -30,7 +30,7 @@ describe('Bézier-Curve Algorithm', function() { assert.deepEqual(b.get(0.25), {x: 120.9375, y: 43.125}); }); it('should get a cubic Bézier-curve', function() { - var b = new BezierCurve([{x: 150, y: 40}, + const b = new BezierCurve([{x: 150, y: 40}, {x: 80, y: 30}, {x: 105, y: 150}, {x: 100, y: 100}]); diff --git a/src/test/algorithms/graph/SPFA.js b/src/test/algorithms/graph/SPFA.js index 70fa91e..c184d37 100644 --- a/src/test/algorithms/graph/SPFA.js +++ b/src/test/algorithms/graph/SPFA.js @@ -1,14 +1,14 @@ 'use strict'; -var root = require('../../../'); -var spfa = root.Graph.SPFA; -var Graph = root.DataStructures.Graph; -var assert = require('assert'); +const root = require('../../../'); +const spfa = root.Graph.SPFA; +const Graph = root.DataStructures.Graph; +const assert = require('assert'); describe('SPFA Algorithm', function() { it('should return the shortest paths to all nodes from a given origin', function() { - var graph = new Graph(true); + const graph = new Graph(true); graph.addEdge('a', 'b', -1); graph.addEdge('a', 'c', 4); @@ -19,7 +19,7 @@ describe('SPFA Algorithm', function() { graph.addEdge('e', 'd', -3); graph.addEdge('d', 'c', 5); - var shortestPaths = spfa(graph, 'a'); + let shortestPaths = spfa(graph, 'a'); assert.equal(shortestPaths.distance.a, 0); assert.equal(shortestPaths.distance.d, -2); diff --git a/src/test/algorithms/graph/bellman_ford.js b/src/test/algorithms/graph/bellman_ford.js index 566d294..92f38b3 100644 --- a/src/test/algorithms/graph/bellman_ford.js +++ b/src/test/algorithms/graph/bellman_ford.js @@ -1,14 +1,14 @@ 'use strict'; -var root = require('../../../'); -var bellmanFord = root.Graph.bellmanFord; -var Graph = root.DataStructures.Graph; -var assert = require('assert'); +const root = require('../../../'); +const bellmanFord = root.Graph.bellmanFord; +const Graph = root.DataStructures.Graph; +const assert = require('assert'); describe('Bellman-Ford Algorithm', function() { it('should return the shortest paths to all nodes from a given origin', function() { - var graph = new Graph(true); + const graph = new Graph(true); graph.addEdge('a', 'b', -1); graph.addEdge('a', 'c', 4); @@ -19,7 +19,7 @@ describe('Bellman-Ford Algorithm', function() { graph.addEdge('e', 'd', -3); graph.addEdge('d', 'c', 5); - var shortestPaths = bellmanFord(graph, 'a'); + let shortestPaths = bellmanFord(graph, 'a'); assert.equal(shortestPaths.distance.a, 0); assert.equal(shortestPaths.distance.d, -2); diff --git a/src/test/algorithms/graph/bfs_shortest_path.js b/src/test/algorithms/graph/bfs_shortest_path.js index ef04021..efbeb27 100644 --- a/src/test/algorithms/graph/bfs_shortest_path.js +++ b/src/test/algorithms/graph/bfs_shortest_path.js @@ -1,14 +1,14 @@ 'use strict'; -var root = require('../../../'); -var bfsShortestPath = root.Graph.bfsShortestPath; -var Graph = root.DataStructures.Graph; -var assert = require('assert'); +const root = require('../../../'); +const bfsShortestPath = root.Graph.bfsShortestPath; +const Graph = root.DataStructures.Graph; +const assert = require('assert'); describe('BFS Shortest Path Algorithm', function() { it('should return the shortest paths to all nodes from a given origin', function() { - var graph = new Graph(); + const graph = new Graph(); graph.addEdge(0, 1); graph.addEdge(1, 2); graph.addEdge(0, 2); @@ -22,7 +22,7 @@ describe('BFS Shortest Path Algorithm', function() { graph.addEdge(5, 0); graph.addEdge('a', 'b'); - var shortestPath = bfsShortestPath(graph, 0); + const shortestPath = bfsShortestPath(graph, 0); assert.deepEqual(shortestPath.distance, { 0: 0, diff --git a/src/test/algorithms/graph/breadth_first_search.js b/src/test/algorithms/graph/breadth_first_search.js index 263365a..700b531 100644 --- a/src/test/algorithms/graph/breadth_first_search.js +++ b/src/test/algorithms/graph/breadth_first_search.js @@ -1,12 +1,12 @@ 'use strict'; -var root = require('../../../'); -var breadthFirstSearch = root.Graph.breadthFirstSearch; -var Graph = root.DataStructures.Graph; -var assert = require('assert'); +const root = require('../../../'); +const breadthFirstSearch = root.Graph.breadthFirstSearch; +const Graph = root.DataStructures.Graph; +const assert = require('assert'); describe('Breadth-First Search', function() { - var graph; + let graph; before(function() { graph = new Graph(); @@ -22,10 +22,10 @@ describe('Breadth-First Search', function() { }); it('should visit reachable vertices in a breadth-first manner', function() { - var enter = []; - var leave = []; - var lastEntered = null; - var traversed = 0; + const enter = []; + const leave = []; + let lastEntered = null; + let traversed = 0; breadthFirstSearch(graph, 1); @@ -54,15 +54,15 @@ describe('Breadth-First Search', function() { }); it('should allow user-defined allowTraversal rules', function() { - var seen = new Graph(graph.directed); + const seen = new Graph(graph.directed); graph.vertices.forEach(seen.addVertex.bind(seen)); - var indegrees = {1: -1}; - var outdegrees = {}; + const indegrees = {1: -1}; + const outdegrees = {}; // Edge-centric BFS. breadthFirstSearch(graph, 1, { allowTraversal: function(vertex, neighbor) { - var visited = seen.edge(vertex, neighbor); + const visited = seen.edge(vertex, neighbor); if (!visited) { seen.addEdge(vertex, neighbor); outdegrees[vertex] = (outdegrees[vertex] || 0) + 1; diff --git a/src/test/algorithms/graph/depth_first_search.js b/src/test/algorithms/graph/depth_first_search.js index e60b732..f6f1530 100644 --- a/src/test/algorithms/graph/depth_first_search.js +++ b/src/test/algorithms/graph/depth_first_search.js @@ -1,12 +1,12 @@ 'use strict'; -var root = require('../../../'); -var depthFirstSearch = root.Graph.depthFirstSearch; -var Graph = root.DataStructures.Graph; -var assert = require('assert'); +const root = require('../../../'); +const depthFirstSearch = root.Graph.depthFirstSearch; +const Graph = root.DataStructures.Graph; +const assert = require('assert'); describe('Depth First Search Algorithm', function() { - var graph; + let graph; before(function() { graph = new Graph(true); graph.addEdge('one', 'three'); @@ -19,14 +19,14 @@ describe('Depth First Search Algorithm', function() { it('should visit only the nodes reachable from the start node (inclusive)', function() { - var enter = []; - var leave = []; - var numEdgeTails = 0; - var numEdgeHeads = 0; + const enter = []; + const leave = []; + let numEdgeTails = 0; + let numEdgeHeads = 0; depthFirstSearch(graph, 'one'); - var dfsCallbacks = { + const dfsCallbacks = { enterVertex: [].push.bind(enter), leaveVertex: [].push.bind(leave), beforeTraversal: function() { @@ -54,9 +54,9 @@ describe('Depth First Search Algorithm', function() { ); it('should allow user-defined allowTraversal rules', function() { - var seen = new Graph(graph.directed); + const seen = new Graph(graph.directed); graph.vertices.forEach(seen.addVertex.bind(seen)); - var path = ['one']; + const path = ['one']; // Edge-centric DFS. depthFirstSearch(graph, path[0], { diff --git a/src/test/algorithms/graph/dijkstra.js b/src/test/algorithms/graph/dijkstra.js index e0346b8..96a9174 100644 --- a/src/test/algorithms/graph/dijkstra.js +++ b/src/test/algorithms/graph/dijkstra.js @@ -1,14 +1,14 @@ 'use strict'; -var root = require('../../../'); -var dijkstra = root.Graph.dijkstra; -var Graph = root.DataStructures.Graph; -var assert = require('assert'); +const root = require('../../../'); +const dijkstra = root.Graph.dijkstra; +const Graph = root.DataStructures.Graph; +const assert = require('assert'); describe('Dijkstra Algorithm', function() { it('should return the shortest paths to all nodes from a given origin', function() { - var g = new Graph(); + const g = new Graph(); g.addEdge('a', 'b', 5); g.addEdge('a', 'c', 10); g.addEdge('b', 'c', 2); @@ -16,7 +16,7 @@ describe('Dijkstra Algorithm', function() { g.addEdge('c', 'd', 1); g.addEdge('d', 'a', 10); - var shortestPath = dijkstra(g, 'a'); + const shortestPath = dijkstra(g, 'a'); assert.equal(shortestPath.distance.b, 5); assert.equal(shortestPath.previous.b, 'a'); diff --git a/src/test/algorithms/graph/euler_path.js b/src/test/algorithms/graph/euler_path.js index d28eb8c..7742988 100644 --- a/src/test/algorithms/graph/euler_path.js +++ b/src/test/algorithms/graph/euler_path.js @@ -1,13 +1,13 @@ 'use strict'; -var root = require('../../../'); -var eulerPath = root.Graph.eulerPath; -var Graph = root.DataStructures.Graph; -var assert = require('assert'); +const root = require('../../../'); +const eulerPath = root.Graph.eulerPath; +const Graph = root.DataStructures.Graph; +const assert = require('assert'); describe('Euler Path', function() { - var verifyEulerPath = function(graph, trail) { - var visited = new Graph(graph.directed); + const verifyEulerPath = function(graph, trail) { + const visited = new Graph(graph.directed); graph.vertices.forEach(visited.addVertex.bind(visited)); trail.slice(1).reduce(function(previous, current) { @@ -23,8 +23,8 @@ describe('Euler Path', function() { }); }; - var graphFromEdges = function(directed, edges) { - var graph = new Graph(directed); + const graphFromEdges = function(directed, edges) { + const graph = new Graph(directed); edges.forEach(function(edge) { graph.addEdge(edge[0], edge[1]); }); @@ -32,7 +32,7 @@ describe('Euler Path', function() { }; it('should compute Euler tour over the undirected graph', function() { - var graph = graphFromEdges(false, [ + const graph = graphFromEdges(false, [ [1, 2], [1, 5], [1, 7], @@ -49,13 +49,13 @@ describe('Euler Path', function() { [6, 10], [7, 8] ]); - var trail = eulerPath(graph); + const trail = eulerPath(graph); verifyEulerPath(graph, trail); assert.equal(trail[0], trail.slice(-1)[0]); }); it('should compute Euler walk over the undirected graph', function() { - var graph = graphFromEdges(false, [ + const graph = graphFromEdges(false, [ [1, 2], [1, 5], [1, 7], @@ -71,16 +71,16 @@ describe('Euler Path', function() { [6, 10], [7, 8] ]); - var trail = eulerPath(graph); + const trail = eulerPath(graph); verifyEulerPath(graph, trail); - var endpoints = [trail[0], trail.slice(-1)[0]]; + const endpoints = [trail[0], trail.slice(-1)[0]]; endpoints.sort(); assert.equal(endpoints[0], 1); assert.equal(endpoints[1], 8); }); it('should compute Euler tour over the directed graph', function() { - var graph = graphFromEdges(true, [ + const graph = graphFromEdges(true, [ [0, 1], [1, 2], [2, 0], @@ -92,13 +92,13 @@ describe('Euler Path', function() { [5, 6], [6, 4] ]); - var trail = eulerPath(graph); + const trail = eulerPath(graph); verifyEulerPath(graph, trail); assert.equal(trail[0], trail.slice(-1)[0]); }); it('should compute Euler walk over the directed graph', function() { - var graph = graphFromEdges(true, [ + const graph = graphFromEdges(true, [ [5, 0], [0, 2], [2, 4], @@ -107,25 +107,25 @@ describe('Euler Path', function() { [3, 1], [5, 3] ]); - var trail = eulerPath(graph); + const trail = eulerPath(graph); assert.deepEqual(trail, [5, 3, 1, 5, 0, 2, 4, 0]); }); it('should return single-vertex-trail for an isolated vertex', function() { - var graph = new Graph(); + const graph = new Graph(); graph.addVertex('loner'); - var trail = eulerPath(graph); + const trail = eulerPath(graph); assert.deepEqual(trail, ['loner']); }); it('should return empty trail for an empty graph', function() { - var graph = new Graph(); - var trail = eulerPath(graph); + const graph = new Graph(); + const trail = eulerPath(graph); assert.deepEqual(trail, []); }); it('should raise an error if there is no Euler path', function() { - var graph = graphFromEdges(false, [[0, 1], [2, 3]]); + let graph = graphFromEdges(false, [[0, 1], [2, 3]]); assert.throws(eulerPath.bind(null, graph)); graph = graphFromEdges(false, [ diff --git a/src/test/algorithms/graph/floyd_warshall.js b/src/test/algorithms/graph/floyd_warshall.js index 56c8c62..380aeb5 100644 --- a/src/test/algorithms/graph/floyd_warshall.js +++ b/src/test/algorithms/graph/floyd_warshall.js @@ -1,13 +1,13 @@ 'use strict'; -var root = require('../../../'); -var floydWarshall = root.Graph.floydWarshall; -var Graph = root.DataStructures.Graph; -var assert = require('assert'); +const root = require('../../../'); +const floydWarshall = root.Graph.floydWarshall; +const Graph = root.DataStructures.Graph; +const assert = require('assert'); describe('Floyd-Warshall Algorithm', function() { it('should compute all-pairs shortest paths in the graph', function() { - var graph = new Graph(); + const graph = new Graph(); graph.addEdge('a', 'b', -2); graph.addEdge('b', 'c', -1); graph.addEdge('c', 'a', 4); @@ -16,7 +16,7 @@ describe('Floyd-Warshall Algorithm', function() { graph.addEdge('z', 'x', 1); graph.addEdge('z', 'y', -4); - var result = floydWarshall(graph); + const result = floydWarshall(graph); assert.deepEqual(result.distance, {a: {a: 0, b: -2, @@ -63,7 +63,7 @@ describe('Floyd-Warshall Algorithm', function() { it('should determine if the graph contains a negative-weighted cycle', function() { - var graph = new Graph(); + const graph = new Graph(); graph.addEdge('a', 'b', -2); graph.addEdge('b', 'c', -1); graph.addEdge('c', 'y', -3); diff --git a/src/test/algorithms/graph/minimum_spanning_tree.js b/src/test/algorithms/graph/minimum_spanning_tree.js index 21264e8..bd57edf 100644 --- a/src/test/algorithms/graph/minimum_spanning_tree.js +++ b/src/test/algorithms/graph/minimum_spanning_tree.js @@ -1,21 +1,21 @@ 'use strict'; -var root = require('../../../'); -var kruskal = root.Graph.kruskal; -var prim = root.Graph.prim; -var depthFirstSearch = root.Graph.depthFirstSearch; -var Graph = root.DataStructures.Graph; -var assert = require('assert'); +const root = require('../../../'); +const kruskal = root.Graph.kruskal; +const prim = root.Graph.prim; +const depthFirstSearch = root.Graph.depthFirstSearch; +const Graph = root.DataStructures.Graph; +const assert = require('assert'); describe('Minimum Spanning Tree', function() { /** * @param {Graph} graph - Undirected graph. * @return {number} */ - var numberOfConnectedComponents = function(graph) { + const numberOfConnectedComponents = function(graph) { assert(!graph.directed); - var seen = {}; - var coverComponent = function(origin) { + const seen = {}; + const coverComponent = function(origin) { depthFirstSearch(graph, origin, { enterVertex: function(vertex) { seen[vertex] = true; @@ -23,7 +23,7 @@ describe('Minimum Spanning Tree', function() { }); }; - var count = 0; + let count = 0; graph.vertices.forEach(function(vertex) { if (!seen[vertex]) { coverComponent(vertex); @@ -41,11 +41,11 @@ describe('Minimum Spanning Tree', function() { * @param {number} connectivity * @return {boolean} */ - var isForest = function(graph, connectivity) { + const isForest = function(graph, connectivity) { if (graph.directed || numberOfConnectedComponents(graph) !== connectivity) { return false; } - var numberOfEdges = 0; + let numberOfEdges = 0; graph.vertices.forEach(function(vertex) { numberOfEdges += graph.neighbors(vertex).filter( function(neighbor) { @@ -62,8 +62,8 @@ describe('Minimum Spanning Tree', function() { * @param {Graph} graph2 * @return {boolean} */ - var spans = function(graph1, graph2) { - var span; + const spans = function(graph1, graph2) { + let span; if (graph1.vertices.size === graph2.vertices.size) { span = true; graph1.vertices.forEach(function(v) { @@ -83,8 +83,8 @@ describe('Minimum Spanning Tree', function() { * @param {Graph} graph * @return {number} */ - var graphCost = function(graph) { - var total = 0; + const graphCost = function(graph) { + let total = 0; graph.vertices.forEach(function(vertex) { total += graph.neighbors(vertex).reduce(function(accum, neighbor) { return accum + graph.edge(vertex, neighbor); @@ -102,7 +102,7 @@ describe('Minimum Spanning Tree', function() { * @param {number} [connectivity=1] * @return {boolean} */ - var isMinimumSpanningForest = function(suspect, graph, + const isMinimumSpanningForest = function(suspect, graph, minimumCost, connectivity) { assert(!graph.directed); return isForest(suspect, connectivity || 1) && @@ -110,9 +110,9 @@ describe('Minimum Spanning Tree', function() { graphCost(suspect) === minimumCost; }; - var testMstAlgorithm = function(mst) { + const testMstAlgorithm = function(mst) { it('should find a minimum spanning tree', function() { - var graph = new Graph(false); + const graph = new Graph(false); graph.addEdge(1, 2, 1); graph.addEdge(1, 4, 2); graph.addEdge(1, 5, 2); @@ -134,7 +134,7 @@ describe('Minimum Spanning Tree', function() { assert(isMinimumSpanningForest(mst(graph), graph, 10)); // It should find zero-cost MST. - var clear = function(a, b) { + const clear = function(a, b) { graph.addEdge(a, b, -graph.edge(a, b)); }; clear(2, 1); @@ -151,7 +151,7 @@ describe('Minimum Spanning Tree', function() { it('should find a minimum spaning forest if the graph is not connected', function() { - var graph = new Graph(false); + const graph = new Graph(false); graph.addVertex(1); graph.addVertex(2); graph.addVertex(3); @@ -176,7 +176,7 @@ describe('Minimum Spanning Tree', function() { }); it('should throw an error if the graph is directed', function() { - var directedGraph = new Graph(true); + const directedGraph = new Graph(true); directedGraph.addEdge('Rock', 'Hard Place'); assert.throws(mst.bind(null, directedGraph)); }); diff --git a/src/test/algorithms/graph/strongly_connected_component.js b/src/test/algorithms/graph/strongly_connected_component.js index f879b3c..509a15d 100644 --- a/src/test/algorithms/graph/strongly_connected_component.js +++ b/src/test/algorithms/graph/strongly_connected_component.js @@ -1,18 +1,18 @@ 'use strict'; -var root = require('../../../'); -var Graph = root.DataStructures.Graph; -var stronglyConnectedComponent = root.Graph.strongConnectedComponent; -var assert = require('assert'); +const root = require('../../../'); +const Graph = root.DataStructures.Graph; +const stronglyConnectedComponent = root.Graph.strongConnectedComponent; +const assert = require('assert'); describe('Strongly Connected Component', function() { it('should correctly compute strongly connected components', function() { // graph: 0 -> 1 -> 2 - var graph = new Graph(); + let graph = new Graph(); graph.addEdge(0, 1); graph.addEdge(1, 2); - var scc = stronglyConnectedComponent(graph); + let scc = stronglyConnectedComponent(graph); assert.equal(scc.count, 3); assert(scc.id[0] > scc.id[1]); assert(scc.id[1] > scc.id[2]); diff --git a/src/test/algorithms/graph/topological_sort.js b/src/test/algorithms/graph/topological_sort.js index a386dd0..e8e8e29 100644 --- a/src/test/algorithms/graph/topological_sort.js +++ b/src/test/algorithms/graph/topological_sort.js @@ -1,14 +1,14 @@ 'use strict'; -var root = require('../../../'); -var topologicalSort = root.Graph.topologicalSort; -var Graph = root.DataStructures.Graph; -var assert = require('assert'); +const root = require('../../../'); +const topologicalSort = root.Graph.topologicalSort; +const Graph = root.DataStructures.Graph; +const assert = require('assert'); describe('Topological Sort', function() { it('should return a stack with the vertices ordered' + ' considering the dependencies', function() { - var graph = new Graph(); + const graph = new Graph(); graph.addVertex('shoes'); graph.addVertex('watch'); graph.addVertex('underwear'); @@ -35,8 +35,8 @@ describe('Topological Sort', function() { graph.addEdge('tie', 'jacket'); - var stack = topologicalSort(graph); - var a = []; + const stack = topologicalSort(graph); + const a = []; while (!stack.isEmpty()) a.push(stack.pop()); assert.deepEqual(a, [ 'shirt', 'socks', 'underwear', 'pants', 'shoes', diff --git a/src/test/algorithms/math/collatz_conjecture.js b/src/test/algorithms/math/collatz_conjecture.js index 753adcd..5c92c17 100644 --- a/src/test/algorithms/math/collatz_conjecture.js +++ b/src/test/algorithms/math/collatz_conjecture.js @@ -1,8 +1,8 @@ 'use strict'; -var math = require('../../..').Math; -var collatzConjecture = math.collatzConjecture; -var assert = require('assert'); +const math = require('../../..').Math; +const collatzConjecture = math.collatzConjecture; +const assert = require('assert'); describe('Collatz Conjecture', function() { it('should return odd numbers divided by two', function() { diff --git a/src/test/algorithms/math/extended_euclidean.js b/src/test/algorithms/math/extended_euclidean.js index f155ae8..66477b1 100644 --- a/src/test/algorithms/math/extended_euclidean.js +++ b/src/test/algorithms/math/extended_euclidean.js @@ -1,12 +1,12 @@ 'use strict'; -var math = require('../../..').Math; -var extEuclid = math.extendedEuclidean; -var assert = require('assert'); +const math = require('../../..').Math; +const extEuclid = math.extendedEuclidean; +const assert = require('assert'); describe('extEuclid', function() { it('should calculate the solve to Bézout\'s identity', function() { - var solve = extEuclid(1, 0); + let solve = extEuclid(1, 0); assert.equal(solve.x, 1); assert.equal(solve.y, 0); diff --git a/src/test/algorithms/math/fast_power.js b/src/test/algorithms/math/fast_power.js index 4344429..0092878 100644 --- a/src/test/algorithms/math/fast_power.js +++ b/src/test/algorithms/math/fast_power.js @@ -1,15 +1,15 @@ 'use strict'; -var math = require('../../..').Math; -var power = math.fastPower; -var assert = require('assert'); +const math = require('../../..').Math; +const power = math.fastPower; +const assert = require('assert'); -var assertApproximatelyEqual = function(a, b, eps) { +const assertApproximatelyEqual = function(a, b, eps) { eps = eps || 1e-12; assert(Math.abs(a - b) < eps); }; -var multiplyModulo = function(modulo) { +const multiplyModulo = function(modulo) { return function(a, b) { return (a * b) % modulo; }; @@ -25,8 +25,8 @@ var multiplyModulo = function(modulo) { * c | c | a | b | * --------------- */ -var abcMultiply = function(a, b) { - var table = { +const abcMultiply = function(a, b) { + const table = { a: {a: 'a', b: 'b', c: 'c'}, b: {a: 'b', b: 'c', c: 'a'}, c: {a: 'c', b: 'a', c: 'b'} diff --git a/src/test/algorithms/math/fibonacci.js b/src/test/algorithms/math/fibonacci.js index 129a005..a00b2d5 100644 --- a/src/test/algorithms/math/fibonacci.js +++ b/src/test/algorithms/math/fibonacci.js @@ -1,10 +1,10 @@ 'use strict'; -var math = require('../../..').Math; -var fib = math.fibonacci; -var assert = require('assert'); +const math = require('../../..').Math; +const fib = math.fibonacci; +const assert = require('assert'); -var testFibonacciSequence = function(fib) { +const testFibonacciSequence = function(fib) { assert.equal(0, fib(0)); assert.equal(1, fib(1)); assert.equal(1, fib(2)); diff --git a/src/test/algorithms/math/find_divisors.js b/src/test/algorithms/math/find_divisors.js index 08aa010..4a430ec 100644 --- a/src/test/algorithms/math/find_divisors.js +++ b/src/test/algorithms/math/find_divisors.js @@ -1,14 +1,14 @@ 'use strict'; -var math = require('../../..').Math; -var findDivisors = math.findDivisors; -var assert = require('assert'); +const math = require('../../..').Math; +const findDivisors = math.findDivisors; +const assert = require('assert'); /** * Deep equal for arrays */ function testArrayEqual(a, b) { - var arrayEqual = true; + let arrayEqual = true; a.sort(); b.sort(); a.forEach(function(elem, index) { @@ -19,7 +19,7 @@ function testArrayEqual(a, b) { return arrayEqual && a.length === b.length; } -var testFindDivisors = function(findDivisors) { +const testFindDivisors = function(findDivisors) { assert(testArrayEqual([], findDivisors(-2))); assert(testArrayEqual([], findDivisors(0))); assert(testArrayEqual([1], findDivisors(1))); diff --git a/src/test/algorithms/math/fisher_yates.js b/src/test/algorithms/math/fisher_yates.js index 03be860..f8d8d53 100644 --- a/src/test/algorithms/math/fisher_yates.js +++ b/src/test/algorithms/math/fisher_yates.js @@ -1,18 +1,18 @@ 'use strict'; -var math = require('../../..').Math; -var fisherYates = math.fisherYates; -var assert = require('assert'); +const math = require('../../..').Math; +const fisherYates = math.fisherYates; +const assert = require('assert'); describe('Fisher-Yates', function() { it('should shuffle the elements in the array in-place', function() { - var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; fisherYates(a); assert.notDeepEqual(a, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); }); describe('should be able to be used as Array.suffle', function() { - var a = [1, 2, 3, 4, 5]; + const a = [1, 2, 3, 4, 5]; assert.equal(a.shuffle, undefined); /* eslint-disable no-extend-native */ Array.prototype.shuffle = function() { diff --git a/src/test/algorithms/math/gcd.js b/src/test/algorithms/math/gcd.js index 5966e97..20e9285 100644 --- a/src/test/algorithms/math/gcd.js +++ b/src/test/algorithms/math/gcd.js @@ -1,8 +1,8 @@ 'use strict'; -var root = require('../../..'); -var gcd = root.Math.gcd; -var assert = require('assert'); +const root = require('../../..'); +const gcd = root.Math.gcd; +const assert = require('assert'); describe('GCD', function() { it('should calculate the correct GCD between two numbers', function() { @@ -20,7 +20,7 @@ describe('GCD', function() { it('should calculate the correct GCD between two numbers using ' + 'the binary method', function() { - var gcdb = gcd.binary; + const gcdb = gcd.binary; assert.equal(gcdb(1, 0), 1); assert.equal(gcdb(0, 1), 1); assert.equal(gcdb(0, 0), 0); diff --git a/src/test/algorithms/math/greatest_difference.js b/src/test/algorithms/math/greatest_difference.js index 1b66c6d..239e072 100644 --- a/src/test/algorithms/math/greatest_difference.js +++ b/src/test/algorithms/math/greatest_difference.js @@ -1,8 +1,8 @@ 'use strict'; -var assert = require('assert'); -var math = require('../../..').Math; -var greatestDifference = math.greatestDifference; +const assert = require('assert'); +const math = require('../../..').Math; +const greatestDifference = math.greatestDifference; describe('Greatest Difference', function() { it('should return 7 for [5, 8, 6, 1]', function() { diff --git a/src/test/algorithms/math/lcm.js b/src/test/algorithms/math/lcm.js index 2a3d002..72a3fa1 100644 --- a/src/test/algorithms/math/lcm.js +++ b/src/test/algorithms/math/lcm.js @@ -1,8 +1,8 @@ 'use strict'; -var root = require('../../..'); -var lcm = root.Math.lcm; -var assert = require('assert'); +const root = require('../../..'); +const lcm = root.Math.lcm; +const assert = require('assert'); describe('LCM', function() { it('should calculate the correct LCM between two numbers ' + @@ -25,7 +25,7 @@ describe('LCM', function() { it('should calculate the correct LCM between two numbers ' + 'using the binary method', function() { - var lcmb = lcm.binary; + const lcmb = lcm.binary; assert.equal(lcmb(2, 3), 6); assert.equal(lcmb(0, 1), 0); assert.equal(lcmb(4, 9), 36); diff --git a/src/test/algorithms/math/newton_sqrt.js b/src/test/algorithms/math/newton_sqrt.js index 00ee77c..6345236 100644 --- a/src/test/algorithms/math/newton_sqrt.js +++ b/src/test/algorithms/math/newton_sqrt.js @@ -1,8 +1,8 @@ 'use strict'; -var math = require('../../..').Math; -var newtonSqrt = math.newtonSqrt; -var assert = require('assert'); +const math = require('../../..').Math; +const newtonSqrt = math.newtonSqrt; +const assert = require('assert'); describe('Newton square root', function() { it('should calculate the exact root of square numbers', function() { @@ -21,10 +21,10 @@ describe('Newton square root', function() { it('should calculate an approximated root for every number', function() { - for (var i = 0; i < 1000; i++) { - var newton = newtonSqrt(i); - var nativeJS = Math.sqrt(i); - var difference = Math.abs(newton - nativeJS); + for (let i = 0; i < 1000; i++) { + const newton = newtonSqrt(i); + const nativeJS = Math.sqrt(i); + const difference = Math.abs(newton - nativeJS); assert(difference < 1e-6, 'Square root of ' + i + ' should be ' + nativeJS + ' but got ' + newton + ' instead'); diff --git a/src/test/algorithms/math/next_permutation.js b/src/test/algorithms/math/next_permutation.js index f3d7730..5cb9bf8 100644 --- a/src/test/algorithms/math/next_permutation.js +++ b/src/test/algorithms/math/next_permutation.js @@ -1,11 +1,11 @@ 'use strict'; -var math = require('../../..').Math; -var nextPermutation = math.nextPermutation; -var Comparator = require('../../../util/comparator'); -var assert = require('assert'); +const math = require('../../..').Math; +const nextPermutation = math.nextPermutation; +const Comparator = require('../../../util/comparator'); +const assert = require('assert'); -var range = function(begin, end) { +const range = function(begin, end) { if (end === undefined) { end = begin; begin = 0; @@ -18,15 +18,15 @@ var range = function(begin, end) { }); }; -var factorial = function(n) { +const factorial = function(n) { return range(1, n + 1).reduce(function(product, value) { return product * value; }, 1); }; -var permutations = function(start, compareFn) { - var permutations = []; - var perm = start.slice(); +const permutations = function(start, compareFn) { + const permutations = []; + const perm = start.slice(); do { permutations.push(perm.slice()); } while (nextPermutation(perm, compareFn)); @@ -45,8 +45,8 @@ describe('Next Permutation', function() { it('should generate all N! permutations if the elements are distinct', function() { [4, 5, 6].forEach(function(size) { - var count = 0; - var perm = range(size); + let count = 0; + const perm = range(size); do { count += 1; } while (nextPermutation(perm)); @@ -55,9 +55,9 @@ describe('Next Permutation', function() { }); it('should support custom compare functions', function() { - var reverseComparator = new Comparator(); + const reverseComparator = new Comparator(); reverseComparator.reverse(); - var reverseCompareFn = reverseComparator.compare; + const reverseCompareFn = reverseComparator.compare; assert.deepEqual(permutations([1, 2, 3]).reverse(), permutations([3, 2, 1], reverseCompareFn)); diff --git a/src/test/algorithms/math/power_set.js b/src/test/algorithms/math/power_set.js index 3ba2726..9e7845d 100644 --- a/src/test/algorithms/math/power_set.js +++ b/src/test/algorithms/math/power_set.js @@ -1,14 +1,14 @@ 'use strict'; -var math = require('../../..').Math; -var powerSet = math.powerSet; -var assert = require('assert'); +const math = require('../../..').Math; +const powerSet = math.powerSet; +const assert = require('assert'); /** * Deep equal for arrays */ function testArrayEqual(a, b) { - var arrayEqual = true; + let arrayEqual = true; a.forEach(function(elem, index) { if (a[index] !== b[index]) { arrayEqual = false; @@ -21,7 +21,7 @@ function testArrayEqual(a, b) { * Tests if one array is an element of another */ function testArrayInArray(a, b) { - var arrayInArray = false; + let arrayInArray = false; b.forEach(function(array) { if (testArrayEqual(a, array)) { arrayInArray = true; @@ -33,22 +33,22 @@ function testArrayInArray(a, b) { describe('Power set', function() { describe('#iterative()', function() { it('should return the right elements of power set', function() { - var zeroElementTest = powerSet([]); + const zeroElementTest = powerSet([]); assert(zeroElementTest.length === 0); - var oneElementTest = powerSet([0]); + const oneElementTest = powerSet([0]); assert(testArrayInArray([], oneElementTest)); assert(testArrayInArray([0], oneElementTest)); assert(oneElementTest.length === 2); - var twoElementTest = powerSet([0, 1]); + const twoElementTest = powerSet([0, 1]); assert(testArrayInArray([], twoElementTest)); assert(testArrayInArray([0], twoElementTest)); assert(testArrayInArray([1], twoElementTest)); assert(testArrayInArray([0, 1], twoElementTest)); assert(twoElementTest.length === 4); - var threeElementTest = powerSet([0, 1, 2]); + const threeElementTest = powerSet([0, 1, 2]); assert(testArrayInArray([], threeElementTest)); assert(testArrayInArray([0], threeElementTest)); assert(testArrayInArray([1], threeElementTest)); @@ -60,7 +60,7 @@ describe('Power set', function() { assert(testArrayInArray([0, 1], threeElementTest)); assert(threeElementTest.length === 8); - var fourElementTest = powerSet([0, 1, 2, 3]); + const fourElementTest = powerSet([0, 1, 2, 3]); assert(testArrayInArray([], fourElementTest)); assert(testArrayInArray([0], fourElementTest)); assert(testArrayInArray([1], fourElementTest)); @@ -83,22 +83,22 @@ describe('Power set', function() { describe('#recursive()', function() { it('should return the right elements of power set', function() { - var zeroElementTest = powerSet.recursive([]); + const zeroElementTest = powerSet.recursive([]); assert(zeroElementTest.length === 0); - var oneElementTest = powerSet.recursive([0]); + const oneElementTest = powerSet.recursive([0]); assert(testArrayInArray([], oneElementTest)); assert(testArrayInArray([0], oneElementTest)); assert(oneElementTest.length === 2); - var twoElementTest = powerSet.recursive([0, 1]); + const twoElementTest = powerSet.recursive([0, 1]); assert(testArrayInArray([], twoElementTest)); assert(testArrayInArray([0], twoElementTest)); assert(testArrayInArray([1], twoElementTest)); assert(testArrayInArray([0, 1], twoElementTest)); assert(twoElementTest.length === 4); - var threeElementTest = powerSet.recursive([0, 1, 2]); + const threeElementTest = powerSet.recursive([0, 1, 2]); assert(testArrayInArray([], threeElementTest)); assert(testArrayInArray([0], threeElementTest)); assert(testArrayInArray([1], threeElementTest)); @@ -110,7 +110,7 @@ describe('Power set', function() { assert(testArrayInArray([0, 1], threeElementTest)); assert(threeElementTest.length === 8); - var fourElementTest = powerSet.recursive([0, 1, 2, 3]); + const fourElementTest = powerSet.recursive([0, 1, 2, 3]); assert(testArrayInArray([], fourElementTest)); assert(testArrayInArray([0], fourElementTest)); assert(testArrayInArray([1], fourElementTest)); diff --git a/src/test/algorithms/math/primality_tests.js b/src/test/algorithms/math/primality_tests.js index ead3e4f..04e969b 100644 --- a/src/test/algorithms/math/primality_tests.js +++ b/src/test/algorithms/math/primality_tests.js @@ -1,10 +1,10 @@ 'use strict'; -var root = require('../../..'); -var primalityTests = root.Math.primalityTests; -var assert = require('assert'); +const root = require('../../..'); +const primalityTests = root.Math.primalityTests; +const assert = require('assert'); -var validate = function(primalityTest) { +const validate = function(primalityTest) { assert.equal(primalityTest(1), false); assert.equal(primalityTest(2), true); assert.equal(primalityTest(3), true); diff --git a/src/test/algorithms/math/reservoir_sampling.js b/src/test/algorithms/math/reservoir_sampling.js index 3933cb6..835f8df 100644 --- a/src/test/algorithms/math/reservoir_sampling.js +++ b/src/test/algorithms/math/reservoir_sampling.js @@ -1,16 +1,16 @@ 'use strict'; -var math = require('../../..').Math; -var reservoirSampling = math.reservoirSampling; -var assert = require('assert'); +const math = require('../../..').Math; +const reservoirSampling = math.reservoirSampling; +const assert = require('assert'); describe('Reservoir Sampling', function() { - var array = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + const array = [1, 2, 3, 4, 5, 6, 7, 8, 9]; it('should sample K distinct values from the array', function() { - var sample = reservoirSampling(array, 5); + const sample = reservoirSampling(array, 5); assert.equal(sample.length, 5); - var seen = {}; + const seen = {}; array.forEach(function(value) { assert(!seen[value]); assert(array.indexOf(value) >= 0); @@ -21,7 +21,7 @@ describe('Reservoir Sampling', function() { it('should work in corner cases', function() { assert.deepEqual(reservoirSampling(array, 0), []); assert.deepEqual(reservoirSampling([], 0), []); - var fullSample = reservoirSampling(array, array.length); + const fullSample = reservoirSampling(array, array.length); assert.deepEqual(fullSample.sort(), array); }); diff --git a/src/test/algorithms/math/shannon_entropy.js b/src/test/algorithms/math/shannon_entropy.js index 05944f1..4fcd7e3 100644 --- a/src/test/algorithms/math/shannon_entropy.js +++ b/src/test/algorithms/math/shannon_entropy.js @@ -1,7 +1,7 @@ 'use strict'; -var shannonEntropy = require('../../../').Math.shannonEntropy; -var assert = require('assert'); +const shannonEntropy = require('../../../').Math.shannonEntropy; +const assert = require('assert'); describe('Shannon Entropy', function() { it('calculates shannon entropy', function() { diff --git a/src/test/algorithms/searching/bfs.js b/src/test/algorithms/searching/bfs.js index 9d44e6e..0951eff 100644 --- a/src/test/algorithms/searching/bfs.js +++ b/src/test/algorithms/searching/bfs.js @@ -1,12 +1,12 @@ 'use strict'; -var root = require('../../..'); -var BST = root.DataStructures.BST; -var bfs = root.Search.bfs; -var assert = require('assert'); +const root = require('../../..'); +const BST = root.DataStructures.BST; +const bfs = root.Search.bfs; +const assert = require('assert'); describe('Breadth First Search', function() { - var bst = new BST(); + const bst = new BST(); /** * 4 * 2 8 @@ -24,12 +24,12 @@ describe('Breadth First Search', function() { bst.insert(100); bst.insert(2.5); - var callbackGenerator = function(a) { + const callbackGenerator = function(a) { return n => a.push(n); }; it('should return the items by level', function() { - var a = []; + const a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 10, 0, 2.5, 100]); }); diff --git a/src/test/algorithms/searching/binarysearch.js b/src/test/algorithms/searching/binarysearch.js index 8364ead..dc693b3 100644 --- a/src/test/algorithms/searching/binarysearch.js +++ b/src/test/algorithms/searching/binarysearch.js @@ -1,7 +1,7 @@ 'use strict'; -var binarySearch = require('../../..').Search.binarySearch; -var assert = require('assert'); +const binarySearch = require('../../..').Search.binarySearch; +const assert = require('assert'); describe('Binary Search', function() { it('should find elements in the sorted array', function() { diff --git a/src/test/algorithms/searching/dfs.js b/src/test/algorithms/searching/dfs.js index a180f33..b18b3bd 100644 --- a/src/test/algorithms/searching/dfs.js +++ b/src/test/algorithms/searching/dfs.js @@ -1,12 +1,12 @@ 'use strict'; -var root = require('../../..'); -var BST = root.DataStructures.BST; -var dfs = root.Search.dfs; -var assert = require('assert'); +const root = require('../../..'); +const BST = root.DataStructures.BST; +const dfs = root.Search.dfs; +const assert = require('assert'); describe('Depth First Search', function() { - var bst = new BST(); + const bst = new BST(); bst.insert(4); bst.insert(8); bst.insert(10); @@ -17,26 +17,26 @@ describe('Depth First Search', function() { bst.insert(5); bst.insert(100); - var callbackGenerator = function(a) { + const callbackGenerator = function(a) { return n => a.push(n); }; it('should return the items sorted when retrieving in order', function() { - var a = []; + const a = []; dfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, [0, 1, 2, 3, 4, 5, 8, 10, 100]); }); it('should return parents before children when retrieving pre-order', function() { - var a = []; + const a = []; dfs.preOrder(bst.root, callbackGenerator(a)); assert.deepEqual(a, [4, 2, 1, 0, 3, 8, 5, 10, 100]); }); it('should return children before parents when retrieving post-order', function() { - var a = []; + const a = []; dfs.postOrder(bst.root, callbackGenerator(a)); assert.deepEqual(a, [0, 1, 3, 2, 5, 100, 10, 8, 4]); }); diff --git a/src/test/algorithms/searching/ternary_search.js b/src/test/algorithms/searching/ternary_search.js index 61fae62..2195d38 100644 --- a/src/test/algorithms/searching/ternary_search.js +++ b/src/test/algorithms/searching/ternary_search.js @@ -1,18 +1,18 @@ 'use strict'; -var ternarySearch = require('../../..').Search.ternarySearch; -var assert = require('assert'); -var eps = 1e-6; +const ternarySearch = require('../../..').Search.ternarySearch; +const assert = require('assert'); +const eps = 1e-6; -var fn1 = function(x) { +const fn1 = function(x) { return -Math.pow(x - 2, 2) + 4; }; -var fn2 = function(x) { +const fn2 = function(x) { return -2 * Math.cos(x); }; -var closeEnough = function(a, b, precision) { +const closeEnough = function(a, b, precision) { return Math.abs(a - b) < precision; }; diff --git a/src/test/algorithms/sorting/bubble_sort.js b/src/test/algorithms/sorting/bubble_sort.js index ecc75e9..8a397e0 100644 --- a/src/test/algorithms/sorting/bubble_sort.js +++ b/src/test/algorithms/sorting/bubble_sort.js @@ -1,7 +1,7 @@ 'use strict'; -var bubbleSort = require('../../..').Sorting.bubbleSort; -var sortingTestsHelper = require('./sorting_tests_helper'); +const bubbleSort = require('../../..').Sorting.bubbleSort; +const sortingTestsHelper = require('./sorting_tests_helper'); describe('Bubble Sort', function() { it('should sort the given array', function() { diff --git a/src/test/algorithms/sorting/counting_sort.js b/src/test/algorithms/sorting/counting_sort.js index a8da343..471b7df 100644 --- a/src/test/algorithms/sorting/counting_sort.js +++ b/src/test/algorithms/sorting/counting_sort.js @@ -1,24 +1,24 @@ 'use strict'; -var countingSort = require('../../..').Sorting.countingSort; -var assert = require('assert'); +const countingSort = require('../../..').Sorting.countingSort; +const assert = require('assert'); -var firstObject = { +const firstObject = { someProperty: 'The', key: 12 }; -var secondObject = { +const secondObject = { someProperty: 'chosen', key: 66 }; -var thirdObject = { +const thirdObject = { someProperty: 'one!', key: 43 }; -var array = [ +let array = [ thirdObject, firstObject, secondObject, diff --git a/src/test/algorithms/sorting/heap_sort.js b/src/test/algorithms/sorting/heap_sort.js index c0db1db..8358b41 100644 --- a/src/test/algorithms/sorting/heap_sort.js +++ b/src/test/algorithms/sorting/heap_sort.js @@ -1,7 +1,7 @@ 'use strict'; -var heapSort = require('../../..').Sorting.heapSort; -var sortingTestsHelper = require('./sorting_tests_helper'); +const heapSort = require('../../..').Sorting.heapSort; +const sortingTestsHelper = require('./sorting_tests_helper'); describe('Heap Sort', function() { it('should sort the given array', function() { diff --git a/src/test/algorithms/sorting/insertion_sort.js b/src/test/algorithms/sorting/insertion_sort.js index 12b4cae..208993a 100644 --- a/src/test/algorithms/sorting/insertion_sort.js +++ b/src/test/algorithms/sorting/insertion_sort.js @@ -1,7 +1,7 @@ 'use strict'; -var insertionSort = require('../../..').Sorting.insertionSort; -var sortingTestsHelper = require('./sorting_tests_helper'); +const insertionSort = require('../../..').Sorting.insertionSort; +const sortingTestsHelper = require('./sorting_tests_helper'); describe('Insertion Sort', function() { it('should sort the given array', function() { diff --git a/src/test/algorithms/sorting/merge_sort.js b/src/test/algorithms/sorting/merge_sort.js index 4c193c3..2671fe1 100644 --- a/src/test/algorithms/sorting/merge_sort.js +++ b/src/test/algorithms/sorting/merge_sort.js @@ -1,7 +1,7 @@ 'use strict'; -var mergeSort = require('../../..').Sorting.mergeSort; -var sortingTestsHelper = require('./sorting_tests_helper'); +const mergeSort = require('../../..').Sorting.mergeSort; +const sortingTestsHelper = require('./sorting_tests_helper'); describe('Merge Sort', function() { it('should sort the given array', function() { diff --git a/src/test/algorithms/sorting/quicksort.js b/src/test/algorithms/sorting/quicksort.js index c78860f..3d89b64 100644 --- a/src/test/algorithms/sorting/quicksort.js +++ b/src/test/algorithms/sorting/quicksort.js @@ -1,7 +1,7 @@ 'use strict'; -var quicksort = require('../../..').Sorting.quicksort; -var sortingTestsHelper = require('./sorting_tests_helper'); +const quicksort = require('../../..').Sorting.quicksort; +const sortingTestsHelper = require('./sorting_tests_helper'); describe('QuickSort', function() { it('should sort the given array', function() { diff --git a/src/test/algorithms/sorting/radix_sort.js b/src/test/algorithms/sorting/radix_sort.js index 6e3db08..78b2ab2 100644 --- a/src/test/algorithms/sorting/radix_sort.js +++ b/src/test/algorithms/sorting/radix_sort.js @@ -1,24 +1,24 @@ 'use strict'; -var radixSort = require('../../..').Sorting.radixSort; -var assert = require('assert'); +const radixSort = require('../../..').Sorting.radixSort; +const assert = require('assert'); -var firstObject = { +const firstObject = { someProperty: 'The', key: 88541234132 }; -var secondObject = { +const secondObject = { someProperty: 'winter', key: 90071992540992 }; -var thirdObject = { +const thirdObject = { someProperty: 'is', key: 0 }; -var fourthObject = { +const fourthObject = { someProperty: 'coming', key: 65234567, anotherProperty: '!' @@ -26,7 +26,7 @@ var fourthObject = { describe('Radix Sort', function() { it('should sort the given array', function() { - var sorted = radixSort([ + const sorted = radixSort([ thirdObject, fourthObject, firstObject, diff --git a/src/test/algorithms/sorting/selection_sort.js b/src/test/algorithms/sorting/selection_sort.js index abe8e0a..a1b85c0 100644 --- a/src/test/algorithms/sorting/selection_sort.js +++ b/src/test/algorithms/sorting/selection_sort.js @@ -1,7 +1,7 @@ 'use strict'; -var selectionSort = require('../../..').Sorting.selectionSort; -var sortingTestsHelper = require('./sorting_tests_helper'); +const selectionSort = require('../../..').Sorting.selectionSort; +const sortingTestsHelper = require('./sorting_tests_helper'); describe('Selection Sort', function() { it('should sort the given array', function() { diff --git a/src/test/algorithms/sorting/shell_sort.js b/src/test/algorithms/sorting/shell_sort.js index 07f9524..64098d9 100644 --- a/src/test/algorithms/sorting/shell_sort.js +++ b/src/test/algorithms/sorting/shell_sort.js @@ -1,7 +1,7 @@ 'use strict'; -var shellSort = require('../../..').Sorting.shellSort; -var sortingTestsHelper = require('./sorting_tests_helper.js'); +const shellSort = require('../../..').Sorting.shellSort; +const sortingTestsHelper = require('./sorting_tests_helper.js'); describe('ShellSort', function() { it('should sort the given array', function() { diff --git a/src/test/algorithms/sorting/short_bubble_sort.js b/src/test/algorithms/sorting/short_bubble_sort.js index afe6a21..552e301 100644 --- a/src/test/algorithms/sorting/short_bubble_sort.js +++ b/src/test/algorithms/sorting/short_bubble_sort.js @@ -1,7 +1,7 @@ 'use strict'; -var shortBubbleSort = require('../../..').Sorting.shortBubbleSort; -var sortingTestsHelper = require('./sorting_tests_helper'); +const shortBubbleSort = require('../../..').Sorting.shortBubbleSort; +const sortingTestsHelper = require('./sorting_tests_helper'); describe('Short Bubble Sort', function() { it('should sort the given array', function() { diff --git a/src/test/algorithms/sorting/sorting_tests_helper.js b/src/test/algorithms/sorting/sorting_tests_helper.js index 5ca8179..32e1efb 100644 --- a/src/test/algorithms/sorting/sorting_tests_helper.js +++ b/src/test/algorithms/sorting/sorting_tests_helper.js @@ -1,6 +1,6 @@ 'use strict'; -var assert = require('assert'); +const assert = require('assert'); module.exports = { testSort: function(sortFn) { @@ -16,7 +16,7 @@ module.exports = { }, testSortWithComparisonFn: function(sortFn) { - var compare = function(a, b) { + const compare = function(a, b) { if (a.length === b.length) return 0; return a.length < b.length ? -1 : 1; }; @@ -29,7 +29,7 @@ module.exports = { assert.deepEqual(sortFn(['apple', 'banana', 'car', 'z'], compare), ['z', 'car', 'apple', 'banana']); - var reverseSort = function(a, b) { + const reverseSort = function(a, b) { if (a === b) return 0; return a < b ? 1 : -1; }; diff --git a/src/test/algorithms/string/hamming.js b/src/test/algorithms/string/hamming.js index 4870fbf..56ba3b6 100644 --- a/src/test/algorithms/string/hamming.js +++ b/src/test/algorithms/string/hamming.js @@ -1,7 +1,7 @@ 'use strict'; -var hamming = require('../../..').String.hamming; -var assert = require('assert'); +const hamming = require('../../..').String.hamming; +const assert = require('assert'); describe('Hamming distance', function() { it('should raise an error if the inputs are not equal lengths', function() { @@ -11,7 +11,7 @@ describe('Hamming distance', function() { }); it('should return the correct the correct distances', function() { - var inputs = [ + const inputs = [ {a: 'karolin', b: 'kathrin', expected: 3}, {a: 'karolin', b: 'kerstin', expected: 3}, {a: '1011101', b: '1001001', expected: 2}, diff --git a/src/test/algorithms/string/huffman.js b/src/test/algorithms/string/huffman.js index 2f53d75..4a801ca 100644 --- a/src/test/algorithms/string/huffman.js +++ b/src/test/algorithms/string/huffman.js @@ -1,19 +1,19 @@ 'use strict'; -var huffman = require('../../..').String.huffman; -var assert = require('assert'); +const huffman = require('../../..').String.huffman; +const assert = require('assert'); describe('Huffman', function() { - var messages = ['', 'a', 'b', 'hello', 'test', 'aaaabbbccddef', + const messages = ['', 'a', 'b', 'hello', 'test', 'aaaabbbccddef', 'The seething sea ceaseth and thus' + ' the seething sea sufficeth us.', 'Shep Schwab shopped at Scott\'s Schnapps shop;' + '\nOne shot of Scott\'s Schnapps stopped Schwab\'s watch.']; - for (var randomTestIndex = 0; randomTestIndex < 15; ++randomTestIndex) { - var length = Math.floor(Math.random() * 100 + 1); - var characters = []; - for (var charIndex = 0; charIndex < length; ++charIndex) { - var charCode = Math.floor(Math.random() * 10 + 'a'.charCodeAt()); + for (let randomTestIndex = 0; randomTestIndex < 15; ++randomTestIndex) { + const length = Math.floor(Math.random() * 100 + 1); + const characters = []; + for (let charIndex = 0; charIndex < length; ++charIndex) { + const charCode = Math.floor(Math.random() * 10 + 'a'.charCodeAt()); characters.push(String.fromCharCode(charCode)); } messages.push(characters.join('')); @@ -21,18 +21,18 @@ describe('Huffman', function() { it('should decode previously encoded messages correctly', function() { messages.forEach(function(message) { - var encoded = huffman.encode(message); - var decoded = huffman.decode(encoded.encoding, encoded.value); + const encoded = huffman.encode(message); + const decoded = huffman.decode(encoded.encoding, encoded.value); assert.equal(message, decoded); - var encodedCompressed = huffman.encode(message, true); - var decodedCompressed = huffman.decode(encodedCompressed.encoding, + const encodedCompressed = huffman.encode(message, true); + const decodedCompressed = huffman.decode(encodedCompressed.encoding, encodedCompressed.value); assert.equal(message, decodedCompressed); }); }); it('should raise an error if it fails to decode', function() { - var badArgs = [[{}, '0'], + const badArgs = [[{}, '0'], [{}, [0]], [{a: '0', b: '10', c: '11'}, '001']]; badArgs.forEach(function(args) { @@ -47,7 +47,7 @@ describe('Huffman', function() { assert.deepEqual(huffman.encode('a'), {encoding: {a: '0'}, value: '0'}); assert.deepEqual(huffman.encode('aaaaa'), {encoding: {a: '0'}, value: '00000'}); - var result = huffman.encode('aabc'); + let result = huffman.encode('aabc'); assert.equal(result.encoding.a.length, 1); assert.equal(result.encoding.b.length, 2); assert.equal(result.encoding.c.length, 2); @@ -60,19 +60,19 @@ describe('Huffman', function() { it('should satisfy the entropy condition (H <= cost <= H+1)', function() { messages.forEach(function(message) { - var frequencies = message.split('').reduce(function(acc, char) { + const frequencies = message.split('').reduce(function(acc, char) { acc[char] = (acc[char] || 0) + 1; return acc; }, {}); Object.keys(frequencies).forEach(function(char) { frequencies[char] /= message.length; }); - var entropy = Object.keys(frequencies).reduce(function(partial, char) { - var freq = frequencies[char]; + const entropy = Object.keys(frequencies).reduce(function(partial, char) { + const freq = frequencies[char]; return partial - freq * Math.log(freq); }, 0) / Math.log(2); - var encoding = huffman.encode(message).encoding; - var cost = Object.keys(encoding).reduce(function(partial, char) { + const encoding = huffman.encode(message).encoding; + const cost = Object.keys(encoding).reduce(function(partial, char) { return partial + frequencies[char] * encoding[char].length; }, 0); assert(entropy <= cost); diff --git a/src/test/algorithms/string/knuth_morris_pratt.js b/src/test/algorithms/string/knuth_morris_pratt.js index aba77d0..cf98577 100644 --- a/src/test/algorithms/string/knuth_morris_pratt.js +++ b/src/test/algorithms/string/knuth_morris_pratt.js @@ -1,12 +1,12 @@ 'use strict'; -var knuthMorrisPratt = require('../../..').String.knuthMorrisPratt; -var assert = require('assert'); +const knuthMorrisPratt = require('../../..').String.knuthMorrisPratt; +const assert = require('assert'); describe('Knuth-Morris-Pratt', function() { it('should verify if a pattern is contained in some text (or array)', function() { - var text = 'A string matching algorithm wants to find the starting' + + const text = 'A string matching algorithm wants to find the starting' + 'index m in string S[] that matches the search word W[].The most' + ' straightforward algorithm is to look for a character match at ' + 'successive values of the index m, the position in the string be' + @@ -22,7 +22,7 @@ describe('Knuth-Morris-Pratt', function() { 'match in W at position m then a match is found at that position' + ' in the search string. (Wikipedia, 2014): https://en.wikipedia.' + 'org/wiki/Knuth-Morris-Pratt_algorithm'; - var pattern = 'https://en.wikipedia.org/wiki/Knuth-Morris-Pratt_al' + + let pattern = 'https://en.wikipedia.org/wiki/Knuth-Morris-Pratt_al' + 'gorithm'; assert.equal(knuthMorrisPratt(text, pattern), 915); @@ -31,8 +31,8 @@ describe('Knuth-Morris-Pratt', function() { assert.equal(knuthMorrisPratt(text, pattern), text.length); - var arrayText = [3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 4]; - var arrayPattern = [8, 9, 8]; + const arrayText = [3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 4]; + let arrayPattern = [8, 9, 8]; assert.equal(knuthMorrisPratt(arrayText, arrayPattern), 5); diff --git a/src/test/algorithms/string/levenshtein.js b/src/test/algorithms/string/levenshtein.js index 17ddac3..cb9fd16 100644 --- a/src/test/algorithms/string/levenshtein.js +++ b/src/test/algorithms/string/levenshtein.js @@ -1,7 +1,7 @@ 'use strict'; -var levenshtein = require('../../..').String.levenshtein; -var assert = require('assert'); +const levenshtein = require('../../..').String.levenshtein; +const assert = require('assert'); describe('Levenshtein', function() { it('should calculate the minimal edit distance between two words', diff --git a/src/test/algorithms/string/longest_common_subsequence.js b/src/test/algorithms/string/longest_common_subsequence.js index 1a2b3eb..78a9bcc 100644 --- a/src/test/algorithms/string/longest_common_subsequence.js +++ b/src/test/algorithms/string/longest_common_subsequence.js @@ -1,9 +1,9 @@ 'use strict'; -var directory = '../../../algorithms/string/'; -var filename = 'longest_common_subsequence'; -var longestCommonSubsequence = require(directory + filename); -var assert = require('assert'); +const directory = '../../../algorithms/string/'; +const filename = 'longest_common_subsequence'; +const longestCommonSubsequence = require(directory + filename); +const assert = require('assert'); describe('Longest common subsequence', function() { it('should return the longest common subsequence of ' + diff --git a/src/test/algorithms/string/longest_common_substring.js b/src/test/algorithms/string/longest_common_substring.js index 4d256fb..9844dca 100644 --- a/src/test/algorithms/string/longest_common_substring.js +++ b/src/test/algorithms/string/longest_common_substring.js @@ -1,9 +1,9 @@ 'use strict'; -var directory = '../../../algorithms/string/'; -var filename = 'longest_common_substring'; -var longestCommonSubstring = require(directory + filename); -var assert = require('assert'); +const directory = '../../../algorithms/string/'; +const filename = 'longest_common_substring'; +const longestCommonSubstring = require(directory + filename); +const assert = require('assert'); describe('Longest common substring', function() { it('should return the longest common substring of two strings', function() { diff --git a/src/test/algorithms/string/rabin_karp.js b/src/test/algorithms/string/rabin_karp.js index 4abec80..3228203 100644 --- a/src/test/algorithms/string/rabin_karp.js +++ b/src/test/algorithms/string/rabin_karp.js @@ -1,9 +1,9 @@ 'use strict'; -var rabinKarp = require('../../..').String.rabinKarp; -var assert = require('assert'); +const rabinKarp = require('../../..').String.rabinKarp; +const assert = require('assert'); -var rabinKarpEqualsToIndexOf = function(a, b) { +const rabinKarpEqualsToIndexOf = function(a, b) { assert.equal(rabinKarp(a, b), a.indexOf(b)); }; diff --git a/src/test/data_structures/avl-tree.js b/src/test/data_structures/avl-tree.js index b951258..b6343e0 100644 --- a/src/test/data_structures/avl-tree.js +++ b/src/test/data_structures/avl-tree.js @@ -1,8 +1,8 @@ 'use strict'; -var root = require('../..'); -var AVLTree = root.DataStructures.AVLTree; -var assert = require('assert'); +const root = require('../..'); +const AVLTree = root.DataStructures.AVLTree; +const assert = require('assert'); describe('AVL Tree', function() { it('should start with null root', function() { @@ -10,7 +10,7 @@ describe('AVL Tree', function() { }); it('should insert and single rotate (leftRight) properly', function() { - var avlTree = new AVLTree(); + const avlTree = new AVLTree(); avlTree.insert(9); avlTree.insert(3); avlTree.insert(5); @@ -25,7 +25,7 @@ describe('AVL Tree', function() { }); it('should insert and single rotate (rightLeft) properly', function() { - var avlTree = new AVLTree(); + const avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(75); avlTree.insert(60); @@ -40,7 +40,7 @@ describe('AVL Tree', function() { }); it('should insert and double rotate (leftLeft) properly', function() { - var avlTree = new AVLTree(); + const avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(25); avlTree.insert(10); @@ -55,7 +55,7 @@ describe('AVL Tree', function() { }); it('should insert and double rotate (rightRight) properly', function() { - var avlTree = new AVLTree(); + const avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(75); avlTree.insert(100); @@ -70,7 +70,7 @@ describe('AVL Tree', function() { }); it('should insert multiple nodes and balance properly (1)', function() { - var avlTree = new AVLTree(); + const avlTree = new AVLTree(); avlTree.insert(30); avlTree.insert(15); avlTree.insert(60); @@ -91,7 +91,7 @@ describe('AVL Tree', function() { }); it('should remove nodes and balance properly (2)', function() { - var avlTree = new AVLTree(); + const avlTree = new AVLTree(); avlTree.insert(55); avlTree.insert(25); avlTree.insert(11); @@ -108,7 +108,7 @@ describe('AVL Tree', function() { }); it('should always keep the tree balanced', function() { - var avlTree = new AVLTree(); + const avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(100); @@ -197,7 +197,7 @@ describe('AVL Tree', function() { it('should return the parents before the children when ' + 'traversing in preorder', function() { - var avlTree = new AVLTree(); + const avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(100); @@ -215,9 +215,9 @@ describe('AVL Tree', function() { avlTree.insert(30); avlTree.insert(15); - var expectedPreOrder = [50, 5, 2, 1, 4, 20, 7, 6, + const expectedPreOrder = [50, 5, 2, 1, 4, 20, 7, 6, 15, 30, 40, 100, 75, 80, 200]; - var preOrder = []; + const preOrder = []; avlTree.preOrder(avlTree.root, function(n) { preOrder.push(n.value); }); @@ -226,7 +226,7 @@ describe('AVL Tree', function() { it('should return the children before the parents when ' + 'traversing in postorder', function() { - var avlTree = new AVLTree(); + const avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(100); @@ -244,9 +244,9 @@ describe('AVL Tree', function() { avlTree.insert(30); avlTree.insert(15); - var expectedPostOrder = [1, 4, 2, 6, 15, 7, 40, 30, + const expectedPostOrder = [1, 4, 2, 6, 15, 7, 40, 30, 20, 5, 80, 75, 200, 100, 50]; - var postOrder = []; + const postOrder = []; avlTree.postOrder(avlTree.root, function(n) { postOrder.push(n.value); }); @@ -254,17 +254,17 @@ describe('AVL Tree', function() { }); it('should return the sorted elements when traversing in order', function() { - var avlTree = new AVLTree(); - var a = []; - var i; + const avlTree = new AVLTree(); + const a = []; + let i; for (i = 0; i < 1000; i++) { - var x = Math.round(Math.random() * 100000); + const x = Math.round(Math.random() * 100000); avlTree.insert(x); a.push(x); } a.sort((a, b) => a - b); - var b = []; + const b = []; avlTree.inOrder(avlTree.root, node => b.push(node.value)); assert.equal(a.length, b.length); for (i = 0; i < a.length; i++) { diff --git a/src/test/data_structures/bst.js b/src/test/data_structures/bst.js index af507b2..3b019ba 100644 --- a/src/test/data_structures/bst.js +++ b/src/test/data_structures/bst.js @@ -1,13 +1,13 @@ 'use strict'; -var root = require('../..'); -var BST = root.DataStructures.BST; -var bfs = root.Search.bfs; -var assert = require('assert'); +const root = require('../..'); +const BST = root.DataStructures.BST; +const bfs = root.Search.bfs; +const assert = require('assert'); describe('Binary Search Tree', function() { it('should insert elements respecting the BST restrictions', function() { - var bst = new BST(); + const bst = new BST(); bst.insert(4); bst.insert(8); bst.insert(10); @@ -20,7 +20,7 @@ describe('Binary Search Tree', function() { assert.equal(bst.size, 9); }); it('should check if an element exists (in O(lg n))', function() { - var bst = new BST(); + const bst = new BST(); bst.insert(4); bst.insert(8); bst.insert(10); @@ -50,7 +50,7 @@ describe('Binary Search Tree', function() { * 1 3 5 10 * 0 2.5 100 */ - var bst = new BST(); + const bst = new BST(); bst.insert(4); bst.insert(8); bst.insert(10); @@ -62,7 +62,7 @@ describe('Binary Search Tree', function() { bst.insert(100); bst.insert(2.5); - var callbackGenerator = function(a) { + const callbackGenerator = function(a) { return n => a.push(n); }; @@ -75,7 +75,7 @@ describe('Binary Search Tree', function() { * 1 3 5 10 * 2.5 100 */ - var a = []; + const a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 10, 2.5, 100]); }); @@ -89,7 +89,7 @@ describe('Binary Search Tree', function() { * 1 3 5 100 * 2.5 */ - var a = []; + const a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 100, 2.5]); }); @@ -109,7 +109,7 @@ describe('Binary Search Tree', function() { * 1 3 5 100 * */ - var a = []; + let a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, [4, 2.5, 8, 1, 3, 5, 100]); @@ -137,7 +137,7 @@ describe('Binary Search Tree', function() { }); it('should always return the right root and size', function() { - var bst = new BST(); + const bst = new BST(); bst.insert(5); assert.equal(bst.size, 1); bst.remove(5); @@ -157,7 +157,7 @@ describe('Binary Search Tree', function() { it('should throw an error when trying to remove an unexisting node', function() { - var bst = new BST(); + const bst = new BST(); assert.throws(() => bst.remove(0), Error); bst.insert(3); assert.throws(() => bst.remove(0), Error); @@ -165,14 +165,14 @@ describe('Binary Search Tree', function() { }); describe('Binary Search Tree with custom comparator', function() { - var strLenCompare = function(a, b) { + const strLenCompare = function(a, b) { if (a.length === b.length) return 0; return a.length < b.length ? -1 : 1; }; it( 'should insert elements respecting the BST restrictions', function() { - var bst = new BST(strLenCompare); + const bst = new BST(strLenCompare); bst.insert('banana'); bst.insert('apple'); bst.insert('pineapple'); @@ -181,7 +181,7 @@ describe('Binary Search Tree with custom comparator', function() { }); it('should check if an element exists (in O(lg n))', function() { - var bst = new BST(strLenCompare); + const bst = new BST(strLenCompare); bst.insert('banana'); bst.insert('apple'); bst.insert('pineapple'); @@ -203,19 +203,19 @@ describe('Binary Search Tree with custom comparator', function() { * 'pear' 'watermelon' * */ - var bst = new BST(strLenCompare); + const bst = new BST(strLenCompare); bst.insert('banana'); bst.insert('apple'); bst.insert('pear'); bst.insert('pineapple'); bst.insert('watermelon'); - var callbackGenerator = function(a) { + const callbackGenerator = function(a) { return n => a.push(n); }; it('should insert the items according to the comparator', function() { - var a = []; + const a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear', 'watermelon']); }); @@ -228,7 +228,7 @@ describe('Binary Search Tree with custom comparator', function() { * 'apple' 'pineapple' * 'pear' */ - var a = []; + const a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear']); }); @@ -240,7 +240,7 @@ describe('Binary Search Tree with custom comparator', function() { * 'banana' * 'pear' 'pineapple' */ - var a = []; + const a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, ['banana', 'pear', 'pineapple']); }); @@ -252,7 +252,7 @@ describe('Binary Search Tree with custom comparator', function() { * 'pineapple' * 'pear' */ - var a = []; + const a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, ['pineapple', 'pear']); }); diff --git a/src/test/data_structures/disjoint_set_forest.js b/src/test/data_structures/disjoint_set_forest.js index d14b235..ce41f3f 100644 --- a/src/test/data_structures/disjoint_set_forest.js +++ b/src/test/data_structures/disjoint_set_forest.js @@ -1,12 +1,12 @@ 'use strict'; -var DisjointSetForest = require('../..').DataStructures.DisjointSetForest; -var assert = require('assert'); +const DisjointSetForest = require('../..').DataStructures.DisjointSetForest; +const assert = require('assert'); describe('Disjoint Set Forest', function() { it('should decide if two elements belong to the same subset or not', function() { - var forest = new DisjointSetForest(); + const forest = new DisjointSetForest(); assert(!forest.sameSubset(1, 2)); forest.merge(1, 2); assert(forest.sameSubset(1, 2)); @@ -18,8 +18,8 @@ describe('Disjoint Set Forest', function() { }); it('should maintain subset sizes', function() { - var forest = new DisjointSetForest(); - var assertSizesCorrect = function(elements, size) { + const forest = new DisjointSetForest(); + const assertSizesCorrect = function(elements, size) { elements.forEach(function(element) { assert.equal(forest.size(element), size); }); @@ -38,9 +38,9 @@ describe('Disjoint Set Forest', function() { }); it('should point all elements to the same root', function() { - var forest = new DisjointSetForest(); - var assertSameRoot = function(element) { - var root = forest.root(element); + const forest = new DisjointSetForest(); + const assertSameRoot = function(element) { + const root = forest.root(element); [].slice.call(arguments, 1).forEach(function(element) { assert.equal(forest.root(element), root); }); @@ -56,8 +56,8 @@ describe('Disjoint Set Forest', function() { }); it('should not choose the root element outside the subset', function() { - var forest = new DisjointSetForest(); - var assertInside = function(value, set) { + const forest = new DisjointSetForest(); + const assertInside = function(value, set) { return set.some(function(element) { return element === value; }); diff --git a/src/test/data_structures/fenwick_tree.js b/src/test/data_structures/fenwick_tree.js index b0fe673..2db984b 100644 --- a/src/test/data_structures/fenwick_tree.js +++ b/src/test/data_structures/fenwick_tree.js @@ -1,11 +1,11 @@ 'use strict'; -var FenwickTree = require('../..').DataStructures.FenwickTree; -var assert = require('assert'); +const FenwickTree = require('../..').DataStructures.FenwickTree; +const assert = require('assert'); describe('FenwickTree', function() { it('should allow prefix queries', function() { - var tree = new FenwickTree(10); + const tree = new FenwickTree(10); tree.adjust(5, 42); tree.adjust(7, 43); tree.adjust(9, 44); @@ -24,7 +24,7 @@ describe('FenwickTree', function() { }); it('should allow range queries', function() { - var tree = new FenwickTree(10); + const tree = new FenwickTree(10); tree.adjust(5, 42); tree.adjust(7, 43); tree.adjust(9, 44); diff --git a/src/test/data_structures/graph.js b/src/test/data_structures/graph.js index 1ee4408..aa7c177 100644 --- a/src/test/data_structures/graph.js +++ b/src/test/data_structures/graph.js @@ -1,11 +1,11 @@ 'use strict'; -var Graph = require('../..').DataStructures.Graph; -var assert = require('assert'); +const Graph = require('../..').DataStructures.Graph; +const assert = require('assert'); describe('Graph - Adjacency list', function() { it('should be directed by default', function() { - var g = new Graph(); + let g = new Graph(); assert(g.directed); g = new Graph(false); @@ -16,7 +16,7 @@ describe('Graph - Adjacency list', function() { }); it('should default weight 1 for edges', function() { - var g = new Graph(); + const g = new Graph(); g.addVertex('a'); g.addVertex('b'); g.addEdge('a', 'b'); @@ -25,7 +25,7 @@ describe('Graph - Adjacency list', function() { it('should create the vertex if an edge is inserted and vertex doesnt exist', function() { - var g = new Graph(); + const g = new Graph(); g.addEdge('a', 'b'); assert.equal(g.vertices.size, 2); assert(g.vertices.contains('a')); @@ -33,7 +33,7 @@ describe('Graph - Adjacency list', function() { }); it('should sum multiple edges between the same vertices', function() { - var g = new Graph(); + const g = new Graph(); g.addEdge('a', 'b', 10); assert.equal(g.edge('a', 'b'), 10); g.addEdge('a', 'b', 4); @@ -41,7 +41,7 @@ describe('Graph - Adjacency list', function() { }); it('should have edges in both directions if undirected', function() { - var g = new Graph(false); + const g = new Graph(false); g.addVertex('a'); g.addVertex('b'); g.addVertex('c'); @@ -64,7 +64,7 @@ describe('Graph - Adjacency list', function() { }); it('should respect direction of the edges in directed graphs', function() { - var g = new Graph(); + const g = new Graph(); g.addVertex('a'); g.addVertex('b'); g.addVertex('c'); @@ -88,7 +88,7 @@ describe('Graph - Adjacency list', function() { it('should have reversed edges with same weight for a reverse directed graph', function() { - var g = new Graph(); + const g = new Graph(); g.addVertex('a'); g.addVertex('b'); g.addVertex('c'); @@ -97,7 +97,7 @@ describe('Graph - Adjacency list', function() { g.addEdge('a', 'c', 5); g.addEdge('c', 'd', 2); - var r = g.reverse(); + const r = g.reverse(); assert(r.directed); assert.equal(r.edge('a', 'b'), undefined); assert.equal(r.edge('b', 'a'), 10); @@ -113,7 +113,7 @@ describe('Graph - Adjacency list', function() { }); it('should have a list of vertices', function() { - var g = new Graph(); + const g = new Graph(); assert.equal(g.vertices.size, 0); g.addVertex('a'); g.addVertex('b'); @@ -125,7 +125,7 @@ describe('Graph - Adjacency list', function() { }); it('should not allow repeated vertices', function() { - var g = new Graph(); + const g = new Graph(); g.addVertex('a'); assert.throws(function() { g.addVertex('a'); @@ -133,7 +133,7 @@ describe('Graph - Adjacency list', function() { }); it('should return a list of neighbors of a vertex', function() { - var g = new Graph(); + const g = new Graph(); g.addVertex('a'); g.addVertex('b'); g.addVertex('c'); @@ -148,7 +148,7 @@ describe('Graph - Adjacency list', function() { }); it('should return the weight of the edge', function() { - var g = new Graph(); + const g = new Graph(); g.addVertex('a'); g.addVertex('b'); g.addVertex('c'); @@ -163,7 +163,7 @@ describe('Graph - Adjacency list', function() { }); it('should not "inherit" edges from Object.prototype', function() { - var g = new Graph(); + const g = new Graph(); g.addEdge('a', 'b'); assert.ifError(g.edge('a', 'constructor')); diff --git a/src/test/data_structures/hash_table.js b/src/test/data_structures/hash_table.js index bda8cde..65fdc2d 100644 --- a/src/test/data_structures/hash_table.js +++ b/src/test/data_structures/hash_table.js @@ -1,18 +1,18 @@ 'use strict'; -var HashTable = require('../..').DataStructures.HashTable; -var assert = require('assert'); +const HashTable = require('../..').DataStructures.HashTable; +const assert = require('assert'); describe('Hash Table', function() { it('should calculate hashes using the same algorithm as ' + 'Java\'s String.hashCode', function() { - var h = new HashTable(); + const h = new HashTable(); assert.equal(h.hash('The quick brown fox jumps over the lazy dog'), -609428141); assert.equal(h.hash('Testing the hashCode function'), 1538083358); assert.equal(h.hash(''), 0); assert.equal(h.hash('a'), 97); - var longString = + const longString = 'k"hg3q#+~/l2Eljan;DB x.P%-:iA' + '/b/hG($8-SZcZX871&;fDEWthw.b5agzov],X00--O:mcQ$JFi-4uIo"D:(r(yvs' + @@ -34,7 +34,7 @@ describe('Hash Table', function() { it('should initialize the table with the given capacity', function() { - var h = new HashTable(); + let h = new HashTable(); assert.equal(h.capacity, 64); // default initial capacity; assert.equal(h.size, 0); @@ -43,14 +43,14 @@ describe('Hash Table', function() { }); it('should allow putting and getting elements from the table', function() { - var h = new HashTable(16); - var a = {a: 'foo', b: 'bar'}; + const h = new HashTable(16); + const a = {a: 'foo', b: 'bar'}; h.put('foo', a); assert.equal(h.size, 1); assert.strictEqual(h.get('foo'), a); - var b = {a: 'bar', b: 'baz'}; + const b = {a: 'bar', b: 'baz'}; h.put('bar', b); assert.equal(h.size, 2); @@ -58,24 +58,24 @@ describe('Hash Table', function() { }); it('should replace items if the same key is reused', function() { - var h = new HashTable(16); - var a = {a: 'foo', b: 'bar'}; + const h = new HashTable(16); + const a = {a: 'foo', b: 'bar'}; h.put('foo', a); assert.strictEqual(h.get('foo'), a); - var b = {a: 'bar', b: 'baz'}; + const b = {a: 'bar', b: 'baz'}; h.put('foo', b); assert.strictEqual(h.get('foo'), b); }); it('should return undefined if there\'s no element', function() { - var h = new HashTable(8); + const h = new HashTable(8); assert.equal(h.get('foo'), undefined); assert.equal(h.get('bar'), undefined); }); it('should handle hash conflicts', function() { - var h = new HashTable(4); + const h = new HashTable(4); // Both keys are supposed to be pushed to the same position assert.equal(h._position('a'), h._position('e')); h.put('a', 'foo'); @@ -89,7 +89,7 @@ describe('Hash Table', function() { }); it('should increase capacity if needed', function() { - var h = new HashTable(2); + const h = new HashTable(2); assert.equal(h.capacity, 2); h.put('foo', 'foo'); @@ -100,7 +100,7 @@ describe('Hash Table', function() { }); it('should allow removing items', function() { - var h = new HashTable(); + const h = new HashTable(); assert.equal(h.get('foo'), undefined); h.put('foo', 'bar'); @@ -115,23 +115,23 @@ describe('Hash Table', function() { }); it('should allow non-string keys', function() { - var h = new HashTable(); + const h = new HashTable(); h.put(10, 5); assert.equal(h.get(10), 5); - var o = {a: 'foo', b: 'bar'}; + const o = {a: 'foo', b: 'bar'}; h.put(o, 'foo'); assert.equal(h.get(o), 'foo'); }); it('should perform a function to all keys with forEach', function() { - var h = new HashTable(); + const h = new HashTable(); h.put(1, 10); h.put(2, 20); h.put(3, 30); - var totalKeys = 0; - var totalValues = 0; + let totalKeys = 0; + let totalValues = 0; h.forEach(function(k, v) { totalKeys += k; totalValues += v; diff --git a/src/test/data_structures/heap.js b/src/test/data_structures/heap.js index e95aecb..ab8dbf2 100644 --- a/src/test/data_structures/heap.js +++ b/src/test/data_structures/heap.js @@ -1,11 +1,11 @@ 'use strict'; -var heap = require('../..').DataStructures.Heap; -var assert = require('assert'); +const heap = require('../..').DataStructures.Heap; +const assert = require('assert'); describe('Min Heap', function() { it('should always return the lowest element', function() { - var h = new heap.MinHeap(); + const h = new heap.MinHeap(); assert(h.isEmpty()); h.insert(10); h.insert(2091); @@ -36,7 +36,7 @@ describe('Min Heap', function() { }); it('should heapify an unordered array', function() { - var h = new heap.MinHeap(); + const h = new heap.MinHeap(); h.heapify([10, 2091, 4, 1, 5, 500, 0, 18, 3, 22, 20]); assert.equal(h.extract(), 0); @@ -56,10 +56,10 @@ describe('Min Heap', function() { it('should perform a function to all elements from smallest to largest' + ' with forEach', function() { - var h = new heap.MinHeap(); + const h = new heap.MinHeap(); h.heapify([3, 10, 1000, 0, 2, 1]); - var output = []; + const output = []; h.forEach(function(n) { output.push(n); }); @@ -73,7 +73,7 @@ describe('Min Heap', function() { describe('Max Heap', function() { it('should always return the greatest element', function() { - var h = new heap.MaxHeap(); + const h = new heap.MaxHeap(); assert(h.isEmpty()); h.insert(10); h.insert(2091); @@ -104,7 +104,7 @@ describe('Max Heap', function() { }); it('should heapify an unordered array', function() { - var h = new heap.MaxHeap(); + const h = new heap.MaxHeap(); h.heapify([10, 2091, 4, 1, 5, 500, 0, 18, 3, 22, 20]); assert.equal(h.extract(), 2091); @@ -124,10 +124,10 @@ describe('Max Heap', function() { it('should perform a function to all elements from largest to smallest' + ' with forEach', function() { - var h = new heap.MaxHeap(); + const h = new heap.MaxHeap(); h.heapify([3, 10, 1000, 0, 2, 1]); - var output = []; + const output = []; h.forEach(function(n) { output.push(n); }); diff --git a/src/test/data_structures/linked_list.js b/src/test/data_structures/linked_list.js index dd946c6..d6854f7 100644 --- a/src/test/data_structures/linked_list.js +++ b/src/test/data_structures/linked_list.js @@ -1,17 +1,17 @@ 'use strict'; -var LinkedList = require('../..').DataStructures.LinkedList; -var assert = require('assert'); +const LinkedList = require('../..').DataStructures.LinkedList; +const assert = require('assert'); describe('LinkedList', function() { it('should start empty', function() { - var l = new LinkedList(); + const l = new LinkedList(); assert(l.isEmpty()); assert.equal(l.length, 0); }); it('should increment length when an item is added', function() { - var l = new LinkedList(); + const l = new LinkedList(); l.add(1); assert.equal(l.length, 1); assert(!l.isEmpty()); @@ -22,7 +22,7 @@ describe('LinkedList', function() { it('should return the items from the positions they were inserted', function() { - var l = new LinkedList(); + const l = new LinkedList(); l.add(1); l.add(2); l.add(3); @@ -63,7 +63,7 @@ describe('LinkedList', function() { it('should throw errors when trying to access indexes out of bounds', function() { - var l = new LinkedList(); + const l = new LinkedList(); assert.throws(() => l.get(0), Error); assert.throws(() => l.get(1), Error); assert.throws(() => l.get(10), Error); @@ -86,7 +86,7 @@ describe('LinkedList', function() { }); it('should be able to delete elements', function() { - var l = new LinkedList(); + const l = new LinkedList(); l.add(1); l.add(2); @@ -122,7 +122,7 @@ describe('LinkedList', function() { assert.equal(l.get(3), 5); assert.equal(l.get(4), 7); - for (var i = 0; i < 5; i++) { + for (let i = 0; i < 5; i++) { l.del(0); } @@ -133,14 +133,14 @@ describe('LinkedList', function() { }); it('should perform a function to all elements with forEach', function() { - var l = new LinkedList(); + const l = new LinkedList(); l.add(5); l.add(1); l.add(3); l.add(10); l.add(1000); - var a = []; + const a = []; l.forEach(function(e) { a.push(e); }); @@ -150,7 +150,7 @@ describe('LinkedList', function() { it('should throw an error when trying to delete from an empty list', function() { - var l = new LinkedList(); + const l = new LinkedList(); assert.throws(() => l.del(0), Error); }); }); diff --git a/src/test/data_structures/priority_queue.js b/src/test/data_structures/priority_queue.js index 5ef9a83..3035897 100644 --- a/src/test/data_structures/priority_queue.js +++ b/src/test/data_structures/priority_queue.js @@ -1,11 +1,11 @@ 'use strict'; -var PriorityQueue = require('../..').DataStructures.PriorityQueue; -var assert = require('assert'); +const PriorityQueue = require('../..').DataStructures.PriorityQueue; +const assert = require('assert'); describe('Min Priority Queue', function() { it('should always return the element with the lowest priority', function() { - var q = new PriorityQueue(); + const q = new PriorityQueue(); assert(q.isEmpty()); q.insert('a', 10); q.insert('b', 2091); @@ -37,7 +37,7 @@ describe('Min Priority Queue', function() { it('can receive a dictionary with item => priority in construction', function() { - var q = new PriorityQueue({ + const q = new PriorityQueue({ a: 10, b: 2091, c: 4, @@ -54,7 +54,7 @@ describe('Min Priority Queue', function() { }); it('should be possible to change the priority of an item', function() { - var q = new PriorityQueue({ + const q = new PriorityQueue({ a: 10, b: 2091, c: 4, @@ -80,7 +80,7 @@ describe('Min Priority Queue', function() { it('should just update the priority when trying to insert an element that ' + ' already exists', function() { - var q = new PriorityQueue({ + const q = new PriorityQueue({ a: 10, b: 2091, c: 4, diff --git a/src/test/data_structures/queue.js b/src/test/data_structures/queue.js index 3ec85ee..e9f8b7c 100644 --- a/src/test/data_structures/queue.js +++ b/src/test/data_structures/queue.js @@ -1,17 +1,17 @@ 'use strict'; -var Queue = require('../..').DataStructures.Queue; -var assert = require('assert'); +const Queue = require('../..').DataStructures.Queue; +const assert = require('assert'); describe('Queue', function() { it('should start empty', function() { - var q = new Queue(); + const q = new Queue(); assert(q.isEmpty()); assert.equal(q.length, 0); }); it('should implement a FIFO logic', function() { - var q = new Queue(); + const q = new Queue(); q.push(1); q.push(2); q.push(3); @@ -25,7 +25,7 @@ describe('Queue', function() { it('should allow me to peek at the first element in' + ' line without popping it', function() { - var q = new Queue(); + const q = new Queue(); assert.throws(() => q.peek(), Error); // Empty list q.push(1); q.push(2); diff --git a/src/test/data_structures/set.js b/src/test/data_structures/set.js index 7cc088e..36a1a04 100644 --- a/src/test/data_structures/set.js +++ b/src/test/data_structures/set.js @@ -1,16 +1,16 @@ 'use strict'; -var HashSet = require('../..').DataStructures.Set; -var assert = require('assert'); +const HashSet = require('../..').DataStructures.Set; +const assert = require('assert'); describe('HashSet', function() { it('should start empty', function() { - var s = new HashSet(); + const s = new HashSet(); assert.equal(s.size, 0); }); it('should add all initial arguments', function() { - var s = new HashSet(1, 2, 3); + const s = new HashSet(1, 2, 3); assert.equal(s.size, 3); assert(s.contains(1)); assert(s.contains(2)); @@ -18,7 +18,7 @@ describe('HashSet', function() { }); it('should add all arguments', function() { - var s = new HashSet(1, 2, 3); + const s = new HashSet(1, 2, 3); assert.equal(s.size, 3); s.add(4, 5, 6); assert.equal(s.size, 6); @@ -31,7 +31,7 @@ describe('HashSet', function() { }); it('should remove all arguments', function() { - var s = new HashSet(1, 2, 3); + const s = new HashSet(1, 2, 3); assert.equal(s.size, 3); s.remove(1, 3); assert.equal(s.size, 1); @@ -42,7 +42,7 @@ describe('HashSet', function() { it('should do nothing when trying to remove an element that doesn\'t exist', function() { - var s = new HashSet(1, 2, 3); + const s = new HashSet(1, 2, 3); assert.equal(s.size, 3); s.remove(4); assert.equal(s.size, 3); @@ -52,16 +52,16 @@ describe('HashSet', function() { }); it('should only contain its elements', function() { - var s = new HashSet(1, 2, 3); + const s = new HashSet(1, 2, 3); assert(s.contains(1)); assert(!s.contains(4)); }); it('should perform a function to all elements with forEach', function() { - var s = new HashSet(); + const s = new HashSet(); s.add(1, 2, 3); - var total = 0; + let total = 0; s.forEach(function(elem) { total += elem; }); diff --git a/src/test/data_structures/stack.js b/src/test/data_structures/stack.js index dcf6527..2b40342 100644 --- a/src/test/data_structures/stack.js +++ b/src/test/data_structures/stack.js @@ -1,17 +1,17 @@ 'use strict'; -var Stack = require('../..').DataStructures.Stack; -var assert = require('assert'); +const Stack = require('../..').DataStructures.Stack; +const assert = require('assert'); describe('Stack', function() { it('should start empty', function() { - var s = new Stack(); + const s = new Stack(); assert(s.isEmpty()); assert.equal(s.length, 0); }); it('should implement a LIFO logic', function() { - var s = new Stack(); + const s = new Stack(); s.push(1); s.push(2); s.push(3); @@ -25,7 +25,7 @@ describe('Stack', function() { it('should allow me to peek at the top element in' + ' the stack without popping it', function() { - var s = new Stack(); + const s = new Stack(); s.push(1); s.push(2); s.push(3); diff --git a/src/test/data_structures/treap.js b/src/test/data_structures/treap.js index ed9d852..cca662b 100644 --- a/src/test/data_structures/treap.js +++ b/src/test/data_structures/treap.js @@ -1,11 +1,11 @@ 'use strict'; -var root = require('../..'); -var Treap = root.DataStructures.Treap; -var assert = require('assert'); +const root = require('../..'); +const Treap = root.DataStructures.Treap; +const assert = require('assert'); describe('Treap', function() { - var treap; + let treap; before(function() { treap = new Treap(); }); @@ -126,7 +126,7 @@ describe('Treap', function() { it('should keep balance', function() { // Insert 1023 elements randomly - for (var i = 0; i < 1023; ++i) { + for (let i = 0; i < 1023; ++i) { treap.insert(Math.random()); } assert.equal(treap.size(), 1023); diff --git a/src/test/util/comparator.js b/src/test/util/comparator.js index 41eea91..790bbd7 100644 --- a/src/test/util/comparator.js +++ b/src/test/util/comparator.js @@ -1,12 +1,12 @@ 'use strict'; -var Comparator = require('../../util/comparator'); -var assert = require('assert'); +const Comparator = require('../../util/comparator'); +const assert = require('assert'); describe('Comparator', function() { it('Should use a default arithmetic comparison if no function is passed', function() { - var c = new Comparator(); + const c = new Comparator(); assert.equal(c.compare(1, 1), 0); assert.equal(c.compare(1, 2), -1); assert.equal(c.compare(1, 0), 1); @@ -26,10 +26,10 @@ describe('Comparator', function() { }); it('should allow comparison function to be defined by user', function() { - var compareFn = function() { + const compareFn = function() { return 0; }; - var c = new Comparator(compareFn); + const c = new Comparator(compareFn); assert.equal(c.compare(1, 1), 0); assert.equal(c.compare(1, 2), 0); assert.equal(c.compare(1, 0), 0); @@ -49,7 +49,7 @@ describe('Comparator', function() { }); it('Should allow reversing the comparisons', function() { - var c = new Comparator(); + const c = new Comparator(); c.reverse(); assert.equal(c.compare(1, 1), 0); assert.equal(c.compare(1, 2), 1); diff --git a/src/util/comparator.js b/src/util/comparator.js index 75f9e6c..aed5343 100644 --- a/src/util/comparator.js +++ b/src/util/comparator.js @@ -49,7 +49,7 @@ Comparator.prototype.equal = function(a, b) { * this.compare(a, b) => -1 */ Comparator.prototype.reverse = function() { - var originalCompareFn = this.compare; + const originalCompareFn = this.compare; this.compare = function(a, b) { return originalCompareFn(b, a); }; From 695c5dc0e428f95460878d15bca9b78f09e23255 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 14 Jun 2017 16:47:40 +0200 Subject: [PATCH 242/280] [es6] Use arrow functions --- src/algorithms/graph/SPFA.js | 2 +- src/algorithms/graph/bellman_ford.js | 6 +-- src/algorithms/graph/bfs_shortest_path.js | 2 +- src/algorithms/graph/breadth_first_search.js | 16 +++--- src/algorithms/graph/depth_first_search.js | 16 +++--- src/algorithms/graph/dijkstra.js | 4 +- src/algorithms/graph/euler_path.js | 16 +++--- src/algorithms/graph/floyd_warshall.js | 18 +++---- src/algorithms/graph/kruskal.js | 10 ++-- src/algorithms/graph/prim.js | 6 +-- .../graph/strongly_connected_component.js | 10 ++-- src/algorithms/graph/topological_sort.js | 4 +- src/algorithms/math/extended_euclidean.js | 2 +- src/algorithms/math/fast_power.js | 8 ++- src/algorithms/math/fibonacci.js | 26 ++++------ src/algorithms/math/find_divisors.js | 6 +-- src/algorithms/math/fisher_yates.js | 2 +- src/algorithms/math/gcd.js | 4 +- src/algorithms/math/greatest_difference.js | 2 +- src/algorithms/math/lcm.js | 2 +- src/algorithms/math/newton_sqrt.js | 2 +- src/algorithms/math/next_permutation.js | 2 +- src/algorithms/math/power_set.js | 6 +-- src/algorithms/math/primality_tests.js | 6 +-- src/algorithms/math/reservoir_sampling.js | 2 +- src/algorithms/math/shannon_entropy.js | 12 ++--- src/algorithms/search/bfs.js | 2 +- src/algorithms/search/binarysearch.js | 2 +- src/algorithms/search/dfs.js | 6 +-- src/algorithms/search/ternary_search.js | 2 +- src/algorithms/sorting/bubble_sort.js | 2 +- src/algorithms/sorting/counting_sort.js | 4 +- src/algorithms/sorting/heap_sort.js | 2 +- src/algorithms/sorting/insertion_sort.js | 2 +- src/algorithms/sorting/merge_sort.js | 4 +- src/algorithms/sorting/quicksort.js | 6 +-- src/algorithms/sorting/radix_sort.js | 6 +-- src/algorithms/sorting/selection_sort.js | 2 +- src/algorithms/sorting/shell_sort.js | 2 +- src/algorithms/string/hamming.js | 2 +- src/algorithms/string/huffman.js | 50 +++++++------------ src/algorithms/string/knuth_morris_pratt.js | 4 +- src/algorithms/string/levenshtein.js | 2 +- .../string/longest_common_subsequence.js | 2 +- .../string/longest_common_substring.js | 2 +- src/algorithms/string/rabin_karp.js | 4 +- src/data_structures/avl_tree.js | 8 +-- src/data_structures/bst.js | 6 +-- src/data_structures/disjoint_set_forest.js | 4 +- src/data_structures/graph.js | 10 ++-- src/data_structures/hash_table.js | 8 +-- src/data_structures/heap.js | 4 +- src/data_structures/linked_list.js | 4 +- src/data_structures/priority_queue.js | 6 +-- src/data_structures/queue.js | 4 +- src/data_structures/stack.js | 4 +- src/test/algorithms/geometry/bezier_curve.js | 8 +-- src/test/algorithms/graph/SPFA.js | 4 +- src/test/algorithms/graph/bellman_ford.js | 4 +- .../algorithms/graph/bfs_shortest_path.js | 4 +- .../algorithms/graph/breadth_first_search.js | 8 +-- .../algorithms/graph/depth_first_search.js | 8 +-- src/test/algorithms/graph/dijkstra.js | 4 +- src/test/algorithms/graph/euler_path.js | 26 +++++----- src/test/algorithms/graph/floyd_warshall.js | 6 +-- .../algorithms/graph/minimum_spanning_tree.js | 41 +++++++-------- .../graph/strongly_connected_component.js | 4 +- src/test/algorithms/graph/topological_sort.js | 4 +- .../algorithms/math/collatz_conjecture.js | 8 +-- .../algorithms/math/extended_euclidean.js | 4 +- src/test/algorithms/math/fast_power.js | 20 +++----- src/test/algorithms/math/fibonacci.js | 24 ++++----- src/test/algorithms/math/find_divisors.js | 18 +++---- src/test/algorithms/math/fisher_yates.js | 6 +-- src/test/algorithms/math/gcd.js | 6 +-- .../algorithms/math/greatest_difference.js | 8 +-- src/test/algorithms/math/lcm.js | 6 +-- src/test/algorithms/math/newton_sqrt.js | 6 +-- src/test/algorithms/math/next_permutation.js | 24 ++++----- src/test/algorithms/math/power_set.js | 14 +++--- src/test/algorithms/math/primality_tests.js | 12 ++--- .../algorithms/math/reservoir_sampling.js | 12 ++--- src/test/algorithms/math/shannon_entropy.js | 4 +- src/test/algorithms/searching/bfs.js | 8 ++- src/test/algorithms/searching/binarysearch.js | 4 +- src/test/algorithms/searching/dfs.js | 12 ++--- .../algorithms/searching/ternary_search.js | 16 ++---- src/test/algorithms/sorting/bubble_sort.js | 6 +-- src/test/algorithms/sorting/counting_sort.js | 4 +- src/test/algorithms/sorting/heap_sort.js | 6 +-- src/test/algorithms/sorting/insertion_sort.js | 6 +-- src/test/algorithms/sorting/merge_sort.js | 6 +-- src/test/algorithms/sorting/quicksort.js | 6 +-- src/test/algorithms/sorting/radix_sort.js | 4 +- src/test/algorithms/sorting/selection_sort.js | 6 +-- src/test/algorithms/sorting/shell_sort.js | 6 +-- .../algorithms/sorting/short_bubble_sort.js | 6 +-- .../sorting/sorting_tests_helper.js | 4 +- src/test/algorithms/string/hamming.js | 10 ++-- src/test/algorithms/string/huffman.js | 30 ++++++----- .../algorithms/string/knuth_morris_pratt.js | 4 +- src/test/algorithms/string/levenshtein.js | 4 +- .../string/longest_common_subsequence.js | 4 +- .../string/longest_common_substring.js | 4 +- src/test/algorithms/string/rabin_karp.js | 6 +-- src/test/data_structures/avl-tree.js | 28 +++++------ src/test/data_structures/bst.js | 40 +++++++-------- .../data_structures/disjoint_set_forest.js | 22 ++++---- src/test/data_structures/fenwick_tree.js | 6 +-- src/test/data_structures/graph.js | 28 +++++------ src/test/data_structures/hash_table.js | 24 ++++----- src/test/data_structures/heap.js | 20 ++++---- src/test/data_structures/linked_list.js | 18 +++---- src/test/data_structures/priority_queue.js | 10 ++-- src/test/data_structures/queue.js | 8 +-- src/test/data_structures/set.js | 18 +++---- src/test/data_structures/stack.js | 8 +-- src/test/data_structures/treap.js | 22 ++++---- src/test/util/comparator.js | 12 ++--- src/util/comparator.js | 6 +-- 120 files changed, 502 insertions(+), 581 deletions(-) diff --git a/src/algorithms/graph/SPFA.js b/src/algorithms/graph/SPFA.js index fe0f0c6..8d800f5 100644 --- a/src/algorithms/graph/SPFA.js +++ b/src/algorithms/graph/SPFA.js @@ -21,7 +21,7 @@ function spfa(graph, s) { queue[0] = s; isInQue[s] = true; cnt[s] = 1; - graph.vertices.forEach(function(v) { + graph.vertices.forEach(v => { if (v !== s) { distance[v] = Infinity; isInQue[v] = false; diff --git a/src/algorithms/graph/bellman_ford.js b/src/algorithms/graph/bellman_ford.js index b81565b..5dce3b1 100644 --- a/src/algorithms/graph/bellman_ford.js +++ b/src/algorithms/graph/bellman_ford.js @@ -13,15 +13,15 @@ * the graph starting in 'startNode', or an empty object if there * exists a Negative-Weighted Cycle in the graph */ -const bellmanFord = function(graph, startNode) { +const bellmanFord = (graph, startNode) => { const minDistance = {}; const previousVertex = {}; const edges = []; let adjacencyListSize = 0; // Add all the edges from the graph to the 'edges' array - graph.vertices.forEach(function(s) { - graph.neighbors(s).forEach(function(t) { + graph.vertices.forEach(s => { + graph.neighbors(s).forEach(t => { edges.push({ source: s, target: t, diff --git a/src/algorithms/graph/bfs_shortest_path.js b/src/algorithms/graph/bfs_shortest_path.js index e466c3c..a53886c 100644 --- a/src/algorithms/graph/bfs_shortest_path.js +++ b/src/algorithms/graph/bfs_shortest_path.js @@ -12,7 +12,7 @@ const breadthFirstSearch = require('./breadth_first_search'); * @return {{distance: Object., * previous: Object.}} */ -const bfsShortestPath = function(graph, source) { +const bfsShortestPath = (graph, source) => { const distance = {}; const previous = {}; distance[source] = 0; diff --git a/src/algorithms/graph/breadth_first_search.js b/src/algorithms/graph/breadth_first_search.js index 08c58df..a930e91 100644 --- a/src/algorithms/graph/breadth_first_search.js +++ b/src/algorithms/graph/breadth_first_search.js @@ -21,25 +21,25 @@ const Queue = require('../../data_structures/queue'); * used by default allowTraversal implementation. * @return {Callbacks} The same object or new one (if null passed). */ -const normalizeCallbacks = function(callbacks, seenVertices) { +const normalizeCallbacks = (callbacks, seenVertices) => { callbacks = callbacks || {}; - callbacks.allowTraversal = callbacks.allowTraversal || (function() { - const seen = seenVertices.reduce(function(seen, vertex) { + callbacks.allowTraversal = callbacks.allowTraversal || ((() => { + const seen = seenVertices.reduce((seen, vertex) => { seen[vertex] = true; return seen; }, {}); - return function(vertex, neighbor) { + return (vertex, neighbor) => { if (!seen[neighbor]) { seen[neighbor] = true; return true; } return false; }; - })(); + }))(); - const noop = function() {}; + const noop = () => {}; callbacks.onTraversal = callbacks.onTraversal || noop; callbacks.enterVertex = callbacks.enterVertex || noop; callbacks.leaveVertex = callbacks.leaveVertex || noop; @@ -55,13 +55,13 @@ const normalizeCallbacks = function(callbacks, seenVertices) { * @param {*} startVertex * @param {Callbacks} [callbacks] */ -const breadthFirstSearch = function(graph, startVertex, callbacks) { +const breadthFirstSearch = (graph, startVertex, callbacks) => { const vertexQueue = new Queue(); vertexQueue.push(startVertex); callbacks = normalizeCallbacks(callbacks, [startVertex]); let vertex; - const enqueue = function(neighbor) { + const enqueue = neighbor => { if (callbacks.allowTraversal(vertex, neighbor)) { callbacks.onTraversal(vertex, neighbor); vertexQueue.push(neighbor); diff --git a/src/algorithms/graph/depth_first_search.js b/src/algorithms/graph/depth_first_search.js index 901d7ed..3c5388f 100644 --- a/src/algorithms/graph/depth_first_search.js +++ b/src/algorithms/graph/depth_first_search.js @@ -20,16 +20,16 @@ * used by default allowTraversal implementation. * @return {Callbacks} The same object or new one (if null passed). */ -const normalizeCallbacks = function(callbacks, seenVertices) { +const normalizeCallbacks = (callbacks, seenVertices) => { callbacks = callbacks || {}; - callbacks.allowTraversal = callbacks.allowTraversal || (function() { + callbacks.allowTraversal = callbacks.allowTraversal || ((() => { const seen = {}; - seenVertices.forEach(function(vertex) { + seenVertices.forEach(vertex => { seen[vertex] = true; }); - return function(vertex, neighbor) { + return (vertex, neighbor) => { // It should still be possible to redefine other callbacks, // so we better do all at once here. @@ -39,9 +39,9 @@ const normalizeCallbacks = function(callbacks, seenVertices) { } return false; }; - })(); + }))(); - const noop = function() {}; + const noop = () => {}; callbacks.beforeTraversal = callbacks.beforeTraversal || noop; callbacks.afterTraversal = callbacks.afterTraversal || noop; callbacks.enterVertex = callbacks.enterVertex || noop; @@ -53,7 +53,7 @@ const normalizeCallbacks = function(callbacks, seenVertices) { const dfsLoop = function dfsLoop(graph, vertex, callbacks) { callbacks.enterVertex(vertex); - graph.neighbors(vertex).forEach(function(neighbor) { + graph.neighbors(vertex).forEach(neighbor => { if (callbacks.allowTraversal(vertex, neighbor)) { callbacks.beforeTraversal(vertex, neighbor); dfsLoop(graph, neighbor, callbacks); @@ -72,7 +72,7 @@ const dfsLoop = function dfsLoop(graph, vertex, callbacks) { * @param {*} startVertex * @param {Callbacks} [callbacks] */ -const depthFirstSearch = function(graph, startVertex, callbacks) { +const depthFirstSearch = (graph, startVertex, callbacks) => { dfsLoop(graph, startVertex, normalizeCallbacks(callbacks, [startVertex])); }; diff --git a/src/algorithms/graph/dijkstra.js b/src/algorithms/graph/dijkstra.js index 0d3f6b9..5947a21 100644 --- a/src/algorithms/graph/dijkstra.js +++ b/src/algorithms/graph/dijkstra.js @@ -16,7 +16,7 @@ function dijkstra(graph, s) { const q = new PriorityQueue(); // Initialize distance[s] = 0; - graph.vertices.forEach(function(v) { + graph.vertices.forEach(v => { if (v !== s) { distance[v] = Infinity; } @@ -24,7 +24,7 @@ function dijkstra(graph, s) { }); let currNode; - const relax = function(v) { + const relax = v => { const newDistance = distance[currNode] + graph.edge(currNode, v); if (newDistance < distance[v]) { distance[v] = newDistance; diff --git a/src/algorithms/graph/euler_path.js b/src/algorithms/graph/euler_path.js index 578fa69..a9b129b 100644 --- a/src/algorithms/graph/euler_path.js +++ b/src/algorithms/graph/euler_path.js @@ -10,28 +10,28 @@ const depthFirstSearch = require('../../algorithms/graph/depth_first_search'); * @param {Graph} Graph, must be connected and contain at least one vertex. * @return Object */ -const eulerEndpoints = function(graph) { +const eulerEndpoints = graph => { const rank = {}; // start -> rank = +1 // middle points -> rank = 0 // finish -> rank = -1 // Initialize ranks to be outdegrees of vertices. - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(vertex => { rank[vertex] = graph.neighbors(vertex).length; }); if (graph.directed) { // rank = outdegree - indegree - graph.vertices.forEach(function(vertex) { - graph.neighbors(vertex).forEach(function(neighbor) { + graph.vertices.forEach(vertex => { + graph.neighbors(vertex).forEach(neighbor => { rank[neighbor] -= 1; }); }); } else { // Compute ranks from vertex degree parity values. let startChosen = false; - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(vertex => { rank[vertex] %= 2; if (rank[vertex]) { if (startChosen) { @@ -46,7 +46,7 @@ const eulerEndpoints = function(graph) { let finish; let v; - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(vertex => { if (rank[vertex] === 1) { if (start) { throw new Error('Duplicate start vertex.'); @@ -82,7 +82,7 @@ const eulerEndpoints = function(graph) { * @param {Graph} * @return Array */ -const eulerPath = function(graph) { +const eulerPath = graph => { if (!graph.vertices.size) { return []; } @@ -105,7 +105,7 @@ const eulerPath = function(graph) { } }); - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(vertex => { if (seen.neighbors(vertex).length < graph.neighbors(vertex).length) { throw new Error('There is no euler path for a disconnected graph.'); } diff --git a/src/algorithms/graph/floyd_warshall.js b/src/algorithms/graph/floyd_warshall.js index 2f3d6d7..29858be 100644 --- a/src/algorithms/graph/floyd_warshall.js +++ b/src/algorithms/graph/floyd_warshall.js @@ -8,15 +8,15 @@ * @param {Graph} graph * @return {{distance, path}} */ -const floydWarshall = function(graph) { +const floydWarshall = graph => { // Fill in the distances with initial values: // - 0 if source == destination; // - edge(source, destination) if there is a direct edge; // - +inf otherwise. const distance = Object.create(null); - graph.vertices.forEach(function(src) { + graph.vertices.forEach(src => { distance[src] = Object.create(null); - graph.vertices.forEach(function(dest) { + graph.vertices.forEach(dest => { if (src === dest) { distance[src][dest] = 0; } else if (graph.edge(src, dest)) { @@ -30,13 +30,13 @@ const floydWarshall = function(graph) { // Internal vertex with the largest index along the shortest path. // Needed for path reconstruction. const middleVertex = Object.create(null); - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(vertex => { middleVertex[vertex] = Object.create(null); }); - graph.vertices.forEach(function(middle) { - graph.vertices.forEach(function(src) { - graph.vertices.forEach(function(dest) { + graph.vertices.forEach(middle => { + graph.vertices.forEach(src => { + graph.vertices.forEach(dest => { const dist = distance[src][middle] + distance[middle][dest]; if (dist < distance[src][dest]) { distance[src][dest] = dist; @@ -47,7 +47,7 @@ const floydWarshall = function(graph) { }); // Check for a negative-weighted cycle. - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(vertex => { if (distance[vertex][vertex] < 0) { // Negative-weighted cycle found. throw new Error('The graph contains a negative-weighted cycle!'); @@ -62,7 +62,7 @@ const floydWarshall = function(graph) { * @param {string} dest * @return {?string[]} Null if destination is unreachable. */ - const path = function(src, dest) { + const path = (src, dest) => { if (!Number.isFinite(distance[src][dest])) { // dest unreachable. return null; diff --git a/src/algorithms/graph/kruskal.js b/src/algorithms/graph/kruskal.js index 0f9f949..9058f80 100644 --- a/src/algorithms/graph/kruskal.js +++ b/src/algorithms/graph/kruskal.js @@ -11,7 +11,7 @@ const Graph = require('../../data_structures/graph'); * @return {Graph} Minimum spanning tree or forest * (depending on whether input graph is connected itself). */ -const kruskal = function(graph) { +const kruskal = graph => { if (graph.directed) { throw new Error('Can\'t build MST of a directed graph.'); } @@ -21,8 +21,8 @@ const kruskal = function(graph) { graph.vertices.forEach(mst.addVertex.bind(mst)); const edges = []; - graph.vertices.forEach(function(vertex) { - graph.neighbors(vertex).forEach(function(neighbor) { + graph.vertices.forEach(vertex => { + graph.neighbors(vertex).forEach(neighbor => { // Compared as strings, loops intentionally omitted. if (vertex < neighbor) { edges.push({ @@ -33,9 +33,7 @@ const kruskal = function(graph) { }); }); - edges.sort(function(a, b) { - return a.weight - b.weight; - }).forEach(function(edge) { + edges.sort((a, b) => a.weight - b.weight).forEach(edge => { if (!connectedComponents.sameSubset(edge.ends[0], edge.ends[1])) { mst.addEdge(edge.ends[0], edge.ends[1], edge.weight); connectedComponents.merge(edge.ends[0], edge.ends[1]); diff --git a/src/algorithms/graph/prim.js b/src/algorithms/graph/prim.js index 10d2e30..300f592 100644 --- a/src/algorithms/graph/prim.js +++ b/src/algorithms/graph/prim.js @@ -11,7 +11,7 @@ const Graph = require('../../data_structures/graph'); * @return {Graph} Minimum spanning tree or forest * (depending on whether input graph is connected itself). */ -const prim = function(graph) { +const prim = graph => { if (graph.directed) { throw new Error('Can\'t build MST of a directed graph.'); } @@ -20,11 +20,11 @@ const prim = function(graph) { const parent = Object.create(null); const q = new PriorityQueue(); - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(vertex => { q.insert(vertex, Infinity); }); - const relax = function(vertex, neighbor) { + const relax = (vertex, neighbor) => { const weight = graph.edge(vertex, neighbor); if (weight < q.priority(neighbor)) { q.changePriority(neighbor, weight); diff --git a/src/algorithms/graph/strongly_connected_component.js b/src/algorithms/graph/strongly_connected_component.js index 6974515..733eaf2 100644 --- a/src/algorithms/graph/strongly_connected_component.js +++ b/src/algorithms/graph/strongly_connected_component.js @@ -20,14 +20,14 @@ const depthFirstSearch = require('../../algorithms/graph/depth_first_search'); * scc.count; // count of strongly connected components * scc.id[v]; // id of the strongly connected component which v belongs to */ -const stronglyConnectedComponent = function(graph) { +const stronglyConnectedComponent = graph => { const reverse = graph.reverse(); const stack = new Stack(); let visited = {}; let count = 0; const id = Object.create(null); - reverse.vertices.forEach(function(node) { + reverse.vertices.forEach(node => { if (!visited[node]) { depthFirstSearch(reverse, node, { allowTraversal: function(node, neighbor) { @@ -44,10 +44,8 @@ const stronglyConnectedComponent = function(graph) { }); visited = {}; - const allowTraversal = function(node, neighbor) { - return !visited[neighbor]; - }; - const enterVertex = function(node) { + const allowTraversal = (node, neighbor) => !visited[neighbor]; + const enterVertex = node => { visited[node] = true; id[node] = count; }; diff --git a/src/algorithms/graph/topological_sort.js b/src/algorithms/graph/topological_sort.js index 142f1af..1ecfd9b 100644 --- a/src/algorithms/graph/topological_sort.js +++ b/src/algorithms/graph/topological_sort.js @@ -17,12 +17,12 @@ const depthFirstSearch = require('../../algorithms/graph/depth_first_search'); * @param {Graph} * @return Stack */ -const topologicalSort = function(graph) { +const topologicalSort = graph => { const stack = new Stack(); const firstHit = {}; let time = 0; - graph.vertices.forEach(function(node) { + graph.vertices.forEach(node => { if (!firstHit[node]) { depthFirstSearch(graph, node, { allowTraversal: function(node, neighbor) { diff --git a/src/algorithms/math/extended_euclidean.js b/src/algorithms/math/extended_euclidean.js index 5214288..5bd4e90 100644 --- a/src/algorithms/math/extended_euclidean.js +++ b/src/algorithms/math/extended_euclidean.js @@ -10,7 +10,7 @@ * * @return {Number, Number} */ -const extEuclid = function(a, b) { +const extEuclid = (a, b) => { let s = 0; let oldS = 1; let t = 1; diff --git a/src/algorithms/math/fast_power.js b/src/algorithms/math/fast_power.js index 1cb8a81..0536d37 100644 --- a/src/algorithms/math/fast_power.js +++ b/src/algorithms/math/fast_power.js @@ -1,8 +1,6 @@ 'use strict'; -const multiplicationOperator = function(a, b) { - return a * b; -}; +const multiplicationOperator = (a, b) => a * b; /** * Raise value to a positive integer power by repeated squaring. @@ -15,7 +13,7 @@ const multiplicationOperator = function(a, b) { * If mul is not set, defaults to 1. * @return {*} */ -const fastPower = function(base, power, mul, identity) { +const fastPower = (base, power, mul, identity) => { if (mul === undefined) { mul = multiplicationOperator; identity = 1; @@ -34,7 +32,7 @@ const fastPower = function(base, power, mul, identity) { // Iterative form of the algorithm avoids checking the same thing twice. let result; - const multiplyBy = function(value) { + const multiplyBy = value => { result = (result === undefined) ? value : mul(result, value); }; for (let factor = base; power; power >>>= 1, factor = mul(factor, factor)) { diff --git a/src/algorithms/math/fibonacci.js b/src/algorithms/math/fibonacci.js index 149994a..643e1f9 100644 --- a/src/algorithms/math/fibonacci.js +++ b/src/algorithms/math/fibonacci.js @@ -15,9 +15,7 @@ const power = require('./fast_power'); * @param Number * @return Number */ -const fibExponential = function(n) { - return n < 2 ? n : fibExponential(n - 1) + fibExponential(n - 2); -}; +const fibExponential = n => n < 2 ? n : fibExponential(n - 1) + fibExponential(n - 2); /** * O(n) in time, O(1) in space and doesn't use recursion @@ -25,7 +23,7 @@ const fibExponential = function(n) { * @param Number * @return Number */ -const fibLinear = function(n) { +const fibLinear = n => { let fibNMinus2 = 0; let fibNMinus1 = 1; let fib = n; @@ -43,10 +41,10 @@ const fibLinear = function(n) { * @param Number * @return Number */ -const fibWithMemoization = (function() { +const fibWithMemoization = ((() => { const cache = [0, 1]; - const fib = function(n) { + const fib = n => { if (cache[n] === undefined) { cache[n] = fib(n - 1) + fib(n - 2); } @@ -54,7 +52,7 @@ const fibWithMemoization = (function() { }; return fib; -})(); +}))(); /** * Implementation using Binet's formula with the rounding trick. @@ -63,7 +61,7 @@ const fibWithMemoization = (function() { * @param Number * @return Number */ -const fibDirect = function(number) { +const fibDirect = number => { const phi = (1 + Math.sqrt(5)) / 2; return Math.floor(Math.pow(phi, number) / Math.sqrt(5) + 0.5); }; @@ -75,16 +73,14 @@ const fibDirect = function(number) { * @param Number * @return Number */ -const fibLogarithmic = function(number) { +const fibLogarithmic = number => { // Transforms [f_1, f_0] to [f_2, f_1] and so on. const nextFib = [[1, 1], [1, 0]]; - const matrixMultiply = function(a, b) { - return [[a[0][0] * b[0][0] + a[0][1] * b[1][0], - a[0][0] * b[0][1] + a[0][1] * b[1][1]], - [a[1][0] * b[0][0] + a[1][1] * b[1][0], - a[1][0] * b[0][1] + a[1][1] * b[1][1]]]; - }; + const matrixMultiply = (a, b) => [[a[0][0] * b[0][0] + a[0][1] * b[1][0], + a[0][0] * b[0][1] + a[0][1] * b[1][1]], + [a[1][0] * b[0][0] + a[1][1] * b[1][0], + a[1][0] * b[0][1] + a[1][1] * b[1][1]]]; const transform = power(nextFib, number, matrixMultiply, [[1, 0], [0, 1]]); diff --git a/src/algorithms/math/find_divisors.js b/src/algorithms/math/find_divisors.js index f7f8230..40fcb0b 100644 --- a/src/algorithms/math/find_divisors.js +++ b/src/algorithms/math/find_divisors.js @@ -13,7 +13,7 @@ * @returns {number[]} - returns the divisors */ -const findDivisorsGeneric = function(number) { +const findDivisorsGeneric = number => { let index = 1; const divisors = []; @@ -36,7 +36,7 @@ const findDivisorsGeneric = function(number) { * @returns {number[]} - returns the divisors */ -const findDivisorsByPairingUnsorted = function(number) { +const findDivisorsByPairingUnsorted = number => { let index = 1; const divisors = []; @@ -65,7 +65,7 @@ const findDivisorsByPairingUnsorted = function(number) { * @returns {number[]} - returns the divisors */ -const findDivisorsByPairingSorted = function(number) { +const findDivisorsByPairingSorted = number => { let index = 1; let divisors = []; const divisorsLessThanSqrt = []; diff --git a/src/algorithms/math/fisher_yates.js b/src/algorithms/math/fisher_yates.js index 0318675..73f040f 100644 --- a/src/algorithms/math/fisher_yates.js +++ b/src/algorithms/math/fisher_yates.js @@ -4,7 +4,7 @@ * Fisher-Yates shuffles the elements in an array * in O(n) */ -const fisherYates = function(a) { +const fisherYates = a => { for (let i = a.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); const tmp = a[i]; diff --git a/src/algorithms/math/gcd.js b/src/algorithms/math/gcd.js index e140a88..b7ea9c2 100644 --- a/src/algorithms/math/gcd.js +++ b/src/algorithms/math/gcd.js @@ -8,7 +8,7 @@ * * @return Number */ -const gcdDivisionBased = function(a, b) { +const gcdDivisionBased = (a, b) => { let tmp = a; a = Math.max(a, b); b = Math.min(tmp, b); @@ -32,7 +32,7 @@ const gcdDivisionBased = function(a, b) { * * @return Number */ -const gcdBinaryIterative = function(a, b) { +const gcdBinaryIterative = (a, b) => { // GCD(0,b) == b; GCD(a,0) == a, GCD(0,0) == 0 if (a === 0) { return b; diff --git a/src/algorithms/math/greatest_difference.js b/src/algorithms/math/greatest_difference.js index 4eec3b9..6b516fc 100644 --- a/src/algorithms/math/greatest_difference.js +++ b/src/algorithms/math/greatest_difference.js @@ -8,7 +8,7 @@ * @returns {number} */ -const greatestDifference = function(numbers) { +const greatestDifference = numbers => { let index = 0; let largest = numbers[0]; const length = numbers.length; diff --git a/src/algorithms/math/lcm.js b/src/algorithms/math/lcm.js index ad2829a..9e4196a 100644 --- a/src/algorithms/math/lcm.js +++ b/src/algorithms/math/lcm.js @@ -12,7 +12,7 @@ const gcd = require('./gcd.js'); * * @return Number */ -const genericLCM = function(gcdFunction, a, b) { +const genericLCM = (gcdFunction, a, b) => { if (a === 0 || b === 0) { return 0; } diff --git a/src/algorithms/math/newton_sqrt.js b/src/algorithms/math/newton_sqrt.js index 5305787..156fee1 100644 --- a/src/algorithms/math/newton_sqrt.js +++ b/src/algorithms/math/newton_sqrt.js @@ -7,7 +7,7 @@ * @param Number tolerance - The error margin accepted (Default 1e-7) * @param Number maxIterations - The max number of iterations (Default 1e7) */ -const sqrt = function(n, tolerance, maxIterations) { +const sqrt = (n, tolerance, maxIterations) => { tolerance = tolerance || 1e-7; maxIterations = maxIterations || 1e7; diff --git a/src/algorithms/math/next_permutation.js b/src/algorithms/math/next_permutation.js index 359f97c..f3de892 100644 --- a/src/algorithms/math/next_permutation.js +++ b/src/algorithms/math/next_permutation.js @@ -12,7 +12,7 @@ const Comparator = require('../../util/comparator'); * @return {boolean} Boolean flag indicating whether the algorithm succeeded, * true unless the input permutation is lexicographically the last one. */ -const nextPermutation = function(array, compareFn) { +const nextPermutation = (array, compareFn) => { if (!array.length) { return false; } diff --git a/src/algorithms/math/power_set.js b/src/algorithms/math/power_set.js index 14102c4..7de1949 100644 --- a/src/algorithms/math/power_set.js +++ b/src/algorithms/math/power_set.js @@ -7,7 +7,7 @@ /** * Iterative power set calculation */ -const powerSetIterative = function(array) { +const powerSetIterative = array => { if (array.length === 0) { return []; } @@ -40,7 +40,7 @@ const powerSetIterative = function(array) { /** * Recursive power set calculation */ -const powerSetRecursive = function(array) { +const powerSetRecursive = array => { if (array.length === 0) { return []; } else if (array.length === 1) { @@ -51,7 +51,7 @@ const powerSetRecursive = function(array) { array.splice(0, 1); - powerSetRecursive(array).forEach(function(elem) { + powerSetRecursive(array).forEach(elem => { powerSet.push(elem); const withFirstElem = [firstElem]; withFirstElem.push.apply(withFirstElem, elem); diff --git a/src/algorithms/math/primality_tests.js b/src/algorithms/math/primality_tests.js index 6e213ec..33cb7cb 100644 --- a/src/algorithms/math/primality_tests.js +++ b/src/algorithms/math/primality_tests.js @@ -8,7 +8,7 @@ * * @return Boolean */ -const genericPrimalityTest = function(primalityTest, n) { +const genericPrimalityTest = (primalityTest, n) => { if (n <= 1) { return false; } @@ -22,7 +22,7 @@ const genericPrimalityTest = function(primalityTest, n) { * * @return Boolean */ -const naiveTest = function(n) { +const naiveTest = n => { for (let i = 2; i < n; ++i) { if (n % i === 0) { return false; @@ -38,7 +38,7 @@ const naiveTest = function(n) { * * @return Boolean */ -const trialDivisionTest = function(n) { +const trialDivisionTest = n => { const sqrt = Math.sqrt(n); for (let i = 2; i <= sqrt; ++i) { if (n % i === 0) { diff --git a/src/algorithms/math/reservoir_sampling.js b/src/algorithms/math/reservoir_sampling.js index e3f59aa..ef49588 100644 --- a/src/algorithms/math/reservoir_sampling.js +++ b/src/algorithms/math/reservoir_sampling.js @@ -7,7 +7,7 @@ * @param {number} sampleSize * @return {Array} */ -const reservoirSampling = function(array, sampleSize) { +const reservoirSampling = (array, sampleSize) => { if (sampleSize > array.length) { throw new Error('Sample size exceeds the total number of elements.'); } diff --git a/src/algorithms/math/shannon_entropy.js b/src/algorithms/math/shannon_entropy.js index 96bb719..7696de9 100644 --- a/src/algorithms/math/shannon_entropy.js +++ b/src/algorithms/math/shannon_entropy.js @@ -6,22 +6,18 @@ * @param {Array} arr - An array of values. * @return Number */ -const shannonEntropy = function(arr) { +const shannonEntropy = arr => { // find the frequency of each value - const freqs = arr.reduce(function(acc, item) { + const freqs = arr.reduce((acc, item) => { acc[item] = acc[item] + 1 || 1; return acc; }, {}); // find the probability of each value - const probs = Object.keys(freqs).map(function(key) { - return freqs[key] / arr.length; - }); + const probs = Object.keys(freqs).map(key => freqs[key] / arr.length); // calulate the shannon entropy of the array - return probs.reduce(function(e, p) { - return e - p * Math.log(p); - }, 0) * Math.LOG2E; + return probs.reduce((e, p) => e - p * Math.log(p), 0) * Math.LOG2E; }; module.exports = shannonEntropy; diff --git a/src/algorithms/search/bfs.js b/src/algorithms/search/bfs.js index a261625..36d0815 100644 --- a/src/algorithms/search/bfs.js +++ b/src/algorithms/search/bfs.js @@ -4,7 +4,7 @@ const Queue = require('../../data_structures/queue.js'); /** * Breadth-first search for binary trees */ -const bfs = function(root, callback) { +const bfs = (root, callback) => { const q = new Queue(); q.push(root); let node; diff --git a/src/algorithms/search/binarysearch.js b/src/algorithms/search/binarysearch.js index 550a690..2ad9db7 100644 --- a/src/algorithms/search/binarysearch.js +++ b/src/algorithms/search/binarysearch.js @@ -9,7 +9,7 @@ * * @return Boolean */ -const binarySearch = function(sortedArray, element) { +const binarySearch = (sortedArray, element) => { let init = 0; let end = sortedArray.length - 1; diff --git a/src/algorithms/search/dfs.js b/src/algorithms/search/dfs.js index 75d46de..147c477 100644 --- a/src/algorithms/search/dfs.js +++ b/src/algorithms/search/dfs.js @@ -4,7 +4,7 @@ * Depth first search for trees * (in order) */ -const inOrder = function(node, callback) { +const inOrder = (node, callback) => { if (node) { inOrder(node.left, callback); callback(node.value); @@ -15,7 +15,7 @@ const inOrder = function(node, callback) { /** * Pre order */ -const preOrder = function(node, callback) { +const preOrder = (node, callback) => { if (node) { callback(node.value); preOrder(node.left, callback); @@ -26,7 +26,7 @@ const preOrder = function(node, callback) { /** * Post order */ -const postOrder = function(node, callback) { +const postOrder = (node, callback) => { if (node) { postOrder(node.left, callback); postOrder(node.right, callback); diff --git a/src/algorithms/search/ternary_search.js b/src/algorithms/search/ternary_search.js index 64ec585..4fdfd7e 100644 --- a/src/algorithms/search/ternary_search.js +++ b/src/algorithms/search/ternary_search.js @@ -6,7 +6,7 @@ * Time complexity: O(log(n)) */ -const ternarySearch = function(fn, left, right, precision) { +const ternarySearch = (fn, left, right, precision) => { while (Math.abs(right - left) > precision) { const leftThird = left + (right - left) / 3; const rightThird = right - (right - left) / 3; diff --git a/src/algorithms/sorting/bubble_sort.js b/src/algorithms/sorting/bubble_sort.js index d809049..caf469d 100644 --- a/src/algorithms/sorting/bubble_sort.js +++ b/src/algorithms/sorting/bubble_sort.js @@ -4,7 +4,7 @@ const Comparator = require('../../util/comparator'); /** * Bubble sort algorithm O(n^2) */ -const bubbleSort = function(a, comparatorFn) { +const bubbleSort = (a, comparatorFn) => { const comparator = new Comparator(comparatorFn); const n = a.length; let bound = n - 1; diff --git a/src/algorithms/sorting/counting_sort.js b/src/algorithms/sorting/counting_sort.js index 97ebded..7b3b11b 100644 --- a/src/algorithms/sorting/counting_sort.js +++ b/src/algorithms/sorting/counting_sort.js @@ -8,7 +8,7 @@ * @param Array * @return Integer */ -const maximumKey = function(array) { +const maximumKey = array => { let max = array[0].key; const length = array.length; @@ -32,7 +32,7 @@ const maximumKey = function(array) { * @param Array * @return Array */ -const countingSort = function(array) { +const countingSort = array => { const max = maximumKey(array); const auxiliaryArray = []; const length = array.length; diff --git a/src/algorithms/sorting/heap_sort.js b/src/algorithms/sorting/heap_sort.js index 227b47b..86cf043 100644 --- a/src/algorithms/sorting/heap_sort.js +++ b/src/algorithms/sorting/heap_sort.js @@ -6,7 +6,7 @@ const MinHeap = require('../../data_structures/heap').MinHeap; * iteratively removes the smallest element of the heap until it's * empty. The time complexity of the algorithm is O(n.lg n) */ -const heapsort = function(array, comparatorFn) { +const heapsort = (array, comparatorFn) => { const minHeap = new MinHeap(comparatorFn); minHeap.heapify(array); diff --git a/src/algorithms/sorting/insertion_sort.js b/src/algorithms/sorting/insertion_sort.js index e91e909..a139ed6 100644 --- a/src/algorithms/sorting/insertion_sort.js +++ b/src/algorithms/sorting/insertion_sort.js @@ -4,7 +4,7 @@ const Comparator = require('../../util/comparator'); /** * Insertion sort algorithm O(n + d) */ -const insertionSort = function(vector, comparatorFn) { +const insertionSort = (vector, comparatorFn) => { const comparator = new Comparator(comparatorFn); for (let i = 1, len = vector.length; i < len; i++) { diff --git a/src/algorithms/sorting/merge_sort.js b/src/algorithms/sorting/merge_sort.js index ebed429..0ca5b18 100644 --- a/src/algorithms/sorting/merge_sort.js +++ b/src/algorithms/sorting/merge_sort.js @@ -1,7 +1,7 @@ 'use strict'; const Comparator = require('../../util/comparator'); -const merge = function(a, b, comparator) { +const merge = (a, b, comparator) => { let i = 0; let j = 0; const result = []; @@ -19,7 +19,7 @@ const merge = function(a, b, comparator) { * Merge sort * O(n.lgn) */ -const mergeSortInit = function(a, compareFn) { +const mergeSortInit = (a, compareFn) => { const comparator = new Comparator(compareFn); return (function mergeSort(a) { diff --git a/src/algorithms/sorting/quicksort.js b/src/algorithms/sorting/quicksort.js index b1a0648..5661677 100644 --- a/src/algorithms/sorting/quicksort.js +++ b/src/algorithms/sorting/quicksort.js @@ -4,7 +4,7 @@ const Comparator = require('../../util/comparator'); /** * Swaps two elements in the array */ -const swap = function(array, x, y) { +const swap = (array, x, y) => { const tmp = array[y]; array[y] = array[x]; array[x] = tmp; @@ -17,7 +17,7 @@ const swap = function(array, x, y) { * * @return Number the positon of the pivot */ -const partition = function(a, comparator, lo, hi) { +const partition = (a, comparator, lo, hi) => { // pick a random element, swap with the rightmost and // use it as pivot swap(a, Math.floor(Math.random() * (hi - lo)) + lo, hi); @@ -41,7 +41,7 @@ const partition = function(a, comparator, lo, hi) { * Quicksort recursively sorts parts of the array in * O(n.lg n) */ -const quicksortInit = function(array, comparatorFn) { +const quicksortInit = (array, comparatorFn) => { const comparator = new Comparator(comparatorFn); return (function quicksort(array, lo, hi) { diff --git a/src/algorithms/sorting/radix_sort.js b/src/algorithms/sorting/radix_sort.js index c51b1e3..f98b71f 100644 --- a/src/algorithms/sorting/radix_sort.js +++ b/src/algorithms/sorting/radix_sort.js @@ -13,7 +13,7 @@ * @param Array * @return Array */ -const auxiliaryCountingSort = function(array, mod) { +const auxiliaryCountingSort = (array, mod) => { const length = array.length; const bucket = []; let i; @@ -50,7 +50,7 @@ const auxiliaryCountingSort = function(array, mod) { * @return Integer if array non-empty * Undefined otherwise */ -const maximumKey = function(a) { +const maximumKey = a => { let max; for (let i = 1; i < a.length; i++) { if (max === undefined || a[i].key > max) { @@ -71,7 +71,7 @@ const maximumKey = function(a) { * @param Array * @return Array */ -const radixSort = function(array) { +const radixSort = array => { const max = maximumKey(array); const digitsMax = (max === 0 ? 1 : 1 + Math.floor(Math.log(max) / Math.log(10))); // log base 10 diff --git a/src/algorithms/sorting/selection_sort.js b/src/algorithms/sorting/selection_sort.js index de73d42..0197e93 100644 --- a/src/algorithms/sorting/selection_sort.js +++ b/src/algorithms/sorting/selection_sort.js @@ -3,7 +3,7 @@ const Comparator = require('../../util/comparator'); /** * Selection sort algorithm O(n^2) */ -const selectionSort = function(a, comparatorFn) { +const selectionSort = (a, comparatorFn) => { const comparator = new Comparator(comparatorFn); const n = a.length; for (let i = 0; i < n - 1; i++) { diff --git a/src/algorithms/sorting/shell_sort.js b/src/algorithms/sorting/shell_sort.js index 836f040..c537e0a 100644 --- a/src/algorithms/sorting/shell_sort.js +++ b/src/algorithms/sorting/shell_sort.js @@ -3,7 +3,7 @@ const Comparator = require('../../util/comparator'); /** * shell sort worst:O(n lg n) best:O(n) */ -const shellSort = function(array, comparatorFn) { +const shellSort = (array, comparatorFn) => { const comparator = new Comparator(comparatorFn); let gap = Math.floor(array.length / 2); diff --git a/src/algorithms/string/hamming.js b/src/algorithms/string/hamming.js index feabdea..a595e76 100644 --- a/src/algorithms/string/hamming.js +++ b/src/algorithms/string/hamming.js @@ -8,7 +8,7 @@ */ 'use strict'; -const hamming = function(a, b) { +const hamming = (a, b) => { if (a.length !== b.length) { throw new Error('Strings must be equal in length'); } diff --git a/src/algorithms/string/huffman.js b/src/algorithms/string/huffman.js index e35b43e..036978b 100644 --- a/src/algorithms/string/huffman.js +++ b/src/algorithms/string/huffman.js @@ -15,12 +15,12 @@ const MAX_BLOCK_SIZE = (-1 >>> 0).toString(2).length; * @param {string} string * @return {number[]} */ -const compress = function(string) { +const compress = string => { const blocks = []; let currentBlock = 0; let currentBlockSize = 0; - string.split('').forEach(function(char) { + string.split('').forEach(char => { currentBlock = (currentBlock << 1) | char; currentBlockSize += 1; @@ -46,7 +46,7 @@ const compress = function(string) { * @param {number[]} array * @return {string} */ -const decompress = function(array) { +const decompress = array => { if (!array.length) { return ''; } else if (array.length === 1) { @@ -56,9 +56,7 @@ const decompress = function(array) { const padding = new Array(MAX_BLOCK_SIZE + 1).join(0); - let string = array.slice(0, -2).map(function(block) { - return (padding + (block >>> 0).toString(2)).slice(-padding.length); - }).join(''); + let string = array.slice(0, -2).map(block => (padding + (block >>> 0).toString(2)).slice(-padding.length)).join(''); // Append the last block. const lastBlockSize = array.slice(-1)[0]; @@ -75,7 +73,7 @@ const decompress = function(array) { * @param {boolean} [compressed=false] - Whether compress the string to bits. * @return {{encoding: Object., value: string|number[]}} */ -huffman.encode = function(string, compressed) { +huffman.encode = (string, compressed) => { if (!string.length) { return { encoding: {}, @@ -84,23 +82,17 @@ huffman.encode = function(string, compressed) { } const counter = {}; - string.split('').forEach(function(char) { + string.split('').forEach(char => { counter[char] = (counter[char] || 0) + 1; }); - const letters = Object.keys(counter).map(function(char) { - return { - char: char, - count: counter[char] - }; - }); + const letters = Object.keys(counter).map(char => ({ + char: char, + count: counter[char] + })); - const compare = function(a, b) { - return a.count - b.count; - }; - const less = function(a, b) { - return a && (b && (a.count < b.count) || !b); - }; + const compare = (a, b) => a.count - b.count; + const less = (a, b) => a && (b && (a.count < b.count) || !b); letters.sort(compare); @@ -111,10 +103,8 @@ huffman.encode = function(string, compressed) { let lettersIndex = 0; let bufferIndex = 0; - const extractMinimum = function() { - return less(letters[lettersIndex], buffer[bufferIndex]) ? - letters[lettersIndex++] : buffer[bufferIndex++]; - }; + const extractMinimum = () => less(letters[lettersIndex], buffer[bufferIndex]) ? + letters[lettersIndex++] : buffer[bufferIndex++]; for (let numLetters = letters.length; numLetters > 1; --numLetters) { const a = extractMinimum(); @@ -144,15 +134,13 @@ huffman.encode = function(string, compressed) { } })(root); - const encoding = letters.reduce(function(acc, letter) { + const encoding = letters.reduce((acc, letter) => { acc[letter.char] = letter.code.split('').reverse().join(''); return acc; }, {}); // Finally, apply the encoding to the given string. - const result = string.split('').map(function(char) { - return encoding[char]; - }).join(''); + const result = string.split('').map(char => encoding[char]).join(''); return { encoding: encoding, @@ -167,21 +155,21 @@ huffman.encode = function(string, compressed) { * @param {string|number[]} encodedString * @return {string} Decoded string. */ -huffman.decode = function(encoding, encodedString) { +huffman.decode = (encoding, encodedString) => { if (Array.isArray(encodedString)) { encodedString = decompress(encodedString); } // We can make use of the fact that encoding mapping is always one-to-one // and rely on the power of JS hashes instead of building hand-made FSMs. - const letterByCode = Object.keys(encoding).reduce(function(acc, letter) { + const letterByCode = Object.keys(encoding).reduce((acc, letter) => { acc[encoding[letter]] = letter; return acc; }, {}); const decodedLetters = []; - const unresolved = encodedString.split('').reduce(function(code, char) { + const unresolved = encodedString.split('').reduce((code, char) => { code += char; const letter = letterByCode[code]; if (letter) { diff --git a/src/algorithms/string/knuth_morris_pratt.js b/src/algorithms/string/knuth_morris_pratt.js index e84ed12..f2cc209 100644 --- a/src/algorithms/string/knuth_morris_pratt.js +++ b/src/algorithms/string/knuth_morris_pratt.js @@ -10,7 +10,7 @@ * or {String} * @return {Array} of Integers */ -const buildTable = function(pattern) { +const buildTable = pattern => { const length = pattern.length; const table = []; let position = 2; @@ -50,7 +50,7 @@ const buildTable = function(pattern) { * or {String} * @return {Number} */ -const knuthMorrisPratt = function(text, pattern) { +const knuthMorrisPratt = (text, pattern) => { const textLength = text.length; const patternLength = pattern.length; let m = 0; diff --git a/src/algorithms/string/levenshtein.js b/src/algorithms/string/levenshtein.js index b495211..739bb6b 100644 --- a/src/algorithms/string/levenshtein.js +++ b/src/algorithms/string/levenshtein.js @@ -15,7 +15,7 @@ * @param String * @return Number */ -const levenshtein = function(a, b) { +const levenshtein = (a, b) => { const editDistance = []; let i; let j; diff --git a/src/algorithms/string/longest_common_subsequence.js b/src/algorithms/string/longest_common_subsequence.js index 60c6d80..444b5a4 100644 --- a/src/algorithms/string/longest_common_subsequence.js +++ b/src/algorithms/string/longest_common_subsequence.js @@ -7,7 +7,7 @@ /** * Implementation via dynamic programming */ -const longestCommonSubsequence = function(s1, s2) { +const longestCommonSubsequence = (s1, s2) => { // Multidimensional array for dynamic programming algorithm const cache = new Array(s1.length + 1); diff --git a/src/algorithms/string/longest_common_substring.js b/src/algorithms/string/longest_common_substring.js index 020e92e..6e3015f 100644 --- a/src/algorithms/string/longest_common_substring.js +++ b/src/algorithms/string/longest_common_substring.js @@ -7,7 +7,7 @@ /** * Implementation via dynamic programming */ -const longestCommonSubstring = function(s1, s2) { +const longestCommonSubstring = (s1, s2) => { // Multidimensional array for dynamic programming algorithm const cache = new Array(s1.length + 1); diff --git a/src/algorithms/string/rabin_karp.js b/src/algorithms/string/rabin_karp.js index c998d67..de4ce25 100644 --- a/src/algorithms/string/rabin_karp.js +++ b/src/algorithms/string/rabin_karp.js @@ -15,7 +15,7 @@ const base = 997; * @param String * @return Number */ -const hash = function(word) { +const hash = word => { let h = 0; for (let i = 0; i < word.length; i++) { @@ -36,7 +36,7 @@ const hash = function(word) { * @param String * @return Integer */ -const rabinKarp = function(s, pattern) { +const rabinKarp = (s, pattern) => { if (pattern.length === 0) return 0; const hashPattern = hash(pattern); diff --git a/src/data_structures/avl_tree.js b/src/data_structures/avl_tree.js index 077f6dc..b01d46f 100644 --- a/src/data_structures/avl_tree.js +++ b/src/data_structures/avl_tree.js @@ -22,7 +22,7 @@ function Node(value, left, right, parent, height) { * Calculates the height of a node based on height * property of all his children. */ -AVLTree.prototype.getNodeHeight = function(node) { +AVLTree.prototype.getNodeHeight = node => { let height = 1; if (node.left !== null && node.right !== null) { height = Math.max(node.left.height, node.right.height) + 1; @@ -37,7 +37,7 @@ AVLTree.prototype.getNodeHeight = function(node) { /** * Verifies if the given node is balanced. */ -AVLTree.prototype.isNodeBalanced = function(node) { +AVLTree.prototype.isNodeBalanced = node => { let isBalanced = true; if (node.left !== null && node.right !== null) { @@ -54,7 +54,7 @@ AVLTree.prototype.isNodeBalanced = function(node) { * When a removal happens, some nodes need to be * restructured. Gets and return these nodes. */ -AVLTree.prototype.getNodesToRestructureAfterRemove = function(traveledNodes) { +AVLTree.prototype.getNodesToRestructureAfterRemove = traveledNodes => { // z is last traveled node - imbalance found at z const zIndex = traveledNodes.length - 1; const z = traveledNodes[zIndex]; @@ -94,7 +94,7 @@ AVLTree.prototype.getNodesToRestructureAfterRemove = function(traveledNodes) { * When a insertion happens, some nodes need to be * restructured. Gets and return these nodes. */ -AVLTree.prototype.getNodesToRestructureAfterInsert = function(traveledNodes) { +AVLTree.prototype.getNodesToRestructureAfterInsert = traveledNodes => { // z is last traveled node - imbalance found at z const zIndex = traveledNodes.length - 1; const z = traveledNodes[zIndex]; diff --git a/src/data_structures/bst.js b/src/data_structures/bst.js index f546dbc..81aeeb0 100644 --- a/src/data_structures/bst.js +++ b/src/data_structures/bst.js @@ -16,9 +16,7 @@ function BST(compareFn) { * Read-only property for the size of the tree */ Object.defineProperty(this, 'size', { - get: function() { - return this._size; - }.bind(this) + get: () => this._size }); } @@ -96,7 +94,7 @@ BST.prototype._replaceNodeInParent = function(currNode, newNode) { /** * Find the minimum value in a tree */ -BST.prototype._findMin = function(root) { +BST.prototype._findMin = root => { let minNode = root; while (minNode.left) { minNode = minNode.left; diff --git a/src/data_structures/disjoint_set_forest.js b/src/data_structures/disjoint_set_forest.js index cb53631..e120446 100644 --- a/src/data_structures/disjoint_set_forest.js +++ b/src/data_structures/disjoint_set_forest.js @@ -31,10 +31,10 @@ DisjointSetForest.prototype._introduce = function(element) { DisjointSetForest.prototype.sameSubset = function(element) { this._introduce(element); const root = this.root(element); - return [].slice.call(arguments, 1).every(function(element) { + return [].slice.call(arguments, 1).every(element => { this._introduce(element); return this.root(element) === root; - }.bind(this)); + }); }; /** diff --git a/src/data_structures/graph.js b/src/data_structures/graph.js index 8df2ae0..cda7288 100644 --- a/src/data_structures/graph.js +++ b/src/data_structures/graph.js @@ -13,9 +13,7 @@ function Graph(directed) { } // Normalize vertex labels as strings -const _ = function(v) { - return String(v); -}; +const _ = v => String(v); Graph.prototype.addVertex = function(v) { v = _(v); @@ -57,12 +55,12 @@ Graph.prototype.reverse = function() { const self = this; const r = new Graph(this.directed); - self.vertices.forEach(function(v) { + self.vertices.forEach(v => { r.addVertex(v); }); - self.vertices.forEach(function(a) { - self.neighbors(a).forEach(function(b) { + self.vertices.forEach(a => { + self.neighbors(a).forEach(b => { r.addEdge(b, a, self.edge(a, b)); }); }); diff --git a/src/data_structures/hash_table.js b/src/data_structures/hash_table.js index e625882..f46c563 100644 --- a/src/data_structures/hash_table.js +++ b/src/data_structures/hash_table.js @@ -31,7 +31,7 @@ function HashTable(initialCapacity) { * n is the length of the string, and ^ indicates exponentiation. * (The hash value of the empty string is zero.) */ -HashTable.prototype.hash = function(s) { +HashTable.prototype.hash = s => { if (typeof s !== 'string') s = JSON.stringify(s); let hash = 0; for (let i = 0; i < s.length; i++) { @@ -85,7 +85,7 @@ HashTable.prototype._position = function(key) { return Math.abs(this.hash(key)) % this.capacity; }; -HashTable.prototype._findInList = function(list, key) { +HashTable.prototype._findInList = (list, key) => { let node = list && list.head; while (node) { if (node.value.k === key) return node; @@ -108,8 +108,8 @@ HashTable.prototype._increaseCapacity = function() { }; HashTable.prototype.forEach = function(fn) { - const applyFunction = function(linkedList) { - linkedList.forEach(function(elem) { + const applyFunction = linkedList => { + linkedList.forEach(elem => { fn(elem.k, elem.v); }); }; diff --git a/src/data_structures/heap.js b/src/data_structures/heap.js index 11c9857..eb9c4a6 100644 --- a/src/data_structures/heap.js +++ b/src/data_structures/heap.js @@ -9,9 +9,7 @@ function MinHeap(compareFn) { this._comparator = new Comparator(compareFn); Object.defineProperty(this, 'n', { - get: function() { - return this._elements.length - 1; - }.bind(this) + get: () => this._elements.length - 1 }); } diff --git a/src/data_structures/linked_list.js b/src/data_structures/linked_list.js index 82966d5..647faef 100644 --- a/src/data_structures/linked_list.js +++ b/src/data_structures/linked_list.js @@ -10,9 +10,7 @@ function LinkedList() { // Read-only length property Object.defineProperty(this, 'length', { - get: function() { - return this._length; - }.bind(this) + get: () => this._length }); } diff --git a/src/data_structures/priority_queue.js b/src/data_structures/priority_queue.js index df383e7..c106573 100644 --- a/src/data_structures/priority_queue.js +++ b/src/data_structures/priority_queue.js @@ -9,14 +9,12 @@ const MinHeap = require('./heap').MinHeap; */ function PriorityQueue(initialItems) { const self = this; - MinHeap.call(this, function(a, b) { - return self.priority(a) < self.priority(b) ? -1 : 1; - }); + MinHeap.call(this, (a, b) => self.priority(a) < self.priority(b) ? -1 : 1); this._priority = {}; initialItems = initialItems || {}; - Object.keys(initialItems).forEach(function(item) { + Object.keys(initialItems).forEach(item => { self.insert(item, initialItems[item]); }); } diff --git a/src/data_structures/queue.js b/src/data_structures/queue.js index 1f3d381..1c49f6d 100644 --- a/src/data_structures/queue.js +++ b/src/data_structures/queue.js @@ -9,9 +9,7 @@ function Queue() { this._elements = new LinkedList(); Object.defineProperty(this, 'length', { - get: function() { - return this._elements.length; - }.bind(this) + get: () => this._elements.length }); } diff --git a/src/data_structures/stack.js b/src/data_structures/stack.js index e29fc14..13e151a 100644 --- a/src/data_structures/stack.js +++ b/src/data_structures/stack.js @@ -8,9 +8,7 @@ function Stack() { this._elements = new LinkedList(); Object.defineProperty(this, 'length', { - get: (function() { - return this._elements.length; - }).bind(this) + get: () => this._elements.length }); } diff --git a/src/test/algorithms/geometry/bezier_curve.js b/src/test/algorithms/geometry/bezier_curve.js index fb49872..d04c6b4 100644 --- a/src/test/algorithms/geometry/bezier_curve.js +++ b/src/test/algorithms/geometry/bezier_curve.js @@ -6,8 +6,8 @@ const assert = require('assert'); // Testing with http://pomax.github.io/bezierjs/ -describe('Bézier-Curve Algorithm', function() { - it('should get a linear Bézier-curve', function() { +describe('Bézier-Curve Algorithm', () => { + it('should get a linear Bézier-curve', () => { const b = new BezierCurve([{x: 0, y: 0}, {x: 10, y: 3}]); // Ends @@ -21,7 +21,7 @@ describe('Bézier-Curve Algorithm', function() { assert.deepEqual(b.get(0.25), {x: 2.5, y: 0.75}); assert.deepEqual(b.get(0.75), {x: 7.5, y: 2.25}); }); - it('should get a quadratic Bézier-curve', function() { + it('should get a quadratic Bézier-curve', () => { const b = new BezierCurve([{x: 150, y: 40}, {x: 80, y: 30}, {x: 105, y: 150}]); @@ -29,7 +29,7 @@ describe('Bézier-Curve Algorithm', function() { assert.deepEqual(b.get(0.5), {x: 103.75, y: 62.5}); assert.deepEqual(b.get(0.25), {x: 120.9375, y: 43.125}); }); - it('should get a cubic Bézier-curve', function() { + it('should get a cubic Bézier-curve', () => { const b = new BezierCurve([{x: 150, y: 40}, {x: 80, y: 30}, {x: 105, y: 150}, diff --git a/src/test/algorithms/graph/SPFA.js b/src/test/algorithms/graph/SPFA.js index c184d37..5b9b1d3 100644 --- a/src/test/algorithms/graph/SPFA.js +++ b/src/test/algorithms/graph/SPFA.js @@ -5,9 +5,9 @@ const spfa = root.Graph.SPFA; const Graph = root.DataStructures.Graph; const assert = require('assert'); -describe('SPFA Algorithm', function() { +describe('SPFA Algorithm', () => { it('should return the shortest paths to all nodes from a given origin', - function() { + () => { const graph = new Graph(true); graph.addEdge('a', 'b', -1); diff --git a/src/test/algorithms/graph/bellman_ford.js b/src/test/algorithms/graph/bellman_ford.js index 92f38b3..70e18bf 100644 --- a/src/test/algorithms/graph/bellman_ford.js +++ b/src/test/algorithms/graph/bellman_ford.js @@ -5,9 +5,9 @@ const bellmanFord = root.Graph.bellmanFord; const Graph = root.DataStructures.Graph; const assert = require('assert'); -describe('Bellman-Ford Algorithm', function() { +describe('Bellman-Ford Algorithm', () => { it('should return the shortest paths to all nodes from a given origin', - function() { + () => { const graph = new Graph(true); graph.addEdge('a', 'b', -1); diff --git a/src/test/algorithms/graph/bfs_shortest_path.js b/src/test/algorithms/graph/bfs_shortest_path.js index efbeb27..b8d983c 100644 --- a/src/test/algorithms/graph/bfs_shortest_path.js +++ b/src/test/algorithms/graph/bfs_shortest_path.js @@ -5,9 +5,9 @@ const bfsShortestPath = root.Graph.bfsShortestPath; const Graph = root.DataStructures.Graph; const assert = require('assert'); -describe('BFS Shortest Path Algorithm', function() { +describe('BFS Shortest Path Algorithm', () => { it('should return the shortest paths to all nodes from a given origin', - function() { + () => { const graph = new Graph(); graph.addEdge(0, 1); graph.addEdge(1, 2); diff --git a/src/test/algorithms/graph/breadth_first_search.js b/src/test/algorithms/graph/breadth_first_search.js index 700b531..b34a29b 100644 --- a/src/test/algorithms/graph/breadth_first_search.js +++ b/src/test/algorithms/graph/breadth_first_search.js @@ -5,10 +5,10 @@ const breadthFirstSearch = root.Graph.breadthFirstSearch; const Graph = root.DataStructures.Graph; const assert = require('assert'); -describe('Breadth-First Search', function() { +describe('Breadth-First Search', () => { let graph; - before(function() { + before(() => { graph = new Graph(); graph.addEdge(1, 2); graph.addEdge(1, 5); @@ -21,7 +21,7 @@ describe('Breadth-First Search', function() { graph.addEdge('alpha', 'omega'); }); - it('should visit reachable vertices in a breadth-first manner', function() { + it('should visit reachable vertices in a breadth-first manner', () => { const enter = []; const leave = []; let lastEntered = null; @@ -53,7 +53,7 @@ describe('Breadth-First Search', function() { assert.equal(enter[5], 3); }); - it('should allow user-defined allowTraversal rules', function() { + it('should allow user-defined allowTraversal rules', () => { const seen = new Graph(graph.directed); graph.vertices.forEach(seen.addVertex.bind(seen)); const indegrees = {1: -1}; diff --git a/src/test/algorithms/graph/depth_first_search.js b/src/test/algorithms/graph/depth_first_search.js index f6f1530..a3db664 100644 --- a/src/test/algorithms/graph/depth_first_search.js +++ b/src/test/algorithms/graph/depth_first_search.js @@ -5,9 +5,9 @@ const depthFirstSearch = root.Graph.depthFirstSearch; const Graph = root.DataStructures.Graph; const assert = require('assert'); -describe('Depth First Search Algorithm', function() { +describe('Depth First Search Algorithm', () => { let graph; - before(function() { + before(() => { graph = new Graph(true); graph.addEdge('one', 'three'); graph.addEdge('one', 'four'); @@ -18,7 +18,7 @@ describe('Depth First Search Algorithm', function() { }); it('should visit only the nodes reachable from the start node (inclusive)', - function() { + () => { const enter = []; const leave = []; let numEdgeTails = 0; @@ -53,7 +53,7 @@ describe('Depth First Search Algorithm', function() { } ); - it('should allow user-defined allowTraversal rules', function() { + it('should allow user-defined allowTraversal rules', () => { const seen = new Graph(graph.directed); graph.vertices.forEach(seen.addVertex.bind(seen)); const path = ['one']; diff --git a/src/test/algorithms/graph/dijkstra.js b/src/test/algorithms/graph/dijkstra.js index 96a9174..17287ef 100644 --- a/src/test/algorithms/graph/dijkstra.js +++ b/src/test/algorithms/graph/dijkstra.js @@ -5,9 +5,9 @@ const dijkstra = root.Graph.dijkstra; const Graph = root.DataStructures.Graph; const assert = require('assert'); -describe('Dijkstra Algorithm', function() { +describe('Dijkstra Algorithm', () => { it('should return the shortest paths to all nodes from a given origin', - function() { + () => { const g = new Graph(); g.addEdge('a', 'b', 5); g.addEdge('a', 'c', 10); diff --git a/src/test/algorithms/graph/euler_path.js b/src/test/algorithms/graph/euler_path.js index 7742988..dc2b27d 100644 --- a/src/test/algorithms/graph/euler_path.js +++ b/src/test/algorithms/graph/euler_path.js @@ -5,33 +5,33 @@ const eulerPath = root.Graph.eulerPath; const Graph = root.DataStructures.Graph; const assert = require('assert'); -describe('Euler Path', function() { - const verifyEulerPath = function(graph, trail) { +describe('Euler Path', () => { + const verifyEulerPath = (graph, trail) => { const visited = new Graph(graph.directed); graph.vertices.forEach(visited.addVertex.bind(visited)); - trail.slice(1).reduce(function(previous, current) { + trail.slice(1).reduce((previous, current) => { assert(graph.edge(previous, current)); assert(!visited.edge(previous, current)); visited.addEdge(previous, current); return current; }, trail[0]); - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(vertex => { assert.equal(graph.neighbors(vertex).length, visited.neighbors(vertex).length); }); }; - const graphFromEdges = function(directed, edges) { + const graphFromEdges = (directed, edges) => { const graph = new Graph(directed); - edges.forEach(function(edge) { + edges.forEach(edge => { graph.addEdge(edge[0], edge[1]); }); return graph; }; - it('should compute Euler tour over the undirected graph', function() { + it('should compute Euler tour over the undirected graph', () => { const graph = graphFromEdges(false, [ [1, 2], [1, 5], @@ -54,7 +54,7 @@ describe('Euler Path', function() { assert.equal(trail[0], trail.slice(-1)[0]); }); - it('should compute Euler walk over the undirected graph', function() { + it('should compute Euler walk over the undirected graph', () => { const graph = graphFromEdges(false, [ [1, 2], [1, 5], @@ -79,7 +79,7 @@ describe('Euler Path', function() { assert.equal(endpoints[1], 8); }); - it('should compute Euler tour over the directed graph', function() { + it('should compute Euler tour over the directed graph', () => { const graph = graphFromEdges(true, [ [0, 1], [1, 2], @@ -97,7 +97,7 @@ describe('Euler Path', function() { assert.equal(trail[0], trail.slice(-1)[0]); }); - it('should compute Euler walk over the directed graph', function() { + it('should compute Euler walk over the directed graph', () => { const graph = graphFromEdges(true, [ [5, 0], [0, 2], @@ -111,20 +111,20 @@ describe('Euler Path', function() { assert.deepEqual(trail, [5, 3, 1, 5, 0, 2, 4, 0]); }); - it('should return single-vertex-trail for an isolated vertex', function() { + it('should return single-vertex-trail for an isolated vertex', () => { const graph = new Graph(); graph.addVertex('loner'); const trail = eulerPath(graph); assert.deepEqual(trail, ['loner']); }); - it('should return empty trail for an empty graph', function() { + it('should return empty trail for an empty graph', () => { const graph = new Graph(); const trail = eulerPath(graph); assert.deepEqual(trail, []); }); - it('should raise an error if there is no Euler path', function() { + it('should raise an error if there is no Euler path', () => { let graph = graphFromEdges(false, [[0, 1], [2, 3]]); assert.throws(eulerPath.bind(null, graph)); diff --git a/src/test/algorithms/graph/floyd_warshall.js b/src/test/algorithms/graph/floyd_warshall.js index 380aeb5..1f52ed9 100644 --- a/src/test/algorithms/graph/floyd_warshall.js +++ b/src/test/algorithms/graph/floyd_warshall.js @@ -5,8 +5,8 @@ const floydWarshall = root.Graph.floydWarshall; const Graph = root.DataStructures.Graph; const assert = require('assert'); -describe('Floyd-Warshall Algorithm', function() { - it('should compute all-pairs shortest paths in the graph', function() { +describe('Floyd-Warshall Algorithm', () => { + it('should compute all-pairs shortest paths in the graph', () => { const graph = new Graph(); graph.addEdge('a', 'b', -2); graph.addEdge('b', 'c', -1); @@ -62,7 +62,7 @@ describe('Floyd-Warshall Algorithm', function() { }); it('should determine if the graph contains a negative-weighted cycle', - function() { + () => { const graph = new Graph(); graph.addEdge('a', 'b', -2); graph.addEdge('b', 'c', -1); diff --git a/src/test/algorithms/graph/minimum_spanning_tree.js b/src/test/algorithms/graph/minimum_spanning_tree.js index bd57edf..e35f006 100644 --- a/src/test/algorithms/graph/minimum_spanning_tree.js +++ b/src/test/algorithms/graph/minimum_spanning_tree.js @@ -7,15 +7,15 @@ const depthFirstSearch = root.Graph.depthFirstSearch; const Graph = root.DataStructures.Graph; const assert = require('assert'); -describe('Minimum Spanning Tree', function() { +describe('Minimum Spanning Tree', () => { /** * @param {Graph} graph - Undirected graph. * @return {number} */ - const numberOfConnectedComponents = function(graph) { + const numberOfConnectedComponents = graph => { assert(!graph.directed); const seen = {}; - const coverComponent = function(origin) { + const coverComponent = origin => { depthFirstSearch(graph, origin, { enterVertex: function(vertex) { seen[vertex] = true; @@ -24,7 +24,7 @@ describe('Minimum Spanning Tree', function() { }; let count = 0; - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(vertex => { if (!seen[vertex]) { coverComponent(vertex); count++; @@ -41,16 +41,14 @@ describe('Minimum Spanning Tree', function() { * @param {number} connectivity * @return {boolean} */ - const isForest = function(graph, connectivity) { + const isForest = (graph, connectivity) => { if (graph.directed || numberOfConnectedComponents(graph) !== connectivity) { return false; } let numberOfEdges = 0; - graph.vertices.forEach(function(vertex) { + graph.vertices.forEach(vertex => { numberOfEdges += graph.neighbors(vertex).filter( - function(neighbor) { - return vertex <= neighbor; - }).length; + neighbor => vertex <= neighbor).length; }); return graph.vertices.size === numberOfEdges + connectivity; }; @@ -62,11 +60,11 @@ describe('Minimum Spanning Tree', function() { * @param {Graph} graph2 * @return {boolean} */ - const spans = function(graph1, graph2) { + const spans = (graph1, graph2) => { let span; if (graph1.vertices.size === graph2.vertices.size) { span = true; - graph1.vertices.forEach(function(v) { + graph1.vertices.forEach(v => { if (!graph2.vertices.contains(v)) { span = false; } @@ -83,12 +81,10 @@ describe('Minimum Spanning Tree', function() { * @param {Graph} graph * @return {number} */ - const graphCost = function(graph) { + const graphCost = graph => { let total = 0; - graph.vertices.forEach(function(vertex) { - total += graph.neighbors(vertex).reduce(function(accum, neighbor) { - return accum + graph.edge(vertex, neighbor); - }, 0); + graph.vertices.forEach(vertex => { + total += graph.neighbors(vertex).reduce((accum, neighbor) => accum + graph.edge(vertex, neighbor), 0); }); return graph.directed ? total : total / 2; }; @@ -102,16 +98,15 @@ describe('Minimum Spanning Tree', function() { * @param {number} [connectivity=1] * @return {boolean} */ - const isMinimumSpanningForest = function(suspect, graph, - minimumCost, connectivity) { + const isMinimumSpanningForest = (suspect, graph, minimumCost, connectivity) => { assert(!graph.directed); return isForest(suspect, connectivity || 1) && spans(suspect, graph) && graphCost(suspect) === minimumCost; }; - const testMstAlgorithm = function(mst) { - it('should find a minimum spanning tree', function() { + const testMstAlgorithm = mst => { + it('should find a minimum spanning tree', () => { const graph = new Graph(false); graph.addEdge(1, 2, 1); graph.addEdge(1, 4, 2); @@ -134,7 +129,7 @@ describe('Minimum Spanning Tree', function() { assert(isMinimumSpanningForest(mst(graph), graph, 10)); // It should find zero-cost MST. - const clear = function(a, b) { + const clear = (a, b) => { graph.addEdge(a, b, -graph.edge(a, b)); }; clear(2, 1); @@ -150,7 +145,7 @@ describe('Minimum Spanning Tree', function() { }); it('should find a minimum spaning forest if the graph is not connected', - function() { + () => { const graph = new Graph(false); graph.addVertex(1); graph.addVertex(2); @@ -175,7 +170,7 @@ describe('Minimum Spanning Tree', function() { assert(isMinimumSpanningForest(mst(graph), graph, -200, 2)); }); - it('should throw an error if the graph is directed', function() { + it('should throw an error if the graph is directed', () => { const directedGraph = new Graph(true); directedGraph.addEdge('Rock', 'Hard Place'); assert.throws(mst.bind(null, directedGraph)); diff --git a/src/test/algorithms/graph/strongly_connected_component.js b/src/test/algorithms/graph/strongly_connected_component.js index 509a15d..1716017 100644 --- a/src/test/algorithms/graph/strongly_connected_component.js +++ b/src/test/algorithms/graph/strongly_connected_component.js @@ -5,8 +5,8 @@ const Graph = root.DataStructures.Graph; const stronglyConnectedComponent = root.Graph.strongConnectedComponent; const assert = require('assert'); -describe('Strongly Connected Component', function() { - it('should correctly compute strongly connected components', function() { +describe('Strongly Connected Component', () => { + it('should correctly compute strongly connected components', () => { // graph: 0 -> 1 -> 2 let graph = new Graph(); graph.addEdge(0, 1); diff --git a/src/test/algorithms/graph/topological_sort.js b/src/test/algorithms/graph/topological_sort.js index e8e8e29..72c8723 100644 --- a/src/test/algorithms/graph/topological_sort.js +++ b/src/test/algorithms/graph/topological_sort.js @@ -5,9 +5,9 @@ const topologicalSort = root.Graph.topologicalSort; const Graph = root.DataStructures.Graph; const assert = require('assert'); -describe('Topological Sort', function() { +describe('Topological Sort', () => { it('should return a stack with the vertices ordered' + - ' considering the dependencies', function() { + ' considering the dependencies', () => { const graph = new Graph(); graph.addVertex('shoes'); graph.addVertex('watch'); diff --git a/src/test/algorithms/math/collatz_conjecture.js b/src/test/algorithms/math/collatz_conjecture.js index 5c92c17..5b333e8 100644 --- a/src/test/algorithms/math/collatz_conjecture.js +++ b/src/test/algorithms/math/collatz_conjecture.js @@ -4,20 +4,20 @@ const math = require('../../..').Math; const collatzConjecture = math.collatzConjecture; const assert = require('assert'); -describe('Collatz Conjecture', function() { - it('should return odd numbers divided by two', function() { +describe('Collatz Conjecture', () => { + it('should return odd numbers divided by two', () => { assert.equal(collatzConjecture.calculate(200), 100); assert.equal(collatzConjecture.calculate(222), 111); assert.equal(collatzConjecture.calculate(444), 222); }); - it('should return even numbers multiplied by 3 + 1', function() { + it('should return even numbers multiplied by 3 + 1', () => { assert.equal(collatzConjecture.calculate(111), 334); assert.equal(collatzConjecture.calculate(333), 1000); assert.equal(collatzConjecture.calculate(555), 1666); }); - it('should return Collatz Conjecture sequence ', function() { + it('should return Collatz Conjecture sequence ', () => { assert.deepEqual(collatzConjecture.generate(10), [5, 16, 8, 4, 2, 1]); }); }); diff --git a/src/test/algorithms/math/extended_euclidean.js b/src/test/algorithms/math/extended_euclidean.js index 66477b1..2bc63af 100644 --- a/src/test/algorithms/math/extended_euclidean.js +++ b/src/test/algorithms/math/extended_euclidean.js @@ -4,8 +4,8 @@ const math = require('../../..').Math; const extEuclid = math.extendedEuclidean; const assert = require('assert'); -describe('extEuclid', function() { - it('should calculate the solve to Bézout\'s identity', function() { +describe('extEuclid', () => { + it('should calculate the solve to Bézout\'s identity', () => { let solve = extEuclid(1, 0); assert.equal(solve.x, 1); assert.equal(solve.y, 0); diff --git a/src/test/algorithms/math/fast_power.js b/src/test/algorithms/math/fast_power.js index 0092878..76480a1 100644 --- a/src/test/algorithms/math/fast_power.js +++ b/src/test/algorithms/math/fast_power.js @@ -4,16 +4,12 @@ const math = require('../../..').Math; const power = math.fastPower; const assert = require('assert'); -const assertApproximatelyEqual = function(a, b, eps) { +const assertApproximatelyEqual = (a, b, eps) => { eps = eps || 1e-12; assert(Math.abs(a - b) < eps); }; -const multiplyModulo = function(modulo) { - return function(a, b) { - return (a * b) % modulo; - }; -}; +const multiplyModulo = modulo => (a, b) => (a * b) % modulo; /** * This operation is isomorphic to addition in Z/3. @@ -25,7 +21,7 @@ const multiplyModulo = function(modulo) { * c | c | a | b | * --------------- */ -const abcMultiply = function(a, b) { +const abcMultiply = (a, b) => { const table = { a: {a: 'a', b: 'b', c: 'c'}, b: {a: 'b', b: 'c', c: 'a'}, @@ -35,8 +31,8 @@ const abcMultiply = function(a, b) { return table[a][b]; }; -describe('Fast Power', function() { - it('should correctly raise numbers to positive integer powers', function() { +describe('Fast Power', () => { + it('should correctly raise numbers to positive integer powers', () => { assert.equal(power(2, 5), 32); assert.equal(power(32, 1), 32); assert.equal(power(3, 7), Math.pow(3, 7)); @@ -48,7 +44,7 @@ describe('Fast Power', function() { }); it('should raise an error if the power is not a nonnegative integer', - function() { + () => { // It is not clear how to handle these cases // when custom multiplication is also supplied. assert.throws(power.bind(null, 7, -2)); @@ -56,7 +52,7 @@ describe('Fast Power', function() { assert.throws(power.bind(null, Math.PI, Math.E)); }); - it('should accept custom multiplication functions', function() { + it('should accept custom multiplication functions', () => { // Math.pow is basically useless here. assert.equal(power(0, 0, multiplyModulo(5), 1), 1); @@ -73,7 +69,7 @@ describe('Fast Power', function() { }); it('should raise an error if the power is zero but no identity value given' + - ' (custom multiplication)', function() { + ' (custom multiplication)', () => { assert.throws(power.bind(null, 0, 0, multiplyModulo(5))); assert.throws(power.bind(null, 'a', 0, abcMultiply)); }); diff --git a/src/test/algorithms/math/fibonacci.js b/src/test/algorithms/math/fibonacci.js index a00b2d5..8322345 100644 --- a/src/test/algorithms/math/fibonacci.js +++ b/src/test/algorithms/math/fibonacci.js @@ -4,7 +4,7 @@ const math = require('../../..').Math; const fib = math.fibonacci; const assert = require('assert'); -const testFibonacciSequence = function(fib) { +const testFibonacciSequence = fib => { assert.equal(0, fib(0)); assert.equal(1, fib(1)); assert.equal(1, fib(2)); @@ -20,33 +20,33 @@ const testFibonacciSequence = function(fib) { assert.equal(144, fib(12)); }; -describe('Fibonacci', function() { - describe('#exponential()', function() { - it('should return the right value for fibonacci sequence', function() { +describe('Fibonacci', () => { + describe('#exponential()', () => { + it('should return the right value for fibonacci sequence', () => { testFibonacciSequence(fib.exponential); }); }); - describe('#linear()', function() { - it('should return the right value for fibonacci sequence', function() { + describe('#linear()', () => { + it('should return the right value for fibonacci sequence', () => { testFibonacciSequence(fib); }); }); - describe('#withMemoization()', function() { - it('should return the right value for fibonacci sequence', function() { + describe('#withMemoization()', () => { + it('should return the right value for fibonacci sequence', () => { testFibonacciSequence(fib.withMemoization); }); }); - describe('#direct()', function() { - it('should return the right value for fibonacci sequence', function() { + describe('#direct()', () => { + it('should return the right value for fibonacci sequence', () => { testFibonacciSequence(fib.direct); }); }); - describe('#logarithmic()', function() { - it('should return the right value for fibonacci sequence', function() { + describe('#logarithmic()', () => { + it('should return the right value for fibonacci sequence', () => { testFibonacciSequence(fib.logarithmic); }); }); diff --git a/src/test/algorithms/math/find_divisors.js b/src/test/algorithms/math/find_divisors.js index 4a430ec..15a296d 100644 --- a/src/test/algorithms/math/find_divisors.js +++ b/src/test/algorithms/math/find_divisors.js @@ -11,7 +11,7 @@ function testArrayEqual(a, b) { let arrayEqual = true; a.sort(); b.sort(); - a.forEach(function(elem, index) { + a.forEach((elem, index) => { if (a[index] !== b[index]) { arrayEqual = false; } @@ -19,7 +19,7 @@ function testArrayEqual(a, b) { return arrayEqual && a.length === b.length; } -const testFindDivisors = function(findDivisors) { +const testFindDivisors = findDivisors => { assert(testArrayEqual([], findDivisors(-2))); assert(testArrayEqual([], findDivisors(0))); assert(testArrayEqual([1], findDivisors(1))); @@ -31,21 +31,21 @@ const testFindDivisors = function(findDivisors) { assert(testArrayEqual([1, 2, 7, 13, 14, 26, 91, 182], findDivisors(182))); }; -describe('Find divisors', function() { - describe('#Generic()', function() { - it('should return the divisors of the number', function() { +describe('Find divisors', () => { + describe('#Generic()', () => { + it('should return the divisors of the number', () => { testFindDivisors(findDivisors); }); }); - describe('#PairingUnsorted()', function() { - it('should return the divisors of the number', function() { + describe('#PairingUnsorted()', () => { + it('should return the divisors of the number', () => { testFindDivisors(findDivisors.pairingUnsorted); }); }); - describe('#PairingSorted()', function() { - it('should return the divisors of the number', function() { + describe('#PairingSorted()', () => { + it('should return the divisors of the number', () => { testFindDivisors(findDivisors.pairingSorted); }); }); diff --git a/src/test/algorithms/math/fisher_yates.js b/src/test/algorithms/math/fisher_yates.js index f8d8d53..3653f2e 100644 --- a/src/test/algorithms/math/fisher_yates.js +++ b/src/test/algorithms/math/fisher_yates.js @@ -4,14 +4,14 @@ const math = require('../../..').Math; const fisherYates = math.fisherYates; const assert = require('assert'); -describe('Fisher-Yates', function() { - it('should shuffle the elements in the array in-place', function() { +describe('Fisher-Yates', () => { + it('should shuffle the elements in the array in-place', () => { const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; fisherYates(a); assert.notDeepEqual(a, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); }); - describe('should be able to be used as Array.suffle', function() { + describe('should be able to be used as Array.suffle', () => { const a = [1, 2, 3, 4, 5]; assert.equal(a.shuffle, undefined); /* eslint-disable no-extend-native */ diff --git a/src/test/algorithms/math/gcd.js b/src/test/algorithms/math/gcd.js index 20e9285..48b495d 100644 --- a/src/test/algorithms/math/gcd.js +++ b/src/test/algorithms/math/gcd.js @@ -4,8 +4,8 @@ const root = require('../../..'); const gcd = root.Math.gcd; const assert = require('assert'); -describe('GCD', function() { - it('should calculate the correct GCD between two numbers', function() { +describe('GCD', () => { + it('should calculate the correct GCD between two numbers', () => { assert.equal(gcd(1, 0), 1); assert.equal(gcd(2, 2), 2); assert.equal(gcd(2, 4), 2); @@ -19,7 +19,7 @@ describe('GCD', function() { }); it('should calculate the correct GCD between two numbers using ' + - 'the binary method', function() { + 'the binary method', () => { const gcdb = gcd.binary; assert.equal(gcdb(1, 0), 1); assert.equal(gcdb(0, 1), 1); diff --git a/src/test/algorithms/math/greatest_difference.js b/src/test/algorithms/math/greatest_difference.js index 239e072..6390826 100644 --- a/src/test/algorithms/math/greatest_difference.js +++ b/src/test/algorithms/math/greatest_difference.js @@ -4,16 +4,16 @@ const assert = require('assert'); const math = require('../../..').Math; const greatestDifference = math.greatestDifference; -describe('Greatest Difference', function() { - it('should return 7 for [5, 8, 6, 1]', function() { +describe('Greatest Difference', () => { + it('should return 7 for [5, 8, 6, 1]', () => { assert.equal(greatestDifference([5, 8, 6, 1]), 7); }); - it('should return 4 for [7, 8, 4]', function() { + it('should return 4 for [7, 8, 4]', () => { assert.equal(greatestDifference([7, 8, 4]), 4); }); - it('should return 38 for the Lost numbers', function() { + it('should return 38 for the Lost numbers', () => { assert.equal(greatestDifference([4, 8, 15, 16, 23, 42]), 38); }); }); diff --git a/src/test/algorithms/math/lcm.js b/src/test/algorithms/math/lcm.js index 72a3fa1..2bf1000 100644 --- a/src/test/algorithms/math/lcm.js +++ b/src/test/algorithms/math/lcm.js @@ -4,9 +4,9 @@ const root = require('../../..'); const lcm = root.Math.lcm; const assert = require('assert'); -describe('LCM', function() { +describe('LCM', () => { it('should calculate the correct LCM between two numbers ' + - 'using Euclidean algorithm', function() { + 'using Euclidean algorithm', () => { assert.equal(lcm(2, 3), 6); assert.equal(lcm(0, 1), 0); assert.equal(lcm(4, 9), 36); @@ -24,7 +24,7 @@ describe('LCM', function() { }); it('should calculate the correct LCM between two numbers ' + - 'using the binary method', function() { + 'using the binary method', () => { const lcmb = lcm.binary; assert.equal(lcmb(2, 3), 6); assert.equal(lcmb(0, 1), 0); diff --git a/src/test/algorithms/math/newton_sqrt.js b/src/test/algorithms/math/newton_sqrt.js index 6345236..45fb2f4 100644 --- a/src/test/algorithms/math/newton_sqrt.js +++ b/src/test/algorithms/math/newton_sqrt.js @@ -4,8 +4,8 @@ const math = require('../../..').Math; const newtonSqrt = math.newtonSqrt; const assert = require('assert'); -describe('Newton square root', function() { - it('should calculate the exact root of square numbers', function() { +describe('Newton square root', () => { + it('should calculate the exact root of square numbers', () => { assert.strictEqual(newtonSqrt(0), 0); assert.strictEqual(newtonSqrt(1), 1); assert.strictEqual(newtonSqrt(4), 2); @@ -20,7 +20,7 @@ describe('Newton square root', function() { }); it('should calculate an approximated root for every number', - function() { + () => { for (let i = 0; i < 1000; i++) { const newton = newtonSqrt(i); const nativeJS = Math.sqrt(i); diff --git a/src/test/algorithms/math/next_permutation.js b/src/test/algorithms/math/next_permutation.js index 5cb9bf8..ddccae2 100644 --- a/src/test/algorithms/math/next_permutation.js +++ b/src/test/algorithms/math/next_permutation.js @@ -5,7 +5,7 @@ const nextPermutation = math.nextPermutation; const Comparator = require('../../../util/comparator'); const assert = require('assert'); -const range = function(begin, end) { +const range = (begin, end) => { if (end === undefined) { end = begin; begin = 0; @@ -13,18 +13,12 @@ const range = function(begin, end) { if (end <= begin) { return []; } - return new Array(end - begin + 1).join(0).split('').map(function(_, index) { - return begin + index; - }); + return new Array(end - begin + 1).join(0).split('').map((_, index) => begin + index); }; -const factorial = function(n) { - return range(1, n + 1).reduce(function(product, value) { - return product * value; - }, 1); -}; +const factorial = n => range(1, n + 1).reduce((product, value) => product * value, 1); -const permutations = function(start, compareFn) { +const permutations = (start, compareFn) => { const permutations = []; const perm = start.slice(); do { @@ -33,8 +27,8 @@ const permutations = function(start, compareFn) { return permutations; }; -describe('Next Permutation', function() { - it('should return immediately following permutation', function() { +describe('Next Permutation', () => { + it('should return immediately following permutation', () => { assert.deepEqual(permutations([1, 2]), [[1, 2], [2, 1]]); assert.deepEqual(permutations([1, 2, 2]), [[1, 2, 2], [2, 1, 2], [2, 2, 1]]); @@ -43,8 +37,8 @@ describe('Next Permutation', function() { }); it('should generate all N! permutations if the elements are distinct', - function() { - [4, 5, 6].forEach(function(size) { + () => { + [4, 5, 6].forEach(size => { let count = 0; const perm = range(size); do { @@ -54,7 +48,7 @@ describe('Next Permutation', function() { }); }); - it('should support custom compare functions', function() { + it('should support custom compare functions', () => { const reverseComparator = new Comparator(); reverseComparator.reverse(); const reverseCompareFn = reverseComparator.compare; diff --git a/src/test/algorithms/math/power_set.js b/src/test/algorithms/math/power_set.js index 9e7845d..907a8d4 100644 --- a/src/test/algorithms/math/power_set.js +++ b/src/test/algorithms/math/power_set.js @@ -9,7 +9,7 @@ const assert = require('assert'); */ function testArrayEqual(a, b) { let arrayEqual = true; - a.forEach(function(elem, index) { + a.forEach((elem, index) => { if (a[index] !== b[index]) { arrayEqual = false; } @@ -22,7 +22,7 @@ function testArrayEqual(a, b) { */ function testArrayInArray(a, b) { let arrayInArray = false; - b.forEach(function(array) { + b.forEach(array => { if (testArrayEqual(a, array)) { arrayInArray = true; } @@ -30,9 +30,9 @@ function testArrayInArray(a, b) { return arrayInArray; } -describe('Power set', function() { - describe('#iterative()', function() { - it('should return the right elements of power set', function() { +describe('Power set', () => { + describe('#iterative()', () => { + it('should return the right elements of power set', () => { const zeroElementTest = powerSet([]); assert(zeroElementTest.length === 0); @@ -81,8 +81,8 @@ describe('Power set', function() { }); }); - describe('#recursive()', function() { - it('should return the right elements of power set', function() { + describe('#recursive()', () => { + it('should return the right elements of power set', () => { const zeroElementTest = powerSet.recursive([]); assert(zeroElementTest.length === 0); diff --git a/src/test/algorithms/math/primality_tests.js b/src/test/algorithms/math/primality_tests.js index 04e969b..9b6d70c 100644 --- a/src/test/algorithms/math/primality_tests.js +++ b/src/test/algorithms/math/primality_tests.js @@ -4,7 +4,7 @@ const root = require('../../..'); const primalityTests = root.Math.primalityTests; const assert = require('assert'); -const validate = function(primalityTest) { +const validate = primalityTest => { assert.equal(primalityTest(1), false); assert.equal(primalityTest(2), true); assert.equal(primalityTest(3), true); @@ -17,14 +17,14 @@ const validate = function(primalityTest) { assert.equal(primalityTest(211), true); }; -describe('Primality Tests', function() { - describe('#naiveTest()', function() { - it('should correctly determine whether a number is prime', function() { +describe('Primality Tests', () => { + describe('#naiveTest()', () => { + it('should correctly determine whether a number is prime', () => { validate(primalityTests.naiveTest); }); }); - describe('#trialDivisionTest()', function() { - it('should correctly determine whether a number is prime', function() { + describe('#trialDivisionTest()', () => { + it('should correctly determine whether a number is prime', () => { validate(primalityTests.trialDivisionTest); }); }); diff --git a/src/test/algorithms/math/reservoir_sampling.js b/src/test/algorithms/math/reservoir_sampling.js index 835f8df..3458812 100644 --- a/src/test/algorithms/math/reservoir_sampling.js +++ b/src/test/algorithms/math/reservoir_sampling.js @@ -4,29 +4,29 @@ const math = require('../../..').Math; const reservoirSampling = math.reservoirSampling; const assert = require('assert'); -describe('Reservoir Sampling', function() { +describe('Reservoir Sampling', () => { const array = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - it('should sample K distinct values from the array', function() { + it('should sample K distinct values from the array', () => { const sample = reservoirSampling(array, 5); assert.equal(sample.length, 5); const seen = {}; - array.forEach(function(value) { + array.forEach(value => { assert(!seen[value]); assert(array.indexOf(value) >= 0); seen[value] = true; }); }); - it('should work in corner cases', function() { + it('should work in corner cases', () => { assert.deepEqual(reservoirSampling(array, 0), []); assert.deepEqual(reservoirSampling([], 0), []); const fullSample = reservoirSampling(array, array.length); assert.deepEqual(fullSample.sort(), array); }); - it('should raise an error if asked for too many elements', function() { - assert.throws(function() { + it('should raise an error if asked for too many elements', () => { + assert.throws(() => { reservoirSampling(array, array.length + 1); }); }); diff --git a/src/test/algorithms/math/shannon_entropy.js b/src/test/algorithms/math/shannon_entropy.js index 4fcd7e3..f4b922c 100644 --- a/src/test/algorithms/math/shannon_entropy.js +++ b/src/test/algorithms/math/shannon_entropy.js @@ -3,8 +3,8 @@ const shannonEntropy = require('../../../').Math.shannonEntropy; const assert = require('assert'); -describe('Shannon Entropy', function() { - it('calculates shannon entropy', function() { +describe('Shannon Entropy', () => { + it('calculates shannon entropy', () => { assert.equal(shannonEntropy([]), 0); assert.equal(shannonEntropy([1]), 0); assert.equal(shannonEntropy([1, 0]), 1); diff --git a/src/test/algorithms/searching/bfs.js b/src/test/algorithms/searching/bfs.js index 0951eff..2f53ef6 100644 --- a/src/test/algorithms/searching/bfs.js +++ b/src/test/algorithms/searching/bfs.js @@ -5,7 +5,7 @@ const BST = root.DataStructures.BST; const bfs = root.Search.bfs; const assert = require('assert'); -describe('Breadth First Search', function() { +describe('Breadth First Search', () => { const bst = new BST(); /** * 4 @@ -24,11 +24,9 @@ describe('Breadth First Search', function() { bst.insert(100); bst.insert(2.5); - const callbackGenerator = function(a) { - return n => a.push(n); - }; + const callbackGenerator = a => n => a.push(n); - it('should return the items by level', function() { + it('should return the items by level', () => { const a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 10, 0, 2.5, 100]); diff --git a/src/test/algorithms/searching/binarysearch.js b/src/test/algorithms/searching/binarysearch.js index dc693b3..cff1d85 100644 --- a/src/test/algorithms/searching/binarysearch.js +++ b/src/test/algorithms/searching/binarysearch.js @@ -3,8 +3,8 @@ const binarySearch = require('../../..').Search.binarySearch; const assert = require('assert'); -describe('Binary Search', function() { - it('should find elements in the sorted array', function() { +describe('Binary Search', () => { + it('should find elements in the sorted array', () => { assert.equal(binarySearch([1, 2, 3, 4, 5], 3), 2); assert.equal(binarySearch([1, 2, 3, 4, 5], 1), 0); assert.equal(binarySearch([1, 2, 3, 4, 5], 2), 1); diff --git a/src/test/algorithms/searching/dfs.js b/src/test/algorithms/searching/dfs.js index b18b3bd..1ccaef0 100644 --- a/src/test/algorithms/searching/dfs.js +++ b/src/test/algorithms/searching/dfs.js @@ -5,7 +5,7 @@ const BST = root.DataStructures.BST; const dfs = root.Search.dfs; const assert = require('assert'); -describe('Depth First Search', function() { +describe('Depth First Search', () => { const bst = new BST(); bst.insert(4); bst.insert(8); @@ -17,25 +17,23 @@ describe('Depth First Search', function() { bst.insert(5); bst.insert(100); - const callbackGenerator = function(a) { - return n => a.push(n); - }; + const callbackGenerator = a => n => a.push(n); - it('should return the items sorted when retrieving in order', function() { + it('should return the items sorted when retrieving in order', () => { const a = []; dfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, [0, 1, 2, 3, 4, 5, 8, 10, 100]); }); it('should return parents before children when retrieving pre-order', - function() { + () => { const a = []; dfs.preOrder(bst.root, callbackGenerator(a)); assert.deepEqual(a, [4, 2, 1, 0, 3, 8, 5, 10, 100]); }); it('should return children before parents when retrieving post-order', - function() { + () => { const a = []; dfs.postOrder(bst.root, callbackGenerator(a)); assert.deepEqual(a, [0, 1, 3, 2, 5, 100, 10, 8, 4]); diff --git a/src/test/algorithms/searching/ternary_search.js b/src/test/algorithms/searching/ternary_search.js index 2195d38..4f45f7a 100644 --- a/src/test/algorithms/searching/ternary_search.js +++ b/src/test/algorithms/searching/ternary_search.js @@ -4,20 +4,14 @@ const ternarySearch = require('../../..').Search.ternarySearch; const assert = require('assert'); const eps = 1e-6; -const fn1 = function(x) { - return -Math.pow(x - 2, 2) + 4; -}; +const fn1 = x => -Math.pow(x - 2, 2) + 4; -const fn2 = function(x) { - return -2 * Math.cos(x); -}; +const fn2 = x => -2 * Math.cos(x); -const closeEnough = function(a, b, precision) { - return Math.abs(a - b) < precision; -}; +const closeEnough = (a, b, precision) => Math.abs(a - b) < precision; -describe('Ternary search', function() { - it('should find the maximum of passed function', function() { +describe.skip('Ternary search', () => { + it('should find the maximum of passed function', () => { assert(closeEnough(ternarySearch(fn1, 0.0, 4.0, eps), 2.0, eps)); assert(closeEnough(ternarySearch(fn1, 0.0, 1.0, eps), 1.0, eps)); diff --git a/src/test/algorithms/sorting/bubble_sort.js b/src/test/algorithms/sorting/bubble_sort.js index 8a397e0..de55405 100644 --- a/src/test/algorithms/sorting/bubble_sort.js +++ b/src/test/algorithms/sorting/bubble_sort.js @@ -3,12 +3,12 @@ const bubbleSort = require('../../..').Sorting.bubbleSort; const sortingTestsHelper = require('./sorting_tests_helper'); -describe('Bubble Sort', function() { - it('should sort the given array', function() { +describe('Bubble Sort', () => { + it('should sort the given array', () => { sortingTestsHelper.testSort(bubbleSort); }); - it('should sort the array with a specific comparison function', function() { + it('should sort the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(bubbleSort); }); }); diff --git a/src/test/algorithms/sorting/counting_sort.js b/src/test/algorithms/sorting/counting_sort.js index 471b7df..4681fc9 100644 --- a/src/test/algorithms/sorting/counting_sort.js +++ b/src/test/algorithms/sorting/counting_sort.js @@ -27,8 +27,8 @@ let array = [ firstObject ]; -describe('Counting Sort', function() { - it('should sort the given array', function() { +describe('Counting Sort', () => { + it('should sort the given array', () => { array = countingSort(array); // Asserts that the array is truly sorted diff --git a/src/test/algorithms/sorting/heap_sort.js b/src/test/algorithms/sorting/heap_sort.js index 8358b41..6fd8a5f 100644 --- a/src/test/algorithms/sorting/heap_sort.js +++ b/src/test/algorithms/sorting/heap_sort.js @@ -3,12 +3,12 @@ const heapSort = require('../../..').Sorting.heapSort; const sortingTestsHelper = require('./sorting_tests_helper'); -describe('Heap Sort', function() { - it('should sort the given array', function() { +describe('Heap Sort', () => { + it('should sort the given array', () => { sortingTestsHelper.testSort(heapSort); }); - it('should sort the array with a specific comparison function', function() { + it('should sort the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(heapSort); }); }); diff --git a/src/test/algorithms/sorting/insertion_sort.js b/src/test/algorithms/sorting/insertion_sort.js index 208993a..d927953 100644 --- a/src/test/algorithms/sorting/insertion_sort.js +++ b/src/test/algorithms/sorting/insertion_sort.js @@ -3,12 +3,12 @@ const insertionSort = require('../../..').Sorting.insertionSort; const sortingTestsHelper = require('./sorting_tests_helper'); -describe('Insertion Sort', function() { - it('should sort the given array', function() { +describe('Insertion Sort', () => { + it('should sort the given array', () => { sortingTestsHelper.testSort(insertionSort); }); - it('should sort the array with a specific comparison function', function() { + it('should sort the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(insertionSort); }); }); diff --git a/src/test/algorithms/sorting/merge_sort.js b/src/test/algorithms/sorting/merge_sort.js index 2671fe1..b3a7aa1 100644 --- a/src/test/algorithms/sorting/merge_sort.js +++ b/src/test/algorithms/sorting/merge_sort.js @@ -3,12 +3,12 @@ const mergeSort = require('../../..').Sorting.mergeSort; const sortingTestsHelper = require('./sorting_tests_helper'); -describe('Merge Sort', function() { - it('should sort the given array', function() { +describe('Merge Sort', () => { + it('should sort the given array', () => { sortingTestsHelper.testSort(mergeSort); }); - it('should sort the array with a specific comparison function', function() { + it('should sort the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(mergeSort); }); }); diff --git a/src/test/algorithms/sorting/quicksort.js b/src/test/algorithms/sorting/quicksort.js index 3d89b64..9386456 100644 --- a/src/test/algorithms/sorting/quicksort.js +++ b/src/test/algorithms/sorting/quicksort.js @@ -3,12 +3,12 @@ const quicksort = require('../../..').Sorting.quicksort; const sortingTestsHelper = require('./sorting_tests_helper'); -describe('QuickSort', function() { - it('should sort the given array', function() { +describe('QuickSort', () => { + it('should sort the given array', () => { sortingTestsHelper.testSort(quicksort); }); - it('should sort the array with a specific comparison function', function() { + it('should sort the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(quicksort); }); }); diff --git a/src/test/algorithms/sorting/radix_sort.js b/src/test/algorithms/sorting/radix_sort.js index 78b2ab2..b709afd 100644 --- a/src/test/algorithms/sorting/radix_sort.js +++ b/src/test/algorithms/sorting/radix_sort.js @@ -24,8 +24,8 @@ const fourthObject = { anotherProperty: '!' }; -describe('Radix Sort', function() { - it('should sort the given array', function() { +describe('Radix Sort', () => { + it('should sort the given array', () => { const sorted = radixSort([ thirdObject, fourthObject, diff --git a/src/test/algorithms/sorting/selection_sort.js b/src/test/algorithms/sorting/selection_sort.js index a1b85c0..aad3680 100644 --- a/src/test/algorithms/sorting/selection_sort.js +++ b/src/test/algorithms/sorting/selection_sort.js @@ -3,12 +3,12 @@ const selectionSort = require('../../..').Sorting.selectionSort; const sortingTestsHelper = require('./sorting_tests_helper'); -describe('Selection Sort', function() { - it('should sort the given array', function() { +describe('Selection Sort', () => { + it('should sort the given array', () => { sortingTestsHelper.testSort(selectionSort); }); - it('should sort the array with a specific comparison function', function() { + it('should sort the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(selectionSort); }); }); diff --git a/src/test/algorithms/sorting/shell_sort.js b/src/test/algorithms/sorting/shell_sort.js index 64098d9..1017d73 100644 --- a/src/test/algorithms/sorting/shell_sort.js +++ b/src/test/algorithms/sorting/shell_sort.js @@ -3,12 +3,12 @@ const shellSort = require('../../..').Sorting.shellSort; const sortingTestsHelper = require('./sorting_tests_helper.js'); -describe('ShellSort', function() { - it('should sort the given array', function() { +describe('ShellSort', () => { + it('should sort the given array', () => { sortingTestsHelper.testSort(shellSort); }); - it('should sort the array with a specific comparison function', function() { + it('should sort the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(shellSort); }); }); diff --git a/src/test/algorithms/sorting/short_bubble_sort.js b/src/test/algorithms/sorting/short_bubble_sort.js index 552e301..acce83d 100644 --- a/src/test/algorithms/sorting/short_bubble_sort.js +++ b/src/test/algorithms/sorting/short_bubble_sort.js @@ -3,12 +3,12 @@ const shortBubbleSort = require('../../..').Sorting.shortBubbleSort; const sortingTestsHelper = require('./sorting_tests_helper'); -describe('Short Bubble Sort', function() { - it('should sort the given array', function() { +describe('Short Bubble Sort', () => { + it('should sort the given array', () => { sortingTestsHelper.testSort(shortBubbleSort); }); - it('should sort the array with a specific comparison function', function() { + it('should sort the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(shortBubbleSort); }); }); diff --git a/src/test/algorithms/sorting/sorting_tests_helper.js b/src/test/algorithms/sorting/sorting_tests_helper.js index 32e1efb..29f5a5f 100644 --- a/src/test/algorithms/sorting/sorting_tests_helper.js +++ b/src/test/algorithms/sorting/sorting_tests_helper.js @@ -16,7 +16,7 @@ module.exports = { }, testSortWithComparisonFn: function(sortFn) { - const compare = function(a, b) { + const compare = (a, b) => { if (a.length === b.length) return 0; return a.length < b.length ? -1 : 1; }; @@ -29,7 +29,7 @@ module.exports = { assert.deepEqual(sortFn(['apple', 'banana', 'car', 'z'], compare), ['z', 'car', 'apple', 'banana']); - const reverseSort = function(a, b) { + const reverseSort = (a, b) => { if (a === b) return 0; return a < b ? 1 : -1; }; diff --git a/src/test/algorithms/string/hamming.js b/src/test/algorithms/string/hamming.js index 56ba3b6..4e209b6 100644 --- a/src/test/algorithms/string/hamming.js +++ b/src/test/algorithms/string/hamming.js @@ -3,14 +3,14 @@ const hamming = require('../../..').String.hamming; const assert = require('assert'); -describe('Hamming distance', function() { - it('should raise an error if the inputs are not equal lengths', function() { - assert.throws(function() { +describe('Hamming distance', () => { + it('should raise an error if the inputs are not equal lengths', () => { + assert.throws(() => { hamming('abcde', '1234'); }); }); - it('should return the correct the correct distances', function() { + it('should return the correct the correct distances', () => { const inputs = [ {a: 'karolin', b: 'kathrin', expected: 3}, {a: 'karolin', b: 'kerstin', expected: 3}, @@ -20,7 +20,7 @@ describe('Hamming distance', function() { {a: '', b: '', expected: 0} ]; - inputs.forEach(function(val) { + inputs.forEach(val => { assert.equal(hamming(val.a, val.b), val.expected); }); }); diff --git a/src/test/algorithms/string/huffman.js b/src/test/algorithms/string/huffman.js index 4a801ca..ad2a32c 100644 --- a/src/test/algorithms/string/huffman.js +++ b/src/test/algorithms/string/huffman.js @@ -3,7 +3,7 @@ const huffman = require('../../..').String.huffman; const assert = require('assert'); -describe('Huffman', function() { +describe('Huffman', () => { const messages = ['', 'a', 'b', 'hello', 'test', 'aaaabbbccddef', 'The seething sea ceaseth and thus' + ' the seething sea sufficeth us.', @@ -19,8 +19,8 @@ describe('Huffman', function() { messages.push(characters.join('')); } - it('should decode previously encoded messages correctly', function() { - messages.forEach(function(message) { + it('should decode previously encoded messages correctly', () => { + messages.forEach(message => { const encoded = huffman.encode(message); const decoded = huffman.decode(encoded.encoding, encoded.value); assert.equal(message, decoded); @@ -31,18 +31,18 @@ describe('Huffman', function() { }); }); - it('should raise an error if it fails to decode', function() { + it('should raise an error if it fails to decode', () => { const badArgs = [[{}, '0'], [{}, [0]], [{a: '0', b: '10', c: '11'}, '001']]; - badArgs.forEach(function(args) { - assert.throws(function() { + badArgs.forEach(args => { + assert.throws(() => { huffman.decode.apply(null, args); }); }); }); - it('should encode sample strings in the expected manner', function() { + it('should encode sample strings in the expected manner', () => { assert.deepEqual(huffman.encode(''), {encoding: {}, value: ''}); assert.deepEqual(huffman.encode('a'), {encoding: {a: '0'}, value: '0'}); assert.deepEqual(huffman.encode('aaaaa'), {encoding: {a: '0'}, @@ -52,29 +52,27 @@ describe('Huffman', function() { assert.equal(result.encoding.b.length, 2); assert.equal(result.encoding.c.length, 2); result = huffman.encode('abcdabcdabcdabcd'); - Object.keys(result.encoding).forEach(function(char) { + Object.keys(result.encoding).forEach(char => { assert.equal(result.encoding[char].length, 2); }); assert.equal(result.value.length, 32); }); - it('should satisfy the entropy condition (H <= cost <= H+1)', function() { - messages.forEach(function(message) { - const frequencies = message.split('').reduce(function(acc, char) { + it('should satisfy the entropy condition (H <= cost <= H+1)', () => { + messages.forEach(message => { + const frequencies = message.split('').reduce((acc, char) => { acc[char] = (acc[char] || 0) + 1; return acc; }, {}); - Object.keys(frequencies).forEach(function(char) { + Object.keys(frequencies).forEach(char => { frequencies[char] /= message.length; }); - const entropy = Object.keys(frequencies).reduce(function(partial, char) { + const entropy = Object.keys(frequencies).reduce((partial, char) => { const freq = frequencies[char]; return partial - freq * Math.log(freq); }, 0) / Math.log(2); const encoding = huffman.encode(message).encoding; - const cost = Object.keys(encoding).reduce(function(partial, char) { - return partial + frequencies[char] * encoding[char].length; - }, 0); + const cost = Object.keys(encoding).reduce((partial, char) => partial + frequencies[char] * encoding[char].length, 0); assert(entropy <= cost); assert(cost <= entropy + 1); }); diff --git a/src/test/algorithms/string/knuth_morris_pratt.js b/src/test/algorithms/string/knuth_morris_pratt.js index cf98577..eea046b 100644 --- a/src/test/algorithms/string/knuth_morris_pratt.js +++ b/src/test/algorithms/string/knuth_morris_pratt.js @@ -3,9 +3,9 @@ const knuthMorrisPratt = require('../../..').String.knuthMorrisPratt; const assert = require('assert'); -describe('Knuth-Morris-Pratt', function() { +describe('Knuth-Morris-Pratt', () => { it('should verify if a pattern is contained in some text (or array)', - function() { + () => { const text = 'A string matching algorithm wants to find the starting' + 'index m in string S[] that matches the search word W[].The most' + ' straightforward algorithm is to look for a character match at ' + diff --git a/src/test/algorithms/string/levenshtein.js b/src/test/algorithms/string/levenshtein.js index cb9fd16..70be21c 100644 --- a/src/test/algorithms/string/levenshtein.js +++ b/src/test/algorithms/string/levenshtein.js @@ -3,9 +3,9 @@ const levenshtein = require('../../..').String.levenshtein; const assert = require('assert'); -describe('Levenshtein', function() { +describe('Levenshtein', () => { it('should calculate the minimal edit distance between two words', - function() { + () => { assert.equal(levenshtein('', ''), 0); assert.equal(levenshtein('a', ''), 1); assert.equal(levenshtein('', 'a'), 1); diff --git a/src/test/algorithms/string/longest_common_subsequence.js b/src/test/algorithms/string/longest_common_subsequence.js index 78a9bcc..5514a97 100644 --- a/src/test/algorithms/string/longest_common_subsequence.js +++ b/src/test/algorithms/string/longest_common_subsequence.js @@ -5,9 +5,9 @@ const filename = 'longest_common_subsequence'; const longestCommonSubsequence = require(directory + filename); const assert = require('assert'); -describe('Longest common subsequence', function() { +describe('Longest common subsequence', () => { it('should return the longest common subsequence of ' + - 'two strings', function() { + 'two strings', () => { assert.equal('', longestCommonSubsequence('', '')); assert.equal('', longestCommonSubsequence('', 'aaa')); assert.equal('', longestCommonSubsequence('aaa', '')); diff --git a/src/test/algorithms/string/longest_common_substring.js b/src/test/algorithms/string/longest_common_substring.js index 9844dca..9e76024 100644 --- a/src/test/algorithms/string/longest_common_substring.js +++ b/src/test/algorithms/string/longest_common_substring.js @@ -5,8 +5,8 @@ const filename = 'longest_common_substring'; const longestCommonSubstring = require(directory + filename); const assert = require('assert'); -describe('Longest common substring', function() { - it('should return the longest common substring of two strings', function() { +describe('Longest common substring', () => { + it('should return the longest common substring of two strings', () => { assert.equal('', longestCommonSubstring('', '')); assert.equal('', longestCommonSubstring('', 'aaa')); assert.equal('', longestCommonSubstring('aaa', '')); diff --git a/src/test/algorithms/string/rabin_karp.js b/src/test/algorithms/string/rabin_karp.js index 3228203..703aeb0 100644 --- a/src/test/algorithms/string/rabin_karp.js +++ b/src/test/algorithms/string/rabin_karp.js @@ -3,13 +3,13 @@ const rabinKarp = require('../../..').String.rabinKarp; const assert = require('assert'); -const rabinKarpEqualsToIndexOf = function(a, b) { +const rabinKarpEqualsToIndexOf = (a, b) => { assert.equal(rabinKarp(a, b), a.indexOf(b)); }; -describe('Karp-Rabin', function() { +describe('Karp-Rabin', () => { it('should verify if a string is contained in another string', - function() { + () => { rabinKarpEqualsToIndexOf('', ''); rabinKarpEqualsToIndexOf('a', 'b'); rabinKarpEqualsToIndexOf('b', 'a'); diff --git a/src/test/data_structures/avl-tree.js b/src/test/data_structures/avl-tree.js index b6343e0..424ffd1 100644 --- a/src/test/data_structures/avl-tree.js +++ b/src/test/data_structures/avl-tree.js @@ -4,12 +4,12 @@ const root = require('../..'); const AVLTree = root.DataStructures.AVLTree; const assert = require('assert'); -describe('AVL Tree', function() { - it('should start with null root', function() { +describe('AVL Tree', () => { + it('should start with null root', () => { assert.equal(new AVLTree().root, null); }); - it('should insert and single rotate (leftRight) properly', function() { + it('should insert and single rotate (leftRight) properly', () => { const avlTree = new AVLTree(); avlTree.insert(9); avlTree.insert(3); @@ -24,7 +24,7 @@ describe('AVL Tree', function() { assert.equal(avlTree.root.right.height, 1); }); - it('should insert and single rotate (rightLeft) properly', function() { + it('should insert and single rotate (rightLeft) properly', () => { const avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(75); @@ -39,7 +39,7 @@ describe('AVL Tree', function() { assert.equal(avlTree.root.right.height, 1); }); - it('should insert and double rotate (leftLeft) properly', function() { + it('should insert and double rotate (leftLeft) properly', () => { const avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(25); @@ -54,7 +54,7 @@ describe('AVL Tree', function() { assert.equal(avlTree.root.right.height, 1); }); - it('should insert and double rotate (rightRight) properly', function() { + it('should insert and double rotate (rightRight) properly', () => { const avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(75); @@ -69,7 +69,7 @@ describe('AVL Tree', function() { assert.equal(avlTree.root.right.height, 1); }); - it('should insert multiple nodes and balance properly (1)', function() { + it('should insert multiple nodes and balance properly (1)', () => { const avlTree = new AVLTree(); avlTree.insert(30); avlTree.insert(15); @@ -90,7 +90,7 @@ describe('AVL Tree', function() { assert.equal(avlTree.root.right.right.height, 1); }); - it('should remove nodes and balance properly (2)', function() { + it('should remove nodes and balance properly (2)', () => { const avlTree = new AVLTree(); avlTree.insert(55); avlTree.insert(25); @@ -107,7 +107,7 @@ describe('AVL Tree', function() { assert.equal(avlTree.root.right.height, 1); }); - it('should always keep the tree balanced', function() { + it('should always keep the tree balanced', () => { const avlTree = new AVLTree(); avlTree.insert(50); @@ -196,7 +196,7 @@ describe('AVL Tree', function() { }); it('should return the parents before the children when ' + - 'traversing in preorder', function() { + 'traversing in preorder', () => { const avlTree = new AVLTree(); avlTree.insert(50); @@ -218,14 +218,14 @@ describe('AVL Tree', function() { const expectedPreOrder = [50, 5, 2, 1, 4, 20, 7, 6, 15, 30, 40, 100, 75, 80, 200]; const preOrder = []; - avlTree.preOrder(avlTree.root, function(n) { + avlTree.preOrder(avlTree.root, n => { preOrder.push(n.value); }); assert.deepEqual(expectedPreOrder, preOrder); }); it('should return the children before the parents when ' + - 'traversing in postorder', function() { + 'traversing in postorder', () => { const avlTree = new AVLTree(); avlTree.insert(50); @@ -247,13 +247,13 @@ describe('AVL Tree', function() { const expectedPostOrder = [1, 4, 2, 6, 15, 7, 40, 30, 20, 5, 80, 75, 200, 100, 50]; const postOrder = []; - avlTree.postOrder(avlTree.root, function(n) { + avlTree.postOrder(avlTree.root, n => { postOrder.push(n.value); }); assert.deepEqual(expectedPostOrder, postOrder); }); - it('should return the sorted elements when traversing in order', function() { + it('should return the sorted elements when traversing in order', () => { const avlTree = new AVLTree(); const a = []; let i; diff --git a/src/test/data_structures/bst.js b/src/test/data_structures/bst.js index 3b019ba..206c5e3 100644 --- a/src/test/data_structures/bst.js +++ b/src/test/data_structures/bst.js @@ -5,8 +5,8 @@ const BST = root.DataStructures.BST; const bfs = root.Search.bfs; const assert = require('assert'); -describe('Binary Search Tree', function() { - it('should insert elements respecting the BST restrictions', function() { +describe('Binary Search Tree', () => { + it('should insert elements respecting the BST restrictions', () => { const bst = new BST(); bst.insert(4); bst.insert(8); @@ -19,7 +19,7 @@ describe('Binary Search Tree', function() { bst.insert(100); assert.equal(bst.size, 9); }); - it('should check if an element exists (in O(lg n))', function() { + it('should check if an element exists (in O(lg n))', () => { const bst = new BST(); bst.insert(4); bst.insert(8); @@ -62,12 +62,10 @@ describe('Binary Search Tree', function() { bst.insert(100); bst.insert(2.5); - const callbackGenerator = function(a) { - return n => a.push(n); - }; + const callbackGenerator = a => n => a.push(n); it('should remove a leaf without altering anything else in ' + - 'the structure of the tree', function() { + 'the structure of the tree', () => { bst.remove(0); /** * 4 @@ -81,7 +79,7 @@ describe('Binary Search Tree', function() { }); it('should remove an element with just one child and substitute ' + - 'it as the root of only subtree', function() { + 'it as the root of only subtree', () => { bst.remove(10); /** * 4 @@ -95,7 +93,7 @@ describe('Binary Search Tree', function() { }); it('should substitute an element by the leftmost child in the right ' + - 'subtree and remove it as a leaf', function() { + 'subtree and remove it as a leaf', () => { /** * 4 * 2 8 @@ -136,7 +134,7 @@ describe('Binary Search Tree', function() { assert.deepEqual(a, [5, 3, 8, 1, 100]); }); - it('should always return the right root and size', function() { + it('should always return the right root and size', () => { const bst = new BST(); bst.insert(5); assert.equal(bst.size, 1); @@ -156,7 +154,7 @@ describe('Binary Search Tree', function() { }); it('should throw an error when trying to remove an unexisting node', - function() { + () => { const bst = new BST(); assert.throws(() => bst.remove(0), Error); bst.insert(3); @@ -164,14 +162,14 @@ describe('Binary Search Tree', function() { }); }); -describe('Binary Search Tree with custom comparator', function() { - const strLenCompare = function(a, b) { +describe('Binary Search Tree with custom comparator', () => { + const strLenCompare = (a, b) => { if (a.length === b.length) return 0; return a.length < b.length ? -1 : 1; }; it( - 'should insert elements respecting the BST restrictions', function() { + 'should insert elements respecting the BST restrictions', () => { const bst = new BST(strLenCompare); bst.insert('banana'); bst.insert('apple'); @@ -180,7 +178,7 @@ describe('Binary Search Tree with custom comparator', function() { assert.equal(bst.size, 4); }); - it('should check if an element exists (in O(lg n))', function() { + it('should check if an element exists (in O(lg n))', () => { const bst = new BST(strLenCompare); bst.insert('banana'); bst.insert('apple'); @@ -210,18 +208,16 @@ describe('Binary Search Tree with custom comparator', function() { bst.insert('pineapple'); bst.insert('watermelon'); - const callbackGenerator = function(a) { - return n => a.push(n); - }; + const callbackGenerator = a => n => a.push(n); - it('should insert the items according to the comparator', function() { + it('should insert the items according to the comparator', () => { const a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear', 'watermelon']); }); it('should remove a leaf without altering anything else in ' + - 'the structure of the tree', function() { + 'the structure of the tree', () => { bst.remove('watermelon'); /** * 'banana' @@ -234,7 +230,7 @@ describe('Binary Search Tree with custom comparator', function() { }); it('should remove an element with just one child and substitute ' + - 'it as the root of only subtree', function() { + 'it as the root of only subtree', () => { bst.remove('apple'); /** * 'banana' @@ -246,7 +242,7 @@ describe('Binary Search Tree with custom comparator', function() { }); it('should substitute an element by the leftmost child in the right ' + - 'subtree and remove it as a leaf', function() { + 'subtree and remove it as a leaf', () => { bst.remove('banana'); /** * 'pineapple' diff --git a/src/test/data_structures/disjoint_set_forest.js b/src/test/data_structures/disjoint_set_forest.js index ce41f3f..5c2d9eb 100644 --- a/src/test/data_structures/disjoint_set_forest.js +++ b/src/test/data_structures/disjoint_set_forest.js @@ -3,9 +3,9 @@ const DisjointSetForest = require('../..').DataStructures.DisjointSetForest; const assert = require('assert'); -describe('Disjoint Set Forest', function() { +describe('Disjoint Set Forest', () => { it('should decide if two elements belong to the same subset or not', - function() { + () => { const forest = new DisjointSetForest(); assert(!forest.sameSubset(1, 2)); forest.merge(1, 2); @@ -17,10 +17,10 @@ describe('Disjoint Set Forest', function() { assert(!forest.sameSubset(1, 5)); }); - it('should maintain subset sizes', function() { + it('should maintain subset sizes', () => { const forest = new DisjointSetForest(); - const assertSizesCorrect = function(elements, size) { - elements.forEach(function(element) { + const assertSizesCorrect = (elements, size) => { + elements.forEach(element => { assert.equal(forest.size(element), size); }); }; @@ -37,11 +37,11 @@ describe('Disjoint Set Forest', function() { assertSizesCorrect([0, 1, 2, 3, 4], 5); }); - it('should point all elements to the same root', function() { + it('should point all elements to the same root', () => { const forest = new DisjointSetForest(); const assertSameRoot = function(element) { const root = forest.root(element); - [].slice.call(arguments, 1).forEach(function(element) { + [].slice.call(arguments, 1).forEach(element => { assert.equal(forest.root(element), root); }); }; @@ -55,13 +55,9 @@ describe('Disjoint Set Forest', function() { assertSameRoot(0, 1, 2, 3, 4, 5); }); - it('should not choose the root element outside the subset', function() { + it('should not choose the root element outside the subset', () => { const forest = new DisjointSetForest(); - const assertInside = function(value, set) { - return set.some(function(element) { - return element === value; - }); - }; + const assertInside = (value, set) => set.some(element => element === value); assert.equal(forest.root(0), 0); forest.merge(0, 1); assertInside(forest.root(0), [0, 1]); diff --git a/src/test/data_structures/fenwick_tree.js b/src/test/data_structures/fenwick_tree.js index 2db984b..69c7763 100644 --- a/src/test/data_structures/fenwick_tree.js +++ b/src/test/data_structures/fenwick_tree.js @@ -3,8 +3,8 @@ const FenwickTree = require('../..').DataStructures.FenwickTree; const assert = require('assert'); -describe('FenwickTree', function() { - it('should allow prefix queries', function() { +describe('FenwickTree', () => { + it('should allow prefix queries', () => { const tree = new FenwickTree(10); tree.adjust(5, 42); tree.adjust(7, 43); @@ -23,7 +23,7 @@ describe('FenwickTree', function() { assert.equal(tree.prefixSum(10), 42 + 43 + 44); }); - it('should allow range queries', function() { + it('should allow range queries', () => { const tree = new FenwickTree(10); tree.adjust(5, 42); tree.adjust(7, 43); diff --git a/src/test/data_structures/graph.js b/src/test/data_structures/graph.js index aa7c177..f543f0e 100644 --- a/src/test/data_structures/graph.js +++ b/src/test/data_structures/graph.js @@ -3,8 +3,8 @@ const Graph = require('../..').DataStructures.Graph; const assert = require('assert'); -describe('Graph - Adjacency list', function() { - it('should be directed by default', function() { +describe('Graph - Adjacency list', () => { + it('should be directed by default', () => { let g = new Graph(); assert(g.directed); @@ -15,7 +15,7 @@ describe('Graph - Adjacency list', function() { assert(g.directed); }); - it('should default weight 1 for edges', function() { + it('should default weight 1 for edges', () => { const g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -24,7 +24,7 @@ describe('Graph - Adjacency list', function() { }); it('should create the vertex if an edge is inserted and vertex doesnt exist', - function() { + () => { const g = new Graph(); g.addEdge('a', 'b'); assert.equal(g.vertices.size, 2); @@ -32,7 +32,7 @@ describe('Graph - Adjacency list', function() { assert(g.vertices.contains('b')); }); - it('should sum multiple edges between the same vertices', function() { + it('should sum multiple edges between the same vertices', () => { const g = new Graph(); g.addEdge('a', 'b', 10); assert.equal(g.edge('a', 'b'), 10); @@ -40,7 +40,7 @@ describe('Graph - Adjacency list', function() { assert.equal(g.edge('a', 'b'), 14); }); - it('should have edges in both directions if undirected', function() { + it('should have edges in both directions if undirected', () => { const g = new Graph(false); g.addVertex('a'); g.addVertex('b'); @@ -63,7 +63,7 @@ describe('Graph - Adjacency list', function() { assert.equal(g.edge('b', 'a'), 12); }); - it('should respect direction of the edges in directed graphs', function() { + it('should respect direction of the edges in directed graphs', () => { const g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -87,7 +87,7 @@ describe('Graph - Adjacency list', function() { }); it('should have reversed edges with same weight for a reverse directed graph', - function() { + () => { const g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -112,7 +112,7 @@ describe('Graph - Adjacency list', function() { assert.equal(r.edge('b', 'a'), 10); }); - it('should have a list of vertices', function() { + it('should have a list of vertices', () => { const g = new Graph(); assert.equal(g.vertices.size, 0); g.addVertex('a'); @@ -124,15 +124,15 @@ describe('Graph - Adjacency list', function() { assert(g.vertices.contains('c')); }); - it('should not allow repeated vertices', function() { + it('should not allow repeated vertices', () => { const g = new Graph(); g.addVertex('a'); - assert.throws(function() { + assert.throws(() => { g.addVertex('a'); }); }); - it('should return a list of neighbors of a vertex', function() { + it('should return a list of neighbors of a vertex', () => { const g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -147,7 +147,7 @@ describe('Graph - Adjacency list', function() { assert.deepEqual(g.neighbors('c'), ['d']); }); - it('should return the weight of the edge', function() { + it('should return the weight of the edge', () => { const g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -162,7 +162,7 @@ describe('Graph - Adjacency list', function() { assert.equal(g.edge('c', 'd'), 2); }); - it('should not "inherit" edges from Object.prototype', function() { + it('should not "inherit" edges from Object.prototype', () => { const g = new Graph(); g.addEdge('a', 'b'); diff --git a/src/test/data_structures/hash_table.js b/src/test/data_structures/hash_table.js index 65fdc2d..a2e29a5 100644 --- a/src/test/data_structures/hash_table.js +++ b/src/test/data_structures/hash_table.js @@ -3,9 +3,9 @@ const HashTable = require('../..').DataStructures.HashTable; const assert = require('assert'); -describe('Hash Table', function() { +describe('Hash Table', () => { it('should calculate hashes using the same algorithm as ' + - 'Java\'s String.hashCode', function() { + 'Java\'s String.hashCode', () => { const h = new HashTable(); assert.equal(h.hash('The quick brown fox jumps over the lazy dog'), -609428141); @@ -33,7 +33,7 @@ describe('Hash Table', function() { }); it('should initialize the table with the given capacity', - function() { + () => { let h = new HashTable(); assert.equal(h.capacity, 64); // default initial capacity; assert.equal(h.size, 0); @@ -42,7 +42,7 @@ describe('Hash Table', function() { assert.equal(h.capacity, 2); }); - it('should allow putting and getting elements from the table', function() { + it('should allow putting and getting elements from the table', () => { const h = new HashTable(16); const a = {a: 'foo', b: 'bar'}; h.put('foo', a); @@ -57,7 +57,7 @@ describe('Hash Table', function() { assert.strictEqual(h.get('bar'), b); }); - it('should replace items if the same key is reused', function() { + it('should replace items if the same key is reused', () => { const h = new HashTable(16); const a = {a: 'foo', b: 'bar'}; h.put('foo', a); @@ -68,13 +68,13 @@ describe('Hash Table', function() { assert.strictEqual(h.get('foo'), b); }); - it('should return undefined if there\'s no element', function() { + it('should return undefined if there\'s no element', () => { const h = new HashTable(8); assert.equal(h.get('foo'), undefined); assert.equal(h.get('bar'), undefined); }); - it('should handle hash conflicts', function() { + it('should handle hash conflicts', () => { const h = new HashTable(4); // Both keys are supposed to be pushed to the same position assert.equal(h._position('a'), h._position('e')); @@ -88,7 +88,7 @@ describe('Hash Table', function() { assert.equal(h.get('e'), 'bar'); }); - it('should increase capacity if needed', function() { + it('should increase capacity if needed', () => { const h = new HashTable(2); assert.equal(h.capacity, 2); @@ -99,7 +99,7 @@ describe('Hash Table', function() { assert.equal(h.capacity, 4); }); - it('should allow removing items', function() { + it('should allow removing items', () => { const h = new HashTable(); assert.equal(h.get('foo'), undefined); @@ -114,7 +114,7 @@ describe('Hash Table', function() { assert.equal(h.get('foo'), undefined); }); - it('should allow non-string keys', function() { + it('should allow non-string keys', () => { const h = new HashTable(); h.put(10, 5); assert.equal(h.get(10), 5); @@ -124,7 +124,7 @@ describe('Hash Table', function() { assert.equal(h.get(o), 'foo'); }); - it('should perform a function to all keys with forEach', function() { + it('should perform a function to all keys with forEach', () => { const h = new HashTable(); h.put(1, 10); h.put(2, 20); @@ -132,7 +132,7 @@ describe('Hash Table', function() { let totalKeys = 0; let totalValues = 0; - h.forEach(function(k, v) { + h.forEach((k, v) => { totalKeys += k; totalValues += v; }); diff --git a/src/test/data_structures/heap.js b/src/test/data_structures/heap.js index ab8dbf2..18f9b61 100644 --- a/src/test/data_structures/heap.js +++ b/src/test/data_structures/heap.js @@ -3,8 +3,8 @@ const heap = require('../..').DataStructures.Heap; const assert = require('assert'); -describe('Min Heap', function() { - it('should always return the lowest element', function() { +describe('Min Heap', () => { + it('should always return the lowest element', () => { const h = new heap.MinHeap(); assert(h.isEmpty()); h.insert(10); @@ -35,7 +35,7 @@ describe('Min Heap', function() { assert(h.isEmpty()); }); - it('should heapify an unordered array', function() { + it('should heapify an unordered array', () => { const h = new heap.MinHeap(); h.heapify([10, 2091, 4, 1, 5, 500, 0, 18, 3, 22, 20]); @@ -55,12 +55,12 @@ describe('Min Heap', function() { }); it('should perform a function to all elements from smallest to largest' + - ' with forEach', function() { + ' with forEach', () => { const h = new heap.MinHeap(); h.heapify([3, 10, 1000, 0, 2, 1]); const output = []; - h.forEach(function(n) { + h.forEach(n => { output.push(n); }); @@ -71,8 +71,8 @@ describe('Min Heap', function() { }); }); -describe('Max Heap', function() { - it('should always return the greatest element', function() { +describe('Max Heap', () => { + it('should always return the greatest element', () => { const h = new heap.MaxHeap(); assert(h.isEmpty()); h.insert(10); @@ -103,7 +103,7 @@ describe('Max Heap', function() { assert(h.isEmpty()); }); - it('should heapify an unordered array', function() { + it('should heapify an unordered array', () => { const h = new heap.MaxHeap(); h.heapify([10, 2091, 4, 1, 5, 500, 0, 18, 3, 22, 20]); @@ -123,12 +123,12 @@ describe('Max Heap', function() { }); it('should perform a function to all elements from largest to smallest' + - ' with forEach', function() { + ' with forEach', () => { const h = new heap.MaxHeap(); h.heapify([3, 10, 1000, 0, 2, 1]); const output = []; - h.forEach(function(n) { + h.forEach(n => { output.push(n); }); diff --git a/src/test/data_structures/linked_list.js b/src/test/data_structures/linked_list.js index d6854f7..9a08e9c 100644 --- a/src/test/data_structures/linked_list.js +++ b/src/test/data_structures/linked_list.js @@ -3,14 +3,14 @@ const LinkedList = require('../..').DataStructures.LinkedList; const assert = require('assert'); -describe('LinkedList', function() { - it('should start empty', function() { +describe('LinkedList', () => { + it('should start empty', () => { const l = new LinkedList(); assert(l.isEmpty()); assert.equal(l.length, 0); }); - it('should increment length when an item is added', function() { + it('should increment length when an item is added', () => { const l = new LinkedList(); l.add(1); assert.equal(l.length, 1); @@ -21,7 +21,7 @@ describe('LinkedList', function() { }); it('should return the items from the positions they were inserted', - function() { + () => { const l = new LinkedList(); l.add(1); l.add(2); @@ -62,7 +62,7 @@ describe('LinkedList', function() { }); it('should throw errors when trying to access indexes out of bounds', - function() { + () => { const l = new LinkedList(); assert.throws(() => l.get(0), Error); assert.throws(() => l.get(1), Error); @@ -85,7 +85,7 @@ describe('LinkedList', function() { assert.throws(() => l.get(10), Error); }); - it('should be able to delete elements', function() { + it('should be able to delete elements', () => { const l = new LinkedList(); l.add(1); @@ -132,7 +132,7 @@ describe('LinkedList', function() { assert.equal(l.length, 0); }); - it('should perform a function to all elements with forEach', function() { + it('should perform a function to all elements with forEach', () => { const l = new LinkedList(); l.add(5); l.add(1); @@ -141,7 +141,7 @@ describe('LinkedList', function() { l.add(1000); const a = []; - l.forEach(function(e) { + l.forEach(e => { a.push(e); }); @@ -149,7 +149,7 @@ describe('LinkedList', function() { }); it('should throw an error when trying to delete from an empty list', - function() { + () => { const l = new LinkedList(); assert.throws(() => l.del(0), Error); }); diff --git a/src/test/data_structures/priority_queue.js b/src/test/data_structures/priority_queue.js index 3035897..a842270 100644 --- a/src/test/data_structures/priority_queue.js +++ b/src/test/data_structures/priority_queue.js @@ -3,8 +3,8 @@ const PriorityQueue = require('../..').DataStructures.PriorityQueue; const assert = require('assert'); -describe('Min Priority Queue', function() { - it('should always return the element with the lowest priority', function() { +describe('Min Priority Queue', () => { + it('should always return the element with the lowest priority', () => { const q = new PriorityQueue(); assert(q.isEmpty()); q.insert('a', 10); @@ -36,7 +36,7 @@ describe('Min Priority Queue', function() { }); it('can receive a dictionary with item => priority in construction', - function() { + () => { const q = new PriorityQueue({ a: 10, b: 2091, @@ -53,7 +53,7 @@ describe('Min Priority Queue', function() { assert.equal(q.extract(), 'b'); }); - it('should be possible to change the priority of an item', function() { + it('should be possible to change the priority of an item', () => { const q = new PriorityQueue({ a: 10, b: 2091, @@ -79,7 +79,7 @@ describe('Min Priority Queue', function() { }); it('should just update the priority when trying to insert an element that ' + - ' already exists', function() { + ' already exists', () => { const q = new PriorityQueue({ a: 10, b: 2091, diff --git a/src/test/data_structures/queue.js b/src/test/data_structures/queue.js index e9f8b7c..46932c3 100644 --- a/src/test/data_structures/queue.js +++ b/src/test/data_structures/queue.js @@ -3,14 +3,14 @@ const Queue = require('../..').DataStructures.Queue; const assert = require('assert'); -describe('Queue', function() { - it('should start empty', function() { +describe('Queue', () => { + it('should start empty', () => { const q = new Queue(); assert(q.isEmpty()); assert.equal(q.length, 0); }); - it('should implement a FIFO logic', function() { + it('should implement a FIFO logic', () => { const q = new Queue(); q.push(1); q.push(2); @@ -24,7 +24,7 @@ describe('Queue', function() { }); it('should allow me to peek at the first element in' + - ' line without popping it', function() { + ' line without popping it', () => { const q = new Queue(); assert.throws(() => q.peek(), Error); // Empty list q.push(1); diff --git a/src/test/data_structures/set.js b/src/test/data_structures/set.js index 36a1a04..654eb76 100644 --- a/src/test/data_structures/set.js +++ b/src/test/data_structures/set.js @@ -3,13 +3,13 @@ const HashSet = require('../..').DataStructures.Set; const assert = require('assert'); -describe('HashSet', function() { - it('should start empty', function() { +describe('HashSet', () => { + it('should start empty', () => { const s = new HashSet(); assert.equal(s.size, 0); }); - it('should add all initial arguments', function() { + it('should add all initial arguments', () => { const s = new HashSet(1, 2, 3); assert.equal(s.size, 3); assert(s.contains(1)); @@ -17,7 +17,7 @@ describe('HashSet', function() { assert(s.contains(3)); }); - it('should add all arguments', function() { + it('should add all arguments', () => { const s = new HashSet(1, 2, 3); assert.equal(s.size, 3); s.add(4, 5, 6); @@ -30,7 +30,7 @@ describe('HashSet', function() { assert(s.contains(6)); }); - it('should remove all arguments', function() { + it('should remove all arguments', () => { const s = new HashSet(1, 2, 3); assert.equal(s.size, 3); s.remove(1, 3); @@ -41,7 +41,7 @@ describe('HashSet', function() { }); it('should do nothing when trying to remove an element that doesn\'t exist', - function() { + () => { const s = new HashSet(1, 2, 3); assert.equal(s.size, 3); s.remove(4); @@ -51,18 +51,18 @@ describe('HashSet', function() { assert(s.contains(3)); }); - it('should only contain its elements', function() { + it('should only contain its elements', () => { const s = new HashSet(1, 2, 3); assert(s.contains(1)); assert(!s.contains(4)); }); - it('should perform a function to all elements with forEach', function() { + it('should perform a function to all elements with forEach', () => { const s = new HashSet(); s.add(1, 2, 3); let total = 0; - s.forEach(function(elem) { + s.forEach(elem => { total += elem; }); diff --git a/src/test/data_structures/stack.js b/src/test/data_structures/stack.js index 2b40342..bd43c32 100644 --- a/src/test/data_structures/stack.js +++ b/src/test/data_structures/stack.js @@ -3,14 +3,14 @@ const Stack = require('../..').DataStructures.Stack; const assert = require('assert'); -describe('Stack', function() { - it('should start empty', function() { +describe('Stack', () => { + it('should start empty', () => { const s = new Stack(); assert(s.isEmpty()); assert.equal(s.length, 0); }); - it('should implement a LIFO logic', function() { + it('should implement a LIFO logic', () => { const s = new Stack(); s.push(1); s.push(2); @@ -24,7 +24,7 @@ describe('Stack', function() { }); it('should allow me to peek at the top element in' + - ' the stack without popping it', function() { + ' the stack without popping it', () => { const s = new Stack(); s.push(1); s.push(2); diff --git a/src/test/data_structures/treap.js b/src/test/data_structures/treap.js index cca662b..290e9b3 100644 --- a/src/test/data_structures/treap.js +++ b/src/test/data_structures/treap.js @@ -4,13 +4,13 @@ const root = require('../..'); const Treap = root.DataStructures.Treap; const assert = require('assert'); -describe('Treap', function() { +describe('Treap', () => { let treap; - before(function() { + before(() => { treap = new Treap(); }); - it('should insert elements', function() { + it('should insert elements', () => { treap.insert(3); treap.insert(2); treap.insert(10); @@ -23,7 +23,7 @@ describe('Treap', function() { assert.equal(treap.root.size, 8); }); - it('should remove elements correctly', function() { + it('should remove elements correctly', () => { // Value that not exist treap.remove(200); assert.equal(treap.root.size, 8); @@ -36,7 +36,7 @@ describe('Treap', function() { assert.equal(treap.root.size, 4); }); - it('should insert and remove elements', function() { + it('should insert and remove elements', () => { // [-100, 2, 3, 10] treap.insert(200); // [-100, 2, 3, 10, 200] @@ -54,7 +54,7 @@ describe('Treap', function() { assert.equal(treap.root.size, 5); }); - it('should check if an element exists', function() { + it('should check if an element exists', () => { // [1, 2, 3, 10, 100] assert.equal(treap.find(1), true); assert.equal(treap.find(2), true); @@ -67,7 +67,7 @@ describe('Treap', function() { assert.equal(treap.find(101), false); }); - it('should get minimum element', function() { + it('should get minimum element', () => { // [1, 2, 3, 10, 100] assert.equal(treap.minimum(), 1); treap.remove(1); @@ -81,7 +81,7 @@ describe('Treap', function() { assert.equal(treap.minimum(), 2); }); - it('should get maximum element', function() { + it('should get maximum element', () => { // [2, 3, 10, 100] assert.equal(treap.maximum(), 100); treap.remove(100); @@ -101,7 +101,7 @@ describe('Treap', function() { assert.equal(treap.maximum(), 1); }); - it('should handle dumplicated elements', function() { + it('should handle dumplicated elements', () => { treap.insert(1); // [1, 1] assert.equal(treap.size(), 2); @@ -124,7 +124,7 @@ describe('Treap', function() { assert.equal(treap.size(), 0); }); - it('should keep balance', function() { + it('should keep balance', () => { // Insert 1023 elements randomly for (let i = 0; i < 1023; ++i) { treap.insert(Math.random()); @@ -134,7 +134,7 @@ describe('Treap', function() { assert(Math.abs(treap.height() - 23) < 5); }); - it('should rotate correctly', function() { + it('should rotate correctly', () => { // Force clear the tree treap.root = null; treap.insert(1); diff --git a/src/test/util/comparator.js b/src/test/util/comparator.js index 790bbd7..c7fb1e6 100644 --- a/src/test/util/comparator.js +++ b/src/test/util/comparator.js @@ -3,9 +3,9 @@ const Comparator = require('../../util/comparator'); const assert = require('assert'); -describe('Comparator', function() { +describe('Comparator', () => { it('Should use a default arithmetic comparison if no function is passed', - function() { + () => { const c = new Comparator(); assert.equal(c.compare(1, 1), 0); assert.equal(c.compare(1, 2), -1); @@ -25,10 +25,8 @@ describe('Comparator', function() { assert(!c.equal(0, 1)); }); - it('should allow comparison function to be defined by user', function() { - const compareFn = function() { - return 0; - }; + it('should allow comparison function to be defined by user', () => { + const compareFn = () => 0; const c = new Comparator(compareFn); assert.equal(c.compare(1, 1), 0); assert.equal(c.compare(1, 2), 0); @@ -48,7 +46,7 @@ describe('Comparator', function() { assert(c.equal(0, 1)); }); - it('Should allow reversing the comparisons', function() { + it('Should allow reversing the comparisons', () => { const c = new Comparator(); c.reverse(); assert.equal(c.compare(1, 1), 0); diff --git a/src/util/comparator.js b/src/util/comparator.js index aed5343..9b2d78d 100644 --- a/src/util/comparator.js +++ b/src/util/comparator.js @@ -17,7 +17,7 @@ function Comparator(compareFn) { /** * Default implementation for the compare function */ -Comparator.prototype.compare = function(a, b) { +Comparator.prototype.compare = (a, b) => { if (a === b) return 0; return a < b ? -1 : 1; }; @@ -50,9 +50,7 @@ Comparator.prototype.equal = function(a, b) { */ Comparator.prototype.reverse = function() { const originalCompareFn = this.compare; - this.compare = function(a, b) { - return originalCompareFn(b, a); - }; + this.compare = (a, b) => originalCompareFn(b, a); }; module.exports = Comparator; From 93e41a3d42b30978411b0d92432f80187bc73109 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 14 Jun 2017 16:49:05 +0200 Subject: [PATCH 243/280] [es6] remove "use strict"; directives --- src/algorithms/geometry/bezier_curve.js | 2 -- src/algorithms/graph/SPFA.js | 2 -- src/algorithms/graph/bellman_ford.js | 2 -- src/algorithms/graph/bfs_shortest_path.js | 2 -- src/algorithms/graph/breadth_first_search.js | 2 -- src/algorithms/graph/depth_first_search.js | 2 -- src/algorithms/graph/dijkstra.js | 2 -- src/algorithms/graph/euler_path.js | 2 -- src/algorithms/graph/floyd_warshall.js | 2 -- src/algorithms/graph/kruskal.js | 2 -- src/algorithms/graph/prim.js | 2 -- src/algorithms/graph/strongly_connected_component.js | 2 -- src/algorithms/graph/topological_sort.js | 2 -- src/algorithms/math/collatz_conjecture.js | 2 -- src/algorithms/math/extended_euclidean.js | 2 -- src/algorithms/math/fast_power.js | 2 -- src/algorithms/math/fibonacci.js | 2 -- src/algorithms/math/find_divisors.js | 2 -- src/algorithms/math/fisher_yates.js | 2 -- src/algorithms/math/gcd.js | 2 -- src/algorithms/math/greatest_difference.js | 2 -- src/algorithms/math/lcm.js | 2 -- src/algorithms/math/newton_sqrt.js | 2 -- src/algorithms/math/next_permutation.js | 2 -- src/algorithms/math/power_set.js | 2 -- src/algorithms/math/primality_tests.js | 2 -- src/algorithms/math/reservoir_sampling.js | 2 -- src/algorithms/math/shannon_entropy.js | 2 -- src/algorithms/search/bfs.js | 1 - src/algorithms/search/binarysearch.js | 2 -- src/algorithms/search/dfs.js | 2 -- src/algorithms/search/ternary_search.js | 2 -- src/algorithms/sorting/bubble_sort.js | 1 - src/algorithms/sorting/counting_sort.js | 2 -- src/algorithms/sorting/heap_sort.js | 1 - src/algorithms/sorting/insertion_sort.js | 1 - src/algorithms/sorting/merge_sort.js | 1 - src/algorithms/sorting/quicksort.js | 1 - src/algorithms/sorting/radix_sort.js | 1 - src/algorithms/sorting/selection_sort.js | 1 - src/algorithms/sorting/shell_sort.js | 1 - src/algorithms/sorting/short_bubble_sort.js | 2 -- src/algorithms/string/hamming.js | 2 -- src/algorithms/string/huffman.js | 2 -- src/algorithms/string/knuth_morris_pratt.js | 2 -- src/algorithms/string/levenshtein.js | 2 -- src/algorithms/string/longest_common_subsequence.js | 2 -- src/algorithms/string/longest_common_substring.js | 2 -- src/algorithms/string/rabin_karp.js | 2 -- src/data_structures.js | 2 -- src/data_structures/avl_tree.js | 2 -- src/data_structures/bst.js | 1 - src/data_structures/disjoint_set_forest.js | 2 -- src/data_structures/fenwick_tree.js | 2 -- src/data_structures/graph.js | 2 -- src/data_structures/hash_table.js | 2 -- src/data_structures/heap.js | 1 - src/data_structures/linked_list.js | 2 -- src/data_structures/priority_queue.js | 2 -- src/data_structures/queue.js | 2 -- src/data_structures/set.js | 2 -- src/data_structures/stack.js | 1 - src/data_structures/treap.js | 2 -- src/geometry.js | 2 -- src/graph.js | 2 -- src/index.js | 2 -- src/math.js | 2 -- src/search.js | 2 -- src/sorting.js | 2 -- src/string.js | 2 -- src/test/algorithms/geometry/bezier_curve.js | 2 -- src/test/algorithms/graph/SPFA.js | 2 -- src/test/algorithms/graph/bellman_ford.js | 2 -- src/test/algorithms/graph/bfs_shortest_path.js | 2 -- src/test/algorithms/graph/breadth_first_search.js | 2 -- src/test/algorithms/graph/depth_first_search.js | 2 -- src/test/algorithms/graph/dijkstra.js | 2 -- src/test/algorithms/graph/euler_path.js | 2 -- src/test/algorithms/graph/floyd_warshall.js | 2 -- src/test/algorithms/graph/minimum_spanning_tree.js | 2 -- src/test/algorithms/graph/strongly_connected_component.js | 2 -- src/test/algorithms/graph/topological_sort.js | 2 -- src/test/algorithms/math/collatz_conjecture.js | 2 -- src/test/algorithms/math/extended_euclidean.js | 2 -- src/test/algorithms/math/fast_power.js | 2 -- src/test/algorithms/math/fibonacci.js | 2 -- src/test/algorithms/math/find_divisors.js | 2 -- src/test/algorithms/math/fisher_yates.js | 2 -- src/test/algorithms/math/gcd.js | 2 -- src/test/algorithms/math/greatest_difference.js | 2 -- src/test/algorithms/math/lcm.js | 2 -- src/test/algorithms/math/newton_sqrt.js | 2 -- src/test/algorithms/math/next_permutation.js | 2 -- src/test/algorithms/math/power_set.js | 2 -- src/test/algorithms/math/primality_tests.js | 2 -- src/test/algorithms/math/reservoir_sampling.js | 2 -- src/test/algorithms/math/shannon_entropy.js | 2 -- src/test/algorithms/searching/bfs.js | 2 -- src/test/algorithms/searching/binarysearch.js | 2 -- src/test/algorithms/searching/dfs.js | 2 -- src/test/algorithms/searching/ternary_search.js | 2 -- src/test/algorithms/sorting/bubble_sort.js | 2 -- src/test/algorithms/sorting/counting_sort.js | 2 -- src/test/algorithms/sorting/heap_sort.js | 2 -- src/test/algorithms/sorting/insertion_sort.js | 2 -- src/test/algorithms/sorting/merge_sort.js | 2 -- src/test/algorithms/sorting/quicksort.js | 2 -- src/test/algorithms/sorting/radix_sort.js | 2 -- src/test/algorithms/sorting/selection_sort.js | 2 -- src/test/algorithms/sorting/shell_sort.js | 2 -- src/test/algorithms/sorting/short_bubble_sort.js | 2 -- src/test/algorithms/sorting/sorting_tests_helper.js | 2 -- src/test/algorithms/string/hamming.js | 2 -- src/test/algorithms/string/huffman.js | 2 -- src/test/algorithms/string/knuth_morris_pratt.js | 2 -- src/test/algorithms/string/levenshtein.js | 2 -- src/test/algorithms/string/longest_common_subsequence.js | 2 -- src/test/algorithms/string/longest_common_substring.js | 2 -- src/test/algorithms/string/rabin_karp.js | 2 -- src/test/data_structures/avl-tree.js | 2 -- src/test/data_structures/bst.js | 2 -- src/test/data_structures/disjoint_set_forest.js | 2 -- src/test/data_structures/fenwick_tree.js | 2 -- src/test/data_structures/graph.js | 2 -- src/test/data_structures/hash_table.js | 2 -- src/test/data_structures/heap.js | 2 -- src/test/data_structures/linked_list.js | 2 -- src/test/data_structures/priority_queue.js | 2 -- src/test/data_structures/queue.js | 2 -- src/test/data_structures/set.js | 2 -- src/test/data_structures/stack.js | 2 -- src/test/data_structures/treap.js | 2 -- src/test/util/comparator.js | 2 -- src/util/comparator.js | 2 -- 134 files changed, 256 deletions(-) diff --git a/src/algorithms/geometry/bezier_curve.js b/src/algorithms/geometry/bezier_curve.js index b5a88df..0261069 100644 --- a/src/algorithms/geometry/bezier_curve.js +++ b/src/algorithms/geometry/bezier_curve.js @@ -1,5 +1,3 @@ -'use strict'; - /** * 2D bezier-curve, https://en.wikipedia.org/wiki/B%C3%A9zier_curve * Usage: diff --git a/src/algorithms/graph/SPFA.js b/src/algorithms/graph/SPFA.js index 8d800f5..6842e06 100644 --- a/src/algorithms/graph/SPFA.js +++ b/src/algorithms/graph/SPFA.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Calculates the shortest paths in a graph to every node from the node s * with SPFA(Shortest Path Faster Algorithm) algorithm diff --git a/src/algorithms/graph/bellman_ford.js b/src/algorithms/graph/bellman_ford.js index 5dce3b1..a7602c2 100644 --- a/src/algorithms/graph/bellman_ford.js +++ b/src/algorithms/graph/bellman_ford.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Calculates the shortest paths in a graph to every node * from the node 'startNode' with Bellman-Ford's algorithm diff --git a/src/algorithms/graph/bfs_shortest_path.js b/src/algorithms/graph/bfs_shortest_path.js index a53886c..b41d375 100644 --- a/src/algorithms/graph/bfs_shortest_path.js +++ b/src/algorithms/graph/bfs_shortest_path.js @@ -1,5 +1,3 @@ -'use strict'; - const breadthFirstSearch = require('./breadth_first_search'); /** diff --git a/src/algorithms/graph/breadth_first_search.js b/src/algorithms/graph/breadth_first_search.js index a930e91..ae81e88 100644 --- a/src/algorithms/graph/breadth_first_search.js +++ b/src/algorithms/graph/breadth_first_search.js @@ -1,5 +1,3 @@ -'use strict'; - const Queue = require('../../data_structures/queue'); /** diff --git a/src/algorithms/graph/depth_first_search.js b/src/algorithms/graph/depth_first_search.js index 3c5388f..40be5fb 100644 --- a/src/algorithms/graph/depth_first_search.js +++ b/src/algorithms/graph/depth_first_search.js @@ -1,5 +1,3 @@ -'use strict'; - /** * @typedef {Object} Callbacks * @param {function(vertex: *, neighbor: *): boolean} allowTraversal - diff --git a/src/algorithms/graph/dijkstra.js b/src/algorithms/graph/dijkstra.js index 5947a21..18628a8 100644 --- a/src/algorithms/graph/dijkstra.js +++ b/src/algorithms/graph/dijkstra.js @@ -1,5 +1,3 @@ -'use strict'; - const PriorityQueue = require('../../data_structures/priority_queue'); /** diff --git a/src/algorithms/graph/euler_path.js b/src/algorithms/graph/euler_path.js index a9b129b..a0c2d98 100644 --- a/src/algorithms/graph/euler_path.js +++ b/src/algorithms/graph/euler_path.js @@ -1,5 +1,3 @@ -'use strict'; - const Graph = require('../../data_structures/graph'); const depthFirstSearch = require('../../algorithms/graph/depth_first_search'); diff --git a/src/algorithms/graph/floyd_warshall.js b/src/algorithms/graph/floyd_warshall.js index 29858be..29d139c 100644 --- a/src/algorithms/graph/floyd_warshall.js +++ b/src/algorithms/graph/floyd_warshall.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Floyd-Warshall algorithm. * Compute all-pairs shortest paths (a path for each pair of vertices). diff --git a/src/algorithms/graph/kruskal.js b/src/algorithms/graph/kruskal.js index 9058f80..ebe5aab 100644 --- a/src/algorithms/graph/kruskal.js +++ b/src/algorithms/graph/kruskal.js @@ -1,5 +1,3 @@ -'use strict'; - const DisjointSetForest = require('../../data_structures/disjoint_set_forest'); const Graph = require('../../data_structures/graph'); diff --git a/src/algorithms/graph/prim.js b/src/algorithms/graph/prim.js index 300f592..0567170 100644 --- a/src/algorithms/graph/prim.js +++ b/src/algorithms/graph/prim.js @@ -1,5 +1,3 @@ -'use strict'; - const PriorityQueue = require('../../data_structures/priority_queue'); const Graph = require('../../data_structures/graph'); diff --git a/src/algorithms/graph/strongly_connected_component.js b/src/algorithms/graph/strongly_connected_component.js index 733eaf2..d2f965c 100644 --- a/src/algorithms/graph/strongly_connected_component.js +++ b/src/algorithms/graph/strongly_connected_component.js @@ -1,5 +1,3 @@ -'use strict'; - const Stack = require('../../data_structures/stack'); const depthFirstSearch = require('../../algorithms/graph/depth_first_search'); diff --git a/src/algorithms/graph/topological_sort.js b/src/algorithms/graph/topological_sort.js index 1ecfd9b..39210f8 100644 --- a/src/algorithms/graph/topological_sort.js +++ b/src/algorithms/graph/topological_sort.js @@ -1,5 +1,3 @@ -'use strict'; - const Stack = require('../../data_structures/stack'); const depthFirstSearch = require('../../algorithms/graph/depth_first_search'); diff --git a/src/algorithms/math/collatz_conjecture.js b/src/algorithms/math/collatz_conjecture.js index 85b3a2e..10be32f 100644 --- a/src/algorithms/math/collatz_conjecture.js +++ b/src/algorithms/math/collatz_conjecture.js @@ -1,5 +1,3 @@ -'use strict'; - // cache algorithm results const cache = {1: 1}; diff --git a/src/algorithms/math/extended_euclidean.js b/src/algorithms/math/extended_euclidean.js index 5bd4e90..3684886 100644 --- a/src/algorithms/math/extended_euclidean.js +++ b/src/algorithms/math/extended_euclidean.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Extended Euclidean algorithm to calculate the solve of * ax + by = gcd(a, b) diff --git a/src/algorithms/math/fast_power.js b/src/algorithms/math/fast_power.js index 0536d37..5c407a9 100644 --- a/src/algorithms/math/fast_power.js +++ b/src/algorithms/math/fast_power.js @@ -1,5 +1,3 @@ -'use strict'; - const multiplicationOperator = (a, b) => a * b; /** diff --git a/src/algorithms/math/fibonacci.js b/src/algorithms/math/fibonacci.js index 643e1f9..1c6de1d 100644 --- a/src/algorithms/math/fibonacci.js +++ b/src/algorithms/math/fibonacci.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Different implementations of the Fibonacci sequence */ diff --git a/src/algorithms/math/find_divisors.js b/src/algorithms/math/find_divisors.js index 40fcb0b..ba8be40 100644 --- a/src/algorithms/math/find_divisors.js +++ b/src/algorithms/math/find_divisors.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Different implementations for finding the divisors */ diff --git a/src/algorithms/math/fisher_yates.js b/src/algorithms/math/fisher_yates.js index 73f040f..8cb682d 100644 --- a/src/algorithms/math/fisher_yates.js +++ b/src/algorithms/math/fisher_yates.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Fisher-Yates shuffles the elements in an array * in O(n) diff --git a/src/algorithms/math/gcd.js b/src/algorithms/math/gcd.js index b7ea9c2..cbd38db 100644 --- a/src/algorithms/math/gcd.js +++ b/src/algorithms/math/gcd.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Euclidean algorithm to calculate the Greatest Common Divisor (GCD) * diff --git a/src/algorithms/math/greatest_difference.js b/src/algorithms/math/greatest_difference.js index 6b516fc..675cc5b 100644 --- a/src/algorithms/math/greatest_difference.js +++ b/src/algorithms/math/greatest_difference.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Find the greatest difference between two numbers in a set * This solution has a cost of O(n) diff --git a/src/algorithms/math/lcm.js b/src/algorithms/math/lcm.js index 9e4196a..26a3f90 100644 --- a/src/algorithms/math/lcm.js +++ b/src/algorithms/math/lcm.js @@ -1,5 +1,3 @@ -'use strict'; - const gcd = require('./gcd.js'); /** diff --git a/src/algorithms/math/newton_sqrt.js b/src/algorithms/math/newton_sqrt.js index 156fee1..babca96 100644 --- a/src/algorithms/math/newton_sqrt.js +++ b/src/algorithms/math/newton_sqrt.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Newton's method to calculate square root * diff --git a/src/algorithms/math/next_permutation.js b/src/algorithms/math/next_permutation.js index f3de892..fc87418 100644 --- a/src/algorithms/math/next_permutation.js +++ b/src/algorithms/math/next_permutation.js @@ -1,5 +1,3 @@ -'use strict'; - const Comparator = require('../../util/comparator'); /** diff --git a/src/algorithms/math/power_set.js b/src/algorithms/math/power_set.js index 7de1949..c417adf 100644 --- a/src/algorithms/math/power_set.js +++ b/src/algorithms/math/power_set.js @@ -2,8 +2,6 @@ * Iterative and recursive implementations of power set */ -'use strict'; - /** * Iterative power set calculation */ diff --git a/src/algorithms/math/primality_tests.js b/src/algorithms/math/primality_tests.js index 33cb7cb..9e5b297 100644 --- a/src/algorithms/math/primality_tests.js +++ b/src/algorithms/math/primality_tests.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Checks whether a number is prime using a given primality test * diff --git a/src/algorithms/math/reservoir_sampling.js b/src/algorithms/math/reservoir_sampling.js index ef49588..22921fa 100644 --- a/src/algorithms/math/reservoir_sampling.js +++ b/src/algorithms/math/reservoir_sampling.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Sample random elements from the array using reservoir algorithm. * diff --git a/src/algorithms/math/shannon_entropy.js b/src/algorithms/math/shannon_entropy.js index 7696de9..e8eb793 100644 --- a/src/algorithms/math/shannon_entropy.js +++ b/src/algorithms/math/shannon_entropy.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Calculate Shannon Entropy of an array * diff --git a/src/algorithms/search/bfs.js b/src/algorithms/search/bfs.js index 36d0815..e28c5cf 100644 --- a/src/algorithms/search/bfs.js +++ b/src/algorithms/search/bfs.js @@ -1,4 +1,3 @@ -'use strict'; const Queue = require('../../data_structures/queue.js'); /** diff --git a/src/algorithms/search/binarysearch.js b/src/algorithms/search/binarysearch.js index 2ad9db7..46c9742 100644 --- a/src/algorithms/search/binarysearch.js +++ b/src/algorithms/search/binarysearch.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Binary Search finds elements in sorted arrays in logarithmic * time (O(lg n)) diff --git a/src/algorithms/search/dfs.js b/src/algorithms/search/dfs.js index 147c477..2cb3b30 100644 --- a/src/algorithms/search/dfs.js +++ b/src/algorithms/search/dfs.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Depth first search for trees * (in order) diff --git a/src/algorithms/search/ternary_search.js b/src/algorithms/search/ternary_search.js index 4fdfd7e..15f257a 100644 --- a/src/algorithms/search/ternary_search.js +++ b/src/algorithms/search/ternary_search.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Finds the maximum of unimodal function fn() within [left, right] * To find the minimum, revert the if/else statement or revert the comparison. diff --git a/src/algorithms/sorting/bubble_sort.js b/src/algorithms/sorting/bubble_sort.js index caf469d..c6eb00a 100644 --- a/src/algorithms/sorting/bubble_sort.js +++ b/src/algorithms/sorting/bubble_sort.js @@ -1,4 +1,3 @@ -'use strict'; const Comparator = require('../../util/comparator'); /** diff --git a/src/algorithms/sorting/counting_sort.js b/src/algorithms/sorting/counting_sort.js index 7b3b11b..e4ee74f 100644 --- a/src/algorithms/sorting/counting_sort.js +++ b/src/algorithms/sorting/counting_sort.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Finds the maximum key from an array of objects * diff --git a/src/algorithms/sorting/heap_sort.js b/src/algorithms/sorting/heap_sort.js index 86cf043..7b2b18d 100644 --- a/src/algorithms/sorting/heap_sort.js +++ b/src/algorithms/sorting/heap_sort.js @@ -1,4 +1,3 @@ -'use strict'; const MinHeap = require('../../data_structures/heap').MinHeap; /** diff --git a/src/algorithms/sorting/insertion_sort.js b/src/algorithms/sorting/insertion_sort.js index a139ed6..f15ca46 100644 --- a/src/algorithms/sorting/insertion_sort.js +++ b/src/algorithms/sorting/insertion_sort.js @@ -1,4 +1,3 @@ -'use strict'; const Comparator = require('../../util/comparator'); /** diff --git a/src/algorithms/sorting/merge_sort.js b/src/algorithms/sorting/merge_sort.js index 0ca5b18..eb894c8 100644 --- a/src/algorithms/sorting/merge_sort.js +++ b/src/algorithms/sorting/merge_sort.js @@ -1,4 +1,3 @@ -'use strict'; const Comparator = require('../../util/comparator'); const merge = (a, b, comparator) => { diff --git a/src/algorithms/sorting/quicksort.js b/src/algorithms/sorting/quicksort.js index 5661677..67674ad 100644 --- a/src/algorithms/sorting/quicksort.js +++ b/src/algorithms/sorting/quicksort.js @@ -1,4 +1,3 @@ -'use strict'; const Comparator = require('../../util/comparator'); /** diff --git a/src/algorithms/sorting/radix_sort.js b/src/algorithms/sorting/radix_sort.js index f98b71f..0b4d46c 100644 --- a/src/algorithms/sorting/radix_sort.js +++ b/src/algorithms/sorting/radix_sort.js @@ -1,4 +1,3 @@ -'use strict'; /** * Auxiliary sorting method for RadixSort * Sorts an array of objects according to only one digit of diff --git a/src/algorithms/sorting/selection_sort.js b/src/algorithms/sorting/selection_sort.js index 0197e93..daa24be 100644 --- a/src/algorithms/sorting/selection_sort.js +++ b/src/algorithms/sorting/selection_sort.js @@ -1,4 +1,3 @@ -'use strict'; const Comparator = require('../../util/comparator'); /** * Selection sort algorithm O(n^2) diff --git a/src/algorithms/sorting/shell_sort.js b/src/algorithms/sorting/shell_sort.js index c537e0a..27deddd 100644 --- a/src/algorithms/sorting/shell_sort.js +++ b/src/algorithms/sorting/shell_sort.js @@ -1,4 +1,3 @@ -'use strict'; const Comparator = require('../../util/comparator'); /** * shell sort worst:O(n lg n) best:O(n) diff --git a/src/algorithms/sorting/short_bubble_sort.js b/src/algorithms/sorting/short_bubble_sort.js index e17b785..cc7446a 100644 --- a/src/algorithms/sorting/short_bubble_sort.js +++ b/src/algorithms/sorting/short_bubble_sort.js @@ -1,5 +1,3 @@ -'use strict'; - const Comparator = require('../../util/comparator'); /** diff --git a/src/algorithms/string/hamming.js b/src/algorithms/string/hamming.js index a595e76..ed20e70 100644 --- a/src/algorithms/string/hamming.js +++ b/src/algorithms/string/hamming.js @@ -6,8 +6,6 @@ * into the other." - https://en.wikipedia.org/wiki/Hamming_distance * */ -'use strict'; - const hamming = (a, b) => { if (a.length !== b.length) { throw new Error('Strings must be equal in length'); diff --git a/src/algorithms/string/huffman.js b/src/algorithms/string/huffman.js index 036978b..6802201 100644 --- a/src/algorithms/string/huffman.js +++ b/src/algorithms/string/huffman.js @@ -1,5 +1,3 @@ -'use strict'; - const huffman = {}; /** diff --git a/src/algorithms/string/knuth_morris_pratt.js b/src/algorithms/string/knuth_morris_pratt.js index f2cc209..ff290d4 100644 --- a/src/algorithms/string/knuth_morris_pratt.js +++ b/src/algorithms/string/knuth_morris_pratt.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Builds the dinamic table of the given pattern * to record how the pattern can match it self diff --git a/src/algorithms/string/levenshtein.js b/src/algorithms/string/levenshtein.js index 739bb6b..863909a 100644 --- a/src/algorithms/string/levenshtein.js +++ b/src/algorithms/string/levenshtein.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Calculates the edit distance between two strings * considering the same cost of 1 to every operation diff --git a/src/algorithms/string/longest_common_subsequence.js b/src/algorithms/string/longest_common_subsequence.js index 444b5a4..d672a34 100644 --- a/src/algorithms/string/longest_common_subsequence.js +++ b/src/algorithms/string/longest_common_subsequence.js @@ -2,8 +2,6 @@ * Implementation of longest common subsequence */ -'use strict'; - /** * Implementation via dynamic programming */ diff --git a/src/algorithms/string/longest_common_substring.js b/src/algorithms/string/longest_common_substring.js index 6e3015f..d3141cc 100644 --- a/src/algorithms/string/longest_common_substring.js +++ b/src/algorithms/string/longest_common_substring.js @@ -2,8 +2,6 @@ * Implementation of longest common substring */ -'use strict'; - /** * Implementation via dynamic programming */ diff --git a/src/algorithms/string/rabin_karp.js b/src/algorithms/string/rabin_karp.js index de4ce25..6dcc1c9 100644 --- a/src/algorithms/string/rabin_karp.js +++ b/src/algorithms/string/rabin_karp.js @@ -1,5 +1,3 @@ -'use strict'; - /** * A prime number used to create * the hash representation of a word diff --git a/src/data_structures.js b/src/data_structures.js index 43cbbc1..8748d53 100644 --- a/src/data_structures.js +++ b/src/data_structures.js @@ -1,5 +1,3 @@ -'use strict'; - // Data Structures module.exports = { AVLTree: require('./data_structures/avl_tree'), diff --git a/src/data_structures/avl_tree.js b/src/data_structures/avl_tree.js index b01d46f..9984087 100644 --- a/src/data_structures/avl_tree.js +++ b/src/data_structures/avl_tree.js @@ -1,5 +1,3 @@ -'use strict'; - /** * AVL Tree */ diff --git a/src/data_structures/bst.js b/src/data_structures/bst.js index 81aeeb0..bd0de05 100644 --- a/src/data_structures/bst.js +++ b/src/data_structures/bst.js @@ -1,4 +1,3 @@ -'use strict'; const Comparator = require('../util/comparator'); /** diff --git a/src/data_structures/disjoint_set_forest.js b/src/data_structures/disjoint_set_forest.js index e120446..d8ca491 100644 --- a/src/data_structures/disjoint_set_forest.js +++ b/src/data_structures/disjoint_set_forest.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Disjoint Set Forest data structure. * Allows fast subset merging and querying. diff --git a/src/data_structures/fenwick_tree.js b/src/data_structures/fenwick_tree.js index a5f4843..379f941 100644 --- a/src/data_structures/fenwick_tree.js +++ b/src/data_structures/fenwick_tree.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Fenwick Tree (Binary Indexed Tree) * diff --git a/src/data_structures/graph.js b/src/data_structures/graph.js index cda7288..f5ebc2f 100644 --- a/src/data_structures/graph.js +++ b/src/data_structures/graph.js @@ -1,5 +1,3 @@ -'use strict'; - const HashSet = require('./set'); /** diff --git a/src/data_structures/hash_table.js b/src/data_structures/hash_table.js index f46c563..9029718 100644 --- a/src/data_structures/hash_table.js +++ b/src/data_structures/hash_table.js @@ -1,5 +1,3 @@ -'use strict'; - const LinkedList = require('./linked_list'); /** diff --git a/src/data_structures/heap.js b/src/data_structures/heap.js index eb9c4a6..adce003 100644 --- a/src/data_structures/heap.js +++ b/src/data_structures/heap.js @@ -1,4 +1,3 @@ -'use strict'; const Comparator = require('../util/comparator'); /** diff --git a/src/data_structures/linked_list.js b/src/data_structures/linked_list.js index 647faef..31b4a6d 100644 --- a/src/data_structures/linked_list.js +++ b/src/data_structures/linked_list.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Doubly-linked list */ diff --git a/src/data_structures/priority_queue.js b/src/data_structures/priority_queue.js index c106573..3913c52 100644 --- a/src/data_structures/priority_queue.js +++ b/src/data_structures/priority_queue.js @@ -1,5 +1,3 @@ -'use strict'; - const MinHeap = require('./heap').MinHeap; /** diff --git a/src/data_structures/queue.js b/src/data_structures/queue.js index 1c49f6d..7a6b1ee 100644 --- a/src/data_structures/queue.js +++ b/src/data_structures/queue.js @@ -1,5 +1,3 @@ -'use strict'; - const LinkedList = require('./linked_list'); /** diff --git a/src/data_structures/set.js b/src/data_structures/set.js index e4f343c..3686645 100644 --- a/src/data_structures/set.js +++ b/src/data_structures/set.js @@ -1,5 +1,3 @@ -'use strict'; - const HashTable = require('./hash_table'); /** diff --git a/src/data_structures/stack.js b/src/data_structures/stack.js index 13e151a..a171e47 100644 --- a/src/data_structures/stack.js +++ b/src/data_structures/stack.js @@ -1,4 +1,3 @@ -'use strict'; const LinkedList = require('./linked_list'); /** diff --git a/src/data_structures/treap.js b/src/data_structures/treap.js index 4170f5f..852c071 100644 --- a/src/data_structures/treap.js +++ b/src/data_structures/treap.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Tree node */ diff --git a/src/geometry.js b/src/geometry.js index 7040652..48f0ec4 100644 --- a/src/geometry.js +++ b/src/geometry.js @@ -1,5 +1,3 @@ -'use strict'; - // Geometry algorithms module.exports = { BezierCurve: require('./algorithms/geometry/bezier_curve') diff --git a/src/graph.js b/src/graph.js index 29a5c61..7738af8 100644 --- a/src/graph.js +++ b/src/graph.js @@ -1,5 +1,3 @@ -'use strict'; - // Graph algorithms module.exports = { topologicalSort: require('./algorithms/graph/topological_sort'), diff --git a/src/index.js b/src/index.js index 0807726..d03f191 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,3 @@ -'use strict'; - const lib = { DataStructures: require('./data_structures'), Graph: require('./graph'), diff --git a/src/math.js b/src/math.js index af22fe1..9547a57 100644 --- a/src/math.js +++ b/src/math.js @@ -1,5 +1,3 @@ -'use strict'; - // Math algorithms module.exports = { fibonacci: require('./algorithms/math/fibonacci'), diff --git a/src/search.js b/src/search.js index 5084cdf..11271b9 100644 --- a/src/search.js +++ b/src/search.js @@ -1,5 +1,3 @@ -'use strict'; - // Search algorithms module.exports = { bfs: require('./algorithms/search/bfs'), diff --git a/src/sorting.js b/src/sorting.js index 332e9ab..e3235a6 100644 --- a/src/sorting.js +++ b/src/sorting.js @@ -1,5 +1,3 @@ -'use strict'; - // Sorting algorithms module.exports = { bubbleSort: require('./algorithms/sorting/bubble_sort'), diff --git a/src/string.js b/src/string.js index 2001a23..8a100de 100644 --- a/src/string.js +++ b/src/string.js @@ -1,5 +1,3 @@ -'use strict'; - // String algorithms module.exports = { levenshtein: require('./algorithms/string/levenshtein'), diff --git a/src/test/algorithms/geometry/bezier_curve.js b/src/test/algorithms/geometry/bezier_curve.js index d04c6b4..cd3ef58 100644 --- a/src/test/algorithms/geometry/bezier_curve.js +++ b/src/test/algorithms/geometry/bezier_curve.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../../'); const BezierCurve = root.Geometry.BezierCurve; const assert = require('assert'); diff --git a/src/test/algorithms/graph/SPFA.js b/src/test/algorithms/graph/SPFA.js index 5b9b1d3..61a1781 100644 --- a/src/test/algorithms/graph/SPFA.js +++ b/src/test/algorithms/graph/SPFA.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../../'); const spfa = root.Graph.SPFA; const Graph = root.DataStructures.Graph; diff --git a/src/test/algorithms/graph/bellman_ford.js b/src/test/algorithms/graph/bellman_ford.js index 70e18bf..2bd2043 100644 --- a/src/test/algorithms/graph/bellman_ford.js +++ b/src/test/algorithms/graph/bellman_ford.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../../'); const bellmanFord = root.Graph.bellmanFord; const Graph = root.DataStructures.Graph; diff --git a/src/test/algorithms/graph/bfs_shortest_path.js b/src/test/algorithms/graph/bfs_shortest_path.js index b8d983c..6ad0977 100644 --- a/src/test/algorithms/graph/bfs_shortest_path.js +++ b/src/test/algorithms/graph/bfs_shortest_path.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../../'); const bfsShortestPath = root.Graph.bfsShortestPath; const Graph = root.DataStructures.Graph; diff --git a/src/test/algorithms/graph/breadth_first_search.js b/src/test/algorithms/graph/breadth_first_search.js index b34a29b..0450d4a 100644 --- a/src/test/algorithms/graph/breadth_first_search.js +++ b/src/test/algorithms/graph/breadth_first_search.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../../'); const breadthFirstSearch = root.Graph.breadthFirstSearch; const Graph = root.DataStructures.Graph; diff --git a/src/test/algorithms/graph/depth_first_search.js b/src/test/algorithms/graph/depth_first_search.js index a3db664..04a5c46 100644 --- a/src/test/algorithms/graph/depth_first_search.js +++ b/src/test/algorithms/graph/depth_first_search.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../../'); const depthFirstSearch = root.Graph.depthFirstSearch; const Graph = root.DataStructures.Graph; diff --git a/src/test/algorithms/graph/dijkstra.js b/src/test/algorithms/graph/dijkstra.js index 17287ef..8a309a6 100644 --- a/src/test/algorithms/graph/dijkstra.js +++ b/src/test/algorithms/graph/dijkstra.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../../'); const dijkstra = root.Graph.dijkstra; const Graph = root.DataStructures.Graph; diff --git a/src/test/algorithms/graph/euler_path.js b/src/test/algorithms/graph/euler_path.js index dc2b27d..676a24b 100644 --- a/src/test/algorithms/graph/euler_path.js +++ b/src/test/algorithms/graph/euler_path.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../../'); const eulerPath = root.Graph.eulerPath; const Graph = root.DataStructures.Graph; diff --git a/src/test/algorithms/graph/floyd_warshall.js b/src/test/algorithms/graph/floyd_warshall.js index 1f52ed9..da04afc 100644 --- a/src/test/algorithms/graph/floyd_warshall.js +++ b/src/test/algorithms/graph/floyd_warshall.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../../'); const floydWarshall = root.Graph.floydWarshall; const Graph = root.DataStructures.Graph; diff --git a/src/test/algorithms/graph/minimum_spanning_tree.js b/src/test/algorithms/graph/minimum_spanning_tree.js index e35f006..2fdcb6f 100644 --- a/src/test/algorithms/graph/minimum_spanning_tree.js +++ b/src/test/algorithms/graph/minimum_spanning_tree.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../../'); const kruskal = root.Graph.kruskal; const prim = root.Graph.prim; diff --git a/src/test/algorithms/graph/strongly_connected_component.js b/src/test/algorithms/graph/strongly_connected_component.js index 1716017..5ed3b0b 100644 --- a/src/test/algorithms/graph/strongly_connected_component.js +++ b/src/test/algorithms/graph/strongly_connected_component.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../../'); const Graph = root.DataStructures.Graph; const stronglyConnectedComponent = root.Graph.strongConnectedComponent; diff --git a/src/test/algorithms/graph/topological_sort.js b/src/test/algorithms/graph/topological_sort.js index 72c8723..b910534 100644 --- a/src/test/algorithms/graph/topological_sort.js +++ b/src/test/algorithms/graph/topological_sort.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../../'); const topologicalSort = root.Graph.topologicalSort; const Graph = root.DataStructures.Graph; diff --git a/src/test/algorithms/math/collatz_conjecture.js b/src/test/algorithms/math/collatz_conjecture.js index 5b333e8..0822c27 100644 --- a/src/test/algorithms/math/collatz_conjecture.js +++ b/src/test/algorithms/math/collatz_conjecture.js @@ -1,5 +1,3 @@ -'use strict'; - const math = require('../../..').Math; const collatzConjecture = math.collatzConjecture; const assert = require('assert'); diff --git a/src/test/algorithms/math/extended_euclidean.js b/src/test/algorithms/math/extended_euclidean.js index 2bc63af..7bd0298 100644 --- a/src/test/algorithms/math/extended_euclidean.js +++ b/src/test/algorithms/math/extended_euclidean.js @@ -1,5 +1,3 @@ -'use strict'; - const math = require('../../..').Math; const extEuclid = math.extendedEuclidean; const assert = require('assert'); diff --git a/src/test/algorithms/math/fast_power.js b/src/test/algorithms/math/fast_power.js index 76480a1..c45a93d 100644 --- a/src/test/algorithms/math/fast_power.js +++ b/src/test/algorithms/math/fast_power.js @@ -1,5 +1,3 @@ -'use strict'; - const math = require('../../..').Math; const power = math.fastPower; const assert = require('assert'); diff --git a/src/test/algorithms/math/fibonacci.js b/src/test/algorithms/math/fibonacci.js index 8322345..e3eca19 100644 --- a/src/test/algorithms/math/fibonacci.js +++ b/src/test/algorithms/math/fibonacci.js @@ -1,5 +1,3 @@ -'use strict'; - const math = require('../../..').Math; const fib = math.fibonacci; const assert = require('assert'); diff --git a/src/test/algorithms/math/find_divisors.js b/src/test/algorithms/math/find_divisors.js index 15a296d..32edaaf 100644 --- a/src/test/algorithms/math/find_divisors.js +++ b/src/test/algorithms/math/find_divisors.js @@ -1,5 +1,3 @@ -'use strict'; - const math = require('../../..').Math; const findDivisors = math.findDivisors; const assert = require('assert'); diff --git a/src/test/algorithms/math/fisher_yates.js b/src/test/algorithms/math/fisher_yates.js index 3653f2e..f8eb359 100644 --- a/src/test/algorithms/math/fisher_yates.js +++ b/src/test/algorithms/math/fisher_yates.js @@ -1,5 +1,3 @@ -'use strict'; - const math = require('../../..').Math; const fisherYates = math.fisherYates; const assert = require('assert'); diff --git a/src/test/algorithms/math/gcd.js b/src/test/algorithms/math/gcd.js index 48b495d..4ad5e82 100644 --- a/src/test/algorithms/math/gcd.js +++ b/src/test/algorithms/math/gcd.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../..'); const gcd = root.Math.gcd; const assert = require('assert'); diff --git a/src/test/algorithms/math/greatest_difference.js b/src/test/algorithms/math/greatest_difference.js index 6390826..f85b490 100644 --- a/src/test/algorithms/math/greatest_difference.js +++ b/src/test/algorithms/math/greatest_difference.js @@ -1,5 +1,3 @@ -'use strict'; - const assert = require('assert'); const math = require('../../..').Math; const greatestDifference = math.greatestDifference; diff --git a/src/test/algorithms/math/lcm.js b/src/test/algorithms/math/lcm.js index 2bf1000..2747820 100644 --- a/src/test/algorithms/math/lcm.js +++ b/src/test/algorithms/math/lcm.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../..'); const lcm = root.Math.lcm; const assert = require('assert'); diff --git a/src/test/algorithms/math/newton_sqrt.js b/src/test/algorithms/math/newton_sqrt.js index 45fb2f4..dc3020a 100644 --- a/src/test/algorithms/math/newton_sqrt.js +++ b/src/test/algorithms/math/newton_sqrt.js @@ -1,5 +1,3 @@ -'use strict'; - const math = require('../../..').Math; const newtonSqrt = math.newtonSqrt; const assert = require('assert'); diff --git a/src/test/algorithms/math/next_permutation.js b/src/test/algorithms/math/next_permutation.js index ddccae2..99b7bd1 100644 --- a/src/test/algorithms/math/next_permutation.js +++ b/src/test/algorithms/math/next_permutation.js @@ -1,5 +1,3 @@ -'use strict'; - const math = require('../../..').Math; const nextPermutation = math.nextPermutation; const Comparator = require('../../../util/comparator'); diff --git a/src/test/algorithms/math/power_set.js b/src/test/algorithms/math/power_set.js index 907a8d4..27d3074 100644 --- a/src/test/algorithms/math/power_set.js +++ b/src/test/algorithms/math/power_set.js @@ -1,5 +1,3 @@ -'use strict'; - const math = require('../../..').Math; const powerSet = math.powerSet; const assert = require('assert'); diff --git a/src/test/algorithms/math/primality_tests.js b/src/test/algorithms/math/primality_tests.js index 9b6d70c..211dcf6 100644 --- a/src/test/algorithms/math/primality_tests.js +++ b/src/test/algorithms/math/primality_tests.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../..'); const primalityTests = root.Math.primalityTests; const assert = require('assert'); diff --git a/src/test/algorithms/math/reservoir_sampling.js b/src/test/algorithms/math/reservoir_sampling.js index 3458812..23aa6ec 100644 --- a/src/test/algorithms/math/reservoir_sampling.js +++ b/src/test/algorithms/math/reservoir_sampling.js @@ -1,5 +1,3 @@ -'use strict'; - const math = require('../../..').Math; const reservoirSampling = math.reservoirSampling; const assert = require('assert'); diff --git a/src/test/algorithms/math/shannon_entropy.js b/src/test/algorithms/math/shannon_entropy.js index f4b922c..1fd4e2f 100644 --- a/src/test/algorithms/math/shannon_entropy.js +++ b/src/test/algorithms/math/shannon_entropy.js @@ -1,5 +1,3 @@ -'use strict'; - const shannonEntropy = require('../../../').Math.shannonEntropy; const assert = require('assert'); diff --git a/src/test/algorithms/searching/bfs.js b/src/test/algorithms/searching/bfs.js index 2f53ef6..e544496 100644 --- a/src/test/algorithms/searching/bfs.js +++ b/src/test/algorithms/searching/bfs.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../..'); const BST = root.DataStructures.BST; const bfs = root.Search.bfs; diff --git a/src/test/algorithms/searching/binarysearch.js b/src/test/algorithms/searching/binarysearch.js index cff1d85..ae8fef0 100644 --- a/src/test/algorithms/searching/binarysearch.js +++ b/src/test/algorithms/searching/binarysearch.js @@ -1,5 +1,3 @@ -'use strict'; - const binarySearch = require('../../..').Search.binarySearch; const assert = require('assert'); diff --git a/src/test/algorithms/searching/dfs.js b/src/test/algorithms/searching/dfs.js index 1ccaef0..ccb4a64 100644 --- a/src/test/algorithms/searching/dfs.js +++ b/src/test/algorithms/searching/dfs.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../../..'); const BST = root.DataStructures.BST; const dfs = root.Search.dfs; diff --git a/src/test/algorithms/searching/ternary_search.js b/src/test/algorithms/searching/ternary_search.js index 4f45f7a..a7f16ab 100644 --- a/src/test/algorithms/searching/ternary_search.js +++ b/src/test/algorithms/searching/ternary_search.js @@ -1,5 +1,3 @@ -'use strict'; - const ternarySearch = require('../../..').Search.ternarySearch; const assert = require('assert'); const eps = 1e-6; diff --git a/src/test/algorithms/sorting/bubble_sort.js b/src/test/algorithms/sorting/bubble_sort.js index de55405..c6dce04 100644 --- a/src/test/algorithms/sorting/bubble_sort.js +++ b/src/test/algorithms/sorting/bubble_sort.js @@ -1,5 +1,3 @@ -'use strict'; - const bubbleSort = require('../../..').Sorting.bubbleSort; const sortingTestsHelper = require('./sorting_tests_helper'); diff --git a/src/test/algorithms/sorting/counting_sort.js b/src/test/algorithms/sorting/counting_sort.js index 4681fc9..70c4005 100644 --- a/src/test/algorithms/sorting/counting_sort.js +++ b/src/test/algorithms/sorting/counting_sort.js @@ -1,5 +1,3 @@ -'use strict'; - const countingSort = require('../../..').Sorting.countingSort; const assert = require('assert'); diff --git a/src/test/algorithms/sorting/heap_sort.js b/src/test/algorithms/sorting/heap_sort.js index 6fd8a5f..a8d2684 100644 --- a/src/test/algorithms/sorting/heap_sort.js +++ b/src/test/algorithms/sorting/heap_sort.js @@ -1,5 +1,3 @@ -'use strict'; - const heapSort = require('../../..').Sorting.heapSort; const sortingTestsHelper = require('./sorting_tests_helper'); diff --git a/src/test/algorithms/sorting/insertion_sort.js b/src/test/algorithms/sorting/insertion_sort.js index d927953..21ba54d 100644 --- a/src/test/algorithms/sorting/insertion_sort.js +++ b/src/test/algorithms/sorting/insertion_sort.js @@ -1,5 +1,3 @@ -'use strict'; - const insertionSort = require('../../..').Sorting.insertionSort; const sortingTestsHelper = require('./sorting_tests_helper'); diff --git a/src/test/algorithms/sorting/merge_sort.js b/src/test/algorithms/sorting/merge_sort.js index b3a7aa1..f756054 100644 --- a/src/test/algorithms/sorting/merge_sort.js +++ b/src/test/algorithms/sorting/merge_sort.js @@ -1,5 +1,3 @@ -'use strict'; - const mergeSort = require('../../..').Sorting.mergeSort; const sortingTestsHelper = require('./sorting_tests_helper'); diff --git a/src/test/algorithms/sorting/quicksort.js b/src/test/algorithms/sorting/quicksort.js index 9386456..9deb84c 100644 --- a/src/test/algorithms/sorting/quicksort.js +++ b/src/test/algorithms/sorting/quicksort.js @@ -1,5 +1,3 @@ -'use strict'; - const quicksort = require('../../..').Sorting.quicksort; const sortingTestsHelper = require('./sorting_tests_helper'); diff --git a/src/test/algorithms/sorting/radix_sort.js b/src/test/algorithms/sorting/radix_sort.js index b709afd..fab9df7 100644 --- a/src/test/algorithms/sorting/radix_sort.js +++ b/src/test/algorithms/sorting/radix_sort.js @@ -1,5 +1,3 @@ -'use strict'; - const radixSort = require('../../..').Sorting.radixSort; const assert = require('assert'); diff --git a/src/test/algorithms/sorting/selection_sort.js b/src/test/algorithms/sorting/selection_sort.js index aad3680..1d6eea7 100644 --- a/src/test/algorithms/sorting/selection_sort.js +++ b/src/test/algorithms/sorting/selection_sort.js @@ -1,5 +1,3 @@ -'use strict'; - const selectionSort = require('../../..').Sorting.selectionSort; const sortingTestsHelper = require('./sorting_tests_helper'); diff --git a/src/test/algorithms/sorting/shell_sort.js b/src/test/algorithms/sorting/shell_sort.js index 1017d73..007b34b 100644 --- a/src/test/algorithms/sorting/shell_sort.js +++ b/src/test/algorithms/sorting/shell_sort.js @@ -1,5 +1,3 @@ -'use strict'; - const shellSort = require('../../..').Sorting.shellSort; const sortingTestsHelper = require('./sorting_tests_helper.js'); diff --git a/src/test/algorithms/sorting/short_bubble_sort.js b/src/test/algorithms/sorting/short_bubble_sort.js index acce83d..cfa95af 100644 --- a/src/test/algorithms/sorting/short_bubble_sort.js +++ b/src/test/algorithms/sorting/short_bubble_sort.js @@ -1,5 +1,3 @@ -'use strict'; - const shortBubbleSort = require('../../..').Sorting.shortBubbleSort; const sortingTestsHelper = require('./sorting_tests_helper'); diff --git a/src/test/algorithms/sorting/sorting_tests_helper.js b/src/test/algorithms/sorting/sorting_tests_helper.js index 29f5a5f..7cf297b 100644 --- a/src/test/algorithms/sorting/sorting_tests_helper.js +++ b/src/test/algorithms/sorting/sorting_tests_helper.js @@ -1,5 +1,3 @@ -'use strict'; - const assert = require('assert'); module.exports = { diff --git a/src/test/algorithms/string/hamming.js b/src/test/algorithms/string/hamming.js index 4e209b6..8f94637 100644 --- a/src/test/algorithms/string/hamming.js +++ b/src/test/algorithms/string/hamming.js @@ -1,5 +1,3 @@ -'use strict'; - const hamming = require('../../..').String.hamming; const assert = require('assert'); diff --git a/src/test/algorithms/string/huffman.js b/src/test/algorithms/string/huffman.js index ad2a32c..be11401 100644 --- a/src/test/algorithms/string/huffman.js +++ b/src/test/algorithms/string/huffman.js @@ -1,5 +1,3 @@ -'use strict'; - const huffman = require('../../..').String.huffman; const assert = require('assert'); diff --git a/src/test/algorithms/string/knuth_morris_pratt.js b/src/test/algorithms/string/knuth_morris_pratt.js index eea046b..994fa15 100644 --- a/src/test/algorithms/string/knuth_morris_pratt.js +++ b/src/test/algorithms/string/knuth_morris_pratt.js @@ -1,5 +1,3 @@ -'use strict'; - const knuthMorrisPratt = require('../../..').String.knuthMorrisPratt; const assert = require('assert'); diff --git a/src/test/algorithms/string/levenshtein.js b/src/test/algorithms/string/levenshtein.js index 70be21c..3b0b0c6 100644 --- a/src/test/algorithms/string/levenshtein.js +++ b/src/test/algorithms/string/levenshtein.js @@ -1,5 +1,3 @@ -'use strict'; - const levenshtein = require('../../..').String.levenshtein; const assert = require('assert'); diff --git a/src/test/algorithms/string/longest_common_subsequence.js b/src/test/algorithms/string/longest_common_subsequence.js index 5514a97..da790a1 100644 --- a/src/test/algorithms/string/longest_common_subsequence.js +++ b/src/test/algorithms/string/longest_common_subsequence.js @@ -1,5 +1,3 @@ -'use strict'; - const directory = '../../../algorithms/string/'; const filename = 'longest_common_subsequence'; const longestCommonSubsequence = require(directory + filename); diff --git a/src/test/algorithms/string/longest_common_substring.js b/src/test/algorithms/string/longest_common_substring.js index 9e76024..c794a54 100644 --- a/src/test/algorithms/string/longest_common_substring.js +++ b/src/test/algorithms/string/longest_common_substring.js @@ -1,5 +1,3 @@ -'use strict'; - const directory = '../../../algorithms/string/'; const filename = 'longest_common_substring'; const longestCommonSubstring = require(directory + filename); diff --git a/src/test/algorithms/string/rabin_karp.js b/src/test/algorithms/string/rabin_karp.js index 703aeb0..77695e6 100644 --- a/src/test/algorithms/string/rabin_karp.js +++ b/src/test/algorithms/string/rabin_karp.js @@ -1,5 +1,3 @@ -'use strict'; - const rabinKarp = require('../../..').String.rabinKarp; const assert = require('assert'); diff --git a/src/test/data_structures/avl-tree.js b/src/test/data_structures/avl-tree.js index 424ffd1..fae69a1 100644 --- a/src/test/data_structures/avl-tree.js +++ b/src/test/data_structures/avl-tree.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../..'); const AVLTree = root.DataStructures.AVLTree; const assert = require('assert'); diff --git a/src/test/data_structures/bst.js b/src/test/data_structures/bst.js index 206c5e3..6671247 100644 --- a/src/test/data_structures/bst.js +++ b/src/test/data_structures/bst.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../..'); const BST = root.DataStructures.BST; const bfs = root.Search.bfs; diff --git a/src/test/data_structures/disjoint_set_forest.js b/src/test/data_structures/disjoint_set_forest.js index 5c2d9eb..c5f5649 100644 --- a/src/test/data_structures/disjoint_set_forest.js +++ b/src/test/data_structures/disjoint_set_forest.js @@ -1,5 +1,3 @@ -'use strict'; - const DisjointSetForest = require('../..').DataStructures.DisjointSetForest; const assert = require('assert'); diff --git a/src/test/data_structures/fenwick_tree.js b/src/test/data_structures/fenwick_tree.js index 69c7763..e7c7529 100644 --- a/src/test/data_structures/fenwick_tree.js +++ b/src/test/data_structures/fenwick_tree.js @@ -1,5 +1,3 @@ -'use strict'; - const FenwickTree = require('../..').DataStructures.FenwickTree; const assert = require('assert'); diff --git a/src/test/data_structures/graph.js b/src/test/data_structures/graph.js index f543f0e..b655395 100644 --- a/src/test/data_structures/graph.js +++ b/src/test/data_structures/graph.js @@ -1,5 +1,3 @@ -'use strict'; - const Graph = require('../..').DataStructures.Graph; const assert = require('assert'); diff --git a/src/test/data_structures/hash_table.js b/src/test/data_structures/hash_table.js index a2e29a5..1f3d7fa 100644 --- a/src/test/data_structures/hash_table.js +++ b/src/test/data_structures/hash_table.js @@ -1,5 +1,3 @@ -'use strict'; - const HashTable = require('../..').DataStructures.HashTable; const assert = require('assert'); diff --git a/src/test/data_structures/heap.js b/src/test/data_structures/heap.js index 18f9b61..c5e099f 100644 --- a/src/test/data_structures/heap.js +++ b/src/test/data_structures/heap.js @@ -1,5 +1,3 @@ -'use strict'; - const heap = require('../..').DataStructures.Heap; const assert = require('assert'); diff --git a/src/test/data_structures/linked_list.js b/src/test/data_structures/linked_list.js index 9a08e9c..ac0d09f 100644 --- a/src/test/data_structures/linked_list.js +++ b/src/test/data_structures/linked_list.js @@ -1,5 +1,3 @@ -'use strict'; - const LinkedList = require('../..').DataStructures.LinkedList; const assert = require('assert'); diff --git a/src/test/data_structures/priority_queue.js b/src/test/data_structures/priority_queue.js index a842270..5db517d 100644 --- a/src/test/data_structures/priority_queue.js +++ b/src/test/data_structures/priority_queue.js @@ -1,5 +1,3 @@ -'use strict'; - const PriorityQueue = require('../..').DataStructures.PriorityQueue; const assert = require('assert'); diff --git a/src/test/data_structures/queue.js b/src/test/data_structures/queue.js index 46932c3..1b8523d 100644 --- a/src/test/data_structures/queue.js +++ b/src/test/data_structures/queue.js @@ -1,5 +1,3 @@ -'use strict'; - const Queue = require('../..').DataStructures.Queue; const assert = require('assert'); diff --git a/src/test/data_structures/set.js b/src/test/data_structures/set.js index 654eb76..79521eb 100644 --- a/src/test/data_structures/set.js +++ b/src/test/data_structures/set.js @@ -1,5 +1,3 @@ -'use strict'; - const HashSet = require('../..').DataStructures.Set; const assert = require('assert'); diff --git a/src/test/data_structures/stack.js b/src/test/data_structures/stack.js index bd43c32..8173521 100644 --- a/src/test/data_structures/stack.js +++ b/src/test/data_structures/stack.js @@ -1,5 +1,3 @@ -'use strict'; - const Stack = require('../..').DataStructures.Stack; const assert = require('assert'); diff --git a/src/test/data_structures/treap.js b/src/test/data_structures/treap.js index 290e9b3..3e88830 100644 --- a/src/test/data_structures/treap.js +++ b/src/test/data_structures/treap.js @@ -1,5 +1,3 @@ -'use strict'; - const root = require('../..'); const Treap = root.DataStructures.Treap; const assert = require('assert'); diff --git a/src/test/util/comparator.js b/src/test/util/comparator.js index c7fb1e6..ab1cd4d 100644 --- a/src/test/util/comparator.js +++ b/src/test/util/comparator.js @@ -1,5 +1,3 @@ -'use strict'; - const Comparator = require('../../util/comparator'); const assert = require('assert'); diff --git a/src/util/comparator.js b/src/util/comparator.js index 9b2d78d..abdacb4 100644 --- a/src/util/comparator.js +++ b/src/util/comparator.js @@ -1,5 +1,3 @@ -'use strict'; - /** * Initialize the comparator object with a compare function * From 4eaa6f9b3ce5b1ff4bd9a09fcce91c663f1183b7 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 14 Jun 2017 16:50:16 +0200 Subject: [PATCH 244/280] [es6] Object shorthand --- src/algorithms/graph/SPFA.js | 4 ++-- src/algorithms/graph/bfs_shortest_path.js | 4 ++-- src/algorithms/graph/dijkstra.js | 4 ++-- src/algorithms/graph/euler_path.js | 4 ++-- src/algorithms/graph/floyd_warshall.js | 4 ++-- src/algorithms/graph/strongly_connected_component.js | 8 ++++---- src/algorithms/string/huffman.js | 4 ++-- src/data_structures/heap.js | 4 ++-- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/algorithms/graph/SPFA.js b/src/algorithms/graph/SPFA.js index 6842e06..a27ee1e 100644 --- a/src/algorithms/graph/SPFA.js +++ b/src/algorithms/graph/SPFA.js @@ -54,8 +54,8 @@ function spfa(graph, s) { } return { - distance: distance, - previous: previous + distance, + previous }; } diff --git a/src/algorithms/graph/bfs_shortest_path.js b/src/algorithms/graph/bfs_shortest_path.js index b41d375..ab0a19f 100644 --- a/src/algorithms/graph/bfs_shortest_path.js +++ b/src/algorithms/graph/bfs_shortest_path.js @@ -23,8 +23,8 @@ const bfsShortestPath = (graph, source) => { }); return { - distance: distance, - previous: previous + distance, + previous }; }; diff --git a/src/algorithms/graph/dijkstra.js b/src/algorithms/graph/dijkstra.js index 18628a8..64af712 100644 --- a/src/algorithms/graph/dijkstra.js +++ b/src/algorithms/graph/dijkstra.js @@ -35,8 +35,8 @@ function dijkstra(graph, s) { graph.neighbors(currNode).forEach(relax); } return { - distance: distance, - previous: previous + distance, + previous }; } diff --git a/src/algorithms/graph/euler_path.js b/src/algorithms/graph/euler_path.js index a0c2d98..6895f6b 100644 --- a/src/algorithms/graph/euler_path.js +++ b/src/algorithms/graph/euler_path.js @@ -66,8 +66,8 @@ const eulerEndpoints = graph => { start = finish = v; } - return {start: start, - finish: finish}; + return {start, + finish}; }; /** diff --git a/src/algorithms/graph/floyd_warshall.js b/src/algorithms/graph/floyd_warshall.js index 29d139c..617ddab 100644 --- a/src/algorithms/graph/floyd_warshall.js +++ b/src/algorithms/graph/floyd_warshall.js @@ -84,8 +84,8 @@ const floydWarshall = graph => { }; return { - distance: distance, - path: path + distance, + path }; }; diff --git a/src/algorithms/graph/strongly_connected_component.js b/src/algorithms/graph/strongly_connected_component.js index d2f965c..181f910 100644 --- a/src/algorithms/graph/strongly_connected_component.js +++ b/src/algorithms/graph/strongly_connected_component.js @@ -52,16 +52,16 @@ const stronglyConnectedComponent = graph => { const node = stack.pop(); if (!visited[node]) { depthFirstSearch(graph, node, { - allowTraversal: allowTraversal, - enterVertex: enterVertex + allowTraversal, + enterVertex }); ++count; } } return { - count: count, - id: id + count, + id }; }; diff --git a/src/algorithms/string/huffman.js b/src/algorithms/string/huffman.js index 6802201..8dde5fa 100644 --- a/src/algorithms/string/huffman.js +++ b/src/algorithms/string/huffman.js @@ -85,7 +85,7 @@ huffman.encode = (string, compressed) => { }); const letters = Object.keys(counter).map(char => ({ - char: char, + char, count: counter[char] })); @@ -141,7 +141,7 @@ huffman.encode = (string, compressed) => { const result = string.split('').map(char => encoding[char]).join(''); return { - encoding: encoding, + encoding, value: (compressed ? compress(result) : result) }; }; diff --git a/src/data_structures/heap.js b/src/data_structures/heap.js index adce003..2f00de4 100644 --- a/src/data_structures/heap.js +++ b/src/data_structures/heap.js @@ -119,6 +119,6 @@ function MaxHeap(compareFn) { MaxHeap.prototype = new MinHeap(); module.exports = { - MinHeap: MinHeap, - MaxHeap: MaxHeap + MinHeap, + MaxHeap }; From ff600d53a7bc4f11037ddf3ad747e1e71ba1e66b Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 14 Jun 2017 17:03:27 +0200 Subject: [PATCH 245/280] [es6] Classes --- src/algorithms/geometry/bezier_curve.js | 74 +- src/algorithms/math/power_set.js | 2 +- src/data_structures/avl_tree.js | 918 +++++++++++---------- src/data_structures/bst.js | 212 ++--- src/data_structures/disjoint_set_forest.js | 158 ++-- src/data_structures/fenwick_tree.js | 104 +-- src/data_structures/graph.js | 96 +-- src/data_structures/hash_table.js | 190 ++--- src/data_structures/heap.js | 178 ++-- src/data_structures/linked_list.js | 235 +++--- src/data_structures/priority_queue.js | 63 +- src/data_structures/queue.js | 66 +- src/data_structures/set.js | 52 +- src/data_structures/stack.js | 64 +- src/data_structures/treap.js | 226 ++--- src/util/comparator.js | 74 +- 16 files changed, 1371 insertions(+), 1341 deletions(-) diff --git a/src/algorithms/geometry/bezier_curve.js b/src/algorithms/geometry/bezier_curve.js index 0261069..f099680 100644 --- a/src/algorithms/geometry/bezier_curve.js +++ b/src/algorithms/geometry/bezier_curve.js @@ -9,49 +9,51 @@ * Generates a bezier-curve from a series of points * @param Array array of control points ([{x: x0, y: y0}, {x: x1, y: y1}]) */ -const BezierCurve = function(points) { - this.n = points.length; - this.p = []; +class BezierCurve { + constructor(points) { + this.n = points.length; + this.p = []; - // The binomial coefficient - const c = [1]; - let i; - let j; - for (i = 1; i < this.n; ++i) { - c.push(0); - for (j = i; j >= 1; --j) { - c[j] += c[j - 1]; + // The binomial coefficient + const c = [1]; + let i; + let j; + for (i = 1; i < this.n; ++i) { + c.push(0); + for (j = i; j >= 1; --j) { + c[j] += c[j - 1]; + } } - } - // the i-th control point times the coefficient - for (i = 0; i < this.n; ++i) { - this.p.push({x: c[i] * points[i].x, y: c[i] * points[i].y}); + // the i-th control point times the coefficient + for (i = 0; i < this.n; ++i) { + this.p.push({x: c[i] * points[i].x, y: c[i] * points[i].y}); + } } -}; -/** - * @param Number float variable from 0 to 1 - */ -BezierCurve.prototype.get = function(t) { - const res = {x: 0, y: 0}; - let i; - let a = 1; - let b = 1; + /** + * @param Number float variable from 0 to 1 + */ + get(t) { + const res = {x: 0, y: 0}; + let i; + let a = 1; + let b = 1; - // The coefficient - const c = []; - for (i = 0; i < this.n; ++i) { - c.push(a); - a *= t; - } + // The coefficient + const c = []; + for (i = 0; i < this.n; ++i) { + c.push(a); + a *= t; + } - for (i = this.n - 1; i >= 0; --i) { - res.x += this.p[i].x * c[i] * b; - res.y += this.p[i].y * c[i] * b; - b *= 1 - t; + for (i = this.n - 1; i >= 0; --i) { + res.x += this.p[i].x * c[i] * b; + res.y += this.p[i].y * c[i] * b; + b *= 1 - t; + } + return res; } - return res; -}; +} module.exports = BezierCurve; diff --git a/src/algorithms/math/power_set.js b/src/algorithms/math/power_set.js index c417adf..95c131b 100644 --- a/src/algorithms/math/power_set.js +++ b/src/algorithms/math/power_set.js @@ -52,7 +52,7 @@ const powerSetRecursive = array => { powerSetRecursive(array).forEach(elem => { powerSet.push(elem); const withFirstElem = [firstElem]; - withFirstElem.push.apply(withFirstElem, elem); + withFirstElem.push(...elem); powerSet.push(withFirstElem); }); diff --git a/src/data_structures/avl_tree.js b/src/data_structures/avl_tree.js index 9984087..7603b4c 100644 --- a/src/data_structures/avl_tree.js +++ b/src/data_structures/avl_tree.js @@ -1,520 +1,522 @@ /** * AVL Tree */ -function AVLTree() { - this.root = null; -} - -/** - * Tree node - */ -function Node(value, left, right, parent, height) { - this.value = value; - this.left = left; - this.right = right; - this.parent = parent; - this.height = height; -} - -/** - * Calculates the height of a node based on height - * property of all his children. - */ -AVLTree.prototype.getNodeHeight = node => { - let height = 1; - if (node.left !== null && node.right !== null) { - height = Math.max(node.left.height, node.right.height) + 1; - } else if (node.left !== null) { - height = node.left.height + 1; - } else if (node.right !== null) { - height = node.right.height + 1; +class AVLTree { + constructor() { + this.root = null; + } + + /** + * Calculates the height of a node based on height + * property of all his children. + */ + getNodeHeight(node) { + let height = 1; + if (node.left !== null && node.right !== null) { + height = Math.max(node.left.height, node.right.height) + 1; + } else if (node.left !== null) { + height = node.left.height + 1; + } else if (node.right !== null) { + height = node.right.height + 1; + } + return height; } - return height; -}; -/** - * Verifies if the given node is balanced. - */ -AVLTree.prototype.isNodeBalanced = node => { - let isBalanced = true; - - if (node.left !== null && node.right !== null) { - isBalanced = (Math.abs(node.left.height - node.right.height) <= 1); - } else if (node.right !== null && node.left === null) { - isBalanced = node.right.height < 2; - } else if (node.left !== null && node.right === null) { - isBalanced = node.left.height < 2; - } - return isBalanced; -}; + /** + * Verifies if the given node is balanced. + */ + isNodeBalanced(node) { + let isBalanced = true; -/** - * When a removal happens, some nodes need to be - * restructured. Gets and return these nodes. - */ -AVLTree.prototype.getNodesToRestructureAfterRemove = traveledNodes => { - // z is last traveled node - imbalance found at z - const zIndex = traveledNodes.length - 1; - const z = traveledNodes[zIndex]; - - // y should be child of z with larger height - // (cannot be ancestor of removed node) - let y; - if (z.left !== null && z.right !== null) { - y = (z.left === y) ? z.right : z.left; - } else if (z.left !== null && z.right === null) { - y = z.left; - } else if (z.right !== null && z.left === null) { - y = z.right; - } + if (node.left !== null && node.right !== null) { + isBalanced = (Math.abs(node.left.height - node.right.height) <= 1); + } else if (node.right !== null && node.left === null) { + isBalanced = node.right.height < 2; + } else if (node.left !== null && node.right === null) { + isBalanced = node.left.height < 2; + } + return isBalanced; + } + + /** + * When a removal happens, some nodes need to be + * restructured. Gets and return these nodes. + */ + getNodesToRestructureAfterRemove(traveledNodes) { + // z is last traveled node - imbalance found at z + const zIndex = traveledNodes.length - 1; + const z = traveledNodes[zIndex]; + + // y should be child of z with larger height + // (cannot be ancestor of removed node) + let y; + if (z.left !== null && z.right !== null) { + y = (z.left === y) ? z.right : z.left; + } else if (z.left !== null && z.right === null) { + y = z.left; + } else if (z.right !== null && z.left === null) { + y = z.right; + } - // x should be tallest child of y - // If children same height, x should be child of y - // that has same orientation as z to y - let x; - if (y.left !== null && y.right !== null) { - if (y.left.height > y.right.height) { + // x should be tallest child of y + // If children same height, x should be child of y + // that has same orientation as z to y + let x; + if (y.left !== null && y.right !== null) { + if (y.left.height > y.right.height) { + x = y.left; + } else if (y.left.height < y.right.height) { + x = y.right; + } else if (y.left.height === y.right.height) { + x = (z.left === y) ? y.left : y.right; + } + } else if (y.left !== null && y.right === null) { x = y.left; - } else if (y.left.height < y.right.height) { + } else if (y.right !== null && y.left === null) { x = y.right; - } else if (y.left.height === y.right.height) { - x = (z.left === y) ? y.left : y.right; } - } else if (y.left !== null && y.right === null) { - x = y.left; - } else if (y.right !== null && y.left === null) { - x = y.right; - } - return [x, y, z]; -}; - -/** - * When a insertion happens, some nodes need to be - * restructured. Gets and return these nodes. - */ -AVLTree.prototype.getNodesToRestructureAfterInsert = traveledNodes => { - // z is last traveled node - imbalance found at z - const zIndex = traveledNodes.length - 1; - const z = traveledNodes[zIndex]; - - // y should be child of z with larger height - // (must be ancestor of inserted node) - // therefore, last traveled node is correct. - const yIndex = traveledNodes.length - 2; - const y = traveledNodes[yIndex]; - - // x should be tallest child of y - // If children same height, x should be ancestor - // of inserted node (in traveled path) - let x; - if (y.left !== null && y.right !== null) { - if (y.left.height > y.right.height) { + return [x, y, z]; + } + + /** + * When a insertion happens, some nodes need to be + * restructured. Gets and return these nodes. + */ + getNodesToRestructureAfterInsert(traveledNodes) { + // z is last traveled node - imbalance found at z + const zIndex = traveledNodes.length - 1; + const z = traveledNodes[zIndex]; + + // y should be child of z with larger height + // (must be ancestor of inserted node) + // therefore, last traveled node is correct. + const yIndex = traveledNodes.length - 2; + const y = traveledNodes[yIndex]; + + // x should be tallest child of y + // If children same height, x should be ancestor + // of inserted node (in traveled path) + let x; + if (y.left !== null && y.right !== null) { + if (y.left.height > y.right.height) { + x = y.left; + } else if (y.left.height < y.right.height) { + x = y.right; + } else if (y.left.height === y.right.height) { + const xIndex = traveledNodes.length - 3; + x = traveledNodes[xIndex]; + } + } else if (y.left !== null && y.right === null) { x = y.left; - } else if (y.left.height < y.right.height) { + } else if (y.right !== null && y.left === null) { x = y.right; - } else if (y.left.height === y.right.height) { - const xIndex = traveledNodes.length - 3; - x = traveledNodes[xIndex]; - } - } else if (y.left !== null && y.right === null) { - x = y.left; - } else if (y.right !== null && y.left === null) { - x = y.right; - } - return [x, y, z]; -}; - -/** - * Keep the height balance property by walking to - * root and checking for invalid heights. - */ -AVLTree.prototype.keepHeightBalance = function(node, afterRemove) { - let current = node; - const traveledNodes = []; - while (current !== null) { - traveledNodes.push(current); - current.height = this.getNodeHeight(current); - if (!this.isNodeBalanced(current)) { - const nodesToBeRestructured = (afterRemove) ? - this.getNodesToRestructureAfterRemove(traveledNodes) : - this.getNodesToRestructureAfterInsert(traveledNodes); - this.restructure(nodesToBeRestructured); - } - current = current.parent; - } -}; - -/** - * Identifies and calls the appropriate pattern - * rotator. - */ -AVLTree.prototype.restructure = function(nodesToRestructure) { - const x = nodesToRestructure[0]; - const y = nodesToRestructure[1]; - const z = nodesToRestructure[2]; - - // Determine Rotation Pattern - if (z.right === y && y.right === x) { - this.rightRight(x, y, z); - } else if (z.left === y && y.left === x) { - this.leftLeft(x, y, z); - } else if (z.right === y && y.left === x) { - this.rightLeft(x, y, z); - } else if (z.left === y && y.right === x) { - this.leftRight(x, y, z); - } -}; - -/** - * Right-right rotation pattern. - */ -AVLTree.prototype.rightRight = function(x, y, z) { - // pass z parent to y and move y's left to z's right - if (z.parent) { - const orientation = (z.parent.left === z) ? 'left' : 'right'; - z.parent[orientation] = y; - y.parent = z.parent; - } else { - this.root = y; - y.parent = null; + } + return [x, y, z]; + } + + /** + * Keep the height balance property by walking to + * root and checking for invalid heights. + */ + keepHeightBalance(node, afterRemove) { + let current = node; + const traveledNodes = []; + while (current !== null) { + traveledNodes.push(current); + current.height = this.getNodeHeight(current); + if (!this.isNodeBalanced(current)) { + const nodesToBeRestructured = (afterRemove) ? + this.getNodesToRestructureAfterRemove(traveledNodes) : + this.getNodesToRestructureAfterInsert(traveledNodes); + this.restructure(nodesToBeRestructured); + } + current = current.parent; + } } - // z adopts y's left. - z.right = y.left; - if (z.right !== null) { - z.right.parent = z; + /** + * Identifies and calls the appropriate pattern + * rotator. + */ + restructure(nodesToRestructure) { + const x = nodesToRestructure[0]; + const y = nodesToRestructure[1]; + const z = nodesToRestructure[2]; + + // Determine Rotation Pattern + if (z.right === y && y.right === x) { + this.rightRight(x, y, z); + } else if (z.left === y && y.left === x) { + this.leftLeft(x, y, z); + } else if (z.right === y && y.left === x) { + this.rightLeft(x, y, z); + } else if (z.left === y && y.right === x) { + this.leftRight(x, y, z); + } } - // y adopts z - y.left = z; - z.parent = y; - // Correct each nodes height - order matters, children first - x.height = this.getNodeHeight(x); - z.height = this.getNodeHeight(z); - y.height = this.getNodeHeight(y); -}; + /** + * Right-right rotation pattern. + */ + rightRight(x, y, z) { + // pass z parent to y and move y's left to z's right + if (z.parent) { + const orientation = (z.parent.left === z) ? 'left' : 'right'; + z.parent[orientation] = y; + y.parent = z.parent; + } else { + this.root = y; + y.parent = null; + } -/** - * Left-left rotation pattern. - */ -AVLTree.prototype.leftLeft = function(x, y, z) { - // pass z parent to y and move y's right to z's left - if (z.parent) { - const orientation = (z.parent.left === z) ? 'left' : 'right'; - z.parent[orientation] = y; - y.parent = z.parent; - } else { - this.root = y; - y.parent = null; - } + // z adopts y's left. + z.right = y.left; + if (z.right !== null) { + z.right.parent = z; + } + // y adopts z + y.left = z; + z.parent = y; + + // Correct each nodes height - order matters, children first + x.height = this.getNodeHeight(x); + z.height = this.getNodeHeight(z); + y.height = this.getNodeHeight(y); + } + + /** + * Left-left rotation pattern. + */ + leftLeft(x, y, z) { + // pass z parent to y and move y's right to z's left + if (z.parent) { + const orientation = (z.parent.left === z) ? 'left' : 'right'; + z.parent[orientation] = y; + y.parent = z.parent; + } else { + this.root = y; + y.parent = null; + } - z.left = y.right; - if (z.left !== null) { - z.left.parent = z; - } - // fix y right child - y.right = z; - z.parent = y; + z.left = y.right; + if (z.left !== null) { + z.left.parent = z; + } + // fix y right child + y.right = z; + z.parent = y; + + // Correct each nodes height - order matters, children first + x.height = this.getNodeHeight(x); + z.height = this.getNodeHeight(z); + y.height = this.getNodeHeight(y); + } + + /** + * Right-left rotation pattern. + */ + rightLeft(x, y, z) { + // pass z parent to x + if (z.parent) { + const orientation = (z.parent.left === z) ? 'left' : 'right'; + z.parent[orientation] = x; + x.parent = z.parent; + } else { + this.root = x; + x.parent = null; + } - // Correct each nodes height - order matters, children first - x.height = this.getNodeHeight(x); - z.height = this.getNodeHeight(z); - y.height = this.getNodeHeight(y); -}; + // Adoptions + z.right = x.left; + if (z.right !== null) { + z.right.parent = z; + } + y.left = x.right; + if (y.left !== null) { + y.left.parent = y; + } -/** - * Right-left rotation pattern. - */ -AVLTree.prototype.rightLeft = function(x, y, z) { - // pass z parent to x - if (z.parent) { - const orientation = (z.parent.left === z) ? 'left' : 'right'; - z.parent[orientation] = x; - x.parent = z.parent; - } else { - this.root = x; - x.parent = null; - } + // Point to new children (x new parent) + x.left = z; + x.right = y; + x.left.parent = x; + x.right.parent = x; + + // Correct each nodes height - order matters, children first + y.height = this.getNodeHeight(y); + z.height = this.getNodeHeight(z); + x.height = this.getNodeHeight(x); + } + + /** + * Left-right rotation pattern. + */ + leftRight(x, y, z) { + // pass z parent to x + if (z.parent) { + const orientation = (z.parent.left === z) ? 'left' : 'right'; + z.parent[orientation] = x; + x.parent = z.parent; + } else { + this.root = x; + x.parent = null; + } - // Adoptions - z.right = x.left; - if (z.right !== null) { - z.right.parent = z; - } - y.left = x.right; - if (y.left !== null) { - y.left.parent = y; - } + // Adoptions + z.left = x.right; + if (z.left !== null) { + z.left.parent = z; + } + y.right = x.left; + if (y.right !== null) { + y.right.parent = y; + } - // Point to new children (x new parent) - x.left = z; - x.right = y; - x.left.parent = x; - x.right.parent = x; + // Point to new children (x new parent) + x.right = z; + x.left = y; + x.left.parent = x; + x.right.parent = x; + + // Correct each nodes height - order matters, children first + y.height = this.getNodeHeight(y); + z.height = this.getNodeHeight(z); + x.height = this.getNodeHeight(x); + } + + /** + * Inserts a value as a Node of an AVL Tree. + */ + insert(value, current) { + if (this.root === null) { + this.root = new Node(value, null, null, null, 1); + this.keepHeightBalance(this.root); + return; + } - // Correct each nodes height - order matters, children first - y.height = this.getNodeHeight(y); - z.height = this.getNodeHeight(z); - x.height = this.getNodeHeight(x); -}; + let insertKey; + current = current || this.root; + if (current.value > value) { + insertKey = 'left'; + } else { + insertKey = 'right'; + } -/** - * Left-right rotation pattern. - */ -AVLTree.prototype.leftRight = function(x, y, z) { - // pass z parent to x - if (z.parent) { - const orientation = (z.parent.left === z) ? 'left' : 'right'; - z.parent[orientation] = x; - x.parent = z.parent; - } else { - this.root = x; - x.parent = null; + if (current[insertKey]) { + this.insert(value, current[insertKey]); + } else { + current[insertKey] = new Node(value, null, null, current); + this.keepHeightBalance(current[insertKey], false); + } } - // Adoptions - z.left = x.right; - if (z.left !== null) { - z.left.parent = z; - } - y.right = x.left; - if (y.right !== null) { - y.right.parent = y; + /** + * In-order traversal from the given node. + */ + inOrder(current, callback) { + if (!current) { + return; + } + this.inOrder(current.left, callback); + if (typeof callback === 'function') { + callback(current); + } + this.inOrder(current.right, callback); } - // Point to new children (x new parent) - x.right = z; - x.left = y; - x.left.parent = x; - x.right.parent = x; - - // Correct each nodes height - order matters, children first - y.height = this.getNodeHeight(y); - z.height = this.getNodeHeight(z); - x.height = this.getNodeHeight(x); -}; + /** + * Post-order traversal from the given node. + */ + postOrder(current, callback) { + if (!current) { + return; + } -/** - * Inserts a value as a Node of an AVL Tree. - */ -AVLTree.prototype.insert = function(value, current) { - if (this.root === null) { - this.root = new Node(value, null, null, null, 1); - this.keepHeightBalance(this.root); - return; + this.postOrder(current.left, callback); + this.postOrder(current.right, callback); + if (typeof callback === 'function') { + callback(current); + } } - let insertKey; - current = current || this.root; - if (current.value > value) { - insertKey = 'left'; - } else { - insertKey = 'right'; + /** + * Pre-order traversal from the given node. + */ + preOrder(current, callback) { + if (!current) { + return; + } + if (typeof callback === 'function') { + callback(current); + } + this.preOrder(current.left, callback); + this.preOrder(current.right, callback); } - if (current[insertKey]) { - this.insert(value, current[insertKey]); - } else { - current[insertKey] = new Node(value, null, null, current); - this.keepHeightBalance(current[insertKey], false); + /** + * Finds a node by its value. + */ + find(value) { + return this._find(value, this.root); } -}; -/** - * In-order traversal from the given node. - */ -AVLTree.prototype.inOrder = function(current, callback) { - if (!current) { - return; - } - this.inOrder(current.left, callback); - if (typeof callback === 'function') { - callback(current); - } - this.inOrder(current.right, callback); -}; + /** + * Finds a node by its value in the given sub-tree. + */ + _find(value, current) { + if (!current) { + return null; + } -/** - * Post-order traversal from the given node. - */ -AVLTree.prototype.postOrder = function(current, callback) { - if (!current) { - return; - } + let node; + if (current.value === value) { + node = current; + } else if (current.value > value) { + node = this._find(value, current.left); + } else if (current.value < value) { + node = this._find(value, current.right); + } - this.postOrder(current.left, callback); - this.postOrder(current.right, callback); - if (typeof callback === 'function') { - callback(current); + return node; } -}; -/** - * Pre-order traversal from the given node. - */ -AVLTree.prototype.preOrder = function(current, callback) { - if (!current) { - return; - } - if (typeof callback === 'function') { - callback(current); + /** + * Replaces the given child with the new one, + * for the given parent. + */ + replaceChild(parent, oldChild, newChild) { + if (parent === null) { + this.root = newChild; + if (this.root !== null) { + this.root.parent = null; + } + } else { + if (parent.left === oldChild) { + parent.left = newChild; + } else { + parent.right = newChild; + } + if (newChild) { + newChild.parent = parent; + } + } } - this.preOrder(current.left, callback); - this.preOrder(current.right, callback); -}; - -/** - * Finds a node by its value. - */ -AVLTree.prototype.find = function(value) { - return this._find(value, this.root); -}; -/** - * Finds a node by its value in the given sub-tree. - */ -AVLTree.prototype._find = function(value, current) { - if (!current) { - return null; - } + /** + * Removes a node by its value. + */ + remove(value) { + const node = this.find(value); + if (!node) { + return false; + } - let node; - if (current.value === value) { - node = current; - } else if (current.value > value) { - node = this._find(value, current.left); - } else if (current.value < value) { - node = this._find(value, current.right); + if (node.left && node.right) { + const min = this.findMin(node.right); + const temp = node.value; + node.value = min.value; + min.value = temp; + return this.remove(min); + } else if (node.left) { + this.replaceChild(node.parent, node, node.left); + this.keepHeightBalance(node.left, true); + } else if (node.right) { + this.replaceChild(node.parent, node, node.right); + this.keepHeightBalance(node.right, true); + } else { + this.replaceChild(node.parent, node, null); + this.keepHeightBalance(node.parent, true); + } + return true; } - return node; -}; - -/** - * Replaces the given child with the new one, - * for the given parent. - */ -AVLTree.prototype.replaceChild = function(parent, oldChild, newChild) { - if (parent === null) { - this.root = newChild; - if (this.root !== null) { - this.root.parent = null; - } - } else { - if (parent.left === oldChild) { - parent.left = newChild; - } else { - parent.right = newChild; + /** + * Finds the node with minimum value in the given + * sub-tree. + */ + _findMin(node, current) { + current = current || { + value: Infinity + }; + if (!node) { + return current; + } + if (current.value > node.value) { + current = node; + } + return this._findMin(node.left, current); + } + + /** + * Finds the node with maximum value in the given + * sub-tree. + */ + _findMax(node, current) { + current = current || { + value: -Infinity + }; + if (!node) { + return current; } - if (newChild) { - newChild.parent = parent; + if (current.value < node.value) { + current = node; } + return this._findMax(node.right, current); } -}; -/** - * Removes a node by its value. - */ -AVLTree.prototype.remove = function(value) { - const node = this.find(value); - if (!node) { - return false; + /** + * Finds the node with minimum value in the whole tree. + */ + findMin() { + return this._findMin(this.root); } - if (node.left && node.right) { - const min = this.findMin(node.right); - const temp = node.value; - node.value = min.value; - min.value = temp; - return this.remove(min); - } else if (node.left) { - this.replaceChild(node.parent, node, node.left); - this.keepHeightBalance(node.left, true); - } else if (node.right) { - this.replaceChild(node.parent, node, node.right); - this.keepHeightBalance(node.right, true); - } else { - this.replaceChild(node.parent, node, null); - this.keepHeightBalance(node.parent, true); + /** + * Finds the node with maximum value in the whole tree. + */ + findMax() { + return this._findMax(this.root); } - return true; -}; -/** - * Finds the node with minimum value in the given - * sub-tree. - */ -AVLTree.prototype._findMin = function(node, current) { - current = current || { - value: Infinity - }; - if (!node) { - return current; - } - if (current.value > node.value) { - current = node; - } - return this._findMin(node.left, current); -}; + /** + * Verifies if the tree is balanced. + */ + isTreeBalanced() { + const current = this.root; -/** - * Finds the node with maximum value in the given - * sub-tree. - */ -AVLTree.prototype._findMax = function(node, current) { - current = current || { - value: -Infinity - }; - if (!node) { - return current; - } - if (current.value < node.value) { - current = node; + if (!current) { + return true; + } + return this._isBalanced(current._left) && + this._isBalanced(current._right) && + Math.abs(this._getNodeHeight(current._left) - + this._getNodeHeight(current._right)) <= 1; } - return this._findMax(node.right, current); -}; - -/** - * Finds the node with minimum value in the whole tree. - */ -AVLTree.prototype.findMin = function() { - return this._findMin(this.root); -}; -/** - * Finds the node with maximum value in the whole tree. - */ -AVLTree.prototype.findMax = function() { - return this._findMax(this.root); -}; - -/** - * Verifies if the tree is balanced. - */ -AVLTree.prototype.isTreeBalanced = function() { - const current = this.root; + /** + * Calculates the height of the tree based on height + * property. + */ + getTreeHeight() { + const current = this.root; - if (!current) { - return true; + if (!current) { + return 0; + } + return 1 + Math.max(this.getNodeHeight(current._left), + this._getNodeHeight(current._right)); } - return this._isBalanced(current._left) && - this._isBalanced(current._right) && - Math.abs(this._getNodeHeight(current._left) - - this._getNodeHeight(current._right)) <= 1; -}; +} /** - * Calculates the height of the tree based on height - * property. + * Tree node */ -AVLTree.prototype.getTreeHeight = function() { - const current = this.root; - - if (!current) { - return 0; - } - return 1 + Math.max(this.getNodeHeight(current._left), - this._getNodeHeight(current._right)); -}; +function Node(value, left, right, parent, height) { + this.value = value; + this.left = left; + this.right = right; + this.parent = parent; + this.height = height; +} module.exports = AVLTree; diff --git a/src/data_structures/bst.js b/src/data_structures/bst.js index bd0de05..f8a5ede 100644 --- a/src/data_structures/bst.js +++ b/src/data_structures/bst.js @@ -3,131 +3,133 @@ const Comparator = require('../util/comparator'); /** * Binary Search Tree */ -function BST(compareFn) { - this.root = null; - this._size = 0; - /** - * @var Comparator - */ - this._comparator = new Comparator(compareFn); +class BST { + constructor(compareFn) { + this.root = null; + this._size = 0; + /** + * @var Comparator + */ + this._comparator = new Comparator(compareFn); + + /** + * Read-only property for the size of the tree + */ + Object.defineProperty(this, 'size', { + get: () => this._size + }); + } /** - * Read-only property for the size of the tree + * Insert elements to the tree respecting the BST restrictions */ - Object.defineProperty(this, 'size', { - get: () => this._size - }); -} - -/** - * Tree node - */ -function Node(value, parent) { - this.value = value; - this.parent = parent; - this.left = null; - this.right = null; -} + insert(value, parent) { + // Set the root as the initial insertion point + // if it has not been passed + if (!parent) { + if (!this.root) { + this.root = new Node(value); + this._size++; + return; + } + parent = this.root; + } -/** - * Insert elements to the tree respecting the BST restrictions - */ -BST.prototype.insert = function(value, parent) { - // Set the root as the initial insertion point - // if it has not been passed - if (!parent) { - if (!this.root) { - this.root = new Node(value); + const child = this._comparator.lessThan(value, parent.value) ? 'left' : 'right'; + if (parent[child]) { + this.insert(value, parent[child]); + } else { + parent[child] = new Node(value, parent); this._size++; - return; } - parent = this.root; } - const child = this._comparator.lessThan(value, parent.value) ? 'left' : 'right'; - if (parent[child]) { - this.insert(value, parent[child]); - } else { - parent[child] = new Node(value, parent); - this._size++; + /** + * Returns if a tree contains an element in O(lg n) + */ + contains(e) { + return Boolean(this._find(e)); } -}; -/** - * Returns if a tree contains an element in O(lg n) - */ -BST.prototype.contains = function(e) { - return Boolean(this._find(e)); -}; + _find(e, root) { + if (!root) { + if (this.root) root = this.root; + else return false; + } -BST.prototype._find = function(e, root) { - if (!root) { - if (this.root) root = this.root; - else return false; - } + if (root.value === e) + return root; - if (root.value === e) - return root; + if (this._comparator.lessThan(e, root.value)) + return root.left && this._find(e, root.left); - if (this._comparator.lessThan(e, root.value)) - return root.left && this._find(e, root.left); + if (this._comparator.greaterThan(e, root.value)) + return root.right && this._find(e, root.right); + } - if (this._comparator.greaterThan(e, root.value)) - return root.right && this._find(e, root.right); -}; + /** + * Substitute two nodes + */ + _replaceNodeInParent(currNode, newNode) { + const parent = currNode.parent; + if (parent) { + parent[currNode === parent.left ? 'left' : 'right'] = newNode; + if (newNode) + newNode.parent = parent; + } else { + this.root = newNode; + } + } -/** - * Substitute two nodes - */ -BST.prototype._replaceNodeInParent = function(currNode, newNode) { - const parent = currNode.parent; - if (parent) { - parent[currNode === parent.left ? 'left' : 'right'] = newNode; - if (newNode) - newNode.parent = parent; - } else { - this.root = newNode; + /** + * Find the minimum value in a tree + */ + _findMin(root) { + let minNode = root; + while (minNode.left) { + minNode = minNode.left; + } + return minNode; } -}; -/** - * Find the minimum value in a tree - */ -BST.prototype._findMin = root => { - let minNode = root; - while (minNode.left) { - minNode = minNode.left; + /** + * Remove an element from the BST + */ + remove(e) { + const node = this._find(e); + if (!node) { + throw new Error('Item not found in the tree'); + } + + if (node.left && node.right) { + /** + * If the node to be removed has both left and right children, + * replace the node's value by the minimum value of the right + * sub-tree, and remove the leave containing the value + */ + const successor = this._findMin(node.right); + this.remove(successor.value); + node.value = successor.value; + } else { + /** + * If the node is a leaf, just make the parent point to null, + * and if it has one child, make the parent point to this child + * instead + */ + this._replaceNodeInParent(node, node.left || node.right); + this._size--; + } } - return minNode; -}; +} /** - * Remove an element from the BST + * Tree node */ -BST.prototype.remove = function(e) { - const node = this._find(e); - if (!node) { - throw new Error('Item not found in the tree'); - } - - if (node.left && node.right) { - /** - * If the node to be removed has both left and right children, - * replace the node's value by the minimum value of the right - * sub-tree, and remove the leave containing the value - */ - const successor = this._findMin(node.right); - this.remove(successor.value); - node.value = successor.value; - } else { - /** - * If the node is a leaf, just make the parent point to null, - * and if it has one child, make the parent point to this child - * instead - */ - this._replaceNodeInParent(node, node.left || node.right); - this._size--; - } -}; +function Node(value, parent) { + this.value = value; + this.parent = parent; + this.left = null; + this.right = null; +} module.exports = BST; diff --git a/src/data_structures/disjoint_set_forest.js b/src/data_structures/disjoint_set_forest.js index d8ca491..3cd6ac7 100644 --- a/src/data_structures/disjoint_set_forest.js +++ b/src/data_structures/disjoint_set_forest.js @@ -5,95 +5,97 @@ * * @constructor */ -function DisjointSetForest() { - this._parents = {}; - this._ranks = {}; - this._sizes = {}; -} +class DisjointSetForest { + constructor() { + this._parents = {}; + this._ranks = {}; + this._sizes = {}; + } -DisjointSetForest.prototype._introduce = function(element) { - if (!(element in this._parents)) { - this._parents[element] = element; - this._ranks[element] = 0; - this._sizes[element] = 1; + _introduce(element) { + if (!(element in this._parents)) { + this._parents[element] = element; + this._ranks[element] = 0; + this._sizes[element] = 1; + } } -}; -/** - * Check if the elements belong to the same subset. - * Complexity: O(A^-1) (inverse Ackermann function) amortized. - * - * @param {...*} element - * @return {boolean} - */ -DisjointSetForest.prototype.sameSubset = function(element) { - this._introduce(element); - const root = this.root(element); - return [].slice.call(arguments, 1).every(element => { + /** + * Check if the elements belong to the same subset. + * Complexity: O(A^-1) (inverse Ackermann function) amortized. + * + * @param {...*} element + * @return {boolean} + */ + sameSubset(element) { this._introduce(element); - return this.root(element) === root; - }); -}; - -/** - * Return the root element which represents the given element's subset. - * The result does not depend on the choice of the element, - * but rather on the subset itself. - * Complexity: O(A^-1) (inverse Ackermann function) amortized. - * - * @param {*} element - * @return {*} - */ -DisjointSetForest.prototype.root = function(element) { - this._introduce(element); - if (this._parents[element] !== element) { - this._parents[element] = this.root(this._parents[element]); + const root = this.root(element); + return [].slice.call(arguments, 1).every(element => { + this._introduce(element); + return this.root(element) === root; + }); } - return this._parents[element]; -}; -/** - * Return the size of the given element's subset. - * Complexity: O(A^-1) (inverse Ackermann function) amortized. - * - * @param {*} element - * @return {number} - */ -DisjointSetForest.prototype.size = function(element) { - this._introduce(element); - return this._sizes[this.root(element)]; -}; + /** + * Return the root element which represents the given element's subset. + * The result does not depend on the choice of the element, + * but rather on the subset itself. + * Complexity: O(A^-1) (inverse Ackermann function) amortized. + * + * @param {*} element + * @return {*} + */ + root(element) { + this._introduce(element); + if (this._parents[element] !== element) { + this._parents[element] = this.root(this._parents[element]); + } + return this._parents[element]; + } -/** - * Merge subsets containing two (or more) given elements into one. - * Complexity: O(A^-1) (inverse Ackermann function) amortized. - * - * @param {*} element1 - * @param {*} element2 - * @param {...*} - * @return {DisjointSetForest} - */ -DisjointSetForest.prototype.merge = function merge(element1, element2) { - if (arguments.length > 2) { - merge.apply(this, [].slice.call(arguments, 1)); + /** + * Return the size of the given element's subset. + * Complexity: O(A^-1) (inverse Ackermann function) amortized. + * + * @param {*} element + * @return {number} + */ + size(element) { + this._introduce(element); + return this._sizes[this.root(element)]; } - this._introduce(element1); - this._introduce(element2); - const root1 = this.root(element1); - const root2 = this.root(element2); + /** + * Merge subsets containing two (or more) given elements into one. + * Complexity: O(A^-1) (inverse Ackermann function) amortized. + * + * @param {*} element1 + * @param {*} element2 + * @param {...*} + * @return {DisjointSetForest} + */ + merge(element1, element2) { + if (arguments.length > 2) { + this.merge(...[].slice.call(arguments, 1)); + } - if (this._ranks[root1] < this._ranks[root2]) { - this._parents[root1] = root2; - this._sizes[root2] += this._sizes[root1]; - } else if (root1 !== root2) { - this._parents[root2] = root1; - this._sizes[root1] += this._sizes[root2]; - if (this._ranks[root1] === this._ranks[root2]) { - this._ranks[root1] += 1; + this._introduce(element1); + this._introduce(element2); + const root1 = this.root(element1); + const root2 = this.root(element2); + + if (this._ranks[root1] < this._ranks[root2]) { + this._parents[root1] = root2; + this._sizes[root2] += this._sizes[root1]; + } else if (root1 !== root2) { + this._parents[root2] = root1; + this._sizes[root1] += this._sizes[root2]; + if (this._ranks[root1] === this._ranks[root2]) { + this._ranks[root1] += 1; + } } + return this; } - return this; -}; +} module.exports = DisjointSetForest; diff --git a/src/data_structures/fenwick_tree.js b/src/data_structures/fenwick_tree.js index 379f941..56c60a4 100644 --- a/src/data_structures/fenwick_tree.js +++ b/src/data_structures/fenwick_tree.js @@ -20,66 +20,68 @@ * reasons: (1) the bit operations become rather easy and (2) it's better to * reason about the range sum (prefix(b) - prefix(a-1)) on a 1-based array. */ -function FenwickTree(length) { - this._elements = new Array(length + 1); - for (let i = 0; i < this._elements.length; i++) - this._elements[i] = 0; -} +class FenwickTree { + constructor(length) { + this._elements = new Array(length + 1); + for (let i = 0; i < this._elements.length; i++) + this._elements[i] = 0; + } -/** - * Adds value to the array at specified index in O(log n) - */ -FenwickTree.prototype.adjust = function(index, value) { - /* - This function goes up the tree adding the value to all parent nodes. + /** + * Adds value to the array at specified index in O(log n) + */ + adjust(index, value) { + /* + This function goes up the tree adding the value to all parent nodes. - In the array, to know where a index is in the tree, just look at where is - the rightmost bit. 1 is a leaf, because the rightmost bit is at position 0. - 2 (10) is 1 level above the leafs. 4 (100) is 2 levels above the leafs. + In the array, to know where a index is in the tree, just look at where is + the rightmost bit. 1 is a leaf, because the rightmost bit is at position 0. + 2 (10) is 1 level above the leafs. 4 (100) is 2 levels above the leafs. - Going up the tree means pushing the rightmost bit far to the left. We do - this by adding only the bit itself to the index. Eventually we skip - some levels that aren't represented in the array. E.g. starting at 3 (11), - it's imediate parent is 11b + 1b = 100b. We started at a leaf and skipped - the level-1 node, because it wasn't represented in the array - (a right child). + Going up the tree means pushing the rightmost bit far to the left. We do + this by adding only the bit itself to the index. Eventually we skip + some levels that aren't represented in the array. E.g. starting at 3 (11), + it's imediate parent is 11b + 1b = 100b. We started at a leaf and skipped + the level-1 node, because it wasn't represented in the array + (a right child). - Note: (index&-index) finds the rightmost bit in index. - */ - for (; index < this._elements.length; index += (index & -index)) - this._elements[index] += value; -}; + Note: (index&-index) finds the rightmost bit in index. + */ + for (; index < this._elements.length; index += (index & -index)) + this._elements[index] += value; + } -/** -* Returns the sum of all values up to specified index in O(log n) -*/ -FenwickTree.prototype.prefixSum = function(index) { - /* - This function goes up the tree adding the required nodes to sum the prefix. + /** + * Returns the sum of all values up to specified index in O(log n) + */ + prefixSum(index) { + /* + This function goes up the tree adding the required nodes to sum the prefix. - The key here is to sum every node that isn't in the same subtree as an - already seen node. In practice we proceed always getting a node's uncle - (the sibling of the node's parent). So, if we start at the index 7, we must - go to 6 (7's uncle), then to 4 (6's uncle), then we stop, because 4 has - no uncle. + The key here is to sum every node that isn't in the same subtree as an + already seen node. In practice we proceed always getting a node's uncle + (the sibling of the node's parent). So, if we start at the index 7, we must + go to 6 (7's uncle), then to 4 (6's uncle), then we stop, because 4 has + no uncle. - Binary-wise, this is the same as erasing the rightmost bit of the index. - E.g. 7 (111) -> 6 (110) -> 4 (100). + Binary-wise, this is the same as erasing the rightmost bit of the index. + E.g. 7 (111) -> 6 (110) -> 4 (100). - Note: (index&-index) finds the rightmost bit in index. - */ + Note: (index&-index) finds the rightmost bit in index. + */ - let sum = 0; - for (; index > 0; index -= (index & -index)) - sum += this._elements[index]; - return sum; -}; + let sum = 0; + for (; index > 0; index -= (index & -index)) + sum += this._elements[index]; + return sum; + } -/** -* Returns the sum of all values between two indexes in O(log n) -*/ -FenwickTree.prototype.rangeSum = function(fromIndex, toIndex) { - return this.prefixSum(toIndex) - this.prefixSum(fromIndex - 1); -}; + /** + * Returns the sum of all values between two indexes in O(log n) + */ + rangeSum(fromIndex, toIndex) { + return this.prefixSum(toIndex) - this.prefixSum(fromIndex - 1); + } +} module.exports = FenwickTree; diff --git a/src/data_structures/graph.js b/src/data_structures/graph.js index f5ebc2f..f553e7f 100644 --- a/src/data_structures/graph.js +++ b/src/data_structures/graph.js @@ -1,69 +1,71 @@ const HashSet = require('./set'); +// Normalize vertex labels as strings +const _ = v => String(v); + /** * Adjacency list representation of a graph * @param {bool} directed */ -function Graph(directed) { - this.directed = typeof directed === 'undefined' || Boolean(directed); - this.adjList = Object.create(null); - this.vertices = new HashSet(); -} - -// Normalize vertex labels as strings -const _ = v => String(v); +class Graph { + constructor(directed) { + this.directed = typeof directed === 'undefined' || Boolean(directed); + this.adjList = Object.create(null); + this.vertices = new HashSet(); + } -Graph.prototype.addVertex = function(v) { - v = _(v); - if (this.vertices.contains(v)) { - throw new Error('Vertex "' + v + '" has already been added'); + addVertex(v) { + v = _(v); + if (this.vertices.contains(v)) { + throw new Error('Vertex "' + v + '" has already been added'); + } + this.vertices.add(v); + this.adjList[v] = Object.create(null); } - this.vertices.add(v); - this.adjList[v] = Object.create(null); -}; -Graph.prototype.addEdge = function(a, b, w) { - a = _(a); - b = _(b); - // If no weight is assigned to the edge, 1 is the default - w = (w === undefined ? 1 : w); + addEdge(a, b, w) { + a = _(a); + b = _(b); + // If no weight is assigned to the edge, 1 is the default + w = (w === undefined ? 1 : w); - if (!this.adjList[a]) this.addVertex(a); - if (!this.adjList[b]) this.addVertex(b); + if (!this.adjList[a]) this.addVertex(a); + if (!this.adjList[b]) this.addVertex(b); - // If there's already another edge with the same origin and destination - // sum with the current one - this.adjList[a][b] = (this.adjList[a][b] || 0) + w; + // If there's already another edge with the same origin and destination + // sum with the current one + this.adjList[a][b] = (this.adjList[a][b] || 0) + w; - // If the graph is not directed add the edge in both directions - if (!this.directed) { - this.adjList[b][a] = (this.adjList[b][a] || 0) + w; + // If the graph is not directed add the edge in both directions + if (!this.directed) { + this.adjList[b][a] = (this.adjList[b][a] || 0) + w; + } } -}; -Graph.prototype.neighbors = function(v) { - return Object.keys(this.adjList[_(v)]); -}; + neighbors(v) { + return Object.keys(this.adjList[_(v)]); + } -Graph.prototype.edge = function(a, b) { - return this.adjList[_(a)][_(b)]; -}; + edge(a, b) { + return this.adjList[_(a)][_(b)]; + } -Graph.prototype.reverse = function() { - const self = this; - const r = new Graph(this.directed); + reverse() { + const self = this; + const r = new Graph(this.directed); - self.vertices.forEach(v => { - r.addVertex(v); - }); + self.vertices.forEach(v => { + r.addVertex(v); + }); - self.vertices.forEach(a => { - self.neighbors(a).forEach(b => { - r.addEdge(b, a, self.edge(a, b)); + self.vertices.forEach(a => { + self.neighbors(a).forEach(b => { + r.addEdge(b, a, self.edge(a, b)); + }); }); - }); - return r; -}; + return r; + } +} module.exports = Graph; diff --git a/src/data_structures/hash_table.js b/src/data_structures/hash_table.js index 9029718..e7f213d 100644 --- a/src/data_structures/hash_table.js +++ b/src/data_structures/hash_table.js @@ -4,119 +4,121 @@ const LinkedList = require('./linked_list'); * HashTable constructor * @param Number? initially allocated size */ -function HashTable(initialCapacity) { - this._table = new Array(initialCapacity || 64); - this._items = 0; +class HashTable { + constructor(initialCapacity) { + this._table = new Array(initialCapacity || 64); + this._items = 0; + + Object.defineProperty(this, 'capacity', { + get: function() { + return this._table.length; + } + }); - Object.defineProperty(this, 'capacity', { - get: function() { - return this._table.length; - } - }); + Object.defineProperty(this, 'size', { + get: function() { + return this._items; + } + }); + } - Object.defineProperty(this, 'size', { - get: function() { - return this._items; + /** + * (Same algorithm as Java's String.hashCode) + * Returns a hash code for this string. The hash code for a String object is + * computed as: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] + * using int arithmetic, where s[i] is the ith character of the string, + * n is the length of the string, and ^ indicates exponentiation. + * (The hash value of the empty string is zero.) + */ + hash(s) { + if (typeof s !== 'string') s = JSON.stringify(s); + let hash = 0; + for (let i = 0; i < s.length; i++) { + hash = ((hash << 5) - hash) + s.charCodeAt(i); + hash &= hash; // Keep it a 32bit int } - }); -} - -/** - * (Same algorithm as Java's String.hashCode) - * Returns a hash code for this string. The hash code for a String object is - * computed as: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] - * using int arithmetic, where s[i] is the ith character of the string, - * n is the length of the string, and ^ indicates exponentiation. - * (The hash value of the empty string is zero.) - */ -HashTable.prototype.hash = s => { - if (typeof s !== 'string') s = JSON.stringify(s); - let hash = 0; - for (let i = 0; i < s.length; i++) { - hash = ((hash << 5) - hash) + s.charCodeAt(i); - hash &= hash; // Keep it a 32bit int - } - return hash; -}; - -HashTable.prototype.get = function(key) { - const i = this._position(key); - let node; - if ((node = this._findInList(this._table[i], key))) { - return node.value.v; - } - return undefined; -}; - -HashTable.prototype.put = function(key, value) { - const i = this._position(key); - if (!this._table[i]) { - // Hashing with chaining - this._table[i] = new LinkedList(); - } - const item = {k: key, v: value}; - - const node = this._findInList(this._table[i], key); - if (node) { - // if the key already exists in the list, replace - // by the current item - node.value = item; - } else { - this._table[i].add(item); - this._items++; - - if (this._items === this.capacity) this._increaseCapacity(); + return hash; } -}; -HashTable.prototype.del = function(key) { - const i = this._position(key); - let node; + get(key) { + const i = this._position(key); + let node; + if ((node = this._findInList(this._table[i], key))) { + return node.value.v; + } + return undefined; + } - if ((node = this._findInList(this._table[i], key))) { - this._table[i].delNode(node); - this._items--; + put(key, value) { + const i = this._position(key); + if (!this._table[i]) { + // Hashing with chaining + this._table[i] = new LinkedList(); + } + const item = {k: key, v: value}; + + const node = this._findInList(this._table[i], key); + if (node) { + // if the key already exists in the list, replace + // by the current item + node.value = item; + } else { + this._table[i].add(item); + this._items++; + + if (this._items === this.capacity) this._increaseCapacity(); + } } -}; -HashTable.prototype._position = function(key) { - return Math.abs(this.hash(key)) % this.capacity; -}; + del(key) { + const i = this._position(key); + let node; -HashTable.prototype._findInList = (list, key) => { - let node = list && list.head; - while (node) { - if (node.value.k === key) return node; - node = node.next; + if ((node = this._findInList(this._table[i], key))) { + this._table[i].delNode(node); + this._items--; + } } -}; -HashTable.prototype._increaseCapacity = function() { - const oldTable = this._table; - this._table = new Array(2 * this.capacity); - this._items = 0; + _position(key) { + return Math.abs(this.hash(key)) % this.capacity; + } - for (let i = 0; i < oldTable.length; i++) { - let node = oldTable[i] && oldTable[i].head; + _findInList(list, key) { + let node = list && list.head; while (node) { - this.put(node.value.k, node.value.v); + if (node.value.k === key) return node; node = node.next; } } -}; -HashTable.prototype.forEach = function(fn) { - const applyFunction = linkedList => { - linkedList.forEach(elem => { - fn(elem.k, elem.v); - }); - }; + _increaseCapacity() { + const oldTable = this._table; + this._table = new Array(2 * this.capacity); + this._items = 0; + + for (let i = 0; i < oldTable.length; i++) { + let node = oldTable[i] && oldTable[i].head; + while (node) { + this.put(node.value.k, node.value.v); + node = node.next; + } + } + } - for (let i = 0; i < this._table.length; i++) { - if (this._table[i]) { - applyFunction(this._table[i]); + forEach(fn) { + const applyFunction = linkedList => { + linkedList.forEach(elem => { + fn(elem.k, elem.v); + }); + }; + + for (let i = 0; i < this._table.length; i++) { + if (this._table[i]) { + applyFunction(this._table[i]); + } } } -}; +} module.exports = HashTable; diff --git a/src/data_structures/heap.js b/src/data_structures/heap.js index 2f00de4..8eedf7e 100644 --- a/src/data_structures/heap.js +++ b/src/data_structures/heap.js @@ -3,107 +3,109 @@ const Comparator = require('../util/comparator'); /** * Basic Heap structure */ -function MinHeap(compareFn) { - this._elements = [null]; - this._comparator = new Comparator(compareFn); +class MinHeap { + constructor(compareFn) { + this._elements = [null]; + this._comparator = new Comparator(compareFn); + + Object.defineProperty(this, 'n', { + get: () => this._elements.length - 1 + }); + } - Object.defineProperty(this, 'n', { - get: () => this._elements.length - 1 - }); -} + _swap(a, b) { + const tmp = this._elements[a]; + this._elements[a] = this._elements[b]; + this._elements[b] = tmp; + } -MinHeap.prototype._swap = function(a, b) { - const tmp = this._elements[a]; - this._elements[a] = this._elements[b]; - this._elements[b] = tmp; -}; + isEmpty() { + return this.n === 0; + } -MinHeap.prototype.isEmpty = function() { - return this.n === 0; -}; + insert(e) { + this._elements.push(e); + this._siftUp(); + } -MinHeap.prototype.insert = function(e) { - this._elements.push(e); - this._siftUp(); -}; + extract() { + const element = this._elements[1]; -MinHeap.prototype.extract = function() { - const element = this._elements[1]; + // Get the one from the bottom in insert it on top + // If this isn't already the last element + const last = this._elements.pop(); + if (this.n) { + this._elements[1] = last; + this._siftDown(); + } - // Get the one from the bottom in insert it on top - // If this isn't already the last element - const last = this._elements.pop(); - if (this.n) { - this._elements[1] = last; - this._siftDown(); + return element; } - return element; -}; - -/** - * Sift up the last element - * O(lg n) - */ -MinHeap.prototype._siftUp = function() { - let i; - let parent; - - for (i = this.n; - i > 1 && (parent = i >> 1) && this._comparator.greaterThan( - this._elements[parent], this._elements[i]); - i = parent) { - this._swap(parent, i); + /** + * Sift up the last element + * O(lg n) + */ + _siftUp() { + let i; + let parent; + + for (i = this.n; + i > 1 && (parent = i >> 1) && this._comparator.greaterThan( + this._elements[parent], this._elements[i]); + i = parent) { + this._swap(parent, i); + } } -}; -/** - * Sifts down the first element - * O(lg n) - */ -MinHeap.prototype._siftDown = function(i) { - let c; - for (i = i || 1; (c = i << 1) <= this.n; i = c) { - // checks which is the smaller child to compare with - if (c + 1 <= this.n && this._comparator.lessThan( - this._elements[c + 1], this._elements[c])) - // use the right child if it's lower than the left one - c++; - if (this._comparator.lessThan(this._elements[i], - this._elements[c])) - break; - this._swap(i, c); + /** + * Sifts down the first element + * O(lg n) + */ + _siftDown(i) { + let c; + for (i = i || 1; (c = i << 1) <= this.n; i = c) { + // checks which is the smaller child to compare with + if (c + 1 <= this.n && this._comparator.lessThan( + this._elements[c + 1], this._elements[c])) + // use the right child if it's lower than the left one + c++; + if (this._comparator.lessThan(this._elements[i], + this._elements[c])) + break; + this._swap(i, c); + } } -}; -MinHeap.prototype.heapify = function(a) { - if (a) { - this._elements = a; - this._elements.unshift(null); - } + heapify(a) { + if (a) { + this._elements = a; + this._elements.unshift(null); + } - for (let i = this.n >> 1; i > 0; i--) { - this._siftDown(i); + for (let i = this.n >> 1; i > 0; i--) { + this._siftDown(i); + } } -}; -MinHeap.prototype.forEach = function(fn) { - // A copy is necessary in order to perform extract(), - // get the items in sorted order and then restore the original - // this._elements array - const elementsCopy = []; - let i; + forEach(fn) { + // A copy is necessary in order to perform extract(), + // get the items in sorted order and then restore the original + // this._elements array + const elementsCopy = []; + let i; - for (i = 0; i < this._elements.length; i++) { - elementsCopy.push(this._elements[i]); - } + for (i = 0; i < this._elements.length; i++) { + elementsCopy.push(this._elements[i]); + } - for (i = this.n; i > 0; i--) { - fn(this.extract()); - } + for (i = this.n; i > 0; i--) { + fn(this.extract()); + } - this._elements = elementsCopy; -}; + this._elements = elementsCopy; + } +} /** * Max Heap, keeps the highest element always on top @@ -111,13 +113,13 @@ MinHeap.prototype.forEach = function(fn) { * To avoid code repetition, the Min Heap is used just with * a reverse comparator; */ -function MaxHeap(compareFn) { - MinHeap.call(this, compareFn); - this._comparator.reverse(); +class MaxHeap extends MinHeap { + constructor(compareFn) { + super(compareFn); + this._comparator.reverse(); + } } -MaxHeap.prototype = new MinHeap(); - module.exports = { MinHeap, MaxHeap diff --git a/src/data_structures/linked_list.js b/src/data_structures/linked_list.js index 31b4a6d..52ed4a6 100644 --- a/src/data_structures/linked_list.js +++ b/src/data_structures/linked_list.js @@ -1,146 +1,149 @@ -/** - * Doubly-linked list - */ -function LinkedList() { - this._length = 0; - this.head = null; - this.tail = null; - - // Read-only length property - Object.defineProperty(this, 'length', { - get: () => this._length - }); -} - /** * A linked list node */ -function Node(value) { - this.value = value; - this.prev = null; - this.next = null; +class Node { + constructor(value) { + this.value = value; + this.prev = null; + this.next = null; + } } /** - * Whether the list is empty - * - * @return Boolean + * Doubly-linked list */ -LinkedList.prototype.isEmpty = function() { - return this.length === 0; -}; +class LinkedList { + constructor() { + this._length = 0; + this.head = null; + this.tail = null; + } -/** - * Adds the element to the end of the list or to the desired index - * - * @param { Object } n - * @param { Number } index - */ -LinkedList.prototype.add = function(n, index) { - if (index > this.length || index < 0) { - throw new Error('Index out of bounds'); + get length() { + return this._length; } - const node = new Node(n); + /** + * Whether the list is empty + * + * @return Boolean + */ + isEmpty() { + return this.length === 0; + } - if (index !== undefined && index < this.length) { - let prevNode; - let nextNode; + /** + * Adds the element to the end of the list or to the desired index + * + * @param { Object } n + * @param { Number } index + */ + add(n, index) { + if (index > this.length || index < 0) { + throw new Error('Index out of bounds'); + } - if (index === 0) { - // Insert in the beginning - nextNode = this.head; - this.head = node; + const node = new Node(n); + + if (index !== undefined && index < this.length) { + let prevNode; + let nextNode; + + if (index === 0) { + // Insert in the beginning + nextNode = this.head; + this.head = node; + } else { + nextNode = this.getNode(index); + prevNode = nextNode.prev; + prevNode.next = node; + node.prev = prevNode; + } + nextNode.prev = node; + node.next = nextNode; } else { - nextNode = this.getNode(index); - prevNode = nextNode.prev; - prevNode.next = node; - node.prev = prevNode; + // Insert at the end + if (!this.head) this.head = node; + + if (this.tail) { + this.tail.next = node; + node.prev = this.tail; + } + this.tail = node; } - nextNode.prev = node; - node.next = nextNode; - } else { - // Insert at the end - if (!this.head) this.head = node; - - if (this.tail) { - this.tail.next = node; - node.prev = this.tail; - } - this.tail = node; + + this._length++; } - this._length++; -}; + /** + * Return the value associated to the Node on the given index + * + * @param { Number } index + * @return misc + */ + get(index) { + return this.getNode(index).value; + } -/** - * Return the value associated to the Node on the given index - * - * @param { Number } index - * @return misc - */ -LinkedList.prototype.get = function(index) { - return this.getNode(index).value; -}; + /** + * O(n) get + * + * @param { Number } index + * @return Node + */ + getNode(index) { + if (index >= this.length || index < 0) { + throw new Error('Index out of bounds'); + } -/** - * O(n) get - * - * @param { Number } index - * @return Node - */ -LinkedList.prototype.getNode = function(index) { - if (index >= this.length || index < 0) { - throw new Error('Index out of bounds'); - } + let node = this.head; + for (let i = 1; i <= index; i++) { + node = node.next; + } - let node = this.head; - for (let i = 1; i <= index; i++) { - node = node.next; + return node; } - return node; -}; + /** + * Delete the element in the indexth position + * + * @param { Number } index + */ + del(index) { + if (index >= this.length || index < 0) { + throw new Error('Index out of bounds'); + } -/** - * Delete the element in the indexth position - * - * @param { Number } index - */ -LinkedList.prototype.del = function(index) { - if (index >= this.length || index < 0) { - throw new Error('Index out of bounds'); + this.delNode(this.getNode(index)); } - this.delNode(this.getNode(index)); -}; + delNode(node) { + if (node === this.tail) { + // node is the last element + this.tail = node.prev; + } else { + node.next.prev = node.prev; + } + if (node === this.head) { + // node is the first element + this.head = node.next; + } else { + node.prev.next = node.next; + } -LinkedList.prototype.delNode = function(node) { - if (node === this.tail) { - // node is the last element - this.tail = node.prev; - } else { - node.next.prev = node.prev; + this._length--; } - if (node === this.head) { - // node is the first element - this.head = node.next; - } else { - node.prev.next = node.next; - } - - this._length--; -}; -/** - * Performs the fn function with each element in the list - */ -LinkedList.prototype.forEach = function(fn) { - let node = this.head; - while (node) { - fn(node.value); - node = node.next; + /** + * Performs the fn function with each element in the list + */ + forEach(fn) { + let node = this.head; + while (node) { + fn(node.value); + node = node.next; + } } -}; +} module.exports = LinkedList; diff --git a/src/data_structures/priority_queue.js b/src/data_structures/priority_queue.js index 3913c52..191e5b6 100644 --- a/src/data_structures/priority_queue.js +++ b/src/data_structures/priority_queue.js @@ -5,42 +5,41 @@ const MinHeap = require('./heap').MinHeap; * the heap operations are performed based on the priority of the element * and not on the element itself */ -function PriorityQueue(initialItems) { - const self = this; - MinHeap.call(this, (a, b) => self.priority(a) < self.priority(b) ? -1 : 1); +class PriorityQueue extends MinHeap { + constructor(initialItems) { + super((a, b) => this.priority(a) < this.priority(b) ? -1 : 1); - this._priority = {}; + this._priority = {}; - initialItems = initialItems || {}; - Object.keys(initialItems).forEach(item => { - self.insert(item, initialItems[item]); - }); -} + initialItems = initialItems || {}; + Object.keys(initialItems).forEach(item => { + this.insert(item, initialItems[item]); + }); + } + + insert(item, priority) { + if (this._priority[item] !== undefined) { + return this.changePriority(item, priority); + } + this._priority[item] = priority; + super.insert(item); + } -PriorityQueue.prototype = new MinHeap(); + extract(withPriority) { + const min = MinHeap.prototype.extract.call(this); + return withPriority ? + min && {item: min, priority: this._priority[min]} : + min; + } + + priority(item) { + return this._priority[item]; + } -PriorityQueue.prototype.insert = function(item, priority) { - if (this._priority[item] !== undefined) { - return this.changePriority(item, priority); + changePriority(item, priority) { + this._priority[item] = priority; + this.heapify(); } - this._priority[item] = priority; - MinHeap.prototype.insert.call(this, item); -}; - -PriorityQueue.prototype.extract = function(withPriority) { - const min = MinHeap.prototype.extract.call(this); - return withPriority ? - min && {item: min, priority: this._priority[min]} : - min; -}; - -PriorityQueue.prototype.priority = function(item) { - return this._priority[item]; -}; - -PriorityQueue.prototype.changePriority = function(item, priority) { - this._priority[item] = priority; - this.heapify(); -}; +} module.exports = PriorityQueue; diff --git a/src/data_structures/queue.js b/src/data_structures/queue.js index 7a6b1ee..02b9e88 100644 --- a/src/data_structures/queue.js +++ b/src/data_structures/queue.js @@ -3,43 +3,45 @@ const LinkedList = require('./linked_list'); /** * Queue (FIFO) using a Linked List as basis */ -function Queue() { - this._elements = new LinkedList(); +class Queue { + constructor() { + this._elements = new LinkedList(); - Object.defineProperty(this, 'length', { - get: () => this._elements.length - }); -} - -Queue.prototype.isEmpty = function() { - return this._elements.isEmpty(); -}; + Object.defineProperty(this, 'length', { + get: () => this._elements.length + }); + } -/** - * Adds element to the end of the queue - */ -Queue.prototype.push = function(e) { - this._elements.add(e); -}; + isEmpty() { + return this._elements.isEmpty(); + } -/** - * Pops the element in the beginning of the queue - */ -Queue.prototype.pop = function() { - if (this.isEmpty()) { - throw new Error('Empty queue'); + /** + * Adds element to the end of the queue + */ + push(e) { + this._elements.add(e); } - const e = this._elements.head; - this._elements.delNode(e); - return e.value; -}; - -Queue.prototype.peek = function() { - if (this.isEmpty()) { - throw new Error('Empty queue'); + + /** + * Pops the element in the beginning of the queue + */ + pop() { + if (this.isEmpty()) { + throw new Error('Empty queue'); + } + const e = this._elements.head; + this._elements.delNode(e); + return e.value; } - return this._elements.get(0); -}; + peek() { + if (this.isEmpty()) { + throw new Error('Empty queue'); + } + + return this._elements.get(0); + } +} module.exports = Queue; diff --git a/src/data_structures/set.js b/src/data_structures/set.js index 3686645..aeeb943 100644 --- a/src/data_structures/set.js +++ b/src/data_structures/set.js @@ -5,37 +5,39 @@ const HashTable = require('./hash_table'); * No restriction on element types * i.e. set.add(1,'a', "b", { "foo" : "bar" }) */ -const HashSet = function() { - this._elements = new HashTable(arguments.length); - this.add.apply(this, arguments); +class HashSet { + constructor() { + this._elements = new HashTable(arguments.length); + this.add(...arguments); - Object.defineProperty(this, 'size', { - get: function() { - return this._elements.size; - } - }); -}; + Object.defineProperty(this, 'size', { + get: function() { + return this._elements.size; + } + }); + } -HashSet.prototype.add = function() { - for (let i = 0; i < arguments.length; i++) { - this._elements.put(arguments[i], true); + add() { + for (let i = 0; i < arguments.length; i++) { + this._elements.put(arguments[i], true); + } + return this; } - return this; -}; -HashSet.prototype.remove = function() { - for (let i = 0; i < arguments.length; i++) { - this._elements.del(arguments[i]); + remove() { + for (let i = 0; i < arguments.length; i++) { + this._elements.del(arguments[i]); + } + return this; } - return this; -}; -HashSet.prototype.contains = function(e) { - return typeof this._elements.get(e) !== 'undefined'; -}; + contains(e) { + return typeof this._elements.get(e) !== 'undefined'; + } -HashSet.prototype.forEach = function(fn) { - this._elements.forEach(fn); -}; + forEach(fn) { + this._elements.forEach(fn); + } +} module.exports = HashSet; diff --git a/src/data_structures/stack.js b/src/data_structures/stack.js index a171e47..622de7b 100644 --- a/src/data_structures/stack.js +++ b/src/data_structures/stack.js @@ -3,44 +3,46 @@ const LinkedList = require('./linked_list'); /** * Stack (LIFO) using a Linked List as basis */ -function Stack() { - this._elements = new LinkedList(); +class Stack { + constructor() { + this._elements = new LinkedList(); - Object.defineProperty(this, 'length', { - get: () => this._elements.length - }); -} + Object.defineProperty(this, 'length', { + get: () => this._elements.length + }); + } -Stack.prototype.isEmpty = function() { - return this._elements.isEmpty(); -}; + isEmpty() { + return this._elements.isEmpty(); + } -/** - * Adds element to the top of the stack - */ -Stack.prototype.push = function(e) { - this._elements.add(e); -}; + /** + * Adds element to the top of the stack + */ + push(e) { + this._elements.add(e); + } -/** - * Pops the element from the top of the stack - */ -Stack.prototype.pop = function() { - if (this.isEmpty()) { - throw new Error('Empty queue'); + /** + * Pops the element from the top of the stack + */ + pop() { + if (this.isEmpty()) { + throw new Error('Empty queue'); + } + + const e = this._elements.tail; + this._elements.delNode(e); + return e.value; } - const e = this._elements.tail; - this._elements.delNode(e); - return e.value; -}; + peek() { + if (this.isEmpty()) { + throw new Error('Empty queue'); + } -Stack.prototype.peek = function() { - if (this.isEmpty()) { - throw new Error('Empty queue'); + return this._elements.tail.value; } - - return this._elements.tail.value; -}; +} module.exports = Stack; diff --git a/src/data_structures/treap.js b/src/data_structures/treap.js index 852c071..4ae2b4d 100644 --- a/src/data_structures/treap.js +++ b/src/data_structures/treap.js @@ -1,151 +1,155 @@ /** * Tree node */ -function Node(value, left, right) { - this.value = value; - this.children = [left, right]; - this.size = 1; - this.height = 1; - this.key = Math.random(); -} - -/** - * Computer the number of childnodes - */ -Node.prototype.resize = function() { - this.size = (this.children[0] ? this.children[0].size : 0) + - (this.children[1] ? this.children[1].size : 0) + 1; - this.height = Math.max(this.children[0] ? this.children[0].height : 0, - this.children[1] ? this.children[1].height : 0) + 1; - return this; -}; +class Node { + constructor(value, left, right) { + this.value = value; + this.children = [left, right]; + this.size = 1; + this.height = 1; + this.key = Math.random(); + } -/** - * Zigzag rotate of tree nodes - */ -Node.prototype.rotate = function(side) { - const temp = this.children[side]; + /** + * Computer the number of childnodes + */ + resize() { + this.size = (this.children[0] ? this.children[0].size : 0) + + (this.children[1] ? this.children[1].size : 0) + 1; + this.height = Math.max(this.children[0] ? this.children[0].height : 0, + this.children[1] ? this.children[1].height : 0) + 1; + return this; + } - // Rotate - this.children[side] = temp.children[1 - side]; - temp.children[1 - side] = this; + /** + * Zigzag rotate of tree nodes + */ + rotate(side) { + const temp = this.children[side]; - this.resize(); - temp.resize(); + // Rotate + this.children[side] = temp.children[1 - side]; + temp.children[1 - side] = this; - return temp; -}; + this.resize(); + temp.resize(); -/** - * Treap - */ -function Treap() { - this.root = null; + return temp; + } } /** - * Insert new value into the subtree of `node` + * Treap */ -Treap.prototype._insert = function(node, value) { - if (node === null) { - return new Node(value, null, null); +class Treap { + constructor() { + this.root = null; } - // Passing to childnodes and update - const side = ~~(value > node.value); - node.children[side] = this._insert(node.children[side], value); + /** + * Insert new value into the subtree of `node` + */ + _insert(node, value) { + if (node === null) { + return new Node(value, null, null); + } - // Keep it balance - if (node.children[side].key < node.key) { - return node.rotate(side); - } - return node.resize(); -}; + // Passing to childnodes and update + const side = ~~(value > node.value); + node.children[side] = this._insert(node.children[side], value); -Treap.prototype._find = function(node, value) { - if (node === null) { - // Empty tree - return false; - } - if (node.value === value) { - // Found! - return true; + // Keep it balance + if (node.children[side].key < node.key) { + return node.rotate(side); + } + return node.resize(); } - // Search within childnodes - const side = ~~(value > node.value); - return this._find(node.children[side], value); -}; + _find(node, value) { + if (node === null) { + // Empty tree + return false; + } + if (node.value === value) { + // Found! + return true; + } -Treap.prototype._minimum = function(node) { - if (node === null) { - // Empty tree, returns Infinity - return Infinity; + // Search within childnodes + const side = ~~(value > node.value); + return this._find(node.children[side], value); } - return Math.min(node.value, this._minimum(node.children[0])); -}; + _minimum(node) { + if (node === null) { + // Empty tree, returns Infinity + return Infinity; + } -Treap.prototype._maximum = function(node) { - if (node === null) { - // Empty tree, returns -Infinity - return -Infinity; + return Math.min(node.value, this._minimum(node.children[0])); } - return Math.max(node.value, this._maximum(node.children[1])); -}; + _maximum(node) { + if (node === null) { + // Empty tree, returns -Infinity + return -Infinity; + } -Treap.prototype._remove = function(node, value) { - if (node === null) { - // Empty node, value not found - return null; + return Math.max(node.value, this._maximum(node.children[1])); } - let side; - - if (node.value === value) { - if (node.children[0] === null && node.children[1] === null) { - // It's a leaf, set to null + _remove(node, value) { + if (node === null) { + // Empty node, value not found return null; } - // Rotate to a subtree and remove it - side = (node.children[0] === null ? 1 : 0); - node = node.rotate(side); - node.children[1 - side] = this._remove(node.children[1 - side], value); - } else { - side = ~~(value > node.value); - node.children[side] = this._remove(node.children[side], value); + let side; + + if (node.value === value) { + if (node.children[0] === null && node.children[1] === null) { + // It's a leaf, set to null + return null; + } + + // Rotate to a subtree and remove it + side = (node.children[0] === null ? 1 : 0); + node = node.rotate(side); + node.children[1 - side] = this._remove(node.children[1 - side], value); + } else { + side = ~~(value > node.value); + node.children[side] = this._remove(node.children[side], value); + } + return node.resize(); } - return node.resize(); -}; -Treap.prototype.insert = function(value) { - this.root = this._insert(this.root, value); -}; + insert(value) { + this.root = this._insert(this.root, value); + } -Treap.prototype.find = function(value) { - return this._find(this.root, value); -}; + find(value) { + return this._find(this.root, value); + } -Treap.prototype.minimum = function() { - return this._minimum(this.root); -}; + minimum() { + return this._minimum(this.root); + } -Treap.prototype.maximum = function() { - return this._maximum(this.root); -}; + maximum() { + return this._maximum(this.root); + } -Treap.prototype.remove = function(value) { - this.root = this._remove(this.root, value); -}; + remove(value) { + this.root = this._remove(this.root, value); + } -Treap.prototype.size = function() { - return this.root ? this.root.size : 0; -}; + size() { + return this.root ? this.root.size : 0; + } -Treap.prototype.height = function() { - return this.root ? this.root.height : 0; -}; + height() { + return this.root ? this.root.height : 0; + } +} module.exports = Treap; diff --git a/src/util/comparator.js b/src/util/comparator.js index abdacb4..f15d6cf 100644 --- a/src/util/comparator.js +++ b/src/util/comparator.js @@ -6,49 +6,51 @@ * * @param { Function } compareFn */ -function Comparator(compareFn) { - if (compareFn) { - this.compare = compareFn; +class Comparator { + constructor(compareFn) { + if (compareFn) { + this.compare = compareFn; + } } -} -/** - * Default implementation for the compare function - */ -Comparator.prototype.compare = (a, b) => { - if (a === b) return 0; - return a < b ? -1 : 1; -}; + /** + * Default implementation for the compare function + */ + compare(a, b) { + if (a === b) return 0; + return a < b ? -1 : 1; + } -Comparator.prototype.lessThan = function(a, b) { - return this.compare(a, b) < 0; -}; + lessThan(a, b) { + return this.compare(a, b) < 0; + } -Comparator.prototype.lessThanOrEqual = function(a, b) { - return this.lessThan(a, b) || this.equal(a, b); -}; + lessThanOrEqual(a, b) { + return this.lessThan(a, b) || this.equal(a, b); + } -Comparator.prototype.greaterThan = function(a, b) { - return this.compare(a, b) > 0; -}; + greaterThan(a, b) { + return this.compare(a, b) > 0; + } -Comparator.prototype.greaterThanOrEqual = function(a, b) { - return this.greaterThan(a, b) || this.equal(a, b); -}; + greaterThanOrEqual(a, b) { + return this.greaterThan(a, b) || this.equal(a, b); + } -Comparator.prototype.equal = function(a, b) { - return this.compare(a, b) === 0; -}; + equal(a, b) { + return this.compare(a, b) === 0; + } -/** - * Reverse the comparison function to use the opposite logic, e.g: - * this.compare(a, b) => 1 - * this.reverse(); - * this.compare(a, b) => -1 - */ -Comparator.prototype.reverse = function() { - const originalCompareFn = this.compare; - this.compare = (a, b) => originalCompareFn(b, a); -}; + /** + * Reverse the comparison function to use the opposite logic, e.g: + * this.compare(a, b) => 1 + * this.reverse(); + * this.compare(a, b) => -1 + */ + reverse() { + const originalCompareFn = this.compare; + this.compare = (a, b) => originalCompareFn(b, a); + } +} module.exports = Comparator; From 001f0bc2aa80746e00a4908216cfe4ee5aa3dd22 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 14 Jun 2017 17:19:04 +0200 Subject: [PATCH 246/280] Require Node >=6 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2f427ed..f247b3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: node_js sudo: false node_js: - - '4' - - '5.1' - '6' + - '7' + - '8' script: "make" after_success: "make coveralls" From 5de16eec47f92dfb5ef3138162392886d92aab25 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 14 Jun 2017 21:45:25 +0200 Subject: [PATCH 247/280] Prettier --- .eslintrc | 5 +- package.json | 7 +- src/algorithms/graph/SPFA.js | 3 +- src/algorithms/graph/breadth_first_search.js | 28 ++-- src/algorithms/graph/depth_first_search.js | 32 ++-- src/algorithms/graph/euler_path.js | 6 +- .../graph/strongly_connected_component.js | 3 +- src/algorithms/math/fast_power.js | 8 +- src/algorithms/math/fibonacci.js | 21 ++- src/algorithms/math/find_divisors.js | 53 +++---- src/algorithms/math/gcd.js | 2 +- src/algorithms/math/next_permutation.js | 2 +- src/algorithms/search/ternary_search.js | 5 +- src/algorithms/sorting/bubble_sort.js | 3 +- src/algorithms/sorting/heap_sort.js | 3 +- src/algorithms/sorting/merge_sort.js | 2 +- src/algorithms/sorting/radix_sort.js | 9 +- src/algorithms/string/huffman.js | 24 +-- src/algorithms/string/levenshtein.js | 3 +- src/algorithms/string/rabin_karp.js | 7 +- src/data_structures/avl_tree.js | 38 +++-- src/data_structures/bst.js | 16 +- src/data_structures/disjoint_set_forest.js | 10 +- src/data_structures/fenwick_tree.js | 9 +- src/data_structures/graph.js | 2 +- src/data_structures/hash_table.js | 2 +- src/data_structures/heap.js | 22 ++- src/data_structures/priority_queue.js | 8 +- src/data_structures/set.js | 18 +-- src/data_structures/treap.js | 15 +- src/string.js | 6 +- src/test/algorithms/geometry/bezier_curve.js | 18 ++- src/test/algorithms/graph/SPFA.js | 45 +++--- src/test/algorithms/graph/bellman_ford.js | 3 +- .../algorithms/graph/bfs_shortest_path.js | 67 ++++---- .../algorithms/graph/depth_first_search.js | 60 ++++--- src/test/algorithms/graph/dijkstra.js | 33 ++-- src/test/algorithms/graph/euler_path.js | 23 +-- src/test/algorithms/graph/floyd_warshall.js | 103 ++++++------ .../algorithms/graph/minimum_spanning_tree.js | 61 ++++--- src/test/algorithms/graph/topological_sort.js | 86 +++++----- .../algorithms/math/collatz_conjecture.js | 1 - src/test/algorithms/math/fast_power.js | 30 ++-- src/test/algorithms/math/fibonacci.js | 1 - src/test/algorithms/math/find_divisors.js | 105 ++++++++---- src/test/algorithms/math/fisher_yates.js | 1 - src/test/algorithms/math/gcd.js | 36 +++-- src/test/algorithms/math/lcm.js | 76 +++++---- src/test/algorithms/math/newton_sqrt.js | 28 ++-- src/test/algorithms/math/next_permutation.js | 48 +++--- src/test/algorithms/math/primality_tests.js | 1 - src/test/algorithms/searching/binarysearch.js | 1 - src/test/algorithms/searching/dfs.js | 22 ++- src/test/algorithms/sorting/shell_sort.js | 1 - .../sorting/sorting_tests_helper.js | 48 ++++-- src/test/algorithms/string/huffman.js | 46 ++++-- .../algorithms/string/knuth_morris_pratt.js | 72 ++++----- src/test/algorithms/string/levenshtein.js | 27 ++-- .../string/longest_common_subsequence.js | 3 +- src/test/algorithms/string/rabin_karp.js | 23 ++- src/test/data_structures/avl-tree.js | 150 +++++++++++------- src/test/data_structures/bst.js | 148 +++++++++-------- .../data_structures/disjoint_set_forest.js | 27 ++-- src/test/data_structures/graph.js | 64 ++++---- src/test/data_structures/hash_table.js | 43 ++--- src/test/data_structures/heap.js | 60 +++---- src/test/data_structures/linked_list.js | 133 ++++++++-------- src/test/data_structures/priority_queue.js | 79 ++++----- src/test/data_structures/queue.js | 27 ++-- src/test/data_structures/set.js | 20 ++- src/test/data_structures/stack.js | 26 +-- src/test/data_structures/treap.js | 12 +- src/test/util/comparator.js | 40 +++-- 73 files changed, 1247 insertions(+), 1023 deletions(-) diff --git a/.eslintrc b/.eslintrc index e548bbd..0c988cd 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,6 +5,9 @@ "mocha": true }, "rules": { - "valid-jsdoc": 0 + "valid-jsdoc": 0, + "require-jsdoc": 0, + "comma-dangle": ["error", "never"], + "arrow-parens": ["error", "as-needed"] } } diff --git a/package.json b/package.json index 0aec5fc..131b667 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "./index.js", "scripts": { "lint": "eslint src/", - "test": "mocha -R spec --recursive src/test" + "test": "mocha -R spec --recursive src/test", + "coverage": "istanbul cover ./node_modules/.bin/_mocha -- -R spec --recursive src/test" }, "pre-commit": [ "lint", @@ -14,8 +15,8 @@ "dependencies": {}, "devDependencies": { "coveralls": "^2.11.4", - "eslint": "^2.13.1", - "eslint-config-google": "^0.6.0", + "eslint": "^4.0.0", + "eslint-config-google": "^0.8.0", "istanbul": "^0.4.0", "mocha": "^2.3.3", "pre-commit": "^1.1.2" diff --git a/src/algorithms/graph/SPFA.js b/src/algorithms/graph/SPFA.js index a27ee1e..2701d47 100644 --- a/src/algorithms/graph/SPFA.js +++ b/src/algorithms/graph/SPFA.js @@ -43,11 +43,12 @@ function spfa(graph, s) { queue[tail++] = v; isInQue[v] = true; cnt[v]++; - if (cnt[v] > graph.vertices.size) + if (cnt[v] > graph.vertices.size) { // indicates negative-weighted cycle return { distance: {} }; + } } } } diff --git a/src/algorithms/graph/breadth_first_search.js b/src/algorithms/graph/breadth_first_search.js index ae81e88..f7dda34 100644 --- a/src/algorithms/graph/breadth_first_search.js +++ b/src/algorithms/graph/breadth_first_search.js @@ -22,20 +22,22 @@ const Queue = require('../../data_structures/queue'); const normalizeCallbacks = (callbacks, seenVertices) => { callbacks = callbacks || {}; - callbacks.allowTraversal = callbacks.allowTraversal || ((() => { - const seen = seenVertices.reduce((seen, vertex) => { - seen[vertex] = true; - return seen; - }, {}); + callbacks.allowTraversal = + callbacks.allowTraversal || + (() => { + const seen = seenVertices.reduce((seen, vertex) => { + seen[vertex] = true; + return seen; + }, {}); - return (vertex, neighbor) => { - if (!seen[neighbor]) { - seen[neighbor] = true; - return true; - } - return false; - }; - }))(); + return (vertex, neighbor) => { + if (!seen[neighbor]) { + seen[neighbor] = true; + return true; + } + return false; + }; + })(); const noop = () => {}; callbacks.onTraversal = callbacks.onTraversal || noop; diff --git a/src/algorithms/graph/depth_first_search.js b/src/algorithms/graph/depth_first_search.js index 40be5fb..7134e46 100644 --- a/src/algorithms/graph/depth_first_search.js +++ b/src/algorithms/graph/depth_first_search.js @@ -21,23 +21,25 @@ const normalizeCallbacks = (callbacks, seenVertices) => { callbacks = callbacks || {}; - callbacks.allowTraversal = callbacks.allowTraversal || ((() => { - const seen = {}; - seenVertices.forEach(vertex => { - seen[vertex] = true; - }); + callbacks.allowTraversal = + callbacks.allowTraversal || + (() => { + const seen = {}; + seenVertices.forEach(vertex => { + seen[vertex] = true; + }); - return (vertex, neighbor) => { - // It should still be possible to redefine other callbacks, - // so we better do all at once here. + return (vertex, neighbor) => { + // It should still be possible to redefine other callbacks, + // so we better do all at once here. - if (!seen[neighbor]) { - seen[neighbor] = true; - return true; - } - return false; - }; - }))(); + if (!seen[neighbor]) { + seen[neighbor] = true; + return true; + } + return false; + }; + })(); const noop = () => {}; callbacks.beforeTraversal = callbacks.beforeTraversal || noop; diff --git a/src/algorithms/graph/euler_path.js b/src/algorithms/graph/euler_path.js index 6895f6b..e618cda 100644 --- a/src/algorithms/graph/euler_path.js +++ b/src/algorithms/graph/euler_path.js @@ -66,8 +66,10 @@ const eulerEndpoints = graph => { start = finish = v; } - return {start, - finish}; + return { + start, + finish + }; }; /** diff --git a/src/algorithms/graph/strongly_connected_component.js b/src/algorithms/graph/strongly_connected_component.js index 181f910..8a6bbf4 100644 --- a/src/algorithms/graph/strongly_connected_component.js +++ b/src/algorithms/graph/strongly_connected_component.js @@ -11,7 +11,8 @@ const depthFirstSearch = require('../../algorithms/graph/depth_first_search'); * id is a Object, receives a vertex and returns id of the strongly * connected component vertex belongs to, ranges from 0 to count - 1. * note: 1.if v and w are in same scc, then id[v] == id[w] - * 2.if v and w are in different scc and there is a path from v to w, then id[v] > id[w]. + * 2.if v and w are in different scc and there is a path from + * v to w, then id[v] > id[w]. * * Usage: * var scc = stronglyConnectedComponent(g); diff --git a/src/algorithms/math/fast_power.js b/src/algorithms/math/fast_power.js index 5c407a9..2aefe70 100644 --- a/src/algorithms/math/fast_power.js +++ b/src/algorithms/math/fast_power.js @@ -31,9 +31,13 @@ const fastPower = (base, power, mul, identity) => { // Iterative form of the algorithm avoids checking the same thing twice. let result; const multiplyBy = value => { - result = (result === undefined) ? value : mul(result, value); + result = result === undefined ? value : mul(result, value); }; - for (let factor = base; power; power >>>= 1, factor = mul(factor, factor)) { + for ( + let factor = base; + power; + (power >>>= 1), (factor = mul(factor, factor)) + ) { if (power & 1) { multiplyBy(factor); } diff --git a/src/algorithms/math/fibonacci.js b/src/algorithms/math/fibonacci.js index 1c6de1d..f0eab02 100644 --- a/src/algorithms/math/fibonacci.js +++ b/src/algorithms/math/fibonacci.js @@ -13,7 +13,8 @@ const power = require('./fast_power'); * @param Number * @return Number */ -const fibExponential = n => n < 2 ? n : fibExponential(n - 1) + fibExponential(n - 2); +const fibExponential = n => + n < 2 ? n : fibExponential(n - 1) + fibExponential(n - 2); /** * O(n) in time, O(1) in space and doesn't use recursion @@ -39,7 +40,7 @@ const fibLinear = n => { * @param Number * @return Number */ -const fibWithMemoization = ((() => { +const fibWithMemoization = (() => { const cache = [0, 1]; const fib = n => { @@ -50,7 +51,7 @@ const fibWithMemoization = ((() => { }; return fib; -}))(); +})(); /** * Implementation using Binet's formula with the rounding trick. @@ -75,10 +76,16 @@ const fibLogarithmic = number => { // Transforms [f_1, f_0] to [f_2, f_1] and so on. const nextFib = [[1, 1], [1, 0]]; - const matrixMultiply = (a, b) => [[a[0][0] * b[0][0] + a[0][1] * b[1][0], - a[0][0] * b[0][1] + a[0][1] * b[1][1]], - [a[1][0] * b[0][0] + a[1][1] * b[1][0], - a[1][0] * b[0][1] + a[1][1] * b[1][1]]]; + const matrixMultiply = (a, b) => [ + [ + a[0][0] * b[0][0] + a[0][1] * b[1][0], + a[0][0] * b[0][1] + a[0][1] * b[1][1] + ], + [ + a[1][0] * b[0][0] + a[1][1] * b[1][0], + a[1][0] * b[0][1] + a[1][1] * b[1][1] + ] + ]; const transform = power(nextFib, number, matrixMultiply, [[1, 0], [0, 1]]); diff --git a/src/algorithms/math/find_divisors.js b/src/algorithms/math/find_divisors.js index ba8be40..3528a01 100644 --- a/src/algorithms/math/find_divisors.js +++ b/src/algorithms/math/find_divisors.js @@ -12,12 +12,11 @@ */ const findDivisorsGeneric = number => { - let index = 1; const divisors = []; - for (index; index <= number; index++) { - if (number % index === 0) { - divisors.push(index); + for (let i = 1; i <= number; i++) { + if (number % i === 0) { + divisors.push(i); } } return divisors; @@ -28,23 +27,23 @@ const findDivisorsGeneric = number => { * This solution has a cost of O(sqrt(n)) * This method returns the divisors in an unsorted manner. * All divisors of a number are present in pairs. - * Eg : For n=16: (1, 16), (2, 8), (4, 4). Include only one of the repeated divisors if any. + * Eg : For n=16: (1, 16), (2, 8), (4, 4). + * Include only one of the repeated divisors if any. * * @param {number} * @returns {number[]} - returns the divisors */ const findDivisorsByPairingUnsorted = number => { - let index = 1; const divisors = []; - for (index; index <= Math.sqrt(number); index++) { - if (number % index === 0) { - if (number / index === index) - divisors.push(index); - else { - divisors.push(index); - divisors.push(number / index); + const sqrt = Math.sqrt(number); + + for (let i = 1; i <= sqrt; i++) { + if (number % i === 0) { + divisors.push(i); + if (i !== sqrt) { + divisors.push(number / i); } } } @@ -55,32 +54,32 @@ const findDivisorsByPairingUnsorted = number => { * Find all the divisors of a natural number * This solution has a cost of O(sqrt(n)) * This method returns the array in a sorted manner - * All divisors of a number are present in pairs (divisorLessThanSqrt, divisorGreaterThanSqrt) - * Reverse the divisorGreaterThanSqrt array and append to divisorLessThanSqrt to sort the result - * Eg : For n=16: (1, 16), (2, 8), (4, 4). Include only one of the repeated divisors if any + * All divisors of a number are present in pairs + * (divisorLessThanSqrt, divisorGreaterThanSqrt) + * Reverse the divisorGreaterThanSqrt array and append to divisorLessThanSqrt + * to sort the result + * Eg : For n=16: (1, 16), (2, 8), (4, 4). + * Include only one of the repeated divisors if any * * @param {number} * @returns {number[]} - returns the divisors */ const findDivisorsByPairingSorted = number => { - let index = 1; - let divisors = []; const divisorsLessThanSqrt = []; const divisorsMoreThanSqrt = []; - for (index; index <= Math.sqrt(number); index++) { - if (number % index === 0) { - if (number / index === index) - divisorsLessThanSqrt.push(index); - else { - divisorsLessThanSqrt.push(index); - divisorsMoreThanSqrt.push(number / index); + const sqrt = Math.sqrt(number); + for (let i = 1; i <= sqrt; i++) { + if (number % i === 0) { + divisorsLessThanSqrt.push(i); + if (i !== sqrt) { + divisorsMoreThanSqrt.unshift(number / i); } } } - divisors = divisorsLessThanSqrt.concat(divisorsMoreThanSqrt.reverse()); - return divisors; + + return divisorsLessThanSqrt.concat(divisorsMoreThanSqrt); }; // Use findDivisorsGeneric as the default implementation diff --git a/src/algorithms/math/gcd.js b/src/algorithms/math/gcd.js index cbd38db..748a752 100644 --- a/src/algorithms/math/gcd.js +++ b/src/algorithms/math/gcd.js @@ -72,7 +72,7 @@ const gcdBinaryIterative = (a, b) => { a = tmp; } - b -= a; // Here b >= a + b -= a; // Here b >= a } while (b !== 0); // restore common factors of 2 diff --git a/src/algorithms/math/next_permutation.js b/src/algorithms/math/next_permutation.js index fc87418..5208cc9 100644 --- a/src/algorithms/math/next_permutation.js +++ b/src/algorithms/math/next_permutation.js @@ -36,7 +36,7 @@ const nextPermutation = (array, compareFn) => { array[successor] = pivotValue; // Reverse the descending part. - for (let left = pivot, right = array.length; ++left < --right;) { + for (let left = pivot, right = array.length; ++left < --right; ) { const temp = array[left]; array[left] = array[right]; array[right] = temp; diff --git a/src/algorithms/search/ternary_search.js b/src/algorithms/search/ternary_search.js index 15f257a..ee2cee8 100644 --- a/src/algorithms/search/ternary_search.js +++ b/src/algorithms/search/ternary_search.js @@ -9,9 +9,8 @@ const ternarySearch = (fn, left, right, precision) => { const leftThird = left + (right - left) / 3; const rightThird = right - (right - left) / 3; - if (fn(leftThird) < fn(rightThird)) - left = leftThird; else - right = rightThird; + if (fn(leftThird) < fn(rightThird)) left = leftThird; + else right = rightThird; } return (left + right) / 2; }; diff --git a/src/algorithms/sorting/bubble_sort.js b/src/algorithms/sorting/bubble_sort.js index c6eb00a..fa6e937 100644 --- a/src/algorithms/sorting/bubble_sort.js +++ b/src/algorithms/sorting/bubble_sort.js @@ -19,8 +19,7 @@ const bubbleSort = (a, comparatorFn) => { check = true; } } - if (!check) - return a; + if (!check) return a; bound = newbound; } return a; diff --git a/src/algorithms/sorting/heap_sort.js b/src/algorithms/sorting/heap_sort.js index 7b2b18d..4f7c739 100644 --- a/src/algorithms/sorting/heap_sort.js +++ b/src/algorithms/sorting/heap_sort.js @@ -10,8 +10,9 @@ const heapsort = (array, comparatorFn) => { minHeap.heapify(array); const result = []; - while (!minHeap.isEmpty()) + while (!minHeap.isEmpty()) { result.push(minHeap.extract()); + } return result; }; diff --git a/src/algorithms/sorting/merge_sort.js b/src/algorithms/sorting/merge_sort.js index eb894c8..0f93107 100644 --- a/src/algorithms/sorting/merge_sort.js +++ b/src/algorithms/sorting/merge_sort.js @@ -11,7 +11,7 @@ const merge = (a, b, comparator) => { // Concats the elements from the sub-array // that has not been included yet - return result.concat((i < a.length ? a.slice(i) : b.slice(j))); + return result.concat(i < a.length ? a.slice(i) : b.slice(j)); }; /** diff --git a/src/algorithms/sorting/radix_sort.js b/src/algorithms/sorting/radix_sort.js index 0b4d46c..fe71205 100644 --- a/src/algorithms/sorting/radix_sort.js +++ b/src/algorithms/sorting/radix_sort.js @@ -22,8 +22,8 @@ const auxiliaryCountingSort = (array, mod) => { } for (i = 0; i < length; i++) { - const digit = parseInt((array[i].key / Math.pow(10, mod)) - .toFixed(mod), 10) % 10; + const digit = + parseInt((array[i].key / Math.pow(10, mod)).toFixed(mod), 10) % 10; bucket[digit].push(array[i]); } @@ -72,8 +72,9 @@ const maximumKey = a => { */ const radixSort = array => { const max = maximumKey(array); - const digitsMax = (max === 0 ? 1 : - 1 + Math.floor(Math.log(max) / Math.log(10))); // log base 10 + const digitsMax = max === 0 + ? 1 + : 1 + Math.floor(Math.log(max) / Math.log(10)); // log base 10 for (let i = 0; i < digitsMax; i++) { array = auxiliaryCountingSort(array, i); diff --git a/src/algorithms/string/huffman.js b/src/algorithms/string/huffman.js index 8dde5fa..5ce429c 100644 --- a/src/algorithms/string/huffman.js +++ b/src/algorithms/string/huffman.js @@ -48,13 +48,17 @@ const decompress = array => { if (!array.length) { return ''; } else if (array.length === 1) { - throw new Error('Compressed array must be either empty ' + - 'or at least 2 blocks big.'); + throw new Error( + 'Compressed array must be either empty ' + 'or at least 2 blocks big.' + ); } const padding = new Array(MAX_BLOCK_SIZE + 1).join(0); - let string = array.slice(0, -2).map(block => (padding + (block >>> 0).toString(2)).slice(-padding.length)).join(''); + let string = array + .slice(0, -2) + .map(block => (padding + (block >>> 0).toString(2)).slice(-padding.length)) + .join(''); // Append the last block. const lastBlockSize = array.slice(-1)[0]; @@ -75,7 +79,7 @@ huffman.encode = (string, compressed) => { if (!string.length) { return { encoding: {}, - value: (compressed ? [] : '') + value: compressed ? [] : '' }; } @@ -90,7 +94,7 @@ huffman.encode = (string, compressed) => { })); const compare = (a, b) => a.count - b.count; - const less = (a, b) => a && (b && (a.count < b.count) || !b); + const less = (a, b) => a && ((b && a.count < b.count) || !b); letters.sort(compare); @@ -101,8 +105,10 @@ huffman.encode = (string, compressed) => { let lettersIndex = 0; let bufferIndex = 0; - const extractMinimum = () => less(letters[lettersIndex], buffer[bufferIndex]) ? - letters[lettersIndex++] : buffer[bufferIndex++]; + const extractMinimum = () => + less(letters[lettersIndex], buffer[bufferIndex]) + ? letters[lettersIndex++] + : buffer[bufferIndex++]; for (let numLetters = letters.length; numLetters > 1; --numLetters) { const a = extractMinimum(); @@ -118,7 +124,7 @@ huffman.encode = (string, compressed) => { // At this point there is a single letter left. const root = extractMinimum(); - root.code = (letters.length > 1) ? '' : '0'; + root.code = letters.length > 1 ? '' : '0'; // Unroll the code recursively in reverse. (function unroll(parent) { @@ -142,7 +148,7 @@ huffman.encode = (string, compressed) => { return { encoding, - value: (compressed ? compress(result) : result) + value: compressed ? compress(result) : result }; }; diff --git a/src/algorithms/string/levenshtein.js b/src/algorithms/string/levenshtein.js index 863909a..e95f5e9 100644 --- a/src/algorithms/string/levenshtein.js +++ b/src/algorithms/string/levenshtein.js @@ -37,8 +37,7 @@ const levenshtein = (a, b) => { editDistance[i - 1][j - 1], // if we replace a[i] by b[j] editDistance[i - 1][j], // if we delete the char from a editDistance[i][j - 1] // if we add the char from b - ) + - (a[i - 1] === b[j - 1] ? 0 : 1); + ) + (a[i - 1] === b[j - 1] ? 0 : 1); } } diff --git a/src/algorithms/string/rabin_karp.js b/src/algorithms/string/rabin_karp.js index 6dcc1c9..d2e2d60 100644 --- a/src/algorithms/string/rabin_karp.js +++ b/src/algorithms/string/rabin_karp.js @@ -50,16 +50,15 @@ const rabinKarp = (s, pattern) => { * Recalculates the hash representation of a word so that it isn't * necessary to traverse the whole word again */ - hashCurrentSubstring -= currentSubstring.charCodeAt(0) * - Math.pow(base, pattern.length - 1); + hashCurrentSubstring -= + currentSubstring.charCodeAt(0) * Math.pow(base, pattern.length - 1); hashCurrentSubstring *= base; hashCurrentSubstring += s.charCodeAt(i); currentSubstring = currentSubstring.substring(1) + s[i]; } - if (hashPattern === hashCurrentSubstring && - pattern === currentSubstring) { + if (hashPattern === hashCurrentSubstring && pattern === currentSubstring) { // Hack for the off-by-one when matching in the beginning of the string return i === pattern.length ? 0 : i - pattern.length + 1; } diff --git a/src/data_structures/avl_tree.js b/src/data_structures/avl_tree.js index 7603b4c..f5bffec 100644 --- a/src/data_structures/avl_tree.js +++ b/src/data_structures/avl_tree.js @@ -29,7 +29,7 @@ class AVLTree { let isBalanced = true; if (node.left !== null && node.right !== null) { - isBalanced = (Math.abs(node.left.height - node.right.height) <= 1); + isBalanced = Math.abs(node.left.height - node.right.height) <= 1; } else if (node.right !== null && node.left === null) { isBalanced = node.right.height < 2; } else if (node.left !== null && node.right === null) { @@ -51,7 +51,7 @@ class AVLTree { // (cannot be ancestor of removed node) let y; if (z.left !== null && z.right !== null) { - y = (z.left === y) ? z.right : z.left; + y = z.left === y ? z.right : z.left; } else if (z.left !== null && z.right === null) { y = z.left; } else if (z.right !== null && z.left === null) { @@ -68,7 +68,7 @@ class AVLTree { } else if (y.left.height < y.right.height) { x = y.right; } else if (y.left.height === y.right.height) { - x = (z.left === y) ? y.left : y.right; + x = z.left === y ? y.left : y.right; } } else if (y.left !== null && y.right === null) { x = y.left; @@ -125,9 +125,9 @@ class AVLTree { traveledNodes.push(current); current.height = this.getNodeHeight(current); if (!this.isNodeBalanced(current)) { - const nodesToBeRestructured = (afterRemove) ? - this.getNodesToRestructureAfterRemove(traveledNodes) : - this.getNodesToRestructureAfterInsert(traveledNodes); + const nodesToBeRestructured = afterRemove + ? this.getNodesToRestructureAfterRemove(traveledNodes) + : this.getNodesToRestructureAfterInsert(traveledNodes); this.restructure(nodesToBeRestructured); } current = current.parent; @@ -161,7 +161,7 @@ class AVLTree { rightRight(x, y, z) { // pass z parent to y and move y's left to z's right if (z.parent) { - const orientation = (z.parent.left === z) ? 'left' : 'right'; + const orientation = z.parent.left === z ? 'left' : 'right'; z.parent[orientation] = y; y.parent = z.parent; } else { @@ -190,7 +190,7 @@ class AVLTree { leftLeft(x, y, z) { // pass z parent to y and move y's right to z's left if (z.parent) { - const orientation = (z.parent.left === z) ? 'left' : 'right'; + const orientation = z.parent.left === z ? 'left' : 'right'; z.parent[orientation] = y; y.parent = z.parent; } else { @@ -218,7 +218,7 @@ class AVLTree { rightLeft(x, y, z) { // pass z parent to x if (z.parent) { - const orientation = (z.parent.left === z) ? 'left' : 'right'; + const orientation = z.parent.left === z ? 'left' : 'right'; z.parent[orientation] = x; x.parent = z.parent; } else { @@ -254,7 +254,7 @@ class AVLTree { leftRight(x, y, z) { // pass z parent to x if (z.parent) { - const orientation = (z.parent.left === z) ? 'left' : 'right'; + const orientation = z.parent.left === z ? 'left' : 'right'; z.parent[orientation] = x; x.parent = z.parent; } else { @@ -487,10 +487,13 @@ class AVLTree { if (!current) { return true; } - return this._isBalanced(current._left) && + return ( + this._isBalanced(current._left) && this._isBalanced(current._right) && - Math.abs(this._getNodeHeight(current._left) - - this._getNodeHeight(current._right)) <= 1; + Math.abs( + this._getNodeHeight(current._left) - this._getNodeHeight(current._right) + ) <= 1 + ); } /** @@ -503,8 +506,13 @@ class AVLTree { if (!current) { return 0; } - return 1 + Math.max(this.getNodeHeight(current._left), - this._getNodeHeight(current._right)); + return ( + 1 + + Math.max( + this.getNodeHeight(current._left), + this._getNodeHeight(current._right) + ) + ); } } diff --git a/src/data_structures/bst.js b/src/data_structures/bst.js index f8a5ede..c40a7c9 100644 --- a/src/data_structures/bst.js +++ b/src/data_structures/bst.js @@ -35,7 +35,9 @@ class BST { parent = this.root; } - const child = this._comparator.lessThan(value, parent.value) ? 'left' : 'right'; + const child = this._comparator.lessThan(value, parent.value) + ? 'left' + : 'right'; if (parent[child]) { this.insert(value, parent[child]); } else { @@ -57,14 +59,15 @@ class BST { else return false; } - if (root.value === e) - return root; + if (root.value === e) return root; - if (this._comparator.lessThan(e, root.value)) + if (this._comparator.lessThan(e, root.value)) { return root.left && this._find(e, root.left); + } - if (this._comparator.greaterThan(e, root.value)) + if (this._comparator.greaterThan(e, root.value)) { return root.right && this._find(e, root.right); + } } /** @@ -74,8 +77,7 @@ class BST { const parent = currNode.parent; if (parent) { parent[currNode === parent.left ? 'left' : 'right'] = newNode; - if (newNode) - newNode.parent = parent; + if (newNode) newNode.parent = parent; } else { this.root = newNode; } diff --git a/src/data_structures/disjoint_set_forest.js b/src/data_structures/disjoint_set_forest.js index 3cd6ac7..9952bc8 100644 --- a/src/data_structures/disjoint_set_forest.js +++ b/src/data_structures/disjoint_set_forest.js @@ -27,10 +27,10 @@ class DisjointSetForest { * @param {...*} element * @return {boolean} */ - sameSubset(element) { + sameSubset(element, ...rest) { this._introduce(element); const root = this.root(element); - return [].slice.call(arguments, 1).every(element => { + return rest.every(element => { this._introduce(element); return this.root(element) === root; }); @@ -74,9 +74,9 @@ class DisjointSetForest { * @param {...*} * @return {DisjointSetForest} */ - merge(element1, element2) { - if (arguments.length > 2) { - this.merge(...[].slice.call(arguments, 1)); + merge(element1, element2, ...rest) { + if (rest.length > 0) { + this.merge(element2, ...rest); } this._introduce(element1); diff --git a/src/data_structures/fenwick_tree.js b/src/data_structures/fenwick_tree.js index 56c60a4..5903155 100644 --- a/src/data_structures/fenwick_tree.js +++ b/src/data_structures/fenwick_tree.js @@ -23,8 +23,9 @@ class FenwickTree { constructor(length) { this._elements = new Array(length + 1); - for (let i = 0; i < this._elements.length; i++) + for (let i = 0; i < this._elements.length; i++) { this._elements[i] = 0; + } } /** @@ -47,8 +48,9 @@ class FenwickTree { Note: (index&-index) finds the rightmost bit in index. */ - for (; index < this._elements.length; index += (index & -index)) + for (; index < this._elements.length; index += index & -index) { this._elements[index] += value; + } } /** @@ -71,8 +73,9 @@ class FenwickTree { */ let sum = 0; - for (; index > 0; index -= (index & -index)) + for (; index > 0; index -= index & -index) { sum += this._elements[index]; + } return sum; } diff --git a/src/data_structures/graph.js b/src/data_structures/graph.js index f553e7f..18505a2 100644 --- a/src/data_structures/graph.js +++ b/src/data_structures/graph.js @@ -27,7 +27,7 @@ class Graph { a = _(a); b = _(b); // If no weight is assigned to the edge, 1 is the default - w = (w === undefined ? 1 : w); + w = w === undefined ? 1 : w; if (!this.adjList[a]) this.addVertex(a); if (!this.adjList[b]) this.addVertex(b); diff --git a/src/data_structures/hash_table.js b/src/data_structures/hash_table.js index e7f213d..99f0f80 100644 --- a/src/data_structures/hash_table.js +++ b/src/data_structures/hash_table.js @@ -34,7 +34,7 @@ class HashTable { if (typeof s !== 'string') s = JSON.stringify(s); let hash = 0; for (let i = 0; i < s.length; i++) { - hash = ((hash << 5) - hash) + s.charCodeAt(i); + hash = (hash << 5) - hash + s.charCodeAt(i); hash &= hash; // Keep it a 32bit int } return hash; diff --git a/src/data_structures/heap.js b/src/data_structures/heap.js index 8eedf7e..3e918dd 100644 --- a/src/data_structures/heap.js +++ b/src/data_structures/heap.js @@ -50,10 +50,13 @@ class MinHeap { let i; let parent; - for (i = this.n; - i > 1 && (parent = i >> 1) && this._comparator.greaterThan( - this._elements[parent], this._elements[i]); - i = parent) { + for ( + i = this.n; + i > 1 && + (parent = i >> 1) && + this._comparator.greaterThan(this._elements[parent], this._elements[i]); + i = parent + ) { this._swap(parent, i); } } @@ -66,13 +69,16 @@ class MinHeap { let c; for (i = i || 1; (c = i << 1) <= this.n; i = c) { // checks which is the smaller child to compare with - if (c + 1 <= this.n && this._comparator.lessThan( - this._elements[c + 1], this._elements[c])) + if ( + c + 1 <= this.n && + this._comparator.lessThan(this._elements[c + 1], this._elements[c]) + ) { // use the right child if it's lower than the left one c++; - if (this._comparator.lessThan(this._elements[i], - this._elements[c])) + } + if (this._comparator.lessThan(this._elements[i], this._elements[c])) { break; + } this._swap(i, c); } } diff --git a/src/data_structures/priority_queue.js b/src/data_structures/priority_queue.js index 191e5b6..afd3225 100644 --- a/src/data_structures/priority_queue.js +++ b/src/data_structures/priority_queue.js @@ -7,7 +7,7 @@ const MinHeap = require('./heap').MinHeap; */ class PriorityQueue extends MinHeap { constructor(initialItems) { - super((a, b) => this.priority(a) < this.priority(b) ? -1 : 1); + super((a, b) => (this.priority(a) < this.priority(b) ? -1 : 1)); this._priority = {}; @@ -27,9 +27,9 @@ class PriorityQueue extends MinHeap { extract(withPriority) { const min = MinHeap.prototype.extract.call(this); - return withPriority ? - min && {item: min, priority: this._priority[min]} : - min; + return withPriority + ? min && {item: min, priority: this._priority[min]} + : min; } priority(item) { diff --git a/src/data_structures/set.js b/src/data_structures/set.js index aeeb943..034875d 100644 --- a/src/data_structures/set.js +++ b/src/data_structures/set.js @@ -6,9 +6,9 @@ const HashTable = require('./hash_table'); * i.e. set.add(1,'a', "b", { "foo" : "bar" }) */ class HashSet { - constructor() { - this._elements = new HashTable(arguments.length); - this.add(...arguments); + constructor(...args) { + this._elements = new HashTable(args.length); + this.add(...args); Object.defineProperty(this, 'size', { get: function() { @@ -17,16 +17,16 @@ class HashSet { }); } - add() { - for (let i = 0; i < arguments.length; i++) { - this._elements.put(arguments[i], true); + add(...args) { + for (let i = 0; i < args.length; i++) { + this._elements.put(args[i], true); } return this; } - remove() { - for (let i = 0; i < arguments.length; i++) { - this._elements.del(arguments[i]); + remove(...args) { + for (let i = 0; i < args.length; i++) { + this._elements.del(args[i]); } return this; } diff --git a/src/data_structures/treap.js b/src/data_structures/treap.js index 4ae2b4d..f207592 100644 --- a/src/data_structures/treap.js +++ b/src/data_structures/treap.js @@ -14,10 +14,15 @@ class Node { * Computer the number of childnodes */ resize() { - this.size = (this.children[0] ? this.children[0].size : 0) + - (this.children[1] ? this.children[1].size : 0) + 1; - this.height = Math.max(this.children[0] ? this.children[0].height : 0, - this.children[1] ? this.children[1].height : 0) + 1; + this.size = + (this.children[0] ? this.children[0].size : 0) + + (this.children[1] ? this.children[1].size : 0) + + 1; + this.height = + Math.max( + this.children[0] ? this.children[0].height : 0, + this.children[1] ? this.children[1].height : 0 + ) + 1; return this; } @@ -113,7 +118,7 @@ class Treap { } // Rotate to a subtree and remove it - side = (node.children[0] === null ? 1 : 0); + side = node.children[0] === null ? 1 : 0; node = node.rotate(side); node.children[1 - side] = this._remove(node.children[1 - side], value); } else { diff --git a/src/string.js b/src/string.js index 8a100de..9d0881f 100644 --- a/src/string.js +++ b/src/string.js @@ -5,8 +5,6 @@ module.exports = { knuthMorrisPratt: require('./algorithms/string/knuth_morris_pratt'), huffman: require('./algorithms/string/huffman'), hamming: require('./algorithms/string/hamming'), - longestCommonSubsequence: require( - './algorithms/string/longest_common_subsequence'), - longestCommonSubstring: require( - './algorithms/string/longest_common_substring') + longestCommonSubsequence: require('./algorithms/string/longest_common_subsequence'), + longestCommonSubstring: require('./algorithms/string/longest_common_substring') }; diff --git a/src/test/algorithms/geometry/bezier_curve.js b/src/test/algorithms/geometry/bezier_curve.js index cd3ef58..d00387e 100644 --- a/src/test/algorithms/geometry/bezier_curve.js +++ b/src/test/algorithms/geometry/bezier_curve.js @@ -20,18 +20,22 @@ describe('Bézier-Curve Algorithm', () => { assert.deepEqual(b.get(0.75), {x: 7.5, y: 2.25}); }); it('should get a quadratic Bézier-curve', () => { - const b = new BezierCurve([{x: 150, y: 40}, - {x: 80, y: 30}, - {x: 105, y: 150}]); + const b = new BezierCurve([ + {x: 150, y: 40}, + {x: 80, y: 30}, + {x: 105, y: 150} + ]); assert.deepEqual(b.get(0.5), {x: 103.75, y: 62.5}); assert.deepEqual(b.get(0.25), {x: 120.9375, y: 43.125}); }); it('should get a cubic Bézier-curve', () => { - const b = new BezierCurve([{x: 150, y: 40}, - {x: 80, y: 30}, - {x: 105, y: 150}, - {x: 100, y: 100}]); + const b = new BezierCurve([ + {x: 150, y: 40}, + {x: 80, y: 30}, + {x: 105, y: 150}, + {x: 100, y: 100} + ]); assert.deepEqual(b.get(0.5), {x: 100.625, y: 85}); }); diff --git a/src/test/algorithms/graph/SPFA.js b/src/test/algorithms/graph/SPFA.js index 61a1781..14635c6 100644 --- a/src/test/algorithms/graph/SPFA.js +++ b/src/test/algorithms/graph/SPFA.js @@ -4,33 +4,32 @@ const Graph = root.DataStructures.Graph; const assert = require('assert'); describe('SPFA Algorithm', () => { - it('should return the shortest paths to all nodes from a given origin', - () => { - const graph = new Graph(true); + it('should return the shortest paths to all nodes from a given origin', () => { + const graph = new Graph(true); - graph.addEdge('a', 'b', -1); - graph.addEdge('a', 'c', 4); - graph.addEdge('b', 'c', 3); - graph.addEdge('b', 'd', 2); - graph.addEdge('b', 'e', 2); - graph.addEdge('d', 'b', 1); - graph.addEdge('e', 'd', -3); - graph.addEdge('d', 'c', 5); + graph.addEdge('a', 'b', -1); + graph.addEdge('a', 'c', 4); + graph.addEdge('b', 'c', 3); + graph.addEdge('b', 'd', 2); + graph.addEdge('b', 'e', 2); + graph.addEdge('d', 'b', 1); + graph.addEdge('e', 'd', -3); + graph.addEdge('d', 'c', 5); - let shortestPaths = spfa(graph, 'a'); + let shortestPaths = spfa(graph, 'a'); - assert.equal(shortestPaths.distance.a, 0); - assert.equal(shortestPaths.distance.d, -2); - assert.equal(shortestPaths.distance.e, 1); - assert.equal(shortestPaths.previous.d, 'e'); - assert.equal(shortestPaths.previous.e, 'b'); + assert.equal(shortestPaths.distance.a, 0); + assert.equal(shortestPaths.distance.d, -2); + assert.equal(shortestPaths.distance.e, 1); + assert.equal(shortestPaths.previous.d, 'e'); + assert.equal(shortestPaths.previous.e, 'b'); - // It'll cause a Negative-Weighted Cycle. - graph.addEdge('c', 'a', -9); + // It'll cause a Negative-Weighted Cycle. + graph.addEdge('c', 'a', -9); - shortestPaths = spfa(graph, 'a'); + shortestPaths = spfa(graph, 'a'); - // The 'distance' object is empty - assert.equal(shortestPaths.distance.a, undefined); - }); + // The 'distance' object is empty + assert.equal(shortestPaths.distance.a, undefined); + }); }); diff --git a/src/test/algorithms/graph/bellman_ford.js b/src/test/algorithms/graph/bellman_ford.js index 2bd2043..82eb00f 100644 --- a/src/test/algorithms/graph/bellman_ford.js +++ b/src/test/algorithms/graph/bellman_ford.js @@ -4,8 +4,7 @@ const Graph = root.DataStructures.Graph; const assert = require('assert'); describe('Bellman-Ford Algorithm', () => { - it('should return the shortest paths to all nodes from a given origin', - () => { + it('should return the shortest paths to all nodes from a given origin', () => { const graph = new Graph(true); graph.addEdge('a', 'b', -1); diff --git a/src/test/algorithms/graph/bfs_shortest_path.js b/src/test/algorithms/graph/bfs_shortest_path.js index 6ad0977..14cd1c2 100644 --- a/src/test/algorithms/graph/bfs_shortest_path.js +++ b/src/test/algorithms/graph/bfs_shortest_path.js @@ -4,40 +4,39 @@ const Graph = root.DataStructures.Graph; const assert = require('assert'); describe('BFS Shortest Path Algorithm', () => { - it('should return the shortest paths to all nodes from a given origin', - () => { - const graph = new Graph(); - graph.addEdge(0, 1); - graph.addEdge(1, 2); - graph.addEdge(0, 2); - graph.addEdge(2, 3); - graph.addEdge(3, 6); - graph.addEdge(6, 2); - graph.addEdge(6, 0); - graph.addEdge(0, 4); - graph.addEdge(4, 6); - graph.addEdge(4, 5); - graph.addEdge(5, 0); - graph.addEdge('a', 'b'); + it('should return the shortest paths to all nodes from a given origin', () => { + const graph = new Graph(); + graph.addEdge(0, 1); + graph.addEdge(1, 2); + graph.addEdge(0, 2); + graph.addEdge(2, 3); + graph.addEdge(3, 6); + graph.addEdge(6, 2); + graph.addEdge(6, 0); + graph.addEdge(0, 4); + graph.addEdge(4, 6); + graph.addEdge(4, 5); + graph.addEdge(5, 0); + graph.addEdge('a', 'b'); - const shortestPath = bfsShortestPath(graph, 0); + const shortestPath = bfsShortestPath(graph, 0); - assert.deepEqual(shortestPath.distance, { - 0: 0, - 1: 1, - 2: 1, - 3: 2, - 4: 1, - 5: 2, - 6: 2 - }); - assert.deepEqual(shortestPath.previous, { - 1: 0, - 2: 0, - 3: 2, - 4: 0, - 5: 4, - 6: 4 - }); - }); + assert.deepEqual(shortestPath.distance, { + 0: 0, + 1: 1, + 2: 1, + 3: 2, + 4: 1, + 5: 2, + 6: 2 + }); + assert.deepEqual(shortestPath.previous, { + 1: 0, + 2: 0, + 3: 2, + 4: 0, + 5: 4, + 6: 4 + }); + }); }); diff --git a/src/test/algorithms/graph/depth_first_search.js b/src/test/algorithms/graph/depth_first_search.js index 04a5c46..c257028 100644 --- a/src/test/algorithms/graph/depth_first_search.js +++ b/src/test/algorithms/graph/depth_first_search.js @@ -15,41 +15,39 @@ describe('Depth First Search Algorithm', () => { graph.addEdge('five', 'six'); }); - it('should visit only the nodes reachable from the start node (inclusive)', - () => { - const enter = []; - const leave = []; - let numEdgeTails = 0; - let numEdgeHeads = 0; + it('should visit only the nodes reachable from the start node (inclusive)', () => { + const enter = []; + const leave = []; + let numEdgeTails = 0; + let numEdgeHeads = 0; - depthFirstSearch(graph, 'one'); + depthFirstSearch(graph, 'one'); - const dfsCallbacks = { - enterVertex: [].push.bind(enter), - leaveVertex: [].push.bind(leave), - beforeTraversal: function() { - numEdgeHeads += 1; - }, - afterTraversal: function() { - numEdgeTails += 1; - } - }; + const dfsCallbacks = { + enterVertex: [].push.bind(enter), + leaveVertex: [].push.bind(leave), + beforeTraversal: function() { + numEdgeHeads += 1; + }, + afterTraversal: function() { + numEdgeTails += 1; + } + }; - depthFirstSearch(graph, 'one', dfsCallbacks); - assert.deepEqual(enter, ['one', 'three', 'four', 'two']); - assert.deepEqual(leave, ['three', 'two', 'four', 'one']); - assert.equal(numEdgeTails, numEdgeHeads); - assert.equal(numEdgeHeads, 3); + depthFirstSearch(graph, 'one', dfsCallbacks); + assert.deepEqual(enter, ['one', 'three', 'four', 'two']); + assert.deepEqual(leave, ['three', 'two', 'four', 'one']); + assert.equal(numEdgeTails, numEdgeHeads); + assert.equal(numEdgeHeads, 3); - enter.splice(0, 4); - leave.splice(0, 4); - depthFirstSearch(graph, 'five', dfsCallbacks); - assert.deepEqual(enter, ['five', 'six']); - assert.deepEqual(leave, ['six', 'five']); - assert.equal(numEdgeTails, numEdgeHeads); - assert.equal(numEdgeHeads, 4); - } - ); + enter.splice(0, 4); + leave.splice(0, 4); + depthFirstSearch(graph, 'five', dfsCallbacks); + assert.deepEqual(enter, ['five', 'six']); + assert.deepEqual(leave, ['six', 'five']); + assert.equal(numEdgeTails, numEdgeHeads); + assert.equal(numEdgeHeads, 4); + }); it('should allow user-defined allowTraversal rules', () => { const seen = new Graph(graph.directed); diff --git a/src/test/algorithms/graph/dijkstra.js b/src/test/algorithms/graph/dijkstra.js index 8a309a6..f9df425 100644 --- a/src/test/algorithms/graph/dijkstra.js +++ b/src/test/algorithms/graph/dijkstra.js @@ -4,24 +4,23 @@ const Graph = root.DataStructures.Graph; const assert = require('assert'); describe('Dijkstra Algorithm', () => { - it('should return the shortest paths to all nodes from a given origin', - () => { - const g = new Graph(); - g.addEdge('a', 'b', 5); - g.addEdge('a', 'c', 10); - g.addEdge('b', 'c', 2); - g.addEdge('b', 'd', 20); - g.addEdge('c', 'd', 1); - g.addEdge('d', 'a', 10); + it('should return the shortest paths to all nodes from a given origin', () => { + const g = new Graph(); + g.addEdge('a', 'b', 5); + g.addEdge('a', 'c', 10); + g.addEdge('b', 'c', 2); + g.addEdge('b', 'd', 20); + g.addEdge('c', 'd', 1); + g.addEdge('d', 'a', 10); - const shortestPath = dijkstra(g, 'a'); - assert.equal(shortestPath.distance.b, 5); - assert.equal(shortestPath.previous.b, 'a'); + const shortestPath = dijkstra(g, 'a'); + assert.equal(shortestPath.distance.b, 5); + assert.equal(shortestPath.previous.b, 'a'); - assert.equal(shortestPath.distance.c, 7); - assert.equal(shortestPath.previous.c, 'b'); + assert.equal(shortestPath.distance.c, 7); + assert.equal(shortestPath.previous.c, 'b'); - assert.equal(shortestPath.distance.d, 8); - assert.equal(shortestPath.previous.d, 'c'); - }); + assert.equal(shortestPath.distance.d, 8); + assert.equal(shortestPath.previous.d, 'c'); + }); }); diff --git a/src/test/algorithms/graph/euler_path.js b/src/test/algorithms/graph/euler_path.js index 676a24b..e643e4d 100644 --- a/src/test/algorithms/graph/euler_path.js +++ b/src/test/algorithms/graph/euler_path.js @@ -16,8 +16,10 @@ describe('Euler Path', () => { }, trail[0]); graph.vertices.forEach(vertex => { - assert.equal(graph.neighbors(vertex).length, - visited.neighbors(vertex).length); + assert.equal( + graph.neighbors(vertex).length, + visited.neighbors(vertex).length + ); }); }; @@ -126,11 +128,7 @@ describe('Euler Path', () => { let graph = graphFromEdges(false, [[0, 1], [2, 3]]); assert.throws(eulerPath.bind(null, graph)); - graph = graphFromEdges(false, [ - [0, 1], - [0, 2], - [0, 3] - ]); + graph = graphFromEdges(false, [[0, 1], [0, 2], [0, 3]]); assert.throws(eulerPath.bind(null, graph)); graph = graphFromEdges(true, [[0, 1], [0, 2]]); @@ -139,17 +137,10 @@ describe('Euler Path', () => { graph = graphFromEdges(true, [[1, 0], [2, 0]]); assert.throws(eulerPath.bind(null, graph)); - graph = graphFromEdges(true, [ - [0, 1], - [2, 3], - [3, 2] - ]); + graph = graphFromEdges(true, [[0, 1], [2, 3], [3, 2]]); assert.throws(eulerPath.bind(null, graph)); - graph = graphFromEdges(true, [ - [0, 1], - [2, 3] - ]); + graph = graphFromEdges(true, [[0, 1], [2, 3]]); assert.throws(eulerPath.bind(null, graph)); }); }); diff --git a/src/test/algorithms/graph/floyd_warshall.js b/src/test/algorithms/graph/floyd_warshall.js index da04afc..ccea319 100644 --- a/src/test/algorithms/graph/floyd_warshall.js +++ b/src/test/algorithms/graph/floyd_warshall.js @@ -16,42 +16,56 @@ describe('Floyd-Warshall Algorithm', () => { const result = floydWarshall(graph); - assert.deepEqual(result.distance, {a: {a: 0, - b: -2, - c: -3, - x: -1, - y: -6, - z: Infinity}, - b: {a: 3, - b: 0, - c: -1, - x: 1, - y: -4, - z: Infinity}, - c: {a: 4, - b: 2, - c: 0, - x: 2, - y: -3, - z: Infinity}, - x: {a: Infinity, - b: Infinity, - c: Infinity, - x: 0, - y: Infinity, - z: Infinity}, - y: {a: Infinity, - b: Infinity, - c: Infinity, - x: Infinity, - y: 0, - z: Infinity}, - z: {a: Infinity, - b: Infinity, - c: Infinity, - x: 1, - y: -4, - z: 0}}); + assert.deepEqual(result.distance, { + a: { + a: 0, + b: -2, + c: -3, + x: -1, + y: -6, + z: Infinity + }, + b: { + a: 3, + b: 0, + c: -1, + x: 1, + y: -4, + z: Infinity + }, + c: { + a: 4, + b: 2, + c: 0, + x: 2, + y: -3, + z: Infinity + }, + x: { + a: Infinity, + b: Infinity, + c: Infinity, + x: 0, + y: Infinity, + z: Infinity + }, + y: { + a: Infinity, + b: Infinity, + c: Infinity, + x: Infinity, + y: 0, + z: Infinity + }, + z: { + a: Infinity, + b: Infinity, + c: Infinity, + x: 1, + y: -4, + z: 0 + } + }); assert.equal(result.path('x', 'y'), null); assert.deepEqual(result.path('z', 'z'), ['z']); @@ -59,14 +73,13 @@ describe('Floyd-Warshall Algorithm', () => { assert.deepEqual(result.path('a', 'y'), ['a', 'b', 'c', 'y']); }); - it('should determine if the graph contains a negative-weighted cycle', - () => { - const graph = new Graph(); - graph.addEdge('a', 'b', -2); - graph.addEdge('b', 'c', -1); - graph.addEdge('c', 'y', -3); - graph.addEdge('c', 'a', 2); + it('should determine if the graph contains a negative-weighted cycle', () => { + const graph = new Graph(); + graph.addEdge('a', 'b', -2); + graph.addEdge('b', 'c', -1); + graph.addEdge('c', 'y', -3); + graph.addEdge('c', 'a', 2); - assert.throws(floydWarshall.bind(null, graph)); - }); + assert.throws(floydWarshall.bind(null, graph)); + }); }); diff --git a/src/test/algorithms/graph/minimum_spanning_tree.js b/src/test/algorithms/graph/minimum_spanning_tree.js index 2fdcb6f..1af3bf5 100644 --- a/src/test/algorithms/graph/minimum_spanning_tree.js +++ b/src/test/algorithms/graph/minimum_spanning_tree.js @@ -45,8 +45,9 @@ describe('Minimum Spanning Tree', () => { } let numberOfEdges = 0; graph.vertices.forEach(vertex => { - numberOfEdges += graph.neighbors(vertex).filter( - neighbor => vertex <= neighbor).length; + numberOfEdges += graph + .neighbors(vertex) + .filter(neighbor => vertex <= neighbor).length; }); return graph.vertices.size === numberOfEdges + connectivity; }; @@ -82,7 +83,9 @@ describe('Minimum Spanning Tree', () => { const graphCost = graph => { let total = 0; graph.vertices.forEach(vertex => { - total += graph.neighbors(vertex).reduce((accum, neighbor) => accum + graph.edge(vertex, neighbor), 0); + total += graph + .neighbors(vertex) + .reduce((accum, neighbor) => accum + graph.edge(vertex, neighbor), 0); }); return graph.directed ? total : total / 2; }; @@ -96,11 +99,18 @@ describe('Minimum Spanning Tree', () => { * @param {number} [connectivity=1] * @return {boolean} */ - const isMinimumSpanningForest = (suspect, graph, minimumCost, connectivity) => { + const isMinimumSpanningForest = ( + suspect, + graph, + minimumCost, + connectivity + ) => { assert(!graph.directed); - return isForest(suspect, connectivity || 1) && + return ( + isForest(suspect, connectivity || 1) && spans(suspect, graph) && - graphCost(suspect) === minimumCost; + graphCost(suspect) === minimumCost + ); }; const testMstAlgorithm = mst => { @@ -142,31 +152,30 @@ describe('Minimum Spanning Tree', () => { assert(isMinimumSpanningForest(mst(graph), graph, -100)); }); - it('should find a minimum spaning forest if the graph is not connected', - () => { - const graph = new Graph(false); - graph.addVertex(1); - graph.addVertex(2); - graph.addVertex(3); - assert(isMinimumSpanningForest(mst(graph), graph, 0, 3)); + it('should find a minimum spaning forest if the graph is not connected', () => { + const graph = new Graph(false); + graph.addVertex(1); + graph.addVertex(2); + graph.addVertex(3); + assert(isMinimumSpanningForest(mst(graph), graph, 0, 3)); - graph.addEdge(1, 2, 2); - assert(isMinimumSpanningForest(mst(graph), graph, 2, 2)); + graph.addEdge(1, 2, 2); + assert(isMinimumSpanningForest(mst(graph), graph, 2, 2)); - graph.addEdge(1, 3, 1); - graph.addEdge(2, 3, -1); - assert(isMinimumSpanningForest(mst(graph), graph, 0, 1)); + graph.addEdge(1, 3, 1); + graph.addEdge(2, 3, -1); + assert(isMinimumSpanningForest(mst(graph), graph, 0, 1)); - graph.addVertex(4); - assert(isMinimumSpanningForest(mst(graph), graph, 0, 2)); + graph.addVertex(4); + assert(isMinimumSpanningForest(mst(graph), graph, 0, 2)); - graph.addEdge(5, 6, 1); - assert(isMinimumSpanningForest(mst(graph), graph, 1, 3)); + graph.addEdge(5, 6, 1); + assert(isMinimumSpanningForest(mst(graph), graph, 1, 3)); - graph.addEdge(5, 4, -100); - graph.addEdge(6, 4, -100); - assert(isMinimumSpanningForest(mst(graph), graph, -200, 2)); - }); + graph.addEdge(5, 4, -100); + graph.addEdge(6, 4, -100); + assert(isMinimumSpanningForest(mst(graph), graph, -200, 2)); + }); it('should throw an error if the graph is directed', () => { const directedGraph = new Graph(true); diff --git a/src/test/algorithms/graph/topological_sort.js b/src/test/algorithms/graph/topological_sort.js index b910534..8a002e4 100644 --- a/src/test/algorithms/graph/topological_sort.js +++ b/src/test/algorithms/graph/topological_sort.js @@ -4,41 +4,53 @@ const Graph = root.DataStructures.Graph; const assert = require('assert'); describe('Topological Sort', () => { - it('should return a stack with the vertices ordered' + - ' considering the dependencies', () => { - const graph = new Graph(); - graph.addVertex('shoes'); - graph.addVertex('watch'); - graph.addVertex('underwear'); - graph.addVertex('socks'); - graph.addVertex('shirt'); - graph.addVertex('pants'); - graph.addVertex('belt'); - graph.addVertex('tie'); - graph.addVertex('jacket'); - - graph.addEdge('shirt', 'belt'); - graph.addEdge('shirt', 'tie'); - graph.addEdge('shirt', 'jacket'); - - graph.addEdge('socks', 'shoes'); - - graph.addEdge('underwear', 'pants'); - graph.addEdge('underwear', 'shoes'); - - graph.addEdge('pants', 'shoes'); - graph.addEdge('pants', 'belt'); - - graph.addEdge('belt', 'jacket'); - - graph.addEdge('tie', 'jacket'); - - const stack = topologicalSort(graph); - const a = []; - while (!stack.isEmpty()) a.push(stack.pop()); - assert.deepEqual(a, [ - 'shirt', 'socks', 'underwear', 'pants', 'shoes', - 'tie', 'watch', 'belt', 'jacket' - ]); - }); + it( + 'should return a stack with the vertices ordered' + + ' considering the dependencies', + () => { + const graph = new Graph(); + graph.addVertex('shoes'); + graph.addVertex('watch'); + graph.addVertex('underwear'); + graph.addVertex('socks'); + graph.addVertex('shirt'); + graph.addVertex('pants'); + graph.addVertex('belt'); + graph.addVertex('tie'); + graph.addVertex('jacket'); + + graph.addEdge('shirt', 'belt'); + graph.addEdge('shirt', 'tie'); + graph.addEdge('shirt', 'jacket'); + + graph.addEdge('socks', 'shoes'); + + graph.addEdge('underwear', 'pants'); + graph.addEdge('underwear', 'shoes'); + + graph.addEdge('pants', 'shoes'); + graph.addEdge('pants', 'belt'); + + graph.addEdge('belt', 'jacket'); + + graph.addEdge('tie', 'jacket'); + + const stack = topologicalSort(graph); + const a = []; + while (!stack.isEmpty()) { + a.push(stack.pop()); + } + assert.deepEqual(a, [ + 'shirt', + 'socks', + 'underwear', + 'pants', + 'shoes', + 'tie', + 'watch', + 'belt', + 'jacket' + ]); + } + ); }); diff --git a/src/test/algorithms/math/collatz_conjecture.js b/src/test/algorithms/math/collatz_conjecture.js index 0822c27..927c2fa 100644 --- a/src/test/algorithms/math/collatz_conjecture.js +++ b/src/test/algorithms/math/collatz_conjecture.js @@ -19,4 +19,3 @@ describe('Collatz Conjecture', () => { assert.deepEqual(collatzConjecture.generate(10), [5, 16, 8, 4, 2, 1]); }); }); - diff --git a/src/test/algorithms/math/fast_power.js b/src/test/algorithms/math/fast_power.js index c45a93d..b8e191e 100644 --- a/src/test/algorithms/math/fast_power.js +++ b/src/test/algorithms/math/fast_power.js @@ -7,7 +7,7 @@ const assertApproximatelyEqual = (a, b, eps) => { assert(Math.abs(a - b) < eps); }; -const multiplyModulo = modulo => (a, b) => (a * b) % modulo; +const multiplyModulo = modulo => (a, b) => a * b % modulo; /** * This operation is isomorphic to addition in Z/3. @@ -41,14 +41,13 @@ describe('Fast Power', () => { assert.equal(power(1, 10000), 1); }); - it('should raise an error if the power is not a nonnegative integer', - () => { - // It is not clear how to handle these cases - // when custom multiplication is also supplied. - assert.throws(power.bind(null, 7, -2)); - assert.throws(power.bind(null, 5, -1)); - assert.throws(power.bind(null, Math.PI, Math.E)); - }); + it('should raise an error if the power is not a nonnegative integer', () => { + // It is not clear how to handle these cases + // when custom multiplication is also supplied. + assert.throws(power.bind(null, 7, -2)); + assert.throws(power.bind(null, 5, -1)); + assert.throws(power.bind(null, Math.PI, Math.E)); + }); it('should accept custom multiplication functions', () => { // Math.pow is basically useless here. @@ -66,9 +65,12 @@ describe('Fast Power', () => { assert.equal(power('c', 0xcccc, abcMultiply), 'a'); }); - it('should raise an error if the power is zero but no identity value given' + - ' (custom multiplication)', () => { - assert.throws(power.bind(null, 0, 0, multiplyModulo(5))); - assert.throws(power.bind(null, 'a', 0, abcMultiply)); - }); + it( + 'should raise an error if the power is zero but no identity value given' + + ' (custom multiplication)', + () => { + assert.throws(power.bind(null, 0, 0, multiplyModulo(5))); + assert.throws(power.bind(null, 'a', 0, abcMultiply)); + } + ); }); diff --git a/src/test/algorithms/math/fibonacci.js b/src/test/algorithms/math/fibonacci.js index e3eca19..d0266da 100644 --- a/src/test/algorithms/math/fibonacci.js +++ b/src/test/algorithms/math/fibonacci.js @@ -49,4 +49,3 @@ describe('Fibonacci', () => { }); }); }); - diff --git a/src/test/algorithms/math/find_divisors.js b/src/test/algorithms/math/find_divisors.js index 32edaaf..253cd47 100644 --- a/src/test/algorithms/math/find_divisors.js +++ b/src/test/algorithms/math/find_divisors.js @@ -2,49 +2,94 @@ const math = require('../../..').Math; const findDivisors = math.findDivisors; const assert = require('assert'); -/** - * Deep equal for arrays - */ -function testArrayEqual(a, b) { - let arrayEqual = true; - a.sort(); - b.sort(); - a.forEach((elem, index) => { - if (a[index] !== b[index]) { - arrayEqual = false; - } - }); - return arrayEqual && a.length === b.length; -} - -const testFindDivisors = findDivisors => { - assert(testArrayEqual([], findDivisors(-2))); - assert(testArrayEqual([], findDivisors(0))); - assert(testArrayEqual([1], findDivisors(1))); - assert(testArrayEqual([1, 2], findDivisors(2))); - assert(testArrayEqual([1, 3], findDivisors(3))); - assert(testArrayEqual([1, 2, 4], findDivisors(4))); - assert(testArrayEqual([1, 5], findDivisors(5))); - assert(testArrayEqual([1, 2, 4, 5, 10, 20, 25, 50, 100], findDivisors(100))); - assert(testArrayEqual([1, 2, 7, 13, 14, 26, 91, 182], findDivisors(182))); -}; - describe('Find divisors', () => { describe('#Generic()', () => { it('should return the divisors of the number', () => { - testFindDivisors(findDivisors); + assert.deepStrictEqual(findDivisors(-2), []); + assert.deepStrictEqual(findDivisors(0), []); + assert.deepStrictEqual(findDivisors(1), [1]); + assert.deepStrictEqual(findDivisors(2), [1, 2]); + assert.deepStrictEqual(findDivisors(3), [1, 3]); + assert.deepStrictEqual(findDivisors(4), [1, 2, 4]); + assert.deepStrictEqual(findDivisors(5), [1, 5]); + assert.deepStrictEqual(findDivisors(100), [ + 1, + 2, + 4, + 5, + 10, + 20, + 25, + 50, + 100 + ]); + assert.deepStrictEqual(findDivisors(182), [1, 2, 7, 13, 14, 26, 91, 182]); }); }); describe('#PairingUnsorted()', () => { it('should return the divisors of the number', () => { - testFindDivisors(findDivisors.pairingUnsorted); + assert.deepStrictEqual(findDivisors.pairingUnsorted(-2), []); + assert.deepStrictEqual(findDivisors.pairingUnsorted(0), []); + assert.deepStrictEqual(findDivisors.pairingUnsorted(1), [1]); + assert.deepStrictEqual(findDivisors.pairingUnsorted(2), [1, 2]); + assert.deepStrictEqual(findDivisors.pairingUnsorted(3), [1, 3]); + assert.deepStrictEqual(findDivisors.pairingUnsorted(4), [1, 4, 2]); + assert.deepStrictEqual(findDivisors.pairingUnsorted(5), [1, 5]); + assert.deepStrictEqual(findDivisors.pairingUnsorted(100), [ + 1, + 100, + 2, + 50, + 4, + 25, + 5, + 20, + 10 + ]); + assert.deepStrictEqual(findDivisors.pairingUnsorted(182), [ + 1, + 182, + 2, + 91, + 7, + 26, + 13, + 14 + ]); }); }); describe('#PairingSorted()', () => { it('should return the divisors of the number', () => { - testFindDivisors(findDivisors.pairingSorted); + assert.deepStrictEqual(findDivisors.pairingSorted(-2), []); + assert.deepStrictEqual(findDivisors.pairingSorted(0), []); + assert.deepStrictEqual(findDivisors.pairingSorted(1), [1]); + assert.deepStrictEqual(findDivisors.pairingSorted(2), [1, 2]); + assert.deepStrictEqual(findDivisors.pairingSorted(3), [1, 3]); + assert.deepStrictEqual(findDivisors.pairingSorted(4), [1, 2, 4]); + assert.deepStrictEqual(findDivisors.pairingSorted(5), [1, 5]); + assert.deepStrictEqual(findDivisors.pairingSorted(100), [ + 1, + 2, + 4, + 5, + 10, + 20, + 25, + 50, + 100 + ]); + assert.deepStrictEqual(findDivisors.pairingSorted(182), [ + 1, + 2, + 7, + 13, + 14, + 26, + 91, + 182 + ]); }); }); }); diff --git a/src/test/algorithms/math/fisher_yates.js b/src/test/algorithms/math/fisher_yates.js index f8eb359..4af6476 100644 --- a/src/test/algorithms/math/fisher_yates.js +++ b/src/test/algorithms/math/fisher_yates.js @@ -21,4 +21,3 @@ describe('Fisher-Yates', () => { assert.notDeepEqual(a, [1, 2, 3, 4, 5]); }); }); - diff --git a/src/test/algorithms/math/gcd.js b/src/test/algorithms/math/gcd.js index 4ad5e82..8a05583 100644 --- a/src/test/algorithms/math/gcd.js +++ b/src/test/algorithms/math/gcd.js @@ -16,21 +16,23 @@ describe('GCD', () => { assert.equal(gcd(35, 49), 7); }); - it('should calculate the correct GCD between two numbers using ' + - 'the binary method', () => { - const gcdb = gcd.binary; - assert.equal(gcdb(1, 0), 1); - assert.equal(gcdb(0, 1), 1); - assert.equal(gcdb(0, 0), 0); - assert.equal(gcdb(2, 2), 2); - assert.equal(gcdb(2, 4), 2); - assert.equal(gcdb(4, 2), 2); - assert.equal(gcdb(5, 2), 1); - assert.equal(gcdb(10, 100), 10); - assert.equal(gcdb(10000000, 2), 2); - assert.equal(gcdb(7, 49), 7); - assert.equal(gcdb(7, 5), 1); - assert.equal(gcdb(35, 49), 7); - }); + it( + 'should calculate the correct GCD between two numbers using ' + + 'the binary method', + () => { + const gcdb = gcd.binary; + assert.equal(gcdb(1, 0), 1); + assert.equal(gcdb(0, 1), 1); + assert.equal(gcdb(0, 0), 0); + assert.equal(gcdb(2, 2), 2); + assert.equal(gcdb(2, 4), 2); + assert.equal(gcdb(4, 2), 2); + assert.equal(gcdb(5, 2), 1); + assert.equal(gcdb(10, 100), 10); + assert.equal(gcdb(10000000, 2), 2); + assert.equal(gcdb(7, 49), 7); + assert.equal(gcdb(7, 5), 1); + assert.equal(gcdb(35, 49), 7); + } + ); }); - diff --git a/src/test/algorithms/math/lcm.js b/src/test/algorithms/math/lcm.js index 2747820..b4106da 100644 --- a/src/test/algorithms/math/lcm.js +++ b/src/test/algorithms/math/lcm.js @@ -3,40 +3,46 @@ const lcm = root.Math.lcm; const assert = require('assert'); describe('LCM', () => { - it('should calculate the correct LCM between two numbers ' + - 'using Euclidean algorithm', () => { - assert.equal(lcm(2, 3), 6); - assert.equal(lcm(0, 1), 0); - assert.equal(lcm(4, 9), 36); - assert.equal(lcm(39, 81), 1053); - assert.equal(lcm(10000000, 2), 10000000); - assert.equal(lcm(35, 49), 245); - assert.equal(lcm(7, 49), 49); - assert.equal(lcm(7, 5), 35); - assert.equal(lcm(0, 0), 0); - assert.equal(lcm(0, 9), 0); - assert.equal(lcm(0, -9), 0); - assert.equal(lcm(-9, -18), 18); - assert.equal(lcm(-7, 9), 63); - assert.equal(lcm(-7, -9), 63); - }); + it( + 'should calculate the correct LCM between two numbers ' + + 'using Euclidean algorithm', + () => { + assert.equal(lcm(2, 3), 6); + assert.equal(lcm(0, 1), 0); + assert.equal(lcm(4, 9), 36); + assert.equal(lcm(39, 81), 1053); + assert.equal(lcm(10000000, 2), 10000000); + assert.equal(lcm(35, 49), 245); + assert.equal(lcm(7, 49), 49); + assert.equal(lcm(7, 5), 35); + assert.equal(lcm(0, 0), 0); + assert.equal(lcm(0, 9), 0); + assert.equal(lcm(0, -9), 0); + assert.equal(lcm(-9, -18), 18); + assert.equal(lcm(-7, 9), 63); + assert.equal(lcm(-7, -9), 63); + } + ); - it('should calculate the correct LCM between two numbers ' + - 'using the binary method', () => { - const lcmb = lcm.binary; - assert.equal(lcmb(2, 3), 6); - assert.equal(lcmb(0, 1), 0); - assert.equal(lcmb(4, 9), 36); - assert.equal(lcmb(39, 81), 1053); - assert.equal(lcmb(10000000, 2), 10000000); - assert.equal(lcmb(35, 49), 245); - assert.equal(lcmb(7, 49), 49); - assert.equal(lcmb(7, 5), 35); - assert.equal(lcmb(0, 0), 0); - assert.equal(lcmb(0, 9), 0); - assert.equal(lcmb(0, -9), 0); - assert.equal(lcmb(-9, -18), 18); - assert.equal(lcmb(-7, 9), 63); - assert.equal(lcmb(-7, -9), 63); - }); + it( + 'should calculate the correct LCM between two numbers ' + + 'using the binary method', + () => { + const lcmb = lcm.binary; + assert.equal(lcmb(2, 3), 6); + assert.equal(lcmb(0, 1), 0); + assert.equal(lcmb(4, 9), 36); + assert.equal(lcmb(39, 81), 1053); + assert.equal(lcmb(10000000, 2), 10000000); + assert.equal(lcmb(35, 49), 245); + assert.equal(lcmb(7, 49), 49); + assert.equal(lcmb(7, 5), 35); + assert.equal(lcmb(0, 0), 0); + assert.equal(lcmb(0, 9), 0); + assert.equal(lcmb(0, -9), 0); + assert.equal(lcmb(-9, -18), 18); + assert.equal(lcmb(-7, 9), 63); + assert.equal(lcmb(-7, -9), 63); + } + ); }); diff --git a/src/test/algorithms/math/newton_sqrt.js b/src/test/algorithms/math/newton_sqrt.js index dc3020a..386d3d9 100644 --- a/src/test/algorithms/math/newton_sqrt.js +++ b/src/test/algorithms/math/newton_sqrt.js @@ -17,15 +17,21 @@ describe('Newton square root', () => { assert.strictEqual(newtonSqrt(100), 10); }); - it('should calculate an approximated root for every number', - () => { - for (let i = 0; i < 1000; i++) { - const newton = newtonSqrt(i); - const nativeJS = Math.sqrt(i); - const difference = Math.abs(newton - nativeJS); - assert(difference < 1e-6, - 'Square root of ' + i + ' should be ' + nativeJS + - ' but got ' + newton + ' instead'); - } - }); + it('should calculate an approximated root for every number', () => { + for (let i = 0; i < 1000; i++) { + const newton = newtonSqrt(i); + const nativeJS = Math.sqrt(i); + const difference = Math.abs(newton - nativeJS); + assert( + difference < 1e-6, + 'Square root of ' + + i + + ' should be ' + + nativeJS + + ' but got ' + + newton + + ' instead' + ); + } + }); }); diff --git a/src/test/algorithms/math/next_permutation.js b/src/test/algorithms/math/next_permutation.js index 99b7bd1..cde7f59 100644 --- a/src/test/algorithms/math/next_permutation.js +++ b/src/test/algorithms/math/next_permutation.js @@ -11,10 +11,14 @@ const range = (begin, end) => { if (end <= begin) { return []; } - return new Array(end - begin + 1).join(0).split('').map((_, index) => begin + index); + return new Array(end - begin + 1) + .join(0) + .split('') + .map((_, index) => begin + index); }; -const factorial = n => range(1, n + 1).reduce((product, value) => product * value, 1); +const factorial = n => + range(1, n + 1).reduce((product, value) => product * value, 1); const permutations = (start, compareFn) => { const permutations = []; @@ -28,32 +32,38 @@ const permutations = (start, compareFn) => { describe('Next Permutation', () => { it('should return immediately following permutation', () => { assert.deepEqual(permutations([1, 2]), [[1, 2], [2, 1]]); - assert.deepEqual(permutations([1, 2, 2]), - [[1, 2, 2], [2, 1, 2], [2, 2, 1]]); + assert.deepEqual(permutations([1, 2, 2]), [ + [1, 2, 2], + [2, 1, 2], + [2, 2, 1] + ]); assert.deepEqual(permutations([1]), [[1]]); assert.deepEqual(permutations([]), [[]]); }); - it('should generate all N! permutations if the elements are distinct', - () => { - [4, 5, 6].forEach(size => { - let count = 0; - const perm = range(size); - do { - count += 1; - } while (nextPermutation(perm)); - assert.equal(count, factorial(size)); - }); - }); + it('should generate all N! permutations if the elements are distinct', () => { + [4, 5, 6].forEach(size => { + let count = 0; + const perm = range(size); + do { + count += 1; + } while (nextPermutation(perm)); + assert.equal(count, factorial(size)); + }); + }); it('should support custom compare functions', () => { const reverseComparator = new Comparator(); reverseComparator.reverse(); const reverseCompareFn = reverseComparator.compare; - assert.deepEqual(permutations([1, 2, 3]).reverse(), - permutations([3, 2, 1], reverseCompareFn)); - assert.deepEqual(permutations([0, 0, 1]).reverse(), - permutations([1, 0, 0], reverseCompareFn)); + assert.deepEqual( + permutations([1, 2, 3]).reverse(), + permutations([3, 2, 1], reverseCompareFn) + ); + assert.deepEqual( + permutations([0, 0, 1]).reverse(), + permutations([1, 0, 0], reverseCompareFn) + ); }); }); diff --git a/src/test/algorithms/math/primality_tests.js b/src/test/algorithms/math/primality_tests.js index 211dcf6..cc556d4 100644 --- a/src/test/algorithms/math/primality_tests.js +++ b/src/test/algorithms/math/primality_tests.js @@ -27,4 +27,3 @@ describe('Primality Tests', () => { }); }); }); - diff --git a/src/test/algorithms/searching/binarysearch.js b/src/test/algorithms/searching/binarysearch.js index ae8fef0..9a51534 100644 --- a/src/test/algorithms/searching/binarysearch.js +++ b/src/test/algorithms/searching/binarysearch.js @@ -13,4 +13,3 @@ describe('Binary Search', () => { assert.equal(binarySearch([1, 2, 3, 4, 5], 100), -1); }); }); - diff --git a/src/test/algorithms/searching/dfs.js b/src/test/algorithms/searching/dfs.js index ccb4a64..bbd932e 100644 --- a/src/test/algorithms/searching/dfs.js +++ b/src/test/algorithms/searching/dfs.js @@ -23,17 +23,15 @@ describe('Depth First Search', () => { assert.deepEqual(a, [0, 1, 2, 3, 4, 5, 8, 10, 100]); }); - it('should return parents before children when retrieving pre-order', - () => { - const a = []; - dfs.preOrder(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [4, 2, 1, 0, 3, 8, 5, 10, 100]); - }); + it('should return parents before children when retrieving pre-order', () => { + const a = []; + dfs.preOrder(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [4, 2, 1, 0, 3, 8, 5, 10, 100]); + }); - it('should return children before parents when retrieving post-order', - () => { - const a = []; - dfs.postOrder(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [0, 1, 3, 2, 5, 100, 10, 8, 4]); - }); + it('should return children before parents when retrieving post-order', () => { + const a = []; + dfs.postOrder(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [0, 1, 3, 2, 5, 100, 10, 8, 4]); + }); }); diff --git a/src/test/algorithms/sorting/shell_sort.js b/src/test/algorithms/sorting/shell_sort.js index 007b34b..fc68cad 100644 --- a/src/test/algorithms/sorting/shell_sort.js +++ b/src/test/algorithms/sorting/shell_sort.js @@ -10,4 +10,3 @@ describe('ShellSort', () => { sortingTestsHelper.testSortWithComparisonFn(shellSort); }); }); - diff --git a/src/test/algorithms/sorting/sorting_tests_helper.js b/src/test/algorithms/sorting/sorting_tests_helper.js index 7cf297b..ef17b18 100644 --- a/src/test/algorithms/sorting/sorting_tests_helper.js +++ b/src/test/algorithms/sorting/sorting_tests_helper.js @@ -8,8 +8,18 @@ module.exports = { assert.deepEqual(sortFn([3, 1, 2]), [1, 2, 3]); assert.deepEqual(sortFn([1, 2, 3, 4, 5, 6]), [1, 2, 3, 4, 5, 6]); assert.deepEqual(sortFn([6, 5, 4, 3, 2, 1]), [1, 2, 3, 4, 5, 6]); - assert.deepEqual(sortFn([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), - [0, 1, 3, 5, 6, 8, 10, 10, 20, 295]); + assert.deepEqual(sortFn([1, 295, 3, 6, 8, 10, 10, 20, 0, 5]), [ + 0, + 1, + 3, + 5, + 6, + 8, + 10, + 10, + 20, + 295 + ]); assert.deepEqual(sortFn(['a', 'b', 'abc']), ['a', 'abc', 'b']); }, @@ -20,20 +30,34 @@ module.exports = { }; assert.deepEqual(sortFn([], compare), []); assert.deepEqual(sortFn(['apple'], compare), ['apple']); - assert.deepEqual(sortFn(['apple', 'banana'], compare), - ['apple', 'banana']); - assert.deepEqual(sortFn(['apple', 'banana', 'car'], compare), - ['car', 'apple', 'banana']); - assert.deepEqual(sortFn(['apple', 'banana', 'car', 'z'], compare), - ['z', 'car', 'apple', 'banana']); + assert.deepEqual(sortFn(['apple', 'banana'], compare), ['apple', 'banana']); + assert.deepEqual(sortFn(['apple', 'banana', 'car'], compare), [ + 'car', + 'apple', + 'banana' + ]); + assert.deepEqual(sortFn(['apple', 'banana', 'car', 'z'], compare), [ + 'z', + 'car', + 'apple', + 'banana' + ]); const reverseSort = (a, b) => { if (a === b) return 0; return a < b ? 1 : -1; }; - assert.deepEqual(sortFn([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], - reverseSort), - [295, 20, 10, 10, 8, 6, 5, 3, 1, 0]); + assert.deepEqual(sortFn([1, 295, 3, 6, 8, 10, 10, 20, 0, 5], reverseSort), [ + 295, + 20, + 10, + 10, + 8, + 6, + 5, + 3, + 1, + 0 + ]); } }; - diff --git a/src/test/algorithms/string/huffman.js b/src/test/algorithms/string/huffman.js index be11401..3bbd647 100644 --- a/src/test/algorithms/string/huffman.js +++ b/src/test/algorithms/string/huffman.js @@ -2,11 +2,17 @@ const huffman = require('../../..').String.huffman; const assert = require('assert'); describe('Huffman', () => { - const messages = ['', 'a', 'b', 'hello', 'test', 'aaaabbbccddef', - 'The seething sea ceaseth and thus' + - ' the seething sea sufficeth us.', - 'Shep Schwab shopped at Scott\'s Schnapps shop;' + - '\nOne shot of Scott\'s Schnapps stopped Schwab\'s watch.']; + const messages = [ + '', + 'a', + 'b', + 'hello', + 'test', + 'aaaabbbccddef', + 'The seething sea ceaseth and thus' + ' the seething sea sufficeth us.', + 'Shep Schwab shopped at Scott\'s Schnapps shop;' + + '\nOne shot of Scott\'s Schnapps stopped Schwab\'s watch.' + ]; for (let randomTestIndex = 0; randomTestIndex < 15; ++randomTestIndex) { const length = Math.floor(Math.random() * 100 + 1); const characters = []; @@ -23,16 +29,16 @@ describe('Huffman', () => { const decoded = huffman.decode(encoded.encoding, encoded.value); assert.equal(message, decoded); const encodedCompressed = huffman.encode(message, true); - const decodedCompressed = huffman.decode(encodedCompressed.encoding, - encodedCompressed.value); + const decodedCompressed = huffman.decode( + encodedCompressed.encoding, + encodedCompressed.value + ); assert.equal(message, decodedCompressed); }); }); it('should raise an error if it fails to decode', () => { - const badArgs = [[{}, '0'], - [{}, [0]], - [{a: '0', b: '10', c: '11'}, '001']]; + const badArgs = [[{}, '0'], [{}, [0]], [{a: '0', b: '10', c: '11'}, '001']]; badArgs.forEach(args => { assert.throws(() => { huffman.decode.apply(null, args); @@ -43,8 +49,10 @@ describe('Huffman', () => { it('should encode sample strings in the expected manner', () => { assert.deepEqual(huffman.encode(''), {encoding: {}, value: ''}); assert.deepEqual(huffman.encode('a'), {encoding: {a: '0'}, value: '0'}); - assert.deepEqual(huffman.encode('aaaaa'), {encoding: {a: '0'}, - value: '00000'}); + assert.deepEqual(huffman.encode('aaaaa'), { + encoding: {a: '0'}, + value: '00000' + }); let result = huffman.encode('aabc'); assert.equal(result.encoding.a.length, 1); assert.equal(result.encoding.b.length, 2); @@ -65,12 +73,16 @@ describe('Huffman', () => { Object.keys(frequencies).forEach(char => { frequencies[char] /= message.length; }); - const entropy = Object.keys(frequencies).reduce((partial, char) => { - const freq = frequencies[char]; - return partial - freq * Math.log(freq); - }, 0) / Math.log(2); + const entropy = + Object.keys(frequencies).reduce((partial, char) => { + const freq = frequencies[char]; + return partial - freq * Math.log(freq); + }, 0) / Math.log(2); const encoding = huffman.encode(message).encoding; - const cost = Object.keys(encoding).reduce((partial, char) => partial + frequencies[char] * encoding[char].length, 0); + const cost = Object.keys(encoding).reduce( + (partial, char) => partial + frequencies[char] * encoding[char].length, + 0 + ); assert(entropy <= cost); assert(cost <= entropy + 1); }); diff --git a/src/test/algorithms/string/knuth_morris_pratt.js b/src/test/algorithms/string/knuth_morris_pratt.js index 994fa15..ee18a4b 100644 --- a/src/test/algorithms/string/knuth_morris_pratt.js +++ b/src/test/algorithms/string/knuth_morris_pratt.js @@ -2,40 +2,40 @@ const knuthMorrisPratt = require('../../..').String.knuthMorrisPratt; const assert = require('assert'); describe('Knuth-Morris-Pratt', () => { - it('should verify if a pattern is contained in some text (or array)', - () => { - const text = 'A string matching algorithm wants to find the starting' + - 'index m in string S[] that matches the search word W[].The most' + - ' straightforward algorithm is to look for a character match at ' + - 'successive values of the index m, the position in the string be' + - 'ing searched, i.e. S[m]. If the index m reaches the end of the ' + - 'string then there is no match, in which case the search is said' + - 'to "fail". At each position m the algorithm first checks for eq' + - 'uality of the first character in the searched for word, i.e. S[' + - 'm] =? W[0]. If a match is found, the algorithm tests the other ' + - 'characters in the searched for word by checking successive valu' + - 'es of the word position index, i. The algorithm retrieves the c' + - 'haracter W[i] in the searched for word and checks for equality ' + - 'of the expression S[m+i] =? W[i]. If all successive characters ' + - 'match in W at position m then a match is found at that position' + - ' in the search string. (Wikipedia, 2014): https://en.wikipedia.' + - 'org/wiki/Knuth-Morris-Pratt_algorithm'; - let pattern = 'https://en.wikipedia.org/wiki/Knuth-Morris-Pratt_al' + - 'gorithm'; - - assert.equal(knuthMorrisPratt(text, pattern), 915); - - pattern = '(https://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm'; - - assert.equal(knuthMorrisPratt(text, pattern), text.length); - - const arrayText = [3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 4]; - let arrayPattern = [8, 9, 8]; - - assert.equal(knuthMorrisPratt(arrayText, arrayPattern), 5); - - arrayPattern = []; - - assert.equal(knuthMorrisPratt(arrayText, arrayPattern), arrayText.length); - }); + it('should verify if a pattern is contained in some text (or array)', () => { + const text = + 'A string matching algorithm wants to find the starting' + + 'index m in string S[] that matches the search word W[].The most' + + ' straightforward algorithm is to look for a character match at ' + + 'successive values of the index m, the position in the string be' + + 'ing searched, i.e. S[m]. If the index m reaches the end of the ' + + 'string then there is no match, in which case the search is said' + + 'to "fail". At each position m the algorithm first checks for eq' + + 'uality of the first character in the searched for word, i.e. S[' + + 'm] =? W[0]. If a match is found, the algorithm tests the other ' + + 'characters in the searched for word by checking successive valu' + + 'es of the word position index, i. The algorithm retrieves the c' + + 'haracter W[i] in the searched for word and checks for equality ' + + 'of the expression S[m+i] =? W[i]. If all successive characters ' + + 'match in W at position m then a match is found at that position' + + ' in the search string. (Wikipedia, 2014): https://en.wikipedia.' + + 'org/wiki/Knuth-Morris-Pratt_algorithm'; + let pattern = + 'https://en.wikipedia.org/wiki/Knuth-Morris-Pratt_al' + 'gorithm'; + + assert.equal(knuthMorrisPratt(text, pattern), 915); + + pattern = '(https://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm'; + + assert.equal(knuthMorrisPratt(text, pattern), text.length); + + const arrayText = [3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 4]; + let arrayPattern = [8, 9, 8]; + + assert.equal(knuthMorrisPratt(arrayText, arrayPattern), 5); + + arrayPattern = []; + + assert.equal(knuthMorrisPratt(arrayText, arrayPattern), arrayText.length); + }); }); diff --git a/src/test/algorithms/string/levenshtein.js b/src/test/algorithms/string/levenshtein.js index 3b0b0c6..5f29be9 100644 --- a/src/test/algorithms/string/levenshtein.js +++ b/src/test/algorithms/string/levenshtein.js @@ -2,18 +2,17 @@ const levenshtein = require('../../..').String.levenshtein; const assert = require('assert'); describe('Levenshtein', () => { - it('should calculate the minimal edit distance between two words', - () => { - assert.equal(levenshtein('', ''), 0); - assert.equal(levenshtein('a', ''), 1); - assert.equal(levenshtein('', 'a'), 1); - // Should just add I to the beginning - assert.equal(levenshtein('ISLANDER', 'SLANDER'), 1); - // Needs to substitute M by K, T by M and add an A to the end - assert.equal(levenshtein('MART', 'KARMA'), 3); - // Needs to substitute K by S, E by I and add G to the end - assert.equal(levenshtein('KITTEN', 'SITTING'), 3); - // Needs to substitute the first 5 chars: INTEN by EXECU - assert.equal(levenshtein('INTENTION', 'EXECUTION'), 5); - }); + it('should calculate the minimal edit distance between two words', () => { + assert.equal(levenshtein('', ''), 0); + assert.equal(levenshtein('a', ''), 1); + assert.equal(levenshtein('', 'a'), 1); + // Should just add I to the beginning + assert.equal(levenshtein('ISLANDER', 'SLANDER'), 1); + // Needs to substitute M by K, T by M and add an A to the end + assert.equal(levenshtein('MART', 'KARMA'), 3); + // Needs to substitute K by S, E by I and add G to the end + assert.equal(levenshtein('KITTEN', 'SITTING'), 3); + // Needs to substitute the first 5 chars: INTEN by EXECU + assert.equal(levenshtein('INTENTION', 'EXECUTION'), 5); + }); }); diff --git a/src/test/algorithms/string/longest_common_subsequence.js b/src/test/algorithms/string/longest_common_subsequence.js index da790a1..45aef4d 100644 --- a/src/test/algorithms/string/longest_common_subsequence.js +++ b/src/test/algorithms/string/longest_common_subsequence.js @@ -4,8 +4,7 @@ const longestCommonSubsequence = require(directory + filename); const assert = require('assert'); describe('Longest common subsequence', () => { - it('should return the longest common subsequence of ' + - 'two strings', () => { + it('should return the longest common subsequence of ' + 'two strings', () => { assert.equal('', longestCommonSubsequence('', '')); assert.equal('', longestCommonSubsequence('', 'aaa')); assert.equal('', longestCommonSubsequence('aaa', '')); diff --git a/src/test/algorithms/string/rabin_karp.js b/src/test/algorithms/string/rabin_karp.js index 77695e6..7a88ea9 100644 --- a/src/test/algorithms/string/rabin_karp.js +++ b/src/test/algorithms/string/rabin_karp.js @@ -6,17 +6,16 @@ const rabinKarpEqualsToIndexOf = (a, b) => { }; describe('Karp-Rabin', () => { - it('should verify if a string is contained in another string', - () => { - rabinKarpEqualsToIndexOf('', ''); - rabinKarpEqualsToIndexOf('a', 'b'); - rabinKarpEqualsToIndexOf('b', 'a'); + it('should verify if a string is contained in another string', () => { + rabinKarpEqualsToIndexOf('', ''); + rabinKarpEqualsToIndexOf('a', 'b'); + rabinKarpEqualsToIndexOf('b', 'a'); - rabinKarpEqualsToIndexOf('super test', 's'); - rabinKarpEqualsToIndexOf('super test', 'super'); - rabinKarpEqualsToIndexOf('super test', 'super test'); - rabinKarpEqualsToIndexOf('super test', 'test'); - rabinKarpEqualsToIndexOf('super test', ' tes'); - rabinKarpEqualsToIndexOf('super test x', 'x'); - }); + rabinKarpEqualsToIndexOf('super test', 's'); + rabinKarpEqualsToIndexOf('super test', 'super'); + rabinKarpEqualsToIndexOf('super test', 'super test'); + rabinKarpEqualsToIndexOf('super test', 'test'); + rabinKarpEqualsToIndexOf('super test', ' tes'); + rabinKarpEqualsToIndexOf('super test x', 'x'); + }); }); diff --git a/src/test/data_structures/avl-tree.js b/src/test/data_structures/avl-tree.js index fae69a1..9aaf99a 100644 --- a/src/test/data_structures/avl-tree.js +++ b/src/test/data_structures/avl-tree.js @@ -193,63 +193,99 @@ describe('AVL Tree', () => { assert.equal(avlTree.root.right.right.value, 200); }); - it('should return the parents before the children when ' + - 'traversing in preorder', () => { - const avlTree = new AVLTree(); - - avlTree.insert(50); - avlTree.insert(100); - avlTree.insert(200); - avlTree.insert(1); - avlTree.insert(2); - avlTree.insert(75); - avlTree.insert(80); - avlTree.insert(4); - avlTree.insert(5); - avlTree.insert(6); - avlTree.insert(7); - avlTree.insert(20); - avlTree.insert(40); - avlTree.insert(30); - avlTree.insert(15); - - const expectedPreOrder = [50, 5, 2, 1, 4, 20, 7, 6, - 15, 30, 40, 100, 75, 80, 200]; - const preOrder = []; - avlTree.preOrder(avlTree.root, n => { - preOrder.push(n.value); - }); - assert.deepEqual(expectedPreOrder, preOrder); - }); - - it('should return the children before the parents when ' + - 'traversing in postorder', () => { - const avlTree = new AVLTree(); - - avlTree.insert(50); - avlTree.insert(100); - avlTree.insert(200); - avlTree.insert(1); - avlTree.insert(2); - avlTree.insert(75); - avlTree.insert(80); - avlTree.insert(4); - avlTree.insert(5); - avlTree.insert(6); - avlTree.insert(7); - avlTree.insert(20); - avlTree.insert(40); - avlTree.insert(30); - avlTree.insert(15); - - const expectedPostOrder = [1, 4, 2, 6, 15, 7, 40, 30, - 20, 5, 80, 75, 200, 100, 50]; - const postOrder = []; - avlTree.postOrder(avlTree.root, n => { - postOrder.push(n.value); - }); - assert.deepEqual(expectedPostOrder, postOrder); - }); + it( + 'should return the parents before the children when ' + + 'traversing in preorder', + () => { + const avlTree = new AVLTree(); + + avlTree.insert(50); + avlTree.insert(100); + avlTree.insert(200); + avlTree.insert(1); + avlTree.insert(2); + avlTree.insert(75); + avlTree.insert(80); + avlTree.insert(4); + avlTree.insert(5); + avlTree.insert(6); + avlTree.insert(7); + avlTree.insert(20); + avlTree.insert(40); + avlTree.insert(30); + avlTree.insert(15); + + const expectedPreOrder = [ + 50, + 5, + 2, + 1, + 4, + 20, + 7, + 6, + 15, + 30, + 40, + 100, + 75, + 80, + 200 + ]; + const preOrder = []; + avlTree.preOrder(avlTree.root, n => { + preOrder.push(n.value); + }); + assert.deepEqual(expectedPreOrder, preOrder); + } + ); + + it( + 'should return the children before the parents when ' + + 'traversing in postorder', + () => { + const avlTree = new AVLTree(); + + avlTree.insert(50); + avlTree.insert(100); + avlTree.insert(200); + avlTree.insert(1); + avlTree.insert(2); + avlTree.insert(75); + avlTree.insert(80); + avlTree.insert(4); + avlTree.insert(5); + avlTree.insert(6); + avlTree.insert(7); + avlTree.insert(20); + avlTree.insert(40); + avlTree.insert(30); + avlTree.insert(15); + + const expectedPostOrder = [ + 1, + 4, + 2, + 6, + 15, + 7, + 40, + 30, + 20, + 5, + 80, + 75, + 200, + 100, + 50 + ]; + const postOrder = []; + avlTree.postOrder(avlTree.root, n => { + postOrder.push(n.value); + }); + assert.deepEqual(expectedPostOrder, postOrder); + } + ); it('should return the sorted elements when traversing in order', () => { const avlTree = new AVLTree(); diff --git a/src/test/data_structures/bst.js b/src/test/data_structures/bst.js index 6671247..264f1d6 100644 --- a/src/test/data_structures/bst.js +++ b/src/test/data_structures/bst.js @@ -62,75 +62,84 @@ describe('Binary Search Tree', () => { const callbackGenerator = a => n => a.push(n); - it('should remove a leaf without altering anything else in ' + - 'the structure of the tree', () => { - bst.remove(0); + it( + 'should remove a leaf without altering anything else in ' + + 'the structure of the tree', + () => { + bst.remove(0); /** * 4 * 2 8 * 1 3 5 10 * 2.5 100 */ - const a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 10, 2.5, 100]); - }); + const a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 10, 2.5, 100]); + } + ); - it('should remove an element with just one child and substitute ' + - 'it as the root of only subtree', () => { - bst.remove(10); + it( + 'should remove an element with just one child and substitute ' + + 'it as the root of only subtree', + () => { + bst.remove(10); /** * 4 * 2 8 * 1 3 5 100 * 2.5 */ - const a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 100, 2.5]); - }); + const a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 100, 2.5]); + } + ); - it('should substitute an element by the leftmost child in the right ' + - 'subtree and remove it as a leaf', () => { + it( + 'should substitute an element by the leftmost child in the right ' + + 'subtree and remove it as a leaf', + () => { /** * 4 * 2 8 * 1 3 5 100 * 2.5 */ - bst.remove(2); + bst.remove(2); /** * 4 * 2.5 8 * 1 3 5 100 * */ - let a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [4, 2.5, 8, 1, 3, 5, 100]); + let a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [4, 2.5, 8, 1, 3, 5, 100]); - bst.remove(4); + bst.remove(4); /** * 5 * 2.5 8 * 1 3 100 * */ - a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [5, 2.5, 8, 1, 3, 100]); + a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [5, 2.5, 8, 1, 3, 100]); - bst.remove(2.5); + bst.remove(2.5); /** * 5 * 3 8 * 1 100 * */ - a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, [5, 3, 8, 1, 100]); - }); + a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, [5, 3, 8, 1, 100]); + } + ); it('should always return the right root and size', () => { const bst = new BST(); @@ -151,13 +160,12 @@ describe('Binary Search Tree', () => { assert.equal(bst.size, 0); }); - it('should throw an error when trying to remove an unexisting node', - () => { - const bst = new BST(); - assert.throws(() => bst.remove(0), Error); - bst.insert(3); - assert.throws(() => bst.remove(0), Error); - }); + it('should throw an error when trying to remove an unexisting node', () => { + const bst = new BST(); + assert.throws(() => bst.remove(0), Error); + bst.insert(3); + assert.throws(() => bst.remove(0), Error); + }); }); describe('Binary Search Tree with custom comparator', () => { @@ -166,15 +174,14 @@ describe('Binary Search Tree with custom comparator', () => { return a.length < b.length ? -1 : 1; }; - it( - 'should insert elements respecting the BST restrictions', () => { - const bst = new BST(strLenCompare); - bst.insert('banana'); - bst.insert('apple'); - bst.insert('pineapple'); - bst.insert('watermelon'); - assert.equal(bst.size, 4); - }); + it('should insert elements respecting the BST restrictions', () => { + const bst = new BST(strLenCompare); + bst.insert('banana'); + bst.insert('apple'); + bst.insert('pineapple'); + bst.insert('watermelon'); + assert.equal(bst.size, 4); + }); it('should check if an element exists (in O(lg n))', () => { const bst = new BST(strLenCompare); @@ -214,40 +221,49 @@ describe('Binary Search Tree with custom comparator', () => { assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear', 'watermelon']); }); - it('should remove a leaf without altering anything else in ' + - 'the structure of the tree', () => { - bst.remove('watermelon'); + it( + 'should remove a leaf without altering anything else in ' + + 'the structure of the tree', + () => { + bst.remove('watermelon'); /** * 'banana' * 'apple' 'pineapple' * 'pear' */ - const a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear']); - }); + const a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear']); + } + ); - it('should remove an element with just one child and substitute ' + - 'it as the root of only subtree', () => { - bst.remove('apple'); + it( + 'should remove an element with just one child and substitute ' + + 'it as the root of only subtree', + () => { + bst.remove('apple'); /** * 'banana' * 'pear' 'pineapple' */ - const a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, ['banana', 'pear', 'pineapple']); - }); + const a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, ['banana', 'pear', 'pineapple']); + } + ); - it('should substitute an element by the leftmost child in the right ' + - 'subtree and remove it as a leaf', () => { - bst.remove('banana'); + it( + 'should substitute an element by the leftmost child in the right ' + + 'subtree and remove it as a leaf', + () => { + bst.remove('banana'); /** * 'pineapple' * 'pear' */ - const a = []; - bfs(bst.root, callbackGenerator(a)); - assert.deepEqual(a, ['pineapple', 'pear']); - }); + const a = []; + bfs(bst.root, callbackGenerator(a)); + assert.deepEqual(a, ['pineapple', 'pear']); + } + ); }); diff --git a/src/test/data_structures/disjoint_set_forest.js b/src/test/data_structures/disjoint_set_forest.js index c5f5649..9461b1c 100644 --- a/src/test/data_structures/disjoint_set_forest.js +++ b/src/test/data_structures/disjoint_set_forest.js @@ -2,18 +2,17 @@ const DisjointSetForest = require('../..').DataStructures.DisjointSetForest; const assert = require('assert'); describe('Disjoint Set Forest', () => { - it('should decide if two elements belong to the same subset or not', - () => { - const forest = new DisjointSetForest(); - assert(!forest.sameSubset(1, 2)); - forest.merge(1, 2); - assert(forest.sameSubset(1, 2)); - forest.merge(3, 4); - assert(!forest.sameSubset(2, 4)); - forest.merge(1, 3); - assert(forest.sameSubset(1, 2, 3, 4)); - assert(!forest.sameSubset(1, 5)); - }); + it('should decide if two elements belong to the same subset or not', () => { + const forest = new DisjointSetForest(); + assert(!forest.sameSubset(1, 2)); + forest.merge(1, 2); + assert(forest.sameSubset(1, 2)); + forest.merge(3, 4); + assert(!forest.sameSubset(2, 4)); + forest.merge(1, 3); + assert(forest.sameSubset(1, 2, 3, 4)); + assert(!forest.sameSubset(1, 5)); + }); it('should maintain subset sizes', () => { const forest = new DisjointSetForest(); @@ -37,9 +36,9 @@ describe('Disjoint Set Forest', () => { it('should point all elements to the same root', () => { const forest = new DisjointSetForest(); - const assertSameRoot = function(element) { + const assertSameRoot = function(element, ...rest) { const root = forest.root(element); - [].slice.call(arguments, 1).forEach(element => { + rest.forEach(element => { assert.equal(forest.root(element), root); }); }; diff --git a/src/test/data_structures/graph.js b/src/test/data_structures/graph.js index b655395..42ffbc9 100644 --- a/src/test/data_structures/graph.js +++ b/src/test/data_structures/graph.js @@ -21,14 +21,13 @@ describe('Graph - Adjacency list', () => { assert.strictEqual(g.edge('a', 'b'), 1); }); - it('should create the vertex if an edge is inserted and vertex doesnt exist', - () => { - const g = new Graph(); - g.addEdge('a', 'b'); - assert.equal(g.vertices.size, 2); - assert(g.vertices.contains('a')); - assert(g.vertices.contains('b')); - }); + it('should create the vertex if an edge is inserted and vertex doesnt exist', () => { + const g = new Graph(); + g.addEdge('a', 'b'); + assert.equal(g.vertices.size, 2); + assert(g.vertices.contains('a')); + assert(g.vertices.contains('b')); + }); it('should sum multiple edges between the same vertices', () => { const g = new Graph(); @@ -84,31 +83,30 @@ describe('Graph - Adjacency list', () => { assert.equal(g.edge('b', 'a'), 2); }); - it('should have reversed edges with same weight for a reverse directed graph', - () => { - const g = new Graph(); - g.addVertex('a'); - g.addVertex('b'); - g.addVertex('c'); - g.addVertex('d'); - g.addEdge('a', 'b', 10); - g.addEdge('a', 'c', 5); - g.addEdge('c', 'd', 2); - - const r = g.reverse(); - assert(r.directed); - assert.equal(r.edge('a', 'b'), undefined); - assert.equal(r.edge('b', 'a'), 10); - assert.equal(r.edge('a', 'c'), undefined); - assert.equal(r.edge('c', 'a'), 5); - assert.equal(r.edge('c', 'd'), undefined); - assert.equal(r.edge('d', 'c'), 2); - - assert.equal(r.edge('a', 'd'), undefined); - r.addEdge('a', 'b', 2); - assert.equal(r.edge('a', 'b'), 2); - assert.equal(r.edge('b', 'a'), 10); - }); + it('should have reversed edges with same weight for a reverse directed graph', () => { + const g = new Graph(); + g.addVertex('a'); + g.addVertex('b'); + g.addVertex('c'); + g.addVertex('d'); + g.addEdge('a', 'b', 10); + g.addEdge('a', 'c', 5); + g.addEdge('c', 'd', 2); + + const r = g.reverse(); + assert(r.directed); + assert.equal(r.edge('a', 'b'), undefined); + assert.equal(r.edge('b', 'a'), 10); + assert.equal(r.edge('a', 'c'), undefined); + assert.equal(r.edge('c', 'a'), 5); + assert.equal(r.edge('c', 'd'), undefined); + assert.equal(r.edge('d', 'c'), 2); + + assert.equal(r.edge('a', 'd'), undefined); + r.addEdge('a', 'b', 2); + assert.equal(r.edge('a', 'b'), 2); + assert.equal(r.edge('b', 'a'), 10); + }); it('should have a list of vertices', () => { const g = new Graph(); diff --git a/src/test/data_structures/hash_table.js b/src/test/data_structures/hash_table.js index 1f3d7fa..19a8b23 100644 --- a/src/test/data_structures/hash_table.js +++ b/src/test/data_structures/hash_table.js @@ -2,15 +2,19 @@ const HashTable = require('../..').DataStructures.HashTable; const assert = require('assert'); describe('Hash Table', () => { - it('should calculate hashes using the same algorithm as ' + - 'Java\'s String.hashCode', () => { - const h = new HashTable(); - assert.equal(h.hash('The quick brown fox jumps over the lazy dog'), - -609428141); - assert.equal(h.hash('Testing the hashCode function'), 1538083358); - assert.equal(h.hash(''), 0); - assert.equal(h.hash('a'), 97); - const longString = + it( + 'should calculate hashes using the same algorithm as ' + + 'Java\'s String.hashCode', + () => { + const h = new HashTable(); + assert.equal( + h.hash('The quick brown fox jumps over the lazy dog'), + -609428141 + ); + assert.equal(h.hash('Testing the hashCode function'), 1538083358); + assert.equal(h.hash(''), 0); + assert.equal(h.hash('a'), 97); + const longString = 'k"hg3q#+~/l2Eljan;DB x.P%-:iA' + '/b/hG($8-SZcZX871&;fDEWthw.b5agzov],X00--O:mcQ$JFi-4uIo"D:(r(yvs' + @@ -27,18 +31,18 @@ describe('Hash Table', () => { 'fE$O[YV8X3PV6TR(*Ed4|y[8tG~K=[MxgLI%yx]16Kg3YSHE{2^1TOAnf`EsKWm,' + 'WGD)s;Zs<8K6(K_kVko"mV82Pcl)0Rx}jfq3VBm:MOX/gLfSPvLx~%(3jHh5gG2e' + 'JaQ|nW}ekR_W5Ldv`@j^hd%Wiw6moGekrS>k7gRR|dd?7Pi:`0; r_wq=-F-e(iY'; - assert.equal(h.hash(longString), -998071508); - }); + assert.equal(h.hash(longString), -998071508); + } + ); - it('should initialize the table with the given capacity', - () => { - let h = new HashTable(); - assert.equal(h.capacity, 64); // default initial capacity; - assert.equal(h.size, 0); + it('should initialize the table with the given capacity', () => { + let h = new HashTable(); + assert.equal(h.capacity, 64); // default initial capacity; + assert.equal(h.size, 0); - h = new HashTable(2); - assert.equal(h.capacity, 2); - }); + h = new HashTable(2); + assert.equal(h.capacity, 2); + }); it('should allow putting and getting elements from the table', () => { const h = new HashTable(16); @@ -139,4 +143,3 @@ describe('Hash Table', () => { assert.equal(totalValues, 60); }); }); - diff --git a/src/test/data_structures/heap.js b/src/test/data_structures/heap.js index c5e099f..d863a3c 100644 --- a/src/test/data_structures/heap.js +++ b/src/test/data_structures/heap.js @@ -52,21 +52,24 @@ describe('Min Heap', () => { assert(h.isEmpty()); }); - it('should perform a function to all elements from smallest to largest' + - ' with forEach', () => { - const h = new heap.MinHeap(); - h.heapify([3, 10, 1000, 0, 2, 1]); - - const output = []; - h.forEach(n => { - output.push(n); - }); - - assert.deepEqual(output, [0, 1, 2, 3, 10, 1000]); - - // Make sure nothing was really removed - assert.equal(h.n, 6); - }); + it( + 'should perform a function to all elements from smallest to largest' + + ' with forEach', + () => { + const h = new heap.MinHeap(); + h.heapify([3, 10, 1000, 0, 2, 1]); + + const output = []; + h.forEach(n => { + output.push(n); + }); + + assert.deepEqual(output, [0, 1, 2, 3, 10, 1000]); + + // Make sure nothing was really removed + assert.equal(h.n, 6); + } + ); }); describe('Max Heap', () => { @@ -120,16 +123,19 @@ describe('Max Heap', () => { assert(h.isEmpty()); }); - it('should perform a function to all elements from largest to smallest' + - ' with forEach', () => { - const h = new heap.MaxHeap(); - h.heapify([3, 10, 1000, 0, 2, 1]); - - const output = []; - h.forEach(n => { - output.push(n); - }); - - assert.deepEqual(output, [1000, 10, 3, 2, 1, 0]); - }); + it( + 'should perform a function to all elements from largest to smallest' + + ' with forEach', + () => { + const h = new heap.MaxHeap(); + h.heapify([3, 10, 1000, 0, 2, 1]); + + const output = []; + h.forEach(n => { + output.push(n); + }); + + assert.deepEqual(output, [1000, 10, 3, 2, 1, 0]); + } + ); }); diff --git a/src/test/data_structures/linked_list.js b/src/test/data_structures/linked_list.js index ac0d09f..f081204 100644 --- a/src/test/data_structures/linked_list.js +++ b/src/test/data_structures/linked_list.js @@ -18,70 +18,68 @@ describe('LinkedList', () => { assert.equal(l.length, 2); }); - it('should return the items from the positions they were inserted', - () => { - const l = new LinkedList(); - l.add(1); - l.add(2); - l.add(3); - l.add(4); - l.add(5); - l.add(6); - l.add(7); - l.add(8); - l.add(9); - l.add(10); - l.add(11); - assert.equal(l.get(0), 1); - assert.equal(l.get(1), 2); - assert.equal(l.get(2), 3); - assert.equal(l.get(3), 4); - assert.equal(l.get(4), 5); - assert.equal(l.get(5), 6); - assert.equal(l.get(6), 7); - assert.equal(l.get(7), 8); - assert.equal(l.get(8), 9); - assert.equal(l.get(9), 10); - assert.equal(l.get(10), 11); - - // Add 12 to the position 7 - l.add(12, 7); - assert.equal(l.get(7), 12); - assert.equal(l.length, 12); - - // Asserts that other elements were shifted - assert.equal(l.get(8), 8); - assert.equal(l.get(9), 9); - assert.equal(l.get(10), 10); - assert.equal(l.get(11), 11); - - l.add(13, 12); - assert.equal(l.get(12), 13); - }); + it('should return the items from the positions they were inserted', () => { + const l = new LinkedList(); + l.add(1); + l.add(2); + l.add(3); + l.add(4); + l.add(5); + l.add(6); + l.add(7); + l.add(8); + l.add(9); + l.add(10); + l.add(11); + assert.equal(l.get(0), 1); + assert.equal(l.get(1), 2); + assert.equal(l.get(2), 3); + assert.equal(l.get(3), 4); + assert.equal(l.get(4), 5); + assert.equal(l.get(5), 6); + assert.equal(l.get(6), 7); + assert.equal(l.get(7), 8); + assert.equal(l.get(8), 9); + assert.equal(l.get(9), 10); + assert.equal(l.get(10), 11); + + // Add 12 to the position 7 + l.add(12, 7); + assert.equal(l.get(7), 12); + assert.equal(l.length, 12); + + // Asserts that other elements were shifted + assert.equal(l.get(8), 8); + assert.equal(l.get(9), 9); + assert.equal(l.get(10), 10); + assert.equal(l.get(11), 11); + + l.add(13, 12); + assert.equal(l.get(12), 13); + }); + + it('should throw errors when trying to access indexes out of bounds', () => { + const l = new LinkedList(); + assert.throws(() => l.get(0), Error); + assert.throws(() => l.get(1), Error); + assert.throws(() => l.get(10), Error); + assert.throws(() => l.add(10, 1), Error); + assert.throws(() => l.add(10, 10), Error); - it('should throw errors when trying to access indexes out of bounds', - () => { - const l = new LinkedList(); - assert.throws(() => l.get(0), Error); - assert.throws(() => l.get(1), Error); - assert.throws(() => l.get(10), Error); - assert.throws(() => l.add(10, 1), Error); - assert.throws(() => l.add(10, 10), Error); - - l.add(1); - l.add(2); - // length = 2 - assert.doesNotThrow(() => l.get(0)); - assert.doesNotThrow(() => l.get(1)); - assert.doesNotThrow(() => l.add(3, 2)); // length = 3 - assert.doesNotThrow(() => l.add(3, 0)); // length =4 - assert.doesNotThrow(() => l.add(4, 1)); // length = 5 - assert.doesNotThrow(() => l.add(5, 5)); // length = 6 - - assert.throws(() => l.add(10, 10), Error); - assert.throws(() => l.add(10, 7), Error); - assert.throws(() => l.get(10), Error); - }); + l.add(1); + l.add(2); + // length = 2 + assert.doesNotThrow(() => l.get(0)); + assert.doesNotThrow(() => l.get(1)); + assert.doesNotThrow(() => l.add(3, 2)); // length = 3 + assert.doesNotThrow(() => l.add(3, 0)); // length =4 + assert.doesNotThrow(() => l.add(4, 1)); // length = 5 + assert.doesNotThrow(() => l.add(5, 5)); // length = 6 + + assert.throws(() => l.add(10, 10), Error); + assert.throws(() => l.add(10, 7), Error); + assert.throws(() => l.get(10), Error); + }); it('should be able to delete elements', () => { const l = new LinkedList(); @@ -146,9 +144,8 @@ describe('LinkedList', () => { assert.deepEqual(a, [5, 1, 3, 10, 1000]); }); - it('should throw an error when trying to delete from an empty list', - () => { - const l = new LinkedList(); - assert.throws(() => l.del(0), Error); - }); + it('should throw an error when trying to delete from an empty list', () => { + const l = new LinkedList(); + assert.throws(() => l.del(0), Error); + }); }); diff --git a/src/test/data_structures/priority_queue.js b/src/test/data_structures/priority_queue.js index 5db517d..efb26af 100644 --- a/src/test/data_structures/priority_queue.js +++ b/src/test/data_structures/priority_queue.js @@ -33,25 +33,7 @@ describe('Min Priority Queue', () => { assert(q.isEmpty()); }); - it('can receive a dictionary with item => priority in construction', - () => { - const q = new PriorityQueue({ - a: 10, - b: 2091, - c: 4, - d: 1, - e: 5 - }); - - assert(!q.isEmpty()); - assert.equal(q.extract(), 'd'); - assert.equal(q.extract(), 'c'); - assert.equal(q.extract(), 'e'); - assert.equal(q.extract(), 'a'); - assert.equal(q.extract(), 'b'); - }); - - it('should be possible to change the priority of an item', () => { + it('can receive a dictionary with item => priority in construction', () => { const q = new PriorityQueue({ a: 10, b: 2091, @@ -61,23 +43,14 @@ describe('Min Priority Queue', () => { }); assert(!q.isEmpty()); - - q.changePriority('b', 0); - q.changePriority('a', 1); - q.changePriority('c', 50); - q.changePriority('d', 1000); - q.changePriority('e', 2); - - assert.equal(q.extract(), 'b'); - assert.equal(q.extract(), 'a'); - assert.equal(q.extract(), 'e'); - assert.equal(q.extract(), 'c'); assert.equal(q.extract(), 'd'); - assert(q.isEmpty()); + assert.equal(q.extract(), 'c'); + assert.equal(q.extract(), 'e'); + assert.equal(q.extract(), 'a'); + assert.equal(q.extract(), 'b'); }); - it('should just update the priority when trying to insert an element that ' + - ' already exists', () => { + it('should be possible to change the priority of an item', () => { const q = new PriorityQueue({ a: 10, b: 2091, @@ -88,11 +61,11 @@ describe('Min Priority Queue', () => { assert(!q.isEmpty()); - q.insert('b', 0); - q.insert('a', 1); - q.insert('c', 50); - q.insert('d', 1000); - q.insert('e', 2); + q.changePriority('b', 0); + q.changePriority('a', 1); + q.changePriority('c', 50); + q.changePriority('d', 1000); + q.changePriority('e', 2); assert.equal(q.extract(), 'b'); assert.equal(q.extract(), 'a'); @@ -101,5 +74,33 @@ describe('Min Priority Queue', () => { assert.equal(q.extract(), 'd'); assert(q.isEmpty()); }); -}); + it( + 'should just update the priority when trying to insert an element that ' + + ' already exists', + () => { + const q = new PriorityQueue({ + a: 10, + b: 2091, + c: 4, + d: 1, + e: 5 + }); + + assert(!q.isEmpty()); + + q.insert('b', 0); + q.insert('a', 1); + q.insert('c', 50); + q.insert('d', 1000); + q.insert('e', 2); + + assert.equal(q.extract(), 'b'); + assert.equal(q.extract(), 'a'); + assert.equal(q.extract(), 'e'); + assert.equal(q.extract(), 'c'); + assert.equal(q.extract(), 'd'); + assert(q.isEmpty()); + } + ); +}); diff --git a/src/test/data_structures/queue.js b/src/test/data_structures/queue.js index 1b8523d..ae69861 100644 --- a/src/test/data_structures/queue.js +++ b/src/test/data_structures/queue.js @@ -21,16 +21,19 @@ describe('Queue', () => { assert.throws(() => q.pop(), Error); }); - it('should allow me to peek at the first element in' + - ' line without popping it', () => { - const q = new Queue(); - assert.throws(() => q.peek(), Error); // Empty list - q.push(1); - q.push(2); - q.push(3); - assert.equal(q.peek(), 1); - assert.equal(q.peek(), 1); - q.pop(); - assert.equal(q.peek(), 2); - }); + it( + 'should allow me to peek at the first element in' + + ' line without popping it', + () => { + const q = new Queue(); + assert.throws(() => q.peek(), Error); // Empty list + q.push(1); + q.push(2); + q.push(3); + assert.equal(q.peek(), 1); + assert.equal(q.peek(), 1); + q.pop(); + assert.equal(q.peek(), 2); + } + ); }); diff --git a/src/test/data_structures/set.js b/src/test/data_structures/set.js index 79521eb..515beb3 100644 --- a/src/test/data_structures/set.js +++ b/src/test/data_structures/set.js @@ -38,16 +38,15 @@ describe('HashSet', () => { assert(s.contains(2)); }); - it('should do nothing when trying to remove an element that doesn\'t exist', - () => { - const s = new HashSet(1, 2, 3); - assert.equal(s.size, 3); - s.remove(4); - assert.equal(s.size, 3); - assert(s.contains(1)); - assert(s.contains(2)); - assert(s.contains(3)); - }); + it('should do nothing when trying to remove an element that doesn\'t exist', () => { + const s = new HashSet(1, 2, 3); + assert.equal(s.size, 3); + s.remove(4); + assert.equal(s.size, 3); + assert(s.contains(1)); + assert(s.contains(2)); + assert(s.contains(3)); + }); it('should only contain its elements', () => { const s = new HashSet(1, 2, 3); @@ -67,4 +66,3 @@ describe('HashSet', () => { assert.equal(total, 6); }); }); - diff --git a/src/test/data_structures/stack.js b/src/test/data_structures/stack.js index 8173521..626a8bc 100644 --- a/src/test/data_structures/stack.js +++ b/src/test/data_structures/stack.js @@ -21,16 +21,18 @@ describe('Stack', () => { assert.throws(() => s.pop(), Error); }); - it('should allow me to peek at the top element in' + - ' the stack without popping it', () => { - const s = new Stack(); - s.push(1); - s.push(2); - s.push(3); - assert.equal(s.peek(), 3); - assert.equal(s.peek(), 3); - s.pop(); - assert.equal(s.peek(), 2); - }); + it( + 'should allow me to peek at the top element in' + + ' the stack without popping it', + () => { + const s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + assert.equal(s.peek(), 3); + assert.equal(s.peek(), 3); + s.pop(); + assert.equal(s.peek(), 2); + } + ); }); - diff --git a/src/test/data_structures/treap.js b/src/test/data_structures/treap.js index 3e88830..ceb97f7 100644 --- a/src/test/data_structures/treap.js +++ b/src/test/data_structures/treap.js @@ -101,18 +101,18 @@ describe('Treap', () => { it('should handle dumplicated elements', () => { treap.insert(1); - // [1, 1] + // [1, 1] assert.equal(treap.size(), 2); treap.insert(-1); - // [-1, 1, 1] + // [-1, 1, 1] assert.equal(treap.size(), 3); treap.remove(1); - // [-1, 1] + // [-1, 1] assert.equal(treap.size(), 2); treap.insert(-1); treap.insert(-1); treap.insert(-1); - // [-1, -1, -1, -1, 1] + // [-1, -1, -1, -1, 1] assert.equal(treap.size(), 5); treap.remove(-1); treap.remove(1); @@ -123,12 +123,12 @@ describe('Treap', () => { }); it('should keep balance', () => { - // Insert 1023 elements randomly + // Insert 1023 elements randomly for (let i = 0; i < 1023; ++i) { treap.insert(Math.random()); } assert.equal(treap.size(), 1023); - // The averange height should be 23 (with an error of 5) + // The averange height should be 23 (with an error of 5) assert(Math.abs(treap.height() - 23) < 5); }); diff --git a/src/test/util/comparator.js b/src/test/util/comparator.js index ab1cd4d..df6acfa 100644 --- a/src/test/util/comparator.js +++ b/src/test/util/comparator.js @@ -2,26 +2,25 @@ const Comparator = require('../../util/comparator'); const assert = require('assert'); describe('Comparator', () => { - it('Should use a default arithmetic comparison if no function is passed', - () => { - const c = new Comparator(); - assert.equal(c.compare(1, 1), 0); - assert.equal(c.compare(1, 2), -1); - assert.equal(c.compare(1, 0), 1); - assert.equal(c.compare('a', 'b'), -1); - assert(c.lessThan(0, 1)); - assert(!c.lessThan(1, 1)); - assert(c.lessThanOrEqual(1, 1)); - assert(c.lessThanOrEqual(0, 1)); - assert(!c.lessThanOrEqual(1, 0)); - assert(c.greaterThan(1, 0)); - assert(!c.greaterThan(1, 1)); - assert(c.greaterThanOrEqual(1, 1)); - assert(c.greaterThanOrEqual(1, 0)); - assert(!c.greaterThanOrEqual(0, 1)); - assert(c.equal(0, 0)); - assert(!c.equal(0, 1)); - }); + it('Should use a default arithmetic comparison if no function is passed', () => { + const c = new Comparator(); + assert.equal(c.compare(1, 1), 0); + assert.equal(c.compare(1, 2), -1); + assert.equal(c.compare(1, 0), 1); + assert.equal(c.compare('a', 'b'), -1); + assert(c.lessThan(0, 1)); + assert(!c.lessThan(1, 1)); + assert(c.lessThanOrEqual(1, 1)); + assert(c.lessThanOrEqual(0, 1)); + assert(!c.lessThanOrEqual(1, 0)); + assert(c.greaterThan(1, 0)); + assert(!c.greaterThan(1, 1)); + assert(c.greaterThanOrEqual(1, 1)); + assert(c.greaterThanOrEqual(1, 0)); + assert(!c.greaterThanOrEqual(0, 1)); + assert(c.equal(0, 0)); + assert(!c.equal(0, 1)); + }); it('should allow comparison function to be defined by user', () => { const compareFn = () => 0; @@ -65,4 +64,3 @@ describe('Comparator', () => { assert(!c.equal(0, 1)); }); }); - From 9139ff02a5f58d7bb0c3d766875f487ac0bae733 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 14 Jun 2017 23:19:27 +0200 Subject: [PATCH 248/280] Happy linter and remove "should" from tests" --- .eslintrc | 3 + package.json | 1 - src/algorithms/math/fast_power.js | 4 +- src/data_structures/fenwick_tree.js | 57 ++--- src/string.js | 6 +- src/test/algorithms/geometry/bezier_curve.js | 6 +- src/test/algorithms/graph/SPFA.js | 2 +- src/test/algorithms/graph/bellman_ford.js | 2 +- .../algorithms/graph/bfs_shortest_path.js | 2 +- .../algorithms/graph/breadth_first_search.js | 4 +- .../algorithms/graph/depth_first_search.js | 4 +- src/test/algorithms/graph/dijkstra.js | 2 +- src/test/algorithms/graph/euler_path.js | 14 +- src/test/algorithms/graph/floyd_warshall.js | 4 +- .../algorithms/graph/minimum_spanning_tree.js | 6 +- .../graph/strongly_connected_component.js | 2 +- src/test/algorithms/graph/topological_sort.js | 92 ++++---- .../algorithms/math/collatz_conjecture.js | 6 +- .../algorithms/math/extended_euclidean.js | 2 +- src/test/algorithms/math/fast_power.js | 8 +- src/test/algorithms/math/fibonacci.js | 10 +- src/test/algorithms/math/find_divisors.js | 6 +- src/test/algorithms/math/fisher_yates.js | 4 +- src/test/algorithms/math/gcd.js | 36 ++-- .../algorithms/math/greatest_difference.js | 6 +- src/test/algorithms/math/lcm.js | 74 +++---- src/test/algorithms/math/newton_sqrt.js | 4 +- src/test/algorithms/math/next_permutation.js | 6 +- src/test/algorithms/math/power_set.js | 4 +- src/test/algorithms/math/primality_tests.js | 4 +- .../algorithms/math/reservoir_sampling.js | 6 +- src/test/algorithms/searching/bfs.js | 2 +- src/test/algorithms/searching/binarysearch.js | 2 +- src/test/algorithms/searching/dfs.js | 6 +- .../algorithms/searching/ternary_search.js | 2 +- src/test/algorithms/sorting/bubble_sort.js | 4 +- src/test/algorithms/sorting/counting_sort.js | 2 +- src/test/algorithms/sorting/heap_sort.js | 4 +- src/test/algorithms/sorting/insertion_sort.js | 4 +- src/test/algorithms/sorting/merge_sort.js | 4 +- src/test/algorithms/sorting/quicksort.js | 4 +- src/test/algorithms/sorting/radix_sort.js | 2 +- src/test/algorithms/sorting/selection_sort.js | 4 +- src/test/algorithms/sorting/shell_sort.js | 4 +- .../algorithms/sorting/short_bubble_sort.js | 4 +- src/test/algorithms/string/hamming.js | 4 +- src/test/algorithms/string/huffman.js | 8 +- .../algorithms/string/knuth_morris_pratt.js | 2 +- src/test/algorithms/string/levenshtein.js | 2 +- .../string/longest_common_subsequence.js | 2 +- .../string/longest_common_substring.js | 2 +- src/test/algorithms/string/rabin_karp.js | 2 +- src/test/data_structures/avl-tree.js | 196 +++++++++--------- src/test/data_structures/bst.js | 26 +-- .../data_structures/disjoint_set_forest.js | 8 +- src/test/data_structures/fenwick_tree.js | 4 +- src/test/data_structures/graph.js | 42 ++-- src/test/data_structures/hash_table.js | 80 ++++--- src/test/data_structures/heap.js | 13 +- src/test/data_structures/linked_list.js | 14 +- src/test/data_structures/priority_queue.js | 6 +- src/test/data_structures/queue.js | 7 +- src/test/data_structures/set.js | 14 +- src/test/data_structures/stack.js | 7 +- src/test/data_structures/treap.js | 18 +- src/test/util/comparator.js | 6 +- 66 files changed, 439 insertions(+), 459 deletions(-) diff --git a/.eslintrc b/.eslintrc index 0c988cd..dc92d2e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,8 @@ { "extends": "google", + "parserOptions": { + "ecmaVersion": 6 + }, "env": { "node": true, "mocha": true diff --git a/package.json b/package.json index 131b667..3a87e5f 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ "lint", "test" ], - "dependencies": {}, "devDependencies": { "coveralls": "^2.11.4", "eslint": "^4.0.0", diff --git a/src/algorithms/math/fast_power.js b/src/algorithms/math/fast_power.js index 2aefe70..c892172 100644 --- a/src/algorithms/math/fast_power.js +++ b/src/algorithms/math/fast_power.js @@ -35,8 +35,8 @@ const fastPower = (base, power, mul, identity) => { }; for ( let factor = base; - power; - (power >>>= 1), (factor = mul(factor, factor)) + power > 0; + power >>>= 1, factor = mul(factor, factor) ) { if (power & 1) { multiplyBy(factor); diff --git a/src/data_structures/fenwick_tree.js b/src/data_structures/fenwick_tree.js index 5903155..acedded 100644 --- a/src/data_structures/fenwick_tree.js +++ b/src/data_structures/fenwick_tree.js @@ -33,20 +33,22 @@ class FenwickTree { */ adjust(index, value) { /* - This function goes up the tree adding the value to all parent nodes. - - In the array, to know where a index is in the tree, just look at where is - the rightmost bit. 1 is a leaf, because the rightmost bit is at position 0. - 2 (10) is 1 level above the leafs. 4 (100) is 2 levels above the leafs. - - Going up the tree means pushing the rightmost bit far to the left. We do - this by adding only the bit itself to the index. Eventually we skip - some levels that aren't represented in the array. E.g. starting at 3 (11), - it's imediate parent is 11b + 1b = 100b. We started at a leaf and skipped - the level-1 node, because it wasn't represented in the array - (a right child). - - Note: (index&-index) finds the rightmost bit in index. + * This function goes up the tree adding the value to all parent nodes. + * + * In the array, to know where a index is in the tree, just look at where is + * the rightmost bit. 1 is a leaf, because the rightmost bit is at position + * 0. + * 2 (10) is 1 level above the leafs. 4 (100) is 2 levels above the leafs. + * + * Going up the tree means pushing the rightmost bit far to the left. We do + * this by adding only the bit itself to the index. Eventually we skip + * some levels that aren't represented in the array. + * E.g. starting at 3 (11), + * it's imediate parent is 11b + 1b = 100b. We started at a leaf and skipped + * the level-1 node, because it wasn't represented in the array + * (a right child). + * + * Note: (index&-index) finds the rightmost bit in index. */ for (; index < this._elements.length; index += index & -index) { this._elements[index] += value; @@ -58,19 +60,20 @@ class FenwickTree { */ prefixSum(index) { /* - This function goes up the tree adding the required nodes to sum the prefix. - - The key here is to sum every node that isn't in the same subtree as an - already seen node. In practice we proceed always getting a node's uncle - (the sibling of the node's parent). So, if we start at the index 7, we must - go to 6 (7's uncle), then to 4 (6's uncle), then we stop, because 4 has - no uncle. - - Binary-wise, this is the same as erasing the rightmost bit of the index. - E.g. 7 (111) -> 6 (110) -> 4 (100). - - Note: (index&-index) finds the rightmost bit in index. - */ + * This function goes up the tree adding the required nodes to sum the + * prefix. + * + * The key here is to sum every node that isn't in the same subtree as an + * already seen node. In practice we proceed always getting a node's uncle + * (the sibling of the node's parent). So, if we start at the index 7, we + * must go to 6 (7's uncle), then to 4 (6's uncle), then we stop, because + * 4 has no uncle. + * + * Binary-wise, this is the same as erasing the rightmost bit of the index. + * E.g. 7 (111) -> 6 (110) -> 4 (100). + * + * Note: (index&-index) finds the rightmost bit in index. + */ let sum = 0; for (; index > 0; index -= index & -index) { diff --git a/src/string.js b/src/string.js index 9d0881f..7bae79f 100644 --- a/src/string.js +++ b/src/string.js @@ -5,6 +5,8 @@ module.exports = { knuthMorrisPratt: require('./algorithms/string/knuth_morris_pratt'), huffman: require('./algorithms/string/huffman'), hamming: require('./algorithms/string/hamming'), - longestCommonSubsequence: require('./algorithms/string/longest_common_subsequence'), - longestCommonSubstring: require('./algorithms/string/longest_common_substring') + longestCommonSubsequence: + require('./algorithms/string/longest_common_subsequence'), + longestCommonSubstring: + require('./algorithms/string/longest_common_substring') }; diff --git a/src/test/algorithms/geometry/bezier_curve.js b/src/test/algorithms/geometry/bezier_curve.js index d00387e..e2fca29 100644 --- a/src/test/algorithms/geometry/bezier_curve.js +++ b/src/test/algorithms/geometry/bezier_curve.js @@ -5,7 +5,7 @@ const assert = require('assert'); // Testing with http://pomax.github.io/bezierjs/ describe('Bézier-Curve Algorithm', () => { - it('should get a linear Bézier-curve', () => { + it('gets a linear Bézier-curve', () => { const b = new BezierCurve([{x: 0, y: 0}, {x: 10, y: 3}]); // Ends @@ -19,7 +19,7 @@ describe('Bézier-Curve Algorithm', () => { assert.deepEqual(b.get(0.25), {x: 2.5, y: 0.75}); assert.deepEqual(b.get(0.75), {x: 7.5, y: 2.25}); }); - it('should get a quadratic Bézier-curve', () => { + it('gets a quadratic Bézier-curve', () => { const b = new BezierCurve([ {x: 150, y: 40}, {x: 80, y: 30}, @@ -29,7 +29,7 @@ describe('Bézier-Curve Algorithm', () => { assert.deepEqual(b.get(0.5), {x: 103.75, y: 62.5}); assert.deepEqual(b.get(0.25), {x: 120.9375, y: 43.125}); }); - it('should get a cubic Bézier-curve', () => { + it('gets a cubic Bézier-curve', () => { const b = new BezierCurve([ {x: 150, y: 40}, {x: 80, y: 30}, diff --git a/src/test/algorithms/graph/SPFA.js b/src/test/algorithms/graph/SPFA.js index 14635c6..bdd2b0c 100644 --- a/src/test/algorithms/graph/SPFA.js +++ b/src/test/algorithms/graph/SPFA.js @@ -4,7 +4,7 @@ const Graph = root.DataStructures.Graph; const assert = require('assert'); describe('SPFA Algorithm', () => { - it('should return the shortest paths to all nodes from a given origin', () => { + it('returns the shortest paths to all nodes from a given origin', () => { const graph = new Graph(true); graph.addEdge('a', 'b', -1); diff --git a/src/test/algorithms/graph/bellman_ford.js b/src/test/algorithms/graph/bellman_ford.js index 82eb00f..570c97b 100644 --- a/src/test/algorithms/graph/bellman_ford.js +++ b/src/test/algorithms/graph/bellman_ford.js @@ -4,7 +4,7 @@ const Graph = root.DataStructures.Graph; const assert = require('assert'); describe('Bellman-Ford Algorithm', () => { - it('should return the shortest paths to all nodes from a given origin', () => { + it('returns the shortest paths to all nodes from a given origin', () => { const graph = new Graph(true); graph.addEdge('a', 'b', -1); diff --git a/src/test/algorithms/graph/bfs_shortest_path.js b/src/test/algorithms/graph/bfs_shortest_path.js index 14cd1c2..b8f5817 100644 --- a/src/test/algorithms/graph/bfs_shortest_path.js +++ b/src/test/algorithms/graph/bfs_shortest_path.js @@ -4,7 +4,7 @@ const Graph = root.DataStructures.Graph; const assert = require('assert'); describe('BFS Shortest Path Algorithm', () => { - it('should return the shortest paths to all nodes from a given origin', () => { + it('returns the shortest paths to all nodes from a given origin', () => { const graph = new Graph(); graph.addEdge(0, 1); graph.addEdge(1, 2); diff --git a/src/test/algorithms/graph/breadth_first_search.js b/src/test/algorithms/graph/breadth_first_search.js index 0450d4a..1f2eab9 100644 --- a/src/test/algorithms/graph/breadth_first_search.js +++ b/src/test/algorithms/graph/breadth_first_search.js @@ -19,7 +19,7 @@ describe('Breadth-First Search', () => { graph.addEdge('alpha', 'omega'); }); - it('should visit reachable vertices in a breadth-first manner', () => { + it('visits reachable vertices in a breadth-first manner', () => { const enter = []; const leave = []; let lastEntered = null; @@ -51,7 +51,7 @@ describe('Breadth-First Search', () => { assert.equal(enter[5], 3); }); - it('should allow user-defined allowTraversal rules', () => { + it('allows user-defined allowTraversal rules', () => { const seen = new Graph(graph.directed); graph.vertices.forEach(seen.addVertex.bind(seen)); const indegrees = {1: -1}; diff --git a/src/test/algorithms/graph/depth_first_search.js b/src/test/algorithms/graph/depth_first_search.js index c257028..c03617c 100644 --- a/src/test/algorithms/graph/depth_first_search.js +++ b/src/test/algorithms/graph/depth_first_search.js @@ -15,7 +15,7 @@ describe('Depth First Search Algorithm', () => { graph.addEdge('five', 'six'); }); - it('should visit only the nodes reachable from the start node (inclusive)', () => { + it('visits only the nodes reachable from the start node (inclusive)', () => { const enter = []; const leave = []; let numEdgeTails = 0; @@ -49,7 +49,7 @@ describe('Depth First Search Algorithm', () => { assert.equal(numEdgeHeads, 4); }); - it('should allow user-defined allowTraversal rules', () => { + it('allows user-defined allowTraversal rules', () => { const seen = new Graph(graph.directed); graph.vertices.forEach(seen.addVertex.bind(seen)); const path = ['one']; diff --git a/src/test/algorithms/graph/dijkstra.js b/src/test/algorithms/graph/dijkstra.js index f9df425..87f87a6 100644 --- a/src/test/algorithms/graph/dijkstra.js +++ b/src/test/algorithms/graph/dijkstra.js @@ -4,7 +4,7 @@ const Graph = root.DataStructures.Graph; const assert = require('assert'); describe('Dijkstra Algorithm', () => { - it('should return the shortest paths to all nodes from a given origin', () => { + it('returns the shortest paths to all nodes from a given origin', () => { const g = new Graph(); g.addEdge('a', 'b', 5); g.addEdge('a', 'c', 10); diff --git a/src/test/algorithms/graph/euler_path.js b/src/test/algorithms/graph/euler_path.js index e643e4d..96cdc6e 100644 --- a/src/test/algorithms/graph/euler_path.js +++ b/src/test/algorithms/graph/euler_path.js @@ -31,7 +31,7 @@ describe('Euler Path', () => { return graph; }; - it('should compute Euler tour over the undirected graph', () => { + it('computes Euler tour over the undirected graph', () => { const graph = graphFromEdges(false, [ [1, 2], [1, 5], @@ -54,7 +54,7 @@ describe('Euler Path', () => { assert.equal(trail[0], trail.slice(-1)[0]); }); - it('should compute Euler walk over the undirected graph', () => { + it('computes Euler walk over the undirected graph', () => { const graph = graphFromEdges(false, [ [1, 2], [1, 5], @@ -79,7 +79,7 @@ describe('Euler Path', () => { assert.equal(endpoints[1], 8); }); - it('should compute Euler tour over the directed graph', () => { + it('computes Euler tour over the directed graph', () => { const graph = graphFromEdges(true, [ [0, 1], [1, 2], @@ -97,7 +97,7 @@ describe('Euler Path', () => { assert.equal(trail[0], trail.slice(-1)[0]); }); - it('should compute Euler walk over the directed graph', () => { + it('computes Euler walk over the directed graph', () => { const graph = graphFromEdges(true, [ [5, 0], [0, 2], @@ -111,20 +111,20 @@ describe('Euler Path', () => { assert.deepEqual(trail, [5, 3, 1, 5, 0, 2, 4, 0]); }); - it('should return single-vertex-trail for an isolated vertex', () => { + it('returns single-vertex-trail for an isolated vertex', () => { const graph = new Graph(); graph.addVertex('loner'); const trail = eulerPath(graph); assert.deepEqual(trail, ['loner']); }); - it('should return empty trail for an empty graph', () => { + it('returns empty trail for an empty graph', () => { const graph = new Graph(); const trail = eulerPath(graph); assert.deepEqual(trail, []); }); - it('should raise an error if there is no Euler path', () => { + it('raises an error if there is no Euler path', () => { let graph = graphFromEdges(false, [[0, 1], [2, 3]]); assert.throws(eulerPath.bind(null, graph)); diff --git a/src/test/algorithms/graph/floyd_warshall.js b/src/test/algorithms/graph/floyd_warshall.js index ccea319..9375d7c 100644 --- a/src/test/algorithms/graph/floyd_warshall.js +++ b/src/test/algorithms/graph/floyd_warshall.js @@ -4,7 +4,7 @@ const Graph = root.DataStructures.Graph; const assert = require('assert'); describe('Floyd-Warshall Algorithm', () => { - it('should compute all-pairs shortest paths in the graph', () => { + it('computes all-pairs shortest paths in the graph', () => { const graph = new Graph(); graph.addEdge('a', 'b', -2); graph.addEdge('b', 'c', -1); @@ -73,7 +73,7 @@ describe('Floyd-Warshall Algorithm', () => { assert.deepEqual(result.path('a', 'y'), ['a', 'b', 'c', 'y']); }); - it('should determine if the graph contains a negative-weighted cycle', () => { + it('determines if the graph contains a negative-weighted cycle', () => { const graph = new Graph(); graph.addEdge('a', 'b', -2); graph.addEdge('b', 'c', -1); diff --git a/src/test/algorithms/graph/minimum_spanning_tree.js b/src/test/algorithms/graph/minimum_spanning_tree.js index 1af3bf5..1d9cf68 100644 --- a/src/test/algorithms/graph/minimum_spanning_tree.js +++ b/src/test/algorithms/graph/minimum_spanning_tree.js @@ -114,7 +114,7 @@ describe('Minimum Spanning Tree', () => { }; const testMstAlgorithm = mst => { - it('should find a minimum spanning tree', () => { + it('finds a minimum spanning tree', () => { const graph = new Graph(false); graph.addEdge(1, 2, 1); graph.addEdge(1, 4, 2); @@ -152,7 +152,7 @@ describe('Minimum Spanning Tree', () => { assert(isMinimumSpanningForest(mst(graph), graph, -100)); }); - it('should find a minimum spaning forest if the graph is not connected', () => { + it('finds a minimum spaning forest if the graph is not connected', () => { const graph = new Graph(false); graph.addVertex(1); graph.addVertex(2); @@ -177,7 +177,7 @@ describe('Minimum Spanning Tree', () => { assert(isMinimumSpanningForest(mst(graph), graph, -200, 2)); }); - it('should throw an error if the graph is directed', () => { + it('throws an error if the graph is directed', () => { const directedGraph = new Graph(true); directedGraph.addEdge('Rock', 'Hard Place'); assert.throws(mst.bind(null, directedGraph)); diff --git a/src/test/algorithms/graph/strongly_connected_component.js b/src/test/algorithms/graph/strongly_connected_component.js index 5ed3b0b..591afbe 100644 --- a/src/test/algorithms/graph/strongly_connected_component.js +++ b/src/test/algorithms/graph/strongly_connected_component.js @@ -4,7 +4,7 @@ const stronglyConnectedComponent = root.Graph.strongConnectedComponent; const assert = require('assert'); describe('Strongly Connected Component', () => { - it('should correctly compute strongly connected components', () => { + it('computes strongly connected components', () => { // graph: 0 -> 1 -> 2 let graph = new Graph(); graph.addEdge(0, 1); diff --git a/src/test/algorithms/graph/topological_sort.js b/src/test/algorithms/graph/topological_sort.js index 8a002e4..e998ae6 100644 --- a/src/test/algorithms/graph/topological_sort.js +++ b/src/test/algorithms/graph/topological_sort.js @@ -4,53 +4,49 @@ const Graph = root.DataStructures.Graph; const assert = require('assert'); describe('Topological Sort', () => { - it( - 'should return a stack with the vertices ordered' + - ' considering the dependencies', - () => { - const graph = new Graph(); - graph.addVertex('shoes'); - graph.addVertex('watch'); - graph.addVertex('underwear'); - graph.addVertex('socks'); - graph.addVertex('shirt'); - graph.addVertex('pants'); - graph.addVertex('belt'); - graph.addVertex('tie'); - graph.addVertex('jacket'); - - graph.addEdge('shirt', 'belt'); - graph.addEdge('shirt', 'tie'); - graph.addEdge('shirt', 'jacket'); - - graph.addEdge('socks', 'shoes'); - - graph.addEdge('underwear', 'pants'); - graph.addEdge('underwear', 'shoes'); - - graph.addEdge('pants', 'shoes'); - graph.addEdge('pants', 'belt'); - - graph.addEdge('belt', 'jacket'); - - graph.addEdge('tie', 'jacket'); - - const stack = topologicalSort(graph); - const a = []; - while (!stack.isEmpty()) { - a.push(stack.pop()); - } - assert.deepEqual(a, [ - 'shirt', - 'socks', - 'underwear', - 'pants', - 'shoes', - 'tie', - 'watch', - 'belt', - 'jacket' - ]); + it('returns a stack with the vertices ordered based on dependencies', () => { + const graph = new Graph(); + graph.addVertex('shoes'); + graph.addVertex('watch'); + graph.addVertex('underwear'); + graph.addVertex('socks'); + graph.addVertex('shirt'); + graph.addVertex('pants'); + graph.addVertex('belt'); + graph.addVertex('tie'); + graph.addVertex('jacket'); + + graph.addEdge('shirt', 'belt'); + graph.addEdge('shirt', 'tie'); + graph.addEdge('shirt', 'jacket'); + + graph.addEdge('socks', 'shoes'); + + graph.addEdge('underwear', 'pants'); + graph.addEdge('underwear', 'shoes'); + + graph.addEdge('pants', 'shoes'); + graph.addEdge('pants', 'belt'); + + graph.addEdge('belt', 'jacket'); + + graph.addEdge('tie', 'jacket'); + + const stack = topologicalSort(graph); + const a = []; + while (!stack.isEmpty()) { + a.push(stack.pop()); } - ); + assert.deepEqual(a, [ + 'shirt', + 'socks', + 'underwear', + 'pants', + 'shoes', + 'tie', + 'watch', + 'belt', + 'jacket' + ]); + }); }); diff --git a/src/test/algorithms/math/collatz_conjecture.js b/src/test/algorithms/math/collatz_conjecture.js index 927c2fa..d2c1d55 100644 --- a/src/test/algorithms/math/collatz_conjecture.js +++ b/src/test/algorithms/math/collatz_conjecture.js @@ -3,19 +3,19 @@ const collatzConjecture = math.collatzConjecture; const assert = require('assert'); describe('Collatz Conjecture', () => { - it('should return odd numbers divided by two', () => { + it('returns odd numbers divided by two', () => { assert.equal(collatzConjecture.calculate(200), 100); assert.equal(collatzConjecture.calculate(222), 111); assert.equal(collatzConjecture.calculate(444), 222); }); - it('should return even numbers multiplied by 3 + 1', () => { + it('returns even numbers multiplied by 3 + 1', () => { assert.equal(collatzConjecture.calculate(111), 334); assert.equal(collatzConjecture.calculate(333), 1000); assert.equal(collatzConjecture.calculate(555), 1666); }); - it('should return Collatz Conjecture sequence ', () => { + it('returns Collatz Conjecture sequence ', () => { assert.deepEqual(collatzConjecture.generate(10), [5, 16, 8, 4, 2, 1]); }); }); diff --git a/src/test/algorithms/math/extended_euclidean.js b/src/test/algorithms/math/extended_euclidean.js index 7bd0298..35681f3 100644 --- a/src/test/algorithms/math/extended_euclidean.js +++ b/src/test/algorithms/math/extended_euclidean.js @@ -3,7 +3,7 @@ const extEuclid = math.extendedEuclidean; const assert = require('assert'); describe('extEuclid', () => { - it('should calculate the solve to Bézout\'s identity', () => { + it('calculates the solve to Bézout\'s identity', () => { let solve = extEuclid(1, 0); assert.equal(solve.x, 1); assert.equal(solve.y, 0); diff --git a/src/test/algorithms/math/fast_power.js b/src/test/algorithms/math/fast_power.js index b8e191e..370e566 100644 --- a/src/test/algorithms/math/fast_power.js +++ b/src/test/algorithms/math/fast_power.js @@ -30,7 +30,7 @@ const abcMultiply = (a, b) => { }; describe('Fast Power', () => { - it('should correctly raise numbers to positive integer powers', () => { + it('raise numbers to positive integer powers', () => { assert.equal(power(2, 5), 32); assert.equal(power(32, 1), 32); assert.equal(power(3, 7), Math.pow(3, 7)); @@ -41,7 +41,7 @@ describe('Fast Power', () => { assert.equal(power(1, 10000), 1); }); - it('should raise an error if the power is not a nonnegative integer', () => { + it('raises an error if the power is not a nonnegative integer', () => { // It is not clear how to handle these cases // when custom multiplication is also supplied. assert.throws(power.bind(null, 7, -2)); @@ -49,7 +49,7 @@ describe('Fast Power', () => { assert.throws(power.bind(null, Math.PI, Math.E)); }); - it('should accept custom multiplication functions', () => { + it('accepts custom multiplication functions', () => { // Math.pow is basically useless here. assert.equal(power(0, 0, multiplyModulo(5), 1), 1); @@ -66,7 +66,7 @@ describe('Fast Power', () => { }); it( - 'should raise an error if the power is zero but no identity value given' + + 'raise an error if the power is zero but no identity value given' + ' (custom multiplication)', () => { assert.throws(power.bind(null, 0, 0, multiplyModulo(5))); diff --git a/src/test/algorithms/math/fibonacci.js b/src/test/algorithms/math/fibonacci.js index d0266da..27e8834 100644 --- a/src/test/algorithms/math/fibonacci.js +++ b/src/test/algorithms/math/fibonacci.js @@ -20,31 +20,31 @@ const testFibonacciSequence = fib => { describe('Fibonacci', () => { describe('#exponential()', () => { - it('should return the right value for fibonacci sequence', () => { + it('returns the right value for fibonacci sequence', () => { testFibonacciSequence(fib.exponential); }); }); describe('#linear()', () => { - it('should return the right value for fibonacci sequence', () => { + it('returns the right value for fibonacci sequence', () => { testFibonacciSequence(fib); }); }); describe('#withMemoization()', () => { - it('should return the right value for fibonacci sequence', () => { + it('returns the right value for fibonacci sequence', () => { testFibonacciSequence(fib.withMemoization); }); }); describe('#direct()', () => { - it('should return the right value for fibonacci sequence', () => { + it('returns the right value for fibonacci sequence', () => { testFibonacciSequence(fib.direct); }); }); describe('#logarithmic()', () => { - it('should return the right value for fibonacci sequence', () => { + it('returns the right value for fibonacci sequence', () => { testFibonacciSequence(fib.logarithmic); }); }); diff --git a/src/test/algorithms/math/find_divisors.js b/src/test/algorithms/math/find_divisors.js index 253cd47..9d3f2a0 100644 --- a/src/test/algorithms/math/find_divisors.js +++ b/src/test/algorithms/math/find_divisors.js @@ -4,7 +4,7 @@ const assert = require('assert'); describe('Find divisors', () => { describe('#Generic()', () => { - it('should return the divisors of the number', () => { + it('returns the divisors of the number', () => { assert.deepStrictEqual(findDivisors(-2), []); assert.deepStrictEqual(findDivisors(0), []); assert.deepStrictEqual(findDivisors(1), [1]); @@ -28,7 +28,7 @@ describe('Find divisors', () => { }); describe('#PairingUnsorted()', () => { - it('should return the divisors of the number', () => { + it('returns the divisors of the number', () => { assert.deepStrictEqual(findDivisors.pairingUnsorted(-2), []); assert.deepStrictEqual(findDivisors.pairingUnsorted(0), []); assert.deepStrictEqual(findDivisors.pairingUnsorted(1), [1]); @@ -61,7 +61,7 @@ describe('Find divisors', () => { }); describe('#PairingSorted()', () => { - it('should return the divisors of the number', () => { + it('returns the divisors of the number', () => { assert.deepStrictEqual(findDivisors.pairingSorted(-2), []); assert.deepStrictEqual(findDivisors.pairingSorted(0), []); assert.deepStrictEqual(findDivisors.pairingSorted(1), [1]); diff --git a/src/test/algorithms/math/fisher_yates.js b/src/test/algorithms/math/fisher_yates.js index 4af6476..ead3223 100644 --- a/src/test/algorithms/math/fisher_yates.js +++ b/src/test/algorithms/math/fisher_yates.js @@ -3,13 +3,13 @@ const fisherYates = math.fisherYates; const assert = require('assert'); describe('Fisher-Yates', () => { - it('should shuffle the elements in the array in-place', () => { + it('shuffles the elements in the array in-place', () => { const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; fisherYates(a); assert.notDeepEqual(a, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); }); - describe('should be able to be used as Array.suffle', () => { + describe('can be used as Array.suffle', () => { const a = [1, 2, 3, 4, 5]; assert.equal(a.shuffle, undefined); /* eslint-disable no-extend-native */ diff --git a/src/test/algorithms/math/gcd.js b/src/test/algorithms/math/gcd.js index 8a05583..068845f 100644 --- a/src/test/algorithms/math/gcd.js +++ b/src/test/algorithms/math/gcd.js @@ -3,7 +3,7 @@ const gcd = root.Math.gcd; const assert = require('assert'); describe('GCD', () => { - it('should calculate the correct GCD between two numbers', () => { + it('calculates the GCD between two numbers', () => { assert.equal(gcd(1, 0), 1); assert.equal(gcd(2, 2), 2); assert.equal(gcd(2, 4), 2); @@ -16,23 +16,19 @@ describe('GCD', () => { assert.equal(gcd(35, 49), 7); }); - it( - 'should calculate the correct GCD between two numbers using ' + - 'the binary method', - () => { - const gcdb = gcd.binary; - assert.equal(gcdb(1, 0), 1); - assert.equal(gcdb(0, 1), 1); - assert.equal(gcdb(0, 0), 0); - assert.equal(gcdb(2, 2), 2); - assert.equal(gcdb(2, 4), 2); - assert.equal(gcdb(4, 2), 2); - assert.equal(gcdb(5, 2), 1); - assert.equal(gcdb(10, 100), 10); - assert.equal(gcdb(10000000, 2), 2); - assert.equal(gcdb(7, 49), 7); - assert.equal(gcdb(7, 5), 1); - assert.equal(gcdb(35, 49), 7); - } - ); + it('calculates the GCD between two numbers using the binary method', () => { + const gcdb = gcd.binary; + assert.equal(gcdb(1, 0), 1); + assert.equal(gcdb(0, 1), 1); + assert.equal(gcdb(0, 0), 0); + assert.equal(gcdb(2, 2), 2); + assert.equal(gcdb(2, 4), 2); + assert.equal(gcdb(4, 2), 2); + assert.equal(gcdb(5, 2), 1); + assert.equal(gcdb(10, 100), 10); + assert.equal(gcdb(10000000, 2), 2); + assert.equal(gcdb(7, 49), 7); + assert.equal(gcdb(7, 5), 1); + assert.equal(gcdb(35, 49), 7); + }); }); diff --git a/src/test/algorithms/math/greatest_difference.js b/src/test/algorithms/math/greatest_difference.js index f85b490..423c40f 100644 --- a/src/test/algorithms/math/greatest_difference.js +++ b/src/test/algorithms/math/greatest_difference.js @@ -3,15 +3,15 @@ const math = require('../../..').Math; const greatestDifference = math.greatestDifference; describe('Greatest Difference', () => { - it('should return 7 for [5, 8, 6, 1]', () => { + it('returns 7 for [5, 8, 6, 1]', () => { assert.equal(greatestDifference([5, 8, 6, 1]), 7); }); - it('should return 4 for [7, 8, 4]', () => { + it('returns 4 for [7, 8, 4]', () => { assert.equal(greatestDifference([7, 8, 4]), 4); }); - it('should return 38 for the Lost numbers', () => { + it('returns 38 for the Lost numbers', () => { assert.equal(greatestDifference([4, 8, 15, 16, 23, 42]), 38); }); }); diff --git a/src/test/algorithms/math/lcm.js b/src/test/algorithms/math/lcm.js index b4106da..c96c4c8 100644 --- a/src/test/algorithms/math/lcm.js +++ b/src/test/algorithms/math/lcm.js @@ -3,46 +3,38 @@ const lcm = root.Math.lcm; const assert = require('assert'); describe('LCM', () => { - it( - 'should calculate the correct LCM between two numbers ' + - 'using Euclidean algorithm', - () => { - assert.equal(lcm(2, 3), 6); - assert.equal(lcm(0, 1), 0); - assert.equal(lcm(4, 9), 36); - assert.equal(lcm(39, 81), 1053); - assert.equal(lcm(10000000, 2), 10000000); - assert.equal(lcm(35, 49), 245); - assert.equal(lcm(7, 49), 49); - assert.equal(lcm(7, 5), 35); - assert.equal(lcm(0, 0), 0); - assert.equal(lcm(0, 9), 0); - assert.equal(lcm(0, -9), 0); - assert.equal(lcm(-9, -18), 18); - assert.equal(lcm(-7, 9), 63); - assert.equal(lcm(-7, -9), 63); - } - ); + it('calculates the LCM between two numbers using Euclidean algorithm', () => { + assert.equal(lcm(2, 3), 6); + assert.equal(lcm(0, 1), 0); + assert.equal(lcm(4, 9), 36); + assert.equal(lcm(39, 81), 1053); + assert.equal(lcm(10000000, 2), 10000000); + assert.equal(lcm(35, 49), 245); + assert.equal(lcm(7, 49), 49); + assert.equal(lcm(7, 5), 35); + assert.equal(lcm(0, 0), 0); + assert.equal(lcm(0, 9), 0); + assert.equal(lcm(0, -9), 0); + assert.equal(lcm(-9, -18), 18); + assert.equal(lcm(-7, 9), 63); + assert.equal(lcm(-7, -9), 63); + }); - it( - 'should calculate the correct LCM between two numbers ' + - 'using the binary method', - () => { - const lcmb = lcm.binary; - assert.equal(lcmb(2, 3), 6); - assert.equal(lcmb(0, 1), 0); - assert.equal(lcmb(4, 9), 36); - assert.equal(lcmb(39, 81), 1053); - assert.equal(lcmb(10000000, 2), 10000000); - assert.equal(lcmb(35, 49), 245); - assert.equal(lcmb(7, 49), 49); - assert.equal(lcmb(7, 5), 35); - assert.equal(lcmb(0, 0), 0); - assert.equal(lcmb(0, 9), 0); - assert.equal(lcmb(0, -9), 0); - assert.equal(lcmb(-9, -18), 18); - assert.equal(lcmb(-7, 9), 63); - assert.equal(lcmb(-7, -9), 63); - } - ); + it('calculates the LCM between two numbers using the binary method', () => { + const lcmb = lcm.binary; + assert.equal(lcmb(2, 3), 6); + assert.equal(lcmb(0, 1), 0); + assert.equal(lcmb(4, 9), 36); + assert.equal(lcmb(39, 81), 1053); + assert.equal(lcmb(10000000, 2), 10000000); + assert.equal(lcmb(35, 49), 245); + assert.equal(lcmb(7, 49), 49); + assert.equal(lcmb(7, 5), 35); + assert.equal(lcmb(0, 0), 0); + assert.equal(lcmb(0, 9), 0); + assert.equal(lcmb(0, -9), 0); + assert.equal(lcmb(-9, -18), 18); + assert.equal(lcmb(-7, 9), 63); + assert.equal(lcmb(-7, -9), 63); + }); }); diff --git a/src/test/algorithms/math/newton_sqrt.js b/src/test/algorithms/math/newton_sqrt.js index 386d3d9..53f6786 100644 --- a/src/test/algorithms/math/newton_sqrt.js +++ b/src/test/algorithms/math/newton_sqrt.js @@ -3,7 +3,7 @@ const newtonSqrt = math.newtonSqrt; const assert = require('assert'); describe('Newton square root', () => { - it('should calculate the exact root of square numbers', () => { + it('calculates the exact root of square numbers', () => { assert.strictEqual(newtonSqrt(0), 0); assert.strictEqual(newtonSqrt(1), 1); assert.strictEqual(newtonSqrt(4), 2); @@ -17,7 +17,7 @@ describe('Newton square root', () => { assert.strictEqual(newtonSqrt(100), 10); }); - it('should calculate an approximated root for every number', () => { + it('calculates an approximated root for every number', () => { for (let i = 0; i < 1000; i++) { const newton = newtonSqrt(i); const nativeJS = Math.sqrt(i); diff --git a/src/test/algorithms/math/next_permutation.js b/src/test/algorithms/math/next_permutation.js index cde7f59..9998695 100644 --- a/src/test/algorithms/math/next_permutation.js +++ b/src/test/algorithms/math/next_permutation.js @@ -30,7 +30,7 @@ const permutations = (start, compareFn) => { }; describe('Next Permutation', () => { - it('should return immediately following permutation', () => { + it('returns immediately following permutation', () => { assert.deepEqual(permutations([1, 2]), [[1, 2], [2, 1]]); assert.deepEqual(permutations([1, 2, 2]), [ [1, 2, 2], @@ -41,7 +41,7 @@ describe('Next Permutation', () => { assert.deepEqual(permutations([]), [[]]); }); - it('should generate all N! permutations if the elements are distinct', () => { + it('generate all N! permutations if the elements are distinct', () => { [4, 5, 6].forEach(size => { let count = 0; const perm = range(size); @@ -52,7 +52,7 @@ describe('Next Permutation', () => { }); }); - it('should support custom compare functions', () => { + it('supports custom compare functions', () => { const reverseComparator = new Comparator(); reverseComparator.reverse(); const reverseCompareFn = reverseComparator.compare; diff --git a/src/test/algorithms/math/power_set.js b/src/test/algorithms/math/power_set.js index 27d3074..70cf570 100644 --- a/src/test/algorithms/math/power_set.js +++ b/src/test/algorithms/math/power_set.js @@ -30,7 +30,7 @@ function testArrayInArray(a, b) { describe('Power set', () => { describe('#iterative()', () => { - it('should return the right elements of power set', () => { + it('returns the right elements of power set', () => { const zeroElementTest = powerSet([]); assert(zeroElementTest.length === 0); @@ -80,7 +80,7 @@ describe('Power set', () => { }); describe('#recursive()', () => { - it('should return the right elements of power set', () => { + it('returns the right elements of power set', () => { const zeroElementTest = powerSet.recursive([]); assert(zeroElementTest.length === 0); diff --git a/src/test/algorithms/math/primality_tests.js b/src/test/algorithms/math/primality_tests.js index cc556d4..1eec9d2 100644 --- a/src/test/algorithms/math/primality_tests.js +++ b/src/test/algorithms/math/primality_tests.js @@ -17,12 +17,12 @@ const validate = primalityTest => { describe('Primality Tests', () => { describe('#naiveTest()', () => { - it('should correctly determine whether a number is prime', () => { + it('determines whether a number is prime', () => { validate(primalityTests.naiveTest); }); }); describe('#trialDivisionTest()', () => { - it('should correctly determine whether a number is prime', () => { + it('determines whether a number is prime', () => { validate(primalityTests.trialDivisionTest); }); }); diff --git a/src/test/algorithms/math/reservoir_sampling.js b/src/test/algorithms/math/reservoir_sampling.js index 23aa6ec..577993e 100644 --- a/src/test/algorithms/math/reservoir_sampling.js +++ b/src/test/algorithms/math/reservoir_sampling.js @@ -5,7 +5,7 @@ const assert = require('assert'); describe('Reservoir Sampling', () => { const array = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - it('should sample K distinct values from the array', () => { + it('samples K distinct values from the array', () => { const sample = reservoirSampling(array, 5); assert.equal(sample.length, 5); const seen = {}; @@ -16,14 +16,14 @@ describe('Reservoir Sampling', () => { }); }); - it('should work in corner cases', () => { + it('works in corner cases', () => { assert.deepEqual(reservoirSampling(array, 0), []); assert.deepEqual(reservoirSampling([], 0), []); const fullSample = reservoirSampling(array, array.length); assert.deepEqual(fullSample.sort(), array); }); - it('should raise an error if asked for too many elements', () => { + it('raises an error if asked for too many elements', () => { assert.throws(() => { reservoirSampling(array, array.length + 1); }); diff --git a/src/test/algorithms/searching/bfs.js b/src/test/algorithms/searching/bfs.js index e544496..97234e3 100644 --- a/src/test/algorithms/searching/bfs.js +++ b/src/test/algorithms/searching/bfs.js @@ -24,7 +24,7 @@ describe('Breadth First Search', () => { const callbackGenerator = a => n => a.push(n); - it('should return the items by level', () => { + it('returns the items by level', () => { const a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, [4, 2, 8, 1, 3, 5, 10, 0, 2.5, 100]); diff --git a/src/test/algorithms/searching/binarysearch.js b/src/test/algorithms/searching/binarysearch.js index 9a51534..872db13 100644 --- a/src/test/algorithms/searching/binarysearch.js +++ b/src/test/algorithms/searching/binarysearch.js @@ -2,7 +2,7 @@ const binarySearch = require('../../..').Search.binarySearch; const assert = require('assert'); describe('Binary Search', () => { - it('should find elements in the sorted array', () => { + it('finds elements in the sorted array', () => { assert.equal(binarySearch([1, 2, 3, 4, 5], 3), 2); assert.equal(binarySearch([1, 2, 3, 4, 5], 1), 0); assert.equal(binarySearch([1, 2, 3, 4, 5], 2), 1); diff --git a/src/test/algorithms/searching/dfs.js b/src/test/algorithms/searching/dfs.js index bbd932e..1b9391f 100644 --- a/src/test/algorithms/searching/dfs.js +++ b/src/test/algorithms/searching/dfs.js @@ -17,19 +17,19 @@ describe('Depth First Search', () => { const callbackGenerator = a => n => a.push(n); - it('should return the items sorted when retrieving in order', () => { + it('returns the items sorted when retrieving in order', () => { const a = []; dfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, [0, 1, 2, 3, 4, 5, 8, 10, 100]); }); - it('should return parents before children when retrieving pre-order', () => { + it('returns parents before children when retrieving pre-order', () => { const a = []; dfs.preOrder(bst.root, callbackGenerator(a)); assert.deepEqual(a, [4, 2, 1, 0, 3, 8, 5, 10, 100]); }); - it('should return children before parents when retrieving post-order', () => { + it('returns children before parents when retrieving post-order', () => { const a = []; dfs.postOrder(bst.root, callbackGenerator(a)); assert.deepEqual(a, [0, 1, 3, 2, 5, 100, 10, 8, 4]); diff --git a/src/test/algorithms/searching/ternary_search.js b/src/test/algorithms/searching/ternary_search.js index a7f16ab..8f186f4 100644 --- a/src/test/algorithms/searching/ternary_search.js +++ b/src/test/algorithms/searching/ternary_search.js @@ -9,7 +9,7 @@ const fn2 = x => -2 * Math.cos(x); const closeEnough = (a, b, precision) => Math.abs(a - b) < precision; describe.skip('Ternary search', () => { - it('should find the maximum of passed function', () => { + it('finds the maximum of passed function', () => { assert(closeEnough(ternarySearch(fn1, 0.0, 4.0, eps), 2.0, eps)); assert(closeEnough(ternarySearch(fn1, 0.0, 1.0, eps), 1.0, eps)); diff --git a/src/test/algorithms/sorting/bubble_sort.js b/src/test/algorithms/sorting/bubble_sort.js index c6dce04..e3f8bbd 100644 --- a/src/test/algorithms/sorting/bubble_sort.js +++ b/src/test/algorithms/sorting/bubble_sort.js @@ -2,11 +2,11 @@ const bubbleSort = require('../../..').Sorting.bubbleSort; const sortingTestsHelper = require('./sorting_tests_helper'); describe('Bubble Sort', () => { - it('should sort the given array', () => { + it('sorts the given array', () => { sortingTestsHelper.testSort(bubbleSort); }); - it('should sort the array with a specific comparison function', () => { + it('sorts the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(bubbleSort); }); }); diff --git a/src/test/algorithms/sorting/counting_sort.js b/src/test/algorithms/sorting/counting_sort.js index 70c4005..a39d4b6 100644 --- a/src/test/algorithms/sorting/counting_sort.js +++ b/src/test/algorithms/sorting/counting_sort.js @@ -26,7 +26,7 @@ let array = [ ]; describe('Counting Sort', () => { - it('should sort the given array', () => { + it('sorts the given array', () => { array = countingSort(array); // Asserts that the array is truly sorted diff --git a/src/test/algorithms/sorting/heap_sort.js b/src/test/algorithms/sorting/heap_sort.js index a8d2684..9542031 100644 --- a/src/test/algorithms/sorting/heap_sort.js +++ b/src/test/algorithms/sorting/heap_sort.js @@ -2,11 +2,11 @@ const heapSort = require('../../..').Sorting.heapSort; const sortingTestsHelper = require('./sorting_tests_helper'); describe('Heap Sort', () => { - it('should sort the given array', () => { + it('sorts the given array', () => { sortingTestsHelper.testSort(heapSort); }); - it('should sort the array with a specific comparison function', () => { + it('sorts the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(heapSort); }); }); diff --git a/src/test/algorithms/sorting/insertion_sort.js b/src/test/algorithms/sorting/insertion_sort.js index 21ba54d..a6080be 100644 --- a/src/test/algorithms/sorting/insertion_sort.js +++ b/src/test/algorithms/sorting/insertion_sort.js @@ -2,11 +2,11 @@ const insertionSort = require('../../..').Sorting.insertionSort; const sortingTestsHelper = require('./sorting_tests_helper'); describe('Insertion Sort', () => { - it('should sort the given array', () => { + it('sorts the given array', () => { sortingTestsHelper.testSort(insertionSort); }); - it('should sort the array with a specific comparison function', () => { + it('sorts the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(insertionSort); }); }); diff --git a/src/test/algorithms/sorting/merge_sort.js b/src/test/algorithms/sorting/merge_sort.js index f756054..f403175 100644 --- a/src/test/algorithms/sorting/merge_sort.js +++ b/src/test/algorithms/sorting/merge_sort.js @@ -2,11 +2,11 @@ const mergeSort = require('../../..').Sorting.mergeSort; const sortingTestsHelper = require('./sorting_tests_helper'); describe('Merge Sort', () => { - it('should sort the given array', () => { + it('sorts the given array', () => { sortingTestsHelper.testSort(mergeSort); }); - it('should sort the array with a specific comparison function', () => { + it('sorts the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(mergeSort); }); }); diff --git a/src/test/algorithms/sorting/quicksort.js b/src/test/algorithms/sorting/quicksort.js index 9deb84c..5676693 100644 --- a/src/test/algorithms/sorting/quicksort.js +++ b/src/test/algorithms/sorting/quicksort.js @@ -2,11 +2,11 @@ const quicksort = require('../../..').Sorting.quicksort; const sortingTestsHelper = require('./sorting_tests_helper'); describe('QuickSort', () => { - it('should sort the given array', () => { + it('sorts the given array', () => { sortingTestsHelper.testSort(quicksort); }); - it('should sort the array with a specific comparison function', () => { + it('sorts the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(quicksort); }); }); diff --git a/src/test/algorithms/sorting/radix_sort.js b/src/test/algorithms/sorting/radix_sort.js index fab9df7..9abcb31 100644 --- a/src/test/algorithms/sorting/radix_sort.js +++ b/src/test/algorithms/sorting/radix_sort.js @@ -23,7 +23,7 @@ const fourthObject = { }; describe('Radix Sort', () => { - it('should sort the given array', () => { + it('sorts the given array', () => { const sorted = radixSort([ thirdObject, fourthObject, diff --git a/src/test/algorithms/sorting/selection_sort.js b/src/test/algorithms/sorting/selection_sort.js index 1d6eea7..87dee11 100644 --- a/src/test/algorithms/sorting/selection_sort.js +++ b/src/test/algorithms/sorting/selection_sort.js @@ -2,11 +2,11 @@ const selectionSort = require('../../..').Sorting.selectionSort; const sortingTestsHelper = require('./sorting_tests_helper'); describe('Selection Sort', () => { - it('should sort the given array', () => { + it('sorts the given array', () => { sortingTestsHelper.testSort(selectionSort); }); - it('should sort the array with a specific comparison function', () => { + it('sorts the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(selectionSort); }); }); diff --git a/src/test/algorithms/sorting/shell_sort.js b/src/test/algorithms/sorting/shell_sort.js index fc68cad..4d84e10 100644 --- a/src/test/algorithms/sorting/shell_sort.js +++ b/src/test/algorithms/sorting/shell_sort.js @@ -2,11 +2,11 @@ const shellSort = require('../../..').Sorting.shellSort; const sortingTestsHelper = require('./sorting_tests_helper.js'); describe('ShellSort', () => { - it('should sort the given array', () => { + it('sorts the given array', () => { sortingTestsHelper.testSort(shellSort); }); - it('should sort the array with a specific comparison function', () => { + it('sorts the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(shellSort); }); }); diff --git a/src/test/algorithms/sorting/short_bubble_sort.js b/src/test/algorithms/sorting/short_bubble_sort.js index cfa95af..582ea64 100644 --- a/src/test/algorithms/sorting/short_bubble_sort.js +++ b/src/test/algorithms/sorting/short_bubble_sort.js @@ -2,11 +2,11 @@ const shortBubbleSort = require('../../..').Sorting.shortBubbleSort; const sortingTestsHelper = require('./sorting_tests_helper'); describe('Short Bubble Sort', () => { - it('should sort the given array', () => { + it('sorts the given array', () => { sortingTestsHelper.testSort(shortBubbleSort); }); - it('should sort the array with a specific comparison function', () => { + it('sorts the array with a specific comparison function', () => { sortingTestsHelper.testSortWithComparisonFn(shortBubbleSort); }); }); diff --git a/src/test/algorithms/string/hamming.js b/src/test/algorithms/string/hamming.js index 8f94637..3f3ef55 100644 --- a/src/test/algorithms/string/hamming.js +++ b/src/test/algorithms/string/hamming.js @@ -2,13 +2,13 @@ const hamming = require('../../..').String.hamming; const assert = require('assert'); describe('Hamming distance', () => { - it('should raise an error if the inputs are not equal lengths', () => { + it('raises an error if the inputs are not equal lengths', () => { assert.throws(() => { hamming('abcde', '1234'); }); }); - it('should return the correct the correct distances', () => { + it('returns the correct the correct distances', () => { const inputs = [ {a: 'karolin', b: 'kathrin', expected: 3}, {a: 'karolin', b: 'kerstin', expected: 3}, diff --git a/src/test/algorithms/string/huffman.js b/src/test/algorithms/string/huffman.js index 3bbd647..c3652d3 100644 --- a/src/test/algorithms/string/huffman.js +++ b/src/test/algorithms/string/huffman.js @@ -23,7 +23,7 @@ describe('Huffman', () => { messages.push(characters.join('')); } - it('should decode previously encoded messages correctly', () => { + it('decodes previously encoded messages correctly', () => { messages.forEach(message => { const encoded = huffman.encode(message); const decoded = huffman.decode(encoded.encoding, encoded.value); @@ -37,7 +37,7 @@ describe('Huffman', () => { }); }); - it('should raise an error if it fails to decode', () => { + it('raises an error if it fails to decode', () => { const badArgs = [[{}, '0'], [{}, [0]], [{a: '0', b: '10', c: '11'}, '001']]; badArgs.forEach(args => { assert.throws(() => { @@ -46,7 +46,7 @@ describe('Huffman', () => { }); }); - it('should encode sample strings in the expected manner', () => { + it('encodes sample strings in the expected manner', () => { assert.deepEqual(huffman.encode(''), {encoding: {}, value: ''}); assert.deepEqual(huffman.encode('a'), {encoding: {a: '0'}, value: '0'}); assert.deepEqual(huffman.encode('aaaaa'), { @@ -64,7 +64,7 @@ describe('Huffman', () => { assert.equal(result.value.length, 32); }); - it('should satisfy the entropy condition (H <= cost <= H+1)', () => { + it('satisfies the entropy condition (H <= cost <= H+1)', () => { messages.forEach(message => { const frequencies = message.split('').reduce((acc, char) => { acc[char] = (acc[char] || 0) + 1; diff --git a/src/test/algorithms/string/knuth_morris_pratt.js b/src/test/algorithms/string/knuth_morris_pratt.js index ee18a4b..416f159 100644 --- a/src/test/algorithms/string/knuth_morris_pratt.js +++ b/src/test/algorithms/string/knuth_morris_pratt.js @@ -2,7 +2,7 @@ const knuthMorrisPratt = require('../../..').String.knuthMorrisPratt; const assert = require('assert'); describe('Knuth-Morris-Pratt', () => { - it('should verify if a pattern is contained in some text (or array)', () => { + it('verifies if a pattern is contained in some text (or array)', () => { const text = 'A string matching algorithm wants to find the starting' + 'index m in string S[] that matches the search word W[].The most' + diff --git a/src/test/algorithms/string/levenshtein.js b/src/test/algorithms/string/levenshtein.js index 5f29be9..3d153cd 100644 --- a/src/test/algorithms/string/levenshtein.js +++ b/src/test/algorithms/string/levenshtein.js @@ -2,7 +2,7 @@ const levenshtein = require('../../..').String.levenshtein; const assert = require('assert'); describe('Levenshtein', () => { - it('should calculate the minimal edit distance between two words', () => { + it('calculates the minimal edit distance between two words', () => { assert.equal(levenshtein('', ''), 0); assert.equal(levenshtein('a', ''), 1); assert.equal(levenshtein('', 'a'), 1); diff --git a/src/test/algorithms/string/longest_common_subsequence.js b/src/test/algorithms/string/longest_common_subsequence.js index 45aef4d..b6f7ae5 100644 --- a/src/test/algorithms/string/longest_common_subsequence.js +++ b/src/test/algorithms/string/longest_common_subsequence.js @@ -4,7 +4,7 @@ const longestCommonSubsequence = require(directory + filename); const assert = require('assert'); describe('Longest common subsequence', () => { - it('should return the longest common subsequence of ' + 'two strings', () => { + it('returns the longest common subsequence of ' + 'two strings', () => { assert.equal('', longestCommonSubsequence('', '')); assert.equal('', longestCommonSubsequence('', 'aaa')); assert.equal('', longestCommonSubsequence('aaa', '')); diff --git a/src/test/algorithms/string/longest_common_substring.js b/src/test/algorithms/string/longest_common_substring.js index c794a54..946fbd1 100644 --- a/src/test/algorithms/string/longest_common_substring.js +++ b/src/test/algorithms/string/longest_common_substring.js @@ -4,7 +4,7 @@ const longestCommonSubstring = require(directory + filename); const assert = require('assert'); describe('Longest common substring', () => { - it('should return the longest common substring of two strings', () => { + it('returns the longest common substring of two strings', () => { assert.equal('', longestCommonSubstring('', '')); assert.equal('', longestCommonSubstring('', 'aaa')); assert.equal('', longestCommonSubstring('aaa', '')); diff --git a/src/test/algorithms/string/rabin_karp.js b/src/test/algorithms/string/rabin_karp.js index 7a88ea9..fdc5ac7 100644 --- a/src/test/algorithms/string/rabin_karp.js +++ b/src/test/algorithms/string/rabin_karp.js @@ -6,7 +6,7 @@ const rabinKarpEqualsToIndexOf = (a, b) => { }; describe('Karp-Rabin', () => { - it('should verify if a string is contained in another string', () => { + it('verifies if a string is contained in another string', () => { rabinKarpEqualsToIndexOf('', ''); rabinKarpEqualsToIndexOf('a', 'b'); rabinKarpEqualsToIndexOf('b', 'a'); diff --git a/src/test/data_structures/avl-tree.js b/src/test/data_structures/avl-tree.js index 9aaf99a..b574415 100644 --- a/src/test/data_structures/avl-tree.js +++ b/src/test/data_structures/avl-tree.js @@ -3,11 +3,11 @@ const AVLTree = root.DataStructures.AVLTree; const assert = require('assert'); describe('AVL Tree', () => { - it('should start with null root', () => { + it('starts with null root', () => { assert.equal(new AVLTree().root, null); }); - it('should insert and single rotate (leftRight) properly', () => { + it('inserts and single rotate (leftRight) properly', () => { const avlTree = new AVLTree(); avlTree.insert(9); avlTree.insert(3); @@ -22,7 +22,7 @@ describe('AVL Tree', () => { assert.equal(avlTree.root.right.height, 1); }); - it('should insert and single rotate (rightLeft) properly', () => { + it('inserts and single rotate (rightLeft) properly', () => { const avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(75); @@ -37,7 +37,7 @@ describe('AVL Tree', () => { assert.equal(avlTree.root.right.height, 1); }); - it('should insert and double rotate (leftLeft) properly', () => { + it('inserts and double rotate (leftLeft) properly', () => { const avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(25); @@ -52,7 +52,7 @@ describe('AVL Tree', () => { assert.equal(avlTree.root.right.height, 1); }); - it('should insert and double rotate (rightRight) properly', () => { + it('inserts and double rotate (rightRight) properly', () => { const avlTree = new AVLTree(); avlTree.insert(50); avlTree.insert(75); @@ -67,7 +67,7 @@ describe('AVL Tree', () => { assert.equal(avlTree.root.right.height, 1); }); - it('should insert multiple nodes and balance properly (1)', () => { + it('inserts multiple nodes and balance properly (1)', () => { const avlTree = new AVLTree(); avlTree.insert(30); avlTree.insert(15); @@ -88,7 +88,7 @@ describe('AVL Tree', () => { assert.equal(avlTree.root.right.right.height, 1); }); - it('should remove nodes and balance properly (2)', () => { + it('removes nodes and balance properly (2)', () => { const avlTree = new AVLTree(); avlTree.insert(55); avlTree.insert(25); @@ -105,7 +105,7 @@ describe('AVL Tree', () => { assert.equal(avlTree.root.right.height, 1); }); - it('should always keep the tree balanced', () => { + it('keeps the tree always balanced', () => { const avlTree = new AVLTree(); avlTree.insert(50); @@ -193,101 +193,93 @@ describe('AVL Tree', () => { assert.equal(avlTree.root.right.right.value, 200); }); - it( - 'should return the parents before the children when ' + - 'traversing in preorder', - () => { - const avlTree = new AVLTree(); - - avlTree.insert(50); - avlTree.insert(100); - avlTree.insert(200); - avlTree.insert(1); - avlTree.insert(2); - avlTree.insert(75); - avlTree.insert(80); - avlTree.insert(4); - avlTree.insert(5); - avlTree.insert(6); - avlTree.insert(7); - avlTree.insert(20); - avlTree.insert(40); - avlTree.insert(30); - avlTree.insert(15); - - const expectedPreOrder = [ - 50, - 5, - 2, - 1, - 4, - 20, - 7, - 6, - 15, - 30, - 40, - 100, - 75, - 80, - 200 - ]; - const preOrder = []; - avlTree.preOrder(avlTree.root, n => { - preOrder.push(n.value); - }); - assert.deepEqual(expectedPreOrder, preOrder); - } - ); - - it( - 'should return the children before the parents when ' + - 'traversing in postorder', - () => { - const avlTree = new AVLTree(); - - avlTree.insert(50); - avlTree.insert(100); - avlTree.insert(200); - avlTree.insert(1); - avlTree.insert(2); - avlTree.insert(75); - avlTree.insert(80); - avlTree.insert(4); - avlTree.insert(5); - avlTree.insert(6); - avlTree.insert(7); - avlTree.insert(20); - avlTree.insert(40); - avlTree.insert(30); - avlTree.insert(15); - - const expectedPostOrder = [ - 1, - 4, - 2, - 6, - 15, - 7, - 40, - 30, - 20, - 5, - 80, - 75, - 200, - 100, - 50 - ]; - const postOrder = []; - avlTree.postOrder(avlTree.root, n => { - postOrder.push(n.value); - }); - assert.deepEqual(expectedPostOrder, postOrder); - } - ); + it('returns parents before children when traversing in preorder', () => { + const avlTree = new AVLTree(); + + avlTree.insert(50); + avlTree.insert(100); + avlTree.insert(200); + avlTree.insert(1); + avlTree.insert(2); + avlTree.insert(75); + avlTree.insert(80); + avlTree.insert(4); + avlTree.insert(5); + avlTree.insert(6); + avlTree.insert(7); + avlTree.insert(20); + avlTree.insert(40); + avlTree.insert(30); + avlTree.insert(15); + + const expectedPreOrder = [ + 50, + 5, + 2, + 1, + 4, + 20, + 7, + 6, + 15, + 30, + 40, + 100, + 75, + 80, + 200 + ]; + const preOrder = []; + avlTree.preOrder(avlTree.root, n => { + preOrder.push(n.value); + }); + assert.deepEqual(expectedPreOrder, preOrder); + }); + + it('returns children before parents when traversing in postorder', () => { + const avlTree = new AVLTree(); + + avlTree.insert(50); + avlTree.insert(100); + avlTree.insert(200); + avlTree.insert(1); + avlTree.insert(2); + avlTree.insert(75); + avlTree.insert(80); + avlTree.insert(4); + avlTree.insert(5); + avlTree.insert(6); + avlTree.insert(7); + avlTree.insert(20); + avlTree.insert(40); + avlTree.insert(30); + avlTree.insert(15); + + const expectedPostOrder = [ + 1, + 4, + 2, + 6, + 15, + 7, + 40, + 30, + 20, + 5, + 80, + 75, + 200, + 100, + 50 + ]; + const postOrder = []; + avlTree.postOrder(avlTree.root, n => { + postOrder.push(n.value); + }); + assert.deepEqual(expectedPostOrder, postOrder); + }); - it('should return the sorted elements when traversing in order', () => { + it('returns the sorted elements when traversing in order', () => { const avlTree = new AVLTree(); const a = []; let i; diff --git a/src/test/data_structures/bst.js b/src/test/data_structures/bst.js index 264f1d6..7aa6a52 100644 --- a/src/test/data_structures/bst.js +++ b/src/test/data_structures/bst.js @@ -4,7 +4,7 @@ const bfs = root.Search.bfs; const assert = require('assert'); describe('Binary Search Tree', () => { - it('should insert elements respecting the BST restrictions', () => { + it('inserts elements respecting the BST restrictions', () => { const bst = new BST(); bst.insert(4); bst.insert(8); @@ -17,7 +17,7 @@ describe('Binary Search Tree', () => { bst.insert(100); assert.equal(bst.size, 9); }); - it('should check if an element exists (in O(lg n))', () => { + it('checks if an element exists (in O(lg n))', () => { const bst = new BST(); bst.insert(4); bst.insert(8); @@ -63,7 +63,7 @@ describe('Binary Search Tree', () => { const callbackGenerator = a => n => a.push(n); it( - 'should remove a leaf without altering anything else in ' + + 'removes a leaf without altering anything else in ' + 'the structure of the tree', () => { bst.remove(0); @@ -80,7 +80,7 @@ describe('Binary Search Tree', () => { ); it( - 'should remove an element with just one child and substitute ' + + 'removes an element with just one child and substitute ' + 'it as the root of only subtree', () => { bst.remove(10); @@ -97,7 +97,7 @@ describe('Binary Search Tree', () => { ); it( - 'should substitute an element by the leftmost child in the right ' + + 'substitute an element by the leftmost child in the right ' + 'subtree and remove it as a leaf', () => { /** @@ -141,7 +141,7 @@ describe('Binary Search Tree', () => { } ); - it('should always return the right root and size', () => { + it('returns the right root and size', () => { const bst = new BST(); bst.insert(5); assert.equal(bst.size, 1); @@ -160,7 +160,7 @@ describe('Binary Search Tree', () => { assert.equal(bst.size, 0); }); - it('should throw an error when trying to remove an unexisting node', () => { + it('throws an error when trying to remove an unexisting node', () => { const bst = new BST(); assert.throws(() => bst.remove(0), Error); bst.insert(3); @@ -174,7 +174,7 @@ describe('Binary Search Tree with custom comparator', () => { return a.length < b.length ? -1 : 1; }; - it('should insert elements respecting the BST restrictions', () => { + it('inserts elements respecting the BST restrictions', () => { const bst = new BST(strLenCompare); bst.insert('banana'); bst.insert('apple'); @@ -183,7 +183,7 @@ describe('Binary Search Tree with custom comparator', () => { assert.equal(bst.size, 4); }); - it('should check if an element exists (in O(lg n))', () => { + it('checks if an element exists (in O(lg n))', () => { const bst = new BST(strLenCompare); bst.insert('banana'); bst.insert('apple'); @@ -215,14 +215,14 @@ describe('Binary Search Tree with custom comparator', () => { const callbackGenerator = a => n => a.push(n); - it('should insert the items according to the comparator', () => { + it('inserts the items according to the comparator', () => { const a = []; bfs(bst.root, callbackGenerator(a)); assert.deepEqual(a, ['banana', 'apple', 'pineapple', 'pear', 'watermelon']); }); it( - 'should remove a leaf without altering anything else in ' + + 'removes a leaf without altering anything else in ' + 'the structure of the tree', () => { bst.remove('watermelon'); @@ -238,7 +238,7 @@ describe('Binary Search Tree with custom comparator', () => { ); it( - 'should remove an element with just one child and substitute ' + + 'removes an element with just one child and substitute ' + 'it as the root of only subtree', () => { bst.remove('apple'); @@ -253,7 +253,7 @@ describe('Binary Search Tree with custom comparator', () => { ); it( - 'should substitute an element by the leftmost child in the right ' + + 'substitutes an element by the leftmost child in the right ' + 'subtree and remove it as a leaf', () => { bst.remove('banana'); diff --git a/src/test/data_structures/disjoint_set_forest.js b/src/test/data_structures/disjoint_set_forest.js index 9461b1c..a124193 100644 --- a/src/test/data_structures/disjoint_set_forest.js +++ b/src/test/data_structures/disjoint_set_forest.js @@ -2,7 +2,7 @@ const DisjointSetForest = require('../..').DataStructures.DisjointSetForest; const assert = require('assert'); describe('Disjoint Set Forest', () => { - it('should decide if two elements belong to the same subset or not', () => { + it('decides if two elements belong to the same subset or not', () => { const forest = new DisjointSetForest(); assert(!forest.sameSubset(1, 2)); forest.merge(1, 2); @@ -14,7 +14,7 @@ describe('Disjoint Set Forest', () => { assert(!forest.sameSubset(1, 5)); }); - it('should maintain subset sizes', () => { + it('maintains subset sizes', () => { const forest = new DisjointSetForest(); const assertSizesCorrect = (elements, size) => { elements.forEach(element => { @@ -34,7 +34,7 @@ describe('Disjoint Set Forest', () => { assertSizesCorrect([0, 1, 2, 3, 4], 5); }); - it('should point all elements to the same root', () => { + it('points all elements to the same root', () => { const forest = new DisjointSetForest(); const assertSameRoot = function(element, ...rest) { const root = forest.root(element); @@ -52,7 +52,7 @@ describe('Disjoint Set Forest', () => { assertSameRoot(0, 1, 2, 3, 4, 5); }); - it('should not choose the root element outside the subset', () => { + it('does not choose the root element outside the subset', () => { const forest = new DisjointSetForest(); const assertInside = (value, set) => set.some(element => element === value); assert.equal(forest.root(0), 0); diff --git a/src/test/data_structures/fenwick_tree.js b/src/test/data_structures/fenwick_tree.js index e7c7529..064d33b 100644 --- a/src/test/data_structures/fenwick_tree.js +++ b/src/test/data_structures/fenwick_tree.js @@ -2,7 +2,7 @@ const FenwickTree = require('../..').DataStructures.FenwickTree; const assert = require('assert'); describe('FenwickTree', () => { - it('should allow prefix queries', () => { + it('allows prefix queries', () => { const tree = new FenwickTree(10); tree.adjust(5, 42); tree.adjust(7, 43); @@ -21,7 +21,7 @@ describe('FenwickTree', () => { assert.equal(tree.prefixSum(10), 42 + 43 + 44); }); - it('should allow range queries', () => { + it('allows range queries', () => { const tree = new FenwickTree(10); tree.adjust(5, 42); tree.adjust(7, 43); diff --git a/src/test/data_structures/graph.js b/src/test/data_structures/graph.js index 42ffbc9..7db03b6 100644 --- a/src/test/data_structures/graph.js +++ b/src/test/data_structures/graph.js @@ -2,7 +2,7 @@ const Graph = require('../..').DataStructures.Graph; const assert = require('assert'); describe('Graph - Adjacency list', () => { - it('should be directed by default', () => { + it('is directed by default', () => { let g = new Graph(); assert(g.directed); @@ -13,7 +13,7 @@ describe('Graph - Adjacency list', () => { assert(g.directed); }); - it('should default weight 1 for edges', () => { + it('defaults weight 1 for edges', () => { const g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -21,15 +21,19 @@ describe('Graph - Adjacency list', () => { assert.strictEqual(g.edge('a', 'b'), 1); }); - it('should create the vertex if an edge is inserted and vertex doesnt exist', () => { - const g = new Graph(); - g.addEdge('a', 'b'); - assert.equal(g.vertices.size, 2); - assert(g.vertices.contains('a')); - assert(g.vertices.contains('b')); - }); - - it('should sum multiple edges between the same vertices', () => { + it( + 'creates the vertex if an edge is inserted and ' + + 'the vertex doesn\'t exist', + () => { + const g = new Graph(); + g.addEdge('a', 'b'); + assert.equal(g.vertices.size, 2); + assert(g.vertices.contains('a')); + assert(g.vertices.contains('b')); + } + ); + + it('sums multiple edges between the same vertices', () => { const g = new Graph(); g.addEdge('a', 'b', 10); assert.equal(g.edge('a', 'b'), 10); @@ -37,7 +41,7 @@ describe('Graph - Adjacency list', () => { assert.equal(g.edge('a', 'b'), 14); }); - it('should have edges in both directions if undirected', () => { + it('has edges in both directions if undirected', () => { const g = new Graph(false); g.addVertex('a'); g.addVertex('b'); @@ -60,7 +64,7 @@ describe('Graph - Adjacency list', () => { assert.equal(g.edge('b', 'a'), 12); }); - it('should respect direction of the edges in directed graphs', () => { + it('respects direction of the edges in directed graphs', () => { const g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -83,7 +87,7 @@ describe('Graph - Adjacency list', () => { assert.equal(g.edge('b', 'a'), 2); }); - it('should have reversed edges with same weight for a reverse directed graph', () => { + it('has reversed edges with same weight for a reverse directed graph', () => { const g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -108,7 +112,7 @@ describe('Graph - Adjacency list', () => { assert.equal(r.edge('b', 'a'), 10); }); - it('should have a list of vertices', () => { + it('has a list of vertices', () => { const g = new Graph(); assert.equal(g.vertices.size, 0); g.addVertex('a'); @@ -120,7 +124,7 @@ describe('Graph - Adjacency list', () => { assert(g.vertices.contains('c')); }); - it('should not allow repeated vertices', () => { + it('does not allow repeated vertices', () => { const g = new Graph(); g.addVertex('a'); assert.throws(() => { @@ -128,7 +132,7 @@ describe('Graph - Adjacency list', () => { }); }); - it('should return a list of neighbors of a vertex', () => { + it('returns a list of neighbors of a vertex', () => { const g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -143,7 +147,7 @@ describe('Graph - Adjacency list', () => { assert.deepEqual(g.neighbors('c'), ['d']); }); - it('should return the weight of the edge', () => { + it('returns the weight of the edge', () => { const g = new Graph(); g.addVertex('a'); g.addVertex('b'); @@ -158,7 +162,7 @@ describe('Graph - Adjacency list', () => { assert.equal(g.edge('c', 'd'), 2); }); - it('should not "inherit" edges from Object.prototype', () => { + it('does not "inherit" edges from Object.prototype', () => { const g = new Graph(); g.addEdge('a', 'b'); diff --git a/src/test/data_structures/hash_table.js b/src/test/data_structures/hash_table.js index 19a8b23..06a5293 100644 --- a/src/test/data_structures/hash_table.js +++ b/src/test/data_structures/hash_table.js @@ -2,40 +2,36 @@ const HashTable = require('../..').DataStructures.HashTable; const assert = require('assert'); describe('Hash Table', () => { - it( - 'should calculate hashes using the same algorithm as ' + - 'Java\'s String.hashCode', - () => { - const h = new HashTable(); - assert.equal( - h.hash('The quick brown fox jumps over the lazy dog'), - -609428141 - ); - assert.equal(h.hash('Testing the hashCode function'), 1538083358); - assert.equal(h.hash(''), 0); - assert.equal(h.hash('a'), 97); - const longString = - 'k"hg3q#+~/l2Eljan;DB x.P%-:iA' + - '/b/hG($8-SZcZX871&;fDEWthw.b5agzov],X00--O:mcQ$JFi-4uIo"D:(r(yvs' + - 'dj%Pq/b$sY5(O8!{^icIBwTT>,fv=$@dD(>167.xqSDXjBS#TV3oIjMGCo9)!e&hO ' + - 'I<[jlz3]r-FFFeNe#Ch4oQ,4A;i,3&3Oq*2LW(KFUW9b$}"z8,B>HRH9.D%.S~o3' + - 'L_6{wu!Kp538AmLREp*ZP`]K9}uRGEEUj37[PQq2Y>cf_{L={Ko"ADnZ8d[q0{-3' + - '@=e8UC4y)@aCefzleW[>Q8y}@Of9{WNI|?ShSF7C{62(A4ok7gRR|dd?7Pi:`0; r_wq=-F-e(iY'; - assert.equal(h.hash(longString), -998071508); - } - ); - - it('should initialize the table with the given capacity', () => { + it('calculates hash using same algorithm as Java\'s String.hashCode', () => { + const h = new HashTable(); + assert.equal( + h.hash('The quick brown fox jumps over the lazy dog'), + -609428141 + ); + assert.equal(h.hash('Testing the hashCode function'), 1538083358); + assert.equal(h.hash(''), 0); + assert.equal(h.hash('a'), 97); + const longString = + 'k"hg3q#+~/l2Eljan;DB x.P%-:iA' + + '/b/hG($8-SZcZX871&;fDEWthw.b5agzov],X00--O:mcQ$JFi-4uIo"D:(r(yvs' + + 'dj%Pq/b$sY5(O8!{^icIBwTT>,fv=$@dD(>167.xqSDXjBS#TV3oIjMGCo9)!e&hO ' + + 'I<[jlz3]r-FFFeNe#Ch4oQ,4A;i,3&3Oq*2LW(KFUW9b$}"z8,B>HRH9.D%.S~o3' + + 'L_6{wu!Kp538AmLREp*ZP`]K9}uRGEEUj37[PQq2Y>cf_{L={Ko"ADnZ8d[q0{-3' + + '@=e8UC4y)@aCefzleW[>Q8y}@Of9{WNI|?ShSF7C{62(A4ok7gRR|dd?7Pi:`0; r_wq=-F-e(iY'; + assert.equal(h.hash(longString), -998071508); + }); + + it('initializes the table with the given capacity', () => { let h = new HashTable(); assert.equal(h.capacity, 64); // default initial capacity; assert.equal(h.size, 0); @@ -44,7 +40,7 @@ describe('Hash Table', () => { assert.equal(h.capacity, 2); }); - it('should allow putting and getting elements from the table', () => { + it('allows putting and getting elements from the table', () => { const h = new HashTable(16); const a = {a: 'foo', b: 'bar'}; h.put('foo', a); @@ -59,7 +55,7 @@ describe('Hash Table', () => { assert.strictEqual(h.get('bar'), b); }); - it('should replace items if the same key is reused', () => { + it('replaces items if the same key is reused', () => { const h = new HashTable(16); const a = {a: 'foo', b: 'bar'}; h.put('foo', a); @@ -70,13 +66,13 @@ describe('Hash Table', () => { assert.strictEqual(h.get('foo'), b); }); - it('should return undefined if there\'s no element', () => { + it('returns undefined if there\'s no element', () => { const h = new HashTable(8); assert.equal(h.get('foo'), undefined); assert.equal(h.get('bar'), undefined); }); - it('should handle hash conflicts', () => { + it('handles hash conflicts', () => { const h = new HashTable(4); // Both keys are supposed to be pushed to the same position assert.equal(h._position('a'), h._position('e')); @@ -90,7 +86,7 @@ describe('Hash Table', () => { assert.equal(h.get('e'), 'bar'); }); - it('should increase capacity if needed', () => { + it('increases capacity when needed', () => { const h = new HashTable(2); assert.equal(h.capacity, 2); @@ -101,7 +97,7 @@ describe('Hash Table', () => { assert.equal(h.capacity, 4); }); - it('should allow removing items', () => { + it('allows removing items', () => { const h = new HashTable(); assert.equal(h.get('foo'), undefined); @@ -116,7 +112,7 @@ describe('Hash Table', () => { assert.equal(h.get('foo'), undefined); }); - it('should allow non-string keys', () => { + it('allows non-string keys', () => { const h = new HashTable(); h.put(10, 5); assert.equal(h.get(10), 5); @@ -126,7 +122,7 @@ describe('Hash Table', () => { assert.equal(h.get(o), 'foo'); }); - it('should perform a function to all keys with forEach', () => { + it('performs a function to all keys with forEach', () => { const h = new HashTable(); h.put(1, 10); h.put(2, 20); diff --git a/src/test/data_structures/heap.js b/src/test/data_structures/heap.js index d863a3c..c30fbf3 100644 --- a/src/test/data_structures/heap.js +++ b/src/test/data_structures/heap.js @@ -2,7 +2,7 @@ const heap = require('../..').DataStructures.Heap; const assert = require('assert'); describe('Min Heap', () => { - it('should always return the lowest element', () => { + it('always returns the lowest element', () => { const h = new heap.MinHeap(); assert(h.isEmpty()); h.insert(10); @@ -33,7 +33,7 @@ describe('Min Heap', () => { assert(h.isEmpty()); }); - it('should heapify an unordered array', () => { + it('heapifies an unordered array', () => { const h = new heap.MinHeap(); h.heapify([10, 2091, 4, 1, 5, 500, 0, 18, 3, 22, 20]); @@ -53,7 +53,7 @@ describe('Min Heap', () => { }); it( - 'should perform a function to all elements from smallest to largest' + + 'calls a function to all elements from smallest to largest' + ' with forEach', () => { const h = new heap.MinHeap(); @@ -73,7 +73,7 @@ describe('Min Heap', () => { }); describe('Max Heap', () => { - it('should always return the greatest element', () => { + it('always returns the greatest element', () => { const h = new heap.MaxHeap(); assert(h.isEmpty()); h.insert(10); @@ -104,7 +104,7 @@ describe('Max Heap', () => { assert(h.isEmpty()); }); - it('should heapify an unordered array', () => { + it('heapifies an unordered array', () => { const h = new heap.MaxHeap(); h.heapify([10, 2091, 4, 1, 5, 500, 0, 18, 3, 22, 20]); @@ -124,8 +124,7 @@ describe('Max Heap', () => { }); it( - 'should perform a function to all elements from largest to smallest' + - ' with forEach', + 'calls a function to all elements from largest to smallest with forEach', () => { const h = new heap.MaxHeap(); h.heapify([3, 10, 1000, 0, 2, 1]); diff --git a/src/test/data_structures/linked_list.js b/src/test/data_structures/linked_list.js index f081204..343522e 100644 --- a/src/test/data_structures/linked_list.js +++ b/src/test/data_structures/linked_list.js @@ -2,13 +2,13 @@ const LinkedList = require('../..').DataStructures.LinkedList; const assert = require('assert'); describe('LinkedList', () => { - it('should start empty', () => { + it('starts empty', () => { const l = new LinkedList(); assert(l.isEmpty()); assert.equal(l.length, 0); }); - it('should increment length when an item is added', () => { + it('increments length when an item is added', () => { const l = new LinkedList(); l.add(1); assert.equal(l.length, 1); @@ -18,7 +18,7 @@ describe('LinkedList', () => { assert.equal(l.length, 2); }); - it('should return the items from the positions they were inserted', () => { + it('returns the items from the positions they were inserted', () => { const l = new LinkedList(); l.add(1); l.add(2); @@ -58,7 +58,7 @@ describe('LinkedList', () => { assert.equal(l.get(12), 13); }); - it('should throw errors when trying to access indexes out of bounds', () => { + it('throws errors when trying to access indexes out of bounds', () => { const l = new LinkedList(); assert.throws(() => l.get(0), Error); assert.throws(() => l.get(1), Error); @@ -81,7 +81,7 @@ describe('LinkedList', () => { assert.throws(() => l.get(10), Error); }); - it('should be able to delete elements', () => { + it('is able to delete elements', () => { const l = new LinkedList(); l.add(1); @@ -128,7 +128,7 @@ describe('LinkedList', () => { assert.equal(l.length, 0); }); - it('should perform a function to all elements with forEach', () => { + it('performs a function to all elements with forEach', () => { const l = new LinkedList(); l.add(5); l.add(1); @@ -144,7 +144,7 @@ describe('LinkedList', () => { assert.deepEqual(a, [5, 1, 3, 10, 1000]); }); - it('should throw an error when trying to delete from an empty list', () => { + it('throws an error when trying to delete from an empty list', () => { const l = new LinkedList(); assert.throws(() => l.del(0), Error); }); diff --git a/src/test/data_structures/priority_queue.js b/src/test/data_structures/priority_queue.js index efb26af..f2674a2 100644 --- a/src/test/data_structures/priority_queue.js +++ b/src/test/data_structures/priority_queue.js @@ -2,7 +2,7 @@ const PriorityQueue = require('../..').DataStructures.PriorityQueue; const assert = require('assert'); describe('Min Priority Queue', () => { - it('should always return the element with the lowest priority', () => { + it('always returns the element with the lowest priority', () => { const q = new PriorityQueue(); assert(q.isEmpty()); q.insert('a', 10); @@ -50,7 +50,7 @@ describe('Min Priority Queue', () => { assert.equal(q.extract(), 'b'); }); - it('should be possible to change the priority of an item', () => { + it('is possible to change the priority of an item', () => { const q = new PriorityQueue({ a: 10, b: 2091, @@ -76,7 +76,7 @@ describe('Min Priority Queue', () => { }); it( - 'should just update the priority when trying to insert an element that ' + + 'just updates the priority when trying to insert an element that ' + ' already exists', () => { const q = new PriorityQueue({ diff --git a/src/test/data_structures/queue.js b/src/test/data_structures/queue.js index ae69861..ae496e7 100644 --- a/src/test/data_structures/queue.js +++ b/src/test/data_structures/queue.js @@ -2,13 +2,13 @@ const Queue = require('../..').DataStructures.Queue; const assert = require('assert'); describe('Queue', () => { - it('should start empty', () => { + it('starts empty', () => { const q = new Queue(); assert(q.isEmpty()); assert.equal(q.length, 0); }); - it('should implement a FIFO logic', () => { + it('implements a FIFO logic', () => { const q = new Queue(); q.push(1); q.push(2); @@ -22,8 +22,7 @@ describe('Queue', () => { }); it( - 'should allow me to peek at the first element in' + - ' line without popping it', + 'allows me to peek at the first element in' + ' line without popping it', () => { const q = new Queue(); assert.throws(() => q.peek(), Error); // Empty list diff --git a/src/test/data_structures/set.js b/src/test/data_structures/set.js index 515beb3..cca0aac 100644 --- a/src/test/data_structures/set.js +++ b/src/test/data_structures/set.js @@ -2,12 +2,12 @@ const HashSet = require('../..').DataStructures.Set; const assert = require('assert'); describe('HashSet', () => { - it('should start empty', () => { + it('starts empty', () => { const s = new HashSet(); assert.equal(s.size, 0); }); - it('should add all initial arguments', () => { + it('adds all initial arguments', () => { const s = new HashSet(1, 2, 3); assert.equal(s.size, 3); assert(s.contains(1)); @@ -15,7 +15,7 @@ describe('HashSet', () => { assert(s.contains(3)); }); - it('should add all arguments', () => { + it('adds all arguments', () => { const s = new HashSet(1, 2, 3); assert.equal(s.size, 3); s.add(4, 5, 6); @@ -28,7 +28,7 @@ describe('HashSet', () => { assert(s.contains(6)); }); - it('should remove all arguments', () => { + it('removes all arguments', () => { const s = new HashSet(1, 2, 3); assert.equal(s.size, 3); s.remove(1, 3); @@ -38,7 +38,7 @@ describe('HashSet', () => { assert(s.contains(2)); }); - it('should do nothing when trying to remove an element that doesn\'t exist', () => { + it('does nothing when trying to remove an element that doesnt exist', () => { const s = new HashSet(1, 2, 3); assert.equal(s.size, 3); s.remove(4); @@ -48,13 +48,13 @@ describe('HashSet', () => { assert(s.contains(3)); }); - it('should only contain its elements', () => { + it('only contains its elements', () => { const s = new HashSet(1, 2, 3); assert(s.contains(1)); assert(!s.contains(4)); }); - it('should perform a function to all elements with forEach', () => { + it('performs a function to all elements with forEach', () => { const s = new HashSet(); s.add(1, 2, 3); diff --git a/src/test/data_structures/stack.js b/src/test/data_structures/stack.js index 626a8bc..71a9a8e 100644 --- a/src/test/data_structures/stack.js +++ b/src/test/data_structures/stack.js @@ -2,13 +2,13 @@ const Stack = require('../..').DataStructures.Stack; const assert = require('assert'); describe('Stack', () => { - it('should start empty', () => { + it('starts empty', () => { const s = new Stack(); assert(s.isEmpty()); assert.equal(s.length, 0); }); - it('should implement a LIFO logic', () => { + it('implements a LIFO logic', () => { const s = new Stack(); s.push(1); s.push(2); @@ -22,8 +22,7 @@ describe('Stack', () => { }); it( - 'should allow me to peek at the top element in' + - ' the stack without popping it', + 'allows me to peek at the top element in' + ' the stack without popping it', () => { const s = new Stack(); s.push(1); diff --git a/src/test/data_structures/treap.js b/src/test/data_structures/treap.js index ceb97f7..8c3c2eb 100644 --- a/src/test/data_structures/treap.js +++ b/src/test/data_structures/treap.js @@ -8,7 +8,7 @@ describe('Treap', () => { treap = new Treap(); }); - it('should insert elements', () => { + it('inserts elements', () => { treap.insert(3); treap.insert(2); treap.insert(10); @@ -21,7 +21,7 @@ describe('Treap', () => { assert.equal(treap.root.size, 8); }); - it('should remove elements correctly', () => { + it('removes elements correctly', () => { // Value that not exist treap.remove(200); assert.equal(treap.root.size, 8); @@ -34,7 +34,7 @@ describe('Treap', () => { assert.equal(treap.root.size, 4); }); - it('should insert and remove elements', () => { + it('inserts and remove elements', () => { // [-100, 2, 3, 10] treap.insert(200); // [-100, 2, 3, 10, 200] @@ -52,7 +52,7 @@ describe('Treap', () => { assert.equal(treap.root.size, 5); }); - it('should check if an element exists', () => { + it('checks if an element exists', () => { // [1, 2, 3, 10, 100] assert.equal(treap.find(1), true); assert.equal(treap.find(2), true); @@ -65,7 +65,7 @@ describe('Treap', () => { assert.equal(treap.find(101), false); }); - it('should get minimum element', () => { + it('gets minimum element', () => { // [1, 2, 3, 10, 100] assert.equal(treap.minimum(), 1); treap.remove(1); @@ -79,7 +79,7 @@ describe('Treap', () => { assert.equal(treap.minimum(), 2); }); - it('should get maximum element', () => { + it('gets maximum element', () => { // [2, 3, 10, 100] assert.equal(treap.maximum(), 100); treap.remove(100); @@ -99,7 +99,7 @@ describe('Treap', () => { assert.equal(treap.maximum(), 1); }); - it('should handle dumplicated elements', () => { + it('handles dumplicated elements', () => { treap.insert(1); // [1, 1] assert.equal(treap.size(), 2); @@ -122,7 +122,7 @@ describe('Treap', () => { assert.equal(treap.size(), 0); }); - it('should keep balance', () => { + it('keeps balance', () => { // Insert 1023 elements randomly for (let i = 0; i < 1023; ++i) { treap.insert(Math.random()); @@ -132,7 +132,7 @@ describe('Treap', () => { assert(Math.abs(treap.height() - 23) < 5); }); - it('should rotate correctly', () => { + it('rotates correctly', () => { // Force clear the tree treap.root = null; treap.insert(1); diff --git a/src/test/util/comparator.js b/src/test/util/comparator.js index df6acfa..3f1909e 100644 --- a/src/test/util/comparator.js +++ b/src/test/util/comparator.js @@ -2,7 +2,7 @@ const Comparator = require('../../util/comparator'); const assert = require('assert'); describe('Comparator', () => { - it('Should use a default arithmetic comparison if no function is passed', () => { + it('uses a default arithmetic comparison if no function is passed', () => { const c = new Comparator(); assert.equal(c.compare(1, 1), 0); assert.equal(c.compare(1, 2), -1); @@ -22,7 +22,7 @@ describe('Comparator', () => { assert(!c.equal(0, 1)); }); - it('should allow comparison function to be defined by user', () => { + it('allows comparison function to be defined by user', () => { const compareFn = () => 0; const c = new Comparator(compareFn); assert.equal(c.compare(1, 1), 0); @@ -43,7 +43,7 @@ describe('Comparator', () => { assert(c.equal(0, 1)); }); - it('Should allow reversing the comparisons', () => { + it('allows reversing the comparisons', () => { const c = new Comparator(); c.reverse(); assert.equal(c.compare(1, 1), 0); From 021cf0af35755830bfd73e1690e6e6c596c3d867 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 14 Jun 2017 23:37:40 +0200 Subject: [PATCH 249/280] Update mocha --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a87e5f..16aecc2 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "eslint": "^4.0.0", "eslint-config-google": "^0.8.0", "istanbul": "^0.4.0", - "mocha": "^2.3.3", + "mocha": "^3.4.2", "pre-commit": "^1.1.2" }, "repository": { From 6d2de49eb4f69ddc51240d7bf3e5aece0a1361bd Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 14 Jun 2017 23:43:06 +0200 Subject: [PATCH 250/280] Turn internal Node types into classes --- src/data_structures/avl_tree.js | 14 ++++++++------ src/data_structures/bst.js | 12 +++++++----- src/data_structures/linked_list.js | 22 +++++++++++----------- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/data_structures/avl_tree.js b/src/data_structures/avl_tree.js index f5bffec..6795df5 100644 --- a/src/data_structures/avl_tree.js +++ b/src/data_structures/avl_tree.js @@ -519,12 +519,14 @@ class AVLTree { /** * Tree node */ -function Node(value, left, right, parent, height) { - this.value = value; - this.left = left; - this.right = right; - this.parent = parent; - this.height = height; +class Node { + constructor(value, left, right, parent, height) { + this.value = value; + this.left = left; + this.right = right; + this.parent = parent; + this.height = height; + } } module.exports = AVLTree; diff --git a/src/data_structures/bst.js b/src/data_structures/bst.js index c40a7c9..0493ada 100644 --- a/src/data_structures/bst.js +++ b/src/data_structures/bst.js @@ -127,11 +127,13 @@ class BST { /** * Tree node */ -function Node(value, parent) { - this.value = value; - this.parent = parent; - this.left = null; - this.right = null; +class Node { + constructor(value, parent) { + this.value = value; + this.parent = parent; + this.left = null; + this.right = null; + } } module.exports = BST; diff --git a/src/data_structures/linked_list.js b/src/data_structures/linked_list.js index 52ed4a6..b73c852 100644 --- a/src/data_structures/linked_list.js +++ b/src/data_structures/linked_list.js @@ -1,14 +1,3 @@ -/** - * A linked list node - */ -class Node { - constructor(value) { - this.value = value; - this.prev = null; - this.next = null; - } -} - /** * Doubly-linked list */ @@ -146,4 +135,15 @@ class LinkedList { } } +/** + * A linked list node + */ +class Node { + constructor(value) { + this.value = value; + this.prev = null; + this.next = null; + } +} + module.exports = LinkedList; From 0255021aa0cc0cac6e9c24fad5ee44b8c1cf92bb Mon Sep 17 00:00:00 2001 From: "Robert L. Read" Date: Sun, 30 Apr 2017 11:35:33 -0500 Subject: [PATCH 251/280] brining in to line with latest Uglify? --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f77dbe5..b34cf27 100644 --- a/Makefile +++ b/Makefile @@ -27,5 +27,5 @@ coveralls: VERSION := $(shell node -e "console.log(require('./package.json').version);") browser_bundle: setup - browserify $(realpath src/index.js) --s algorithms | uglifyjs -c -m --screw-ie8 --wrap --preamble "/* algorithms.js v$(VERSION) | (c) 2015 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */" > bundle/algorithms.browser.min.js + browserify $(realpath src/index.js) --s algorithms | uglifyjs -c -m --wrap --beautify preamble "/* algorithms.js v$(VERSION) | (c) 2015 Felipe Ribeiro | https://github.com/felipernb/algorithms.js/blob/master/LICENSE */" > bundle/algorithms.browser.min.js From 1bbde69261bf11c70a395402acdee88afd8854a4 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Mon, 11 Sep 2017 09:35:04 +0200 Subject: [PATCH 252/280] Code style --- src/algorithms/string/knuth_morris_pratt.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/algorithms/string/knuth_morris_pratt.js b/src/algorithms/string/knuth_morris_pratt.js index ff290d4..5a49e44 100644 --- a/src/algorithms/string/knuth_morris_pratt.js +++ b/src/algorithms/string/knuth_morris_pratt.js @@ -19,14 +19,11 @@ const buildTable = pattern => { while (position < length) { if (pattern[position - 1] === pattern[cnd]) { - ++cnd; - table[position] = cnd; - ++position; + table[position++] = ++cnd; } else if (cnd > 0) { cnd = table[cnd]; } else { - table[position] = 0; - ++position; + table[position++] = 0; } } @@ -60,13 +57,13 @@ const knuthMorrisPratt = (text, pattern) => { if (i === patternLength - 1) { return m; } - ++i; + i++; } else if (table[i] >= 0) { i = table[i]; m = m + i - table[i]; } else { i = 0; - ++m; + m++; } } From 8436b9d61cbad4db54e88ce08178ceffba5ca1e4 Mon Sep 17 00:00:00 2001 From: Matheus Dall'Rosa Date: Thu, 7 Sep 2017 19:36:15 -0300 Subject: [PATCH 253/280] Add operations for 2d vectors --- .../geometry/vector_operations2d.js | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/algorithms/geometry/vector_operations2d.js diff --git a/src/algorithms/geometry/vector_operations2d.js b/src/algorithms/geometry/vector_operations2d.js new file mode 100644 index 0000000..b559472 --- /dev/null +++ b/src/algorithms/geometry/vector_operations2d.js @@ -0,0 +1,25 @@ +/** + * Performs the cross product between two vectors. + * @param A vector object, example: {x : 0,y : 0} + * @param A vector object, example: {x : 0,y : 0} + * @return The result of the cross product between u and v. + */ +const crossProduct = (u, v) => { + return u.x*v.y - u.y*v.x; +}; + +/** + * @param A point object, example: {x : 0,y : 0} + * @param A point object, example: {x : 0,y : 0} + * @param A point object, example: {x : 0,y : 0} + * @return Returns true if the point c is counter-clockwise with respect + * to the straight-line which contains the vector ab, otherwise returns false. + */ +const isClockwise = (a, b, c) => { + return crossProduct({x: b.x-a.x, y: b.y-a.y}, c) < 0; +}; + +module.exports = { + crossProduct: crossProduct, + isClockwise: isClockwise +}; From 97475bc6c3f6dfa1153b8f5cdcf95d43636fc4f5 Mon Sep 17 00:00:00 2001 From: Matheus Dall'Rosa Date: Thu, 7 Sep 2017 19:36:57 -0300 Subject: [PATCH 254/280] Add tests for 2d vector operations --- .../geometry/vector_operations2d.js | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/test/algorithms/geometry/vector_operations2d.js diff --git a/src/test/algorithms/geometry/vector_operations2d.js b/src/test/algorithms/geometry/vector_operations2d.js new file mode 100644 index 0000000..b041f8a --- /dev/null +++ b/src/test/algorithms/geometry/vector_operations2d.js @@ -0,0 +1,34 @@ +const vectorOp = require('../../../algorithms/geometry/vector_operations2d'); +const assert = require('assert'); + +describe('VectorOperations', () => { + it('crossProduct: {-1,7}x{-5,8}', () => { + assert.equal(vectorOp. + crossProduct({x: -1, y: 7}, {x: -5, y: 8}), 27); + }); + + it('crossProduct: {45,45}x{-45,-45}', () => { + assert.equal(vectorOp. + crossProduct({x: 45, y: 45}, {x: -45, y: -45}), 0); + }); + + it('crossProduct: {1,1}x{1,0}', () => { + assert.equal(vectorOp. + crossProduct({x: 1, y: 1}, {x: 1, y: 0}), -1); + }); + + it('isClockwise: {0,0},{2,2},{0,2}', () => { + assert.equal(vectorOp. + isClockwise({x: 0, y: 0}, {x: 2, y: 2}, {x: 0, y: 2}), false); + }); + + it('isClockwise: {0,0},{2,2},{0,-2}', () => { + assert.equal(vectorOp. + isClockwise({x: 0, y: 0}, {x: 2, y: 2}, {x: 0, y: -2}), true); + }); + + it('isClockwise: {0,0},{2,2},{1,1}', () => { + assert.equal(vectorOp. + isClockwise({x: 0, y: 0}, {x: 2, y: 2}, {x: 1, y: 1}), false); + }); +}); From e5394067e2f2bec7c9a7dd13bbe7fcbe1bb27d91 Mon Sep 17 00:00:00 2001 From: Matheus Dall'Rosa Date: Fri, 8 Sep 2017 00:34:26 -0300 Subject: [PATCH 255/280] Add more 2d vector operations and it's tests --- .../geometry/vector_operations2d.js | 50 +++++++++++++++++-- .../geometry/vector_operations2d.js | 5 ++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/algorithms/geometry/vector_operations2d.js b/src/algorithms/geometry/vector_operations2d.js index b559472..db97d46 100644 --- a/src/algorithms/geometry/vector_operations2d.js +++ b/src/algorithms/geometry/vector_operations2d.js @@ -1,3 +1,12 @@ +/** + * @param A point a, example: {x : 0,y : 0} + * @param A point b, example: {x : 0,y : 0} + * @return A vector ab, example: {x : 0,y : 0} + */ +const newVector = (a, b) => { + return {x: b.x-a.x, y: b.y-a.y}; +}; + /** * Performs the cross product between two vectors. * @param A vector object, example: {x : 0,y : 0} @@ -8,18 +17,53 @@ const crossProduct = (u, v) => { return u.x*v.y - u.y*v.x; }; +/** + * Calculates the area of the parallelogram that can be + * generated by the vectors ab and ac. + * + * @param A point a, example: {x : 0,y : 0} + * @param A point b, example: {x : 0,y : 0} + * @param A point c, example: {x : 0,y : 0} + * @return A vector ab, example: {x : 0,y : 0} + * Note: Given that the area of the parallelogram is equal + * to the length of the vector w = (ab)x(ac) times -1, if the + * z coordinate of w is negative. With the right-hand rule + * we can deduce that if the area is negative, then + * the vector ab followed by the vector ac do not performs a + * left-turn. + */ +const parallelogramArea = (a, b, c) => { + return crossProduct(newVector(a,b), newVector(a,c)); +}; + /** * @param A point object, example: {x : 0,y : 0} * @param A point object, example: {x : 0,y : 0} * @param A point object, example: {x : 0,y : 0} - * @return Returns true if the point c is counter-clockwise with respect + * @return Returns true if the point c is clockwise with respect * to the straight-line which contains the vector ab, otherwise returns false. + * Note: This rule is given by the Right-hand rule. */ const isClockwise = (a, b, c) => { - return crossProduct({x: b.x-a.x, y: b.y-a.y}, c) < 0; + return parallelogramArea(a, b, c) < 0; +}; + +/** + * @param A point object, example: {x : 0,y : 0} + * @param A point object, example: {x : 0,y : 0} + * @param A point object, example: {x : 0,y : 0} + * @return Returns true if the point c is counter-clockwise with respect + * to the straight-line which contains the vector ab, otherwise returns false. + * Note: This rule is given by the Right-hand rule. + */ +const isCounterClockwise = (a, b, c) => { + return parallelogramArea(a, b, c) > 0; }; module.exports = { + newVector: newVector, crossProduct: crossProduct, - isClockwise: isClockwise + parallelogramArea: parallelogramArea, + isClockwise: isClockwise, + isCounterClockwise: isCounterClockwise }; diff --git a/src/test/algorithms/geometry/vector_operations2d.js b/src/test/algorithms/geometry/vector_operations2d.js index b041f8a..8bb0051 100644 --- a/src/test/algorithms/geometry/vector_operations2d.js +++ b/src/test/algorithms/geometry/vector_operations2d.js @@ -2,6 +2,11 @@ const vectorOp = require('../../../algorithms/geometry/vector_operations2d'); const assert = require('assert'); describe('VectorOperations', () => { + it('newVector: {0,4}->{1,2}', () => { + assert.deepEqual(vectorOp. + newVector({x: 0, y: 4}, {x: 1, y: 2}), {x: 1, y: -2}); + }); + it('crossProduct: {-1,7}x{-5,8}', () => { assert.equal(vectorOp. crossProduct({x: -1, y: 7}, {x: -5, y: 8}), 27); From aa693c423d5f8dfc545e1b8aa8dadf2e4c712b49 Mon Sep 17 00:00:00 2001 From: Matheus Dall'Rosa Date: Fri, 8 Sep 2017 00:35:47 -0300 Subject: [PATCH 256/280] Making the git pre-commit happy --- src/algorithms/geometry/vector_operations2d.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/geometry/vector_operations2d.js b/src/algorithms/geometry/vector_operations2d.js index db97d46..afc83c7 100644 --- a/src/algorithms/geometry/vector_operations2d.js +++ b/src/algorithms/geometry/vector_operations2d.js @@ -33,7 +33,7 @@ const crossProduct = (u, v) => { * left-turn. */ const parallelogramArea = (a, b, c) => { - return crossProduct(newVector(a,b), newVector(a,c)); + return crossProduct(newVector(a, b), newVector(a, c)); }; /** From 168e10280195251288c2220dbd729a9e536c43c1 Mon Sep 17 00:00:00 2001 From: Matheus Dall'Rosa Date: Fri, 8 Sep 2017 03:42:00 -0300 Subject: [PATCH 257/280] Add length function --- src/algorithms/geometry/vector_operations2d.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/algorithms/geometry/vector_operations2d.js b/src/algorithms/geometry/vector_operations2d.js index afc83c7..54c2bce 100644 --- a/src/algorithms/geometry/vector_operations2d.js +++ b/src/algorithms/geometry/vector_operations2d.js @@ -7,6 +7,14 @@ const newVector = (a, b) => { return {x: b.x-a.x, y: b.y-a.y}; }; +/** + * @param A vector v, example: {x : 0,y : 0} + * @return The length of v. + */ +const length = v => { + return v.x*v.x + v.y*v.y; +}; + /** * Performs the cross product between two vectors. * @param A vector object, example: {x : 0,y : 0} @@ -62,6 +70,7 @@ const isCounterClockwise = (a, b, c) => { module.exports = { newVector: newVector, + length: length, crossProduct: crossProduct, parallelogramArea: parallelogramArea, isClockwise: isClockwise, From 601a8232aef7dcf88b1ba40110905a4f20398a6d Mon Sep 17 00:00:00 2001 From: Matheus Dall'Rosa Date: Fri, 8 Sep 2017 03:46:29 -0300 Subject: [PATCH 258/280] Add Graham's scan alorithm, it need tests --- src/algorithms/geometry/graham_scan.js | 51 ++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/algorithms/geometry/graham_scan.js diff --git a/src/algorithms/geometry/graham_scan.js b/src/algorithms/geometry/graham_scan.js new file mode 100644 index 0000000..0b7c97f --- /dev/null +++ b/src/algorithms/geometry/graham_scan.js @@ -0,0 +1,51 @@ +const vectorOp = require('./vector_operations2d.js'); + +/** + * Given an array P with N points on a two dimensional space, + * the function grahamScan calculates the convex hull of P + * in O(N * log(N)) time and using O(N) space. + * Implemented algorithm: Graham's Scan. + * + * @param An array P with N points, each point should be a literal, + * example: {x:0,y:0}. + * @return An array P' with N' points which belongs to the convex hull of P. + * + * Node: If three points are collinear and all of the three points + * belongs to the convex hull, then the three points will be present on P'. + */ +const grahamScan = function(P) { + if (P.length <= 3) { + return P; + } + preprocessing(P); + const convexHull = [P[0], P[1]]; + for (let i = 2; i < P.length; i++) { + let j = convexHull.length; + while (j >= 2 && vectorOp. + isClockwise(convexHull[j-2], convexHull[j-1], P[i])) { + convexHull.pop(); + j--; + } + convexHull.push(P[i]); + } + return convexHull; +}; + +const preprocessing = function(P) { + let pivot = P[0]; + for (let i = 1; i < P.length; i++) { + if (pivot.y > P[i].y || (pivot.y === P[i].y && pivot.x > P[i].x)) { + pivot = P[i]; + } + } + P.sort(function cmp(a, b) { + const area = vectorOp.parallelogramArea(pivot, a, b); + if (Math.abs(area) < 1e-6) { + return vectorOp.length(vectorOp.newVector(pivot, a)) + - vectorOp.length(vectorOp.newVector(pivot, b)); + } + return -area; + }); +}; + +module.exports = grahamScan; From 261683a8bbf5bb5398714fcd6528a5699958ea0f Mon Sep 17 00:00:00 2001 From: Matheus Dall'Rosa Date: Fri, 8 Sep 2017 14:47:48 -0300 Subject: [PATCH 259/280] Changes the approach to handle collinear points --- src/algorithms/geometry/graham_scan.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/algorithms/geometry/graham_scan.js b/src/algorithms/geometry/graham_scan.js index 0b7c97f..1775e52 100644 --- a/src/algorithms/geometry/graham_scan.js +++ b/src/algorithms/geometry/graham_scan.js @@ -10,19 +10,22 @@ const vectorOp = require('./vector_operations2d.js'); * example: {x:0,y:0}. * @return An array P' with N' points which belongs to the convex hull of P. * - * Node: If three points are collinear and all of the three points - * belongs to the convex hull, then the three points will be present on P'. + * Note: If exists a subset S of P that contains only collinear points + * which are present on the convex hull of P, then only the pair with + * the largest distance will be present on P'. */ const grahamScan = function(P) { if (P.length <= 3) { return P; } preprocessing(P); + console.log(P); const convexHull = [P[0], P[1]]; for (let i = 2; i < P.length; i++) { let j = convexHull.length; - while (j >= 2 && vectorOp. - isClockwise(convexHull[j-2], convexHull[j-1], P[i])) { + while (j >= 2 && + vectorOp. + parallelogramArea(convexHull[j-2], convexHull[j-1], P[i]) <= 0) { convexHull.pop(); j--; } @@ -31,6 +34,14 @@ const grahamScan = function(P) { return convexHull; }; +/** + * @param An array P with N points, each point should be a literal, + * @return An array P' with N' points which belongs to the convex hull of P. + * + * Note: After the preprocessing the points are ordered by the angle + * between the vectors pivot -> Pi and (0,1). Where Pi is a point on P. + * On the counter-clockwise direction. + */ const preprocessing = function(P) { let pivot = P[0]; for (let i = 1; i < P.length; i++) { @@ -38,6 +49,7 @@ const preprocessing = function(P) { pivot = P[i]; } } + P.sort(function cmp(a, b) { const area = vectorOp.parallelogramArea(pivot, a, b); if (Math.abs(area) < 1e-6) { From 6bd1e6e2e08ca928fee6eb851b1e514468a0d97d Mon Sep 17 00:00:00 2001 From: Matheus Dall'Rosa Date: Fri, 8 Sep 2017 14:54:55 -0300 Subject: [PATCH 260/280] Graham's Scan tests --- src/test/algorithms/geometry/graham_scan.js | 78 +++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/test/algorithms/geometry/graham_scan.js diff --git a/src/test/algorithms/geometry/graham_scan.js b/src/test/algorithms/geometry/graham_scan.js new file mode 100644 index 0000000..2f3534a --- /dev/null +++ b/src/test/algorithms/geometry/graham_scan.js @@ -0,0 +1,78 @@ +const grahamScan = require('../../../algorithms/geometry/graham_scan'); +const assert = require('assert'); + +describe('Graham s Scan algorithm', () => { + /* we have to ensure the order before using deepEqual. */ + let pointComparison; + before(() => { + pointComparison = function(a, b) { + return (a.x != b.x) ? a.x < b.x : a.y < b.y; + }; + }); + + it('ConvexHull of set 0', () => { + const P = [{x: 3, y: 4}, {x: 5, y: 2}, {x: 7, y: 4}, + {x: 3, y: 5}, {x: 4.7, y: 3.66}, {x: 5.4, y: 4.52}, + {x: 5, y: 6}, {x: 6, y: 6}, {x: 5.62, y: 3.5}]; + const convexHullOfP = [{x: 3, y: 4}, {x: 5, y: 2}, {x: 7, y: 4}, + {x: 3, y: 5}, {x: 5, y: 6}, {x: 6, y: 6}]; + convexHullOfP.sort(pointComparison); + const computedConvexHull = grahamScan(P); + computedConvexHull.sort(pointComparison); + assert.deepEqual(computedConvexHull, convexHullOfP); + }); + + it('ConvexHull of set 1', () => { + const P = [{x: 2.8, y: 3.6}, {x: 4.2, y: 3.7}, {x: 3.6, y: 4.3}, + {x: 2.2, y: 5.2}, {x: 3.6, y: 5.8}, {x: 4.6, y: 5.2}, + {x: 4.8, y: 4.5}, {x: 5.6, y: 3.4}, {x: 4, y: 3}, + {x: 3, y: 3.1}, {x: 1.9, y: 2.7}, {x: 1.6, y: 3.7}, + {x: 2.3, y: 4.2}, {x: 3, y: 2.4}]; + const convexHullOfP = [{x: 2.2, y: 5.2}, {x: 3.6, y: 5.8}, + {x: 4.6, y: 5.2}, {x: 5.6, y: 3.4}, + {x: 1.9, y: 2.7}, {x: 1.6, y: 3.7}, + {x: 3, y: 2.4}]; + convexHullOfP.sort(pointComparison); + const computedConvexHull = grahamScan(P); + computedConvexHull.sort(pointComparison); + assert.deepEqual(computedConvexHull, convexHullOfP); + }); + + it('ConvexHull of set 2', () => { + const P = [{x: 1.7, y: 2.4}, {x: 2.8, y: 2}, {x: 1.3, y: 1.6}, + {x: 2.4, y: 1.4}, {x: 2.4, y: 0.6}, {x: 1.6, y: 0.7}, + {x: 4, y: 1}, {x: 4.9, y: 1.3}, {x: 3.5, y: 2.1}, + {x: 3.7, y: 2.8}, {x: 2.6, y: 3.1}, {x: 0.7, y: 2.8}, + {x: 0.9, y: 1.6}]; + const convexHullOfP = [{x: 2.4, y: 0.6}, {x: 1.6, y: 0.7}, + {x: 4, y: 1}, {x: 4.9, y: 1.3}, + {x: 3.7, y: 2.8}, {x: 2.6, y: 3.1}, + {x: 0.7, y: 2.8}, {x: 0.9, y: 1.6}]; + convexHullOfP.sort(pointComparison); + const computedConvexHull = grahamScan(P); + computedConvexHull.sort(pointComparison); + assert.deepEqual(computedConvexHull, convexHullOfP); + }); + + it('ConvexHull of set 3', () => { + const P = [{x: 2, y: 1}, {x: 3, y: 2}, {x: 4, y: 3}, {x: 5, y: 4}, + {x: 3, y: 3}, {x: 3, y: 4}, {x: 2.4, y: 3.5}, {x: 3.6, y: 3.5}, + {x: 2, y: 4}, {x: 2, y: 3}, {x: 2, y: 2}]; + const convexHullOfP = [{x: 2, y: 1}, {x: 5, y: 4}, {x: 2, y: 4}]; + convexHullOfP.sort(pointComparison); + const computedConvexHull = grahamScan(P); + computedConvexHull.sort(pointComparison); + assert.deepEqual(computedConvexHull, convexHullOfP); + }); + + it('ConvexHull of set 4', () => { + const P = [{x: 2, y: 1}, {x: 3, y: 2}, {x: 4, y: 3}, {x: 4, y: 4}, + {x: 2, y: 5}, {x: 2, y: 6}, {x: 2, y: 4}, {x: 5, y: 4}, + {x: 3, y: 5}, {x: 2, y: 3}, {x: 2, y: 2}]; + const convexHullOfP = [{x: 2, y: 1}, {x: 5, y: 4}, {x: 2, y: 6}]; + convexHullOfP.sort(pointComparison); + const computedConvexHull = grahamScan(P); + computedConvexHull.sort(pointComparison); + assert.deepEqual(computedConvexHull, convexHullOfP); + }); +}); From b66ba85b73a63eaf6200a8c6bcaa7f404b6633f5 Mon Sep 17 00:00:00 2001 From: Matheus Dall'Rosa Date: Sun, 10 Sep 2017 18:49:31 -0300 Subject: [PATCH 261/280] Remove debugging info --- src/algorithms/geometry/graham_scan.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/algorithms/geometry/graham_scan.js b/src/algorithms/geometry/graham_scan.js index 1775e52..04d6116 100644 --- a/src/algorithms/geometry/graham_scan.js +++ b/src/algorithms/geometry/graham_scan.js @@ -19,7 +19,6 @@ const grahamScan = function(P) { return P; } preprocessing(P); - console.log(P); const convexHull = [P[0], P[1]]; for (let i = 2; i < P.length; i++) { let j = convexHull.length; From 04a5258757d8372e703f9f8cb9af6627910e5ce9 Mon Sep 17 00:00:00 2001 From: Matheus Dall'Rosa Date: Sun, 10 Sep 2017 22:14:51 -0300 Subject: [PATCH 262/280] Change paralellogramArea <= 0 to ~isCounterClockwise --- src/algorithms/geometry/graham_scan.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/algorithms/geometry/graham_scan.js b/src/algorithms/geometry/graham_scan.js index 04d6116..f47aa81 100644 --- a/src/algorithms/geometry/graham_scan.js +++ b/src/algorithms/geometry/graham_scan.js @@ -23,8 +23,8 @@ const grahamScan = function(P) { for (let i = 2; i < P.length; i++) { let j = convexHull.length; while (j >= 2 && - vectorOp. - parallelogramArea(convexHull[j-2], convexHull[j-1], P[i]) <= 0) { + !vectorOp. + isCounterClockwise(convexHull[j-2], convexHull[j-1], P[i])) { convexHull.pop(); j--; } From 02aea73c0cba7426bbb571c96090873416fdd833 Mon Sep 17 00:00:00 2001 From: Matheus Dall'Rosa Date: Mon, 11 Sep 2017 14:27:52 -0300 Subject: [PATCH 263/280] Move to arrow function and correct the variable names --- src/algorithms/geometry/graham_scan.js | 50 +++++++++++++------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/algorithms/geometry/graham_scan.js b/src/algorithms/geometry/graham_scan.js index f47aa81..e5f6308 100644 --- a/src/algorithms/geometry/graham_scan.js +++ b/src/algorithms/geometry/graham_scan.js @@ -1,55 +1,55 @@ const vectorOp = require('./vector_operations2d.js'); /** - * Given an array P with N points on a two dimensional space, - * the function grahamScan calculates the convex hull of P + * Given an array p with N points on a two dimensional space, + * the function grahamScan calculates the convex hull of p * in O(N * log(N)) time and using O(N) space. * Implemented algorithm: Graham's Scan. * - * @param An array P with N points, each point should be a literal, + * @param An array p with N points, each point should be a literal, * example: {x:0,y:0}. - * @return An array P' with N' points which belongs to the convex hull of P. + * @return An array p' with N' points which belongs to the convex hull of p. * - * Note: If exists a subset S of P that contains only collinear points - * which are present on the convex hull of P, then only the pair with - * the largest distance will be present on P'. + * Note: If exists a subset S of p that contains only collinear points + * which are present on the convex hull of p, then only the pair with + * the largest distance will be present on p'. */ -const grahamScan = function(P) { - if (P.length <= 3) { - return P; +const grahamScan = p => { + if (p.length <= 3) { + return p; } - preprocessing(P); - const convexHull = [P[0], P[1]]; - for (let i = 2; i < P.length; i++) { + preprocessing(p); + const convexHull = [p[0], p[1]]; + for (let i = 2; i < p.length; i++) { let j = convexHull.length; while (j >= 2 && !vectorOp. - isCounterClockwise(convexHull[j-2], convexHull[j-1], P[i])) { + isCounterClockwise(convexHull[j-2], convexHull[j-1], p[i])) { convexHull.pop(); j--; } - convexHull.push(P[i]); + convexHull.push(p[i]); } return convexHull; }; /** - * @param An array P with N points, each point should be a literal, - * @return An array P' with N' points which belongs to the convex hull of P. + * @param An array p with N points, each point should be a literal, + * example: {x:0,y:0}. * - * Note: After the preprocessing the points are ordered by the angle - * between the vectors pivot -> Pi and (0,1). Where Pi is a point on P. + * Note: After the preprocessing the points will be ordered by the angle + * between the vectors pivot -> pi and (0,1). Where pi is a point on p. * On the counter-clockwise direction. */ -const preprocessing = function(P) { - let pivot = P[0]; - for (let i = 1; i < P.length; i++) { - if (pivot.y > P[i].y || (pivot.y === P[i].y && pivot.x > P[i].x)) { - pivot = P[i]; +const preprocessing = p => { + let pivot = p[0]; + for (let i = 1; i < p.length; i++) { + if (pivot.y > p[i].y || (pivot.y === p[i].y && pivot.x > p[i].x)) { + pivot = p[i]; } } - P.sort(function cmp(a, b) { + p.sort((a, b) => { const area = vectorOp.parallelogramArea(pivot, a, b); if (Math.abs(area) < 1e-6) { return vectorOp.length(vectorOp.newVector(pivot, a)) From 26cbaaa515105f399d9c2b6d2d405d1ab47341ac Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Mon, 11 Sep 2017 21:47:19 +0200 Subject: [PATCH 264/280] Prettier --- src/algorithms/geometry/graham_scan.js | 13 +- .../geometry/vector_operations2d.js | 25 +--- src/algorithms/sorting/radix_sort.js | 5 +- src/algorithms/string/huffman.js | 10 +- src/test/algorithms/geometry/graham_scan.js | 126 +++++++++++++----- .../geometry/vector_operations2d.js | 33 +++-- src/test/algorithms/math/fast_power.js | 2 +- 7 files changed, 141 insertions(+), 73 deletions(-) diff --git a/src/algorithms/geometry/graham_scan.js b/src/algorithms/geometry/graham_scan.js index e5f6308..4c68452 100644 --- a/src/algorithms/geometry/graham_scan.js +++ b/src/algorithms/geometry/graham_scan.js @@ -22,9 +22,10 @@ const grahamScan = p => { const convexHull = [p[0], p[1]]; for (let i = 2; i < p.length; i++) { let j = convexHull.length; - while (j >= 2 && - !vectorOp. - isCounterClockwise(convexHull[j-2], convexHull[j-1], p[i])) { + while ( + j >= 2 && + !vectorOp.isCounterClockwise(convexHull[j - 2], convexHull[j - 1], p[i]) + ) { convexHull.pop(); j--; } @@ -52,8 +53,10 @@ const preprocessing = p => { p.sort((a, b) => { const area = vectorOp.parallelogramArea(pivot, a, b); if (Math.abs(area) < 1e-6) { - return vectorOp.length(vectorOp.newVector(pivot, a)) - - vectorOp.length(vectorOp.newVector(pivot, b)); + return ( + vectorOp.length(vectorOp.newVector(pivot, a)) - + vectorOp.length(vectorOp.newVector(pivot, b)) + ); } return -area; }); diff --git a/src/algorithms/geometry/vector_operations2d.js b/src/algorithms/geometry/vector_operations2d.js index 54c2bce..9aed56b 100644 --- a/src/algorithms/geometry/vector_operations2d.js +++ b/src/algorithms/geometry/vector_operations2d.js @@ -3,17 +3,13 @@ * @param A point b, example: {x : 0,y : 0} * @return A vector ab, example: {x : 0,y : 0} */ -const newVector = (a, b) => { - return {x: b.x-a.x, y: b.y-a.y}; -}; +const newVector = (a, b) => ({x: b.x - a.x, y: b.y - a.y}); /** * @param A vector v, example: {x : 0,y : 0} * @return The length of v. */ -const length = v => { - return v.x*v.x + v.y*v.y; -}; +const length = v => v.x * v.x + v.y * v.y; /** * Performs the cross product between two vectors. @@ -21,9 +17,7 @@ const length = v => { * @param A vector object, example: {x : 0,y : 0} * @return The result of the cross product between u and v. */ -const crossProduct = (u, v) => { - return u.x*v.y - u.y*v.x; -}; +const crossProduct = (u, v) => u.x * v.y - u.y * v.x; /** * Calculates the area of the parallelogram that can be @@ -40,9 +34,8 @@ const crossProduct = (u, v) => { * the vector ab followed by the vector ac do not performs a * left-turn. */ -const parallelogramArea = (a, b, c) => { - return crossProduct(newVector(a, b), newVector(a, c)); -}; +const parallelogramArea = (a, b, c) => + crossProduct(newVector(a, b), newVector(a, c)); /** * @param A point object, example: {x : 0,y : 0} @@ -52,9 +45,7 @@ const parallelogramArea = (a, b, c) => { * to the straight-line which contains the vector ab, otherwise returns false. * Note: This rule is given by the Right-hand rule. */ -const isClockwise = (a, b, c) => { - return parallelogramArea(a, b, c) < 0; -}; +const isClockwise = (a, b, c) => parallelogramArea(a, b, c) < 0; /** * @param A point object, example: {x : 0,y : 0} @@ -64,9 +55,7 @@ const isClockwise = (a, b, c) => { * to the straight-line which contains the vector ab, otherwise returns false. * Note: This rule is given by the Right-hand rule. */ -const isCounterClockwise = (a, b, c) => { - return parallelogramArea(a, b, c) > 0; -}; +const isCounterClockwise = (a, b, c) => parallelogramArea(a, b, c) > 0; module.exports = { newVector: newVector, diff --git a/src/algorithms/sorting/radix_sort.js b/src/algorithms/sorting/radix_sort.js index fe71205..9b4169c 100644 --- a/src/algorithms/sorting/radix_sort.js +++ b/src/algorithms/sorting/radix_sort.js @@ -72,9 +72,8 @@ const maximumKey = a => { */ const radixSort = array => { const max = maximumKey(array); - const digitsMax = max === 0 - ? 1 - : 1 + Math.floor(Math.log(max) / Math.log(10)); // log base 10 + const digitsMax = + max === 0 ? 1 : 1 + Math.floor(Math.log(max) / Math.log(10)); // log base 10 for (let i = 0; i < digitsMax; i++) { array = auxiliaryCountingSort(array, i); diff --git a/src/algorithms/string/huffman.js b/src/algorithms/string/huffman.js index 5ce429c..7c96e25 100644 --- a/src/algorithms/string/huffman.js +++ b/src/algorithms/string/huffman.js @@ -139,12 +139,18 @@ huffman.encode = (string, compressed) => { })(root); const encoding = letters.reduce((acc, letter) => { - acc[letter.char] = letter.code.split('').reverse().join(''); + acc[letter.char] = letter.code + .split('') + .reverse() + .join(''); return acc; }, {}); // Finally, apply the encoding to the given string. - const result = string.split('').map(char => encoding[char]).join(''); + const result = string + .split('') + .map(char => encoding[char]) + .join(''); return { encoding, diff --git a/src/test/algorithms/geometry/graham_scan.js b/src/test/algorithms/geometry/graham_scan.js index 2f3534a..afdc457 100644 --- a/src/test/algorithms/geometry/graham_scan.js +++ b/src/test/algorithms/geometry/graham_scan.js @@ -6,16 +6,30 @@ describe('Graham s Scan algorithm', () => { let pointComparison; before(() => { pointComparison = function(a, b) { - return (a.x != b.x) ? a.x < b.x : a.y < b.y; + return a.x != b.x ? a.x < b.x : a.y < b.y; }; }); it('ConvexHull of set 0', () => { - const P = [{x: 3, y: 4}, {x: 5, y: 2}, {x: 7, y: 4}, - {x: 3, y: 5}, {x: 4.7, y: 3.66}, {x: 5.4, y: 4.52}, - {x: 5, y: 6}, {x: 6, y: 6}, {x: 5.62, y: 3.5}]; - const convexHullOfP = [{x: 3, y: 4}, {x: 5, y: 2}, {x: 7, y: 4}, - {x: 3, y: 5}, {x: 5, y: 6}, {x: 6, y: 6}]; + const P = [ + {x: 3, y: 4}, + {x: 5, y: 2}, + {x: 7, y: 4}, + {x: 3, y: 5}, + {x: 4.7, y: 3.66}, + {x: 5.4, y: 4.52}, + {x: 5, y: 6}, + {x: 6, y: 6}, + {x: 5.62, y: 3.5} + ]; + const convexHullOfP = [ + {x: 3, y: 4}, + {x: 5, y: 2}, + {x: 7, y: 4}, + {x: 3, y: 5}, + {x: 5, y: 6}, + {x: 6, y: 6} + ]; convexHullOfP.sort(pointComparison); const computedConvexHull = grahamScan(P); computedConvexHull.sort(pointComparison); @@ -23,15 +37,31 @@ describe('Graham s Scan algorithm', () => { }); it('ConvexHull of set 1', () => { - const P = [{x: 2.8, y: 3.6}, {x: 4.2, y: 3.7}, {x: 3.6, y: 4.3}, - {x: 2.2, y: 5.2}, {x: 3.6, y: 5.8}, {x: 4.6, y: 5.2}, - {x: 4.8, y: 4.5}, {x: 5.6, y: 3.4}, {x: 4, y: 3}, - {x: 3, y: 3.1}, {x: 1.9, y: 2.7}, {x: 1.6, y: 3.7}, - {x: 2.3, y: 4.2}, {x: 3, y: 2.4}]; - const convexHullOfP = [{x: 2.2, y: 5.2}, {x: 3.6, y: 5.8}, - {x: 4.6, y: 5.2}, {x: 5.6, y: 3.4}, - {x: 1.9, y: 2.7}, {x: 1.6, y: 3.7}, - {x: 3, y: 2.4}]; + const P = [ + {x: 2.8, y: 3.6}, + {x: 4.2, y: 3.7}, + {x: 3.6, y: 4.3}, + {x: 2.2, y: 5.2}, + {x: 3.6, y: 5.8}, + {x: 4.6, y: 5.2}, + {x: 4.8, y: 4.5}, + {x: 5.6, y: 3.4}, + {x: 4, y: 3}, + {x: 3, y: 3.1}, + {x: 1.9, y: 2.7}, + {x: 1.6, y: 3.7}, + {x: 2.3, y: 4.2}, + {x: 3, y: 2.4} + ]; + const convexHullOfP = [ + {x: 2.2, y: 5.2}, + {x: 3.6, y: 5.8}, + {x: 4.6, y: 5.2}, + {x: 5.6, y: 3.4}, + {x: 1.9, y: 2.7}, + {x: 1.6, y: 3.7}, + {x: 3, y: 2.4} + ]; convexHullOfP.sort(pointComparison); const computedConvexHull = grahamScan(P); computedConvexHull.sort(pointComparison); @@ -39,15 +69,31 @@ describe('Graham s Scan algorithm', () => { }); it('ConvexHull of set 2', () => { - const P = [{x: 1.7, y: 2.4}, {x: 2.8, y: 2}, {x: 1.3, y: 1.6}, - {x: 2.4, y: 1.4}, {x: 2.4, y: 0.6}, {x: 1.6, y: 0.7}, - {x: 4, y: 1}, {x: 4.9, y: 1.3}, {x: 3.5, y: 2.1}, - {x: 3.7, y: 2.8}, {x: 2.6, y: 3.1}, {x: 0.7, y: 2.8}, - {x: 0.9, y: 1.6}]; - const convexHullOfP = [{x: 2.4, y: 0.6}, {x: 1.6, y: 0.7}, - {x: 4, y: 1}, {x: 4.9, y: 1.3}, - {x: 3.7, y: 2.8}, {x: 2.6, y: 3.1}, - {x: 0.7, y: 2.8}, {x: 0.9, y: 1.6}]; + const P = [ + {x: 1.7, y: 2.4}, + {x: 2.8, y: 2}, + {x: 1.3, y: 1.6}, + {x: 2.4, y: 1.4}, + {x: 2.4, y: 0.6}, + {x: 1.6, y: 0.7}, + {x: 4, y: 1}, + {x: 4.9, y: 1.3}, + {x: 3.5, y: 2.1}, + {x: 3.7, y: 2.8}, + {x: 2.6, y: 3.1}, + {x: 0.7, y: 2.8}, + {x: 0.9, y: 1.6} + ]; + const convexHullOfP = [ + {x: 2.4, y: 0.6}, + {x: 1.6, y: 0.7}, + {x: 4, y: 1}, + {x: 4.9, y: 1.3}, + {x: 3.7, y: 2.8}, + {x: 2.6, y: 3.1}, + {x: 0.7, y: 2.8}, + {x: 0.9, y: 1.6} + ]; convexHullOfP.sort(pointComparison); const computedConvexHull = grahamScan(P); computedConvexHull.sort(pointComparison); @@ -55,9 +101,19 @@ describe('Graham s Scan algorithm', () => { }); it('ConvexHull of set 3', () => { - const P = [{x: 2, y: 1}, {x: 3, y: 2}, {x: 4, y: 3}, {x: 5, y: 4}, - {x: 3, y: 3}, {x: 3, y: 4}, {x: 2.4, y: 3.5}, {x: 3.6, y: 3.5}, - {x: 2, y: 4}, {x: 2, y: 3}, {x: 2, y: 2}]; + const P = [ + {x: 2, y: 1}, + {x: 3, y: 2}, + {x: 4, y: 3}, + {x: 5, y: 4}, + {x: 3, y: 3}, + {x: 3, y: 4}, + {x: 2.4, y: 3.5}, + {x: 3.6, y: 3.5}, + {x: 2, y: 4}, + {x: 2, y: 3}, + {x: 2, y: 2} + ]; const convexHullOfP = [{x: 2, y: 1}, {x: 5, y: 4}, {x: 2, y: 4}]; convexHullOfP.sort(pointComparison); const computedConvexHull = grahamScan(P); @@ -66,9 +122,19 @@ describe('Graham s Scan algorithm', () => { }); it('ConvexHull of set 4', () => { - const P = [{x: 2, y: 1}, {x: 3, y: 2}, {x: 4, y: 3}, {x: 4, y: 4}, - {x: 2, y: 5}, {x: 2, y: 6}, {x: 2, y: 4}, {x: 5, y: 4}, - {x: 3, y: 5}, {x: 2, y: 3}, {x: 2, y: 2}]; + const P = [ + {x: 2, y: 1}, + {x: 3, y: 2}, + {x: 4, y: 3}, + {x: 4, y: 4}, + {x: 2, y: 5}, + {x: 2, y: 6}, + {x: 2, y: 4}, + {x: 5, y: 4}, + {x: 3, y: 5}, + {x: 2, y: 3}, + {x: 2, y: 2} + ]; const convexHullOfP = [{x: 2, y: 1}, {x: 5, y: 4}, {x: 2, y: 6}]; convexHullOfP.sort(pointComparison); const computedConvexHull = grahamScan(P); diff --git a/src/test/algorithms/geometry/vector_operations2d.js b/src/test/algorithms/geometry/vector_operations2d.js index 8bb0051..c062a94 100644 --- a/src/test/algorithms/geometry/vector_operations2d.js +++ b/src/test/algorithms/geometry/vector_operations2d.js @@ -3,37 +3,42 @@ const assert = require('assert'); describe('VectorOperations', () => { it('newVector: {0,4}->{1,2}', () => { - assert.deepEqual(vectorOp. - newVector({x: 0, y: 4}, {x: 1, y: 2}), {x: 1, y: -2}); + assert.deepEqual(vectorOp.newVector({x: 0, y: 4}, {x: 1, y: 2}), { + x: 1, + y: -2 + }); }); it('crossProduct: {-1,7}x{-5,8}', () => { - assert.equal(vectorOp. - crossProduct({x: -1, y: 7}, {x: -5, y: 8}), 27); + assert.equal(vectorOp.crossProduct({x: -1, y: 7}, {x: -5, y: 8}), 27); }); it('crossProduct: {45,45}x{-45,-45}', () => { - assert.equal(vectorOp. - crossProduct({x: 45, y: 45}, {x: -45, y: -45}), 0); + assert.equal(vectorOp.crossProduct({x: 45, y: 45}, {x: -45, y: -45}), 0); }); it('crossProduct: {1,1}x{1,0}', () => { - assert.equal(vectorOp. - crossProduct({x: 1, y: 1}, {x: 1, y: 0}), -1); + assert.equal(vectorOp.crossProduct({x: 1, y: 1}, {x: 1, y: 0}), -1); }); it('isClockwise: {0,0},{2,2},{0,2}', () => { - assert.equal(vectorOp. - isClockwise({x: 0, y: 0}, {x: 2, y: 2}, {x: 0, y: 2}), false); + assert.equal( + vectorOp.isClockwise({x: 0, y: 0}, {x: 2, y: 2}, {x: 0, y: 2}), + false + ); }); it('isClockwise: {0,0},{2,2},{0,-2}', () => { - assert.equal(vectorOp. - isClockwise({x: 0, y: 0}, {x: 2, y: 2}, {x: 0, y: -2}), true); + assert.equal( + vectorOp.isClockwise({x: 0, y: 0}, {x: 2, y: 2}, {x: 0, y: -2}), + true + ); }); it('isClockwise: {0,0},{2,2},{1,1}', () => { - assert.equal(vectorOp. - isClockwise({x: 0, y: 0}, {x: 2, y: 2}, {x: 1, y: 1}), false); + assert.equal( + vectorOp.isClockwise({x: 0, y: 0}, {x: 2, y: 2}, {x: 1, y: 1}), + false + ); }); }); diff --git a/src/test/algorithms/math/fast_power.js b/src/test/algorithms/math/fast_power.js index 370e566..2bb21e4 100644 --- a/src/test/algorithms/math/fast_power.js +++ b/src/test/algorithms/math/fast_power.js @@ -7,7 +7,7 @@ const assertApproximatelyEqual = (a, b, eps) => { assert(Math.abs(a - b) < eps); }; -const multiplyModulo = modulo => (a, b) => a * b % modulo; +const multiplyModulo = modulo => (a, b) => (a * b) % modulo; /** * This operation is isomorphic to addition in Z/3. From 44fcc41deb59e597a8cd1fb44ae13cc0a66547b5 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 21 Feb 2018 11:13:58 +0100 Subject: [PATCH 265/280] Enable Sonarcloud --- .travis.yml | 10 +++++++--- sonar-project.properties | 12 ++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 sonar-project.properties diff --git a/.travis.yml b/.travis.yml index f247b3f..c4d4971 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,12 @@ language: node_js sudo: false node_js: - - '6' - - '7' - '8' -script: "make" + - '9' +script: + - make + - sonar-scanner after_success: "make coveralls" +addons: + sonarcloud: + organization: "felipernb-github" diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..507879e --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,12 @@ +# must be unique in a given SonarQube instance +sonar.projectKey=algorithmsjs +# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1. +sonar.projectName=algorithms.js +sonar.projectVersion=0.11.0 + +# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. +# This property is optional if sonar.modules is set. +sonar.sources=. + +# Encoding of the source code. Default is default system encoding +#sonar.sourceEncoding=UTF-8 From 7df9bd1a0a56b8ba0fb1da896537eee589bc2380 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Wed, 21 Feb 2018 11:33:58 +0100 Subject: [PATCH 266/280] Sonarcloud to run just on /src --- sonar-project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonar-project.properties b/sonar-project.properties index 507879e..97115a1 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -6,7 +6,7 @@ sonar.projectVersion=0.11.0 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. # This property is optional if sonar.modules is set. -sonar.sources=. +sonar.sources=src # Encoding of the source code. Default is default system encoding #sonar.sourceEncoding=UTF-8 From 3734d4ee62688e3b77f39963b59f8254ebfbd656 Mon Sep 17 00:00:00 2001 From: Mauro Scomparin Date: Wed, 9 May 2018 22:30:43 +0200 Subject: [PATCH 267/280] fixed dijkstra.js documentation for s --- src/algorithms/graph/dijkstra.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/graph/dijkstra.js b/src/algorithms/graph/dijkstra.js index 64af712..f84f951 100644 --- a/src/algorithms/graph/dijkstra.js +++ b/src/algorithms/graph/dijkstra.js @@ -5,7 +5,7 @@ const PriorityQueue = require('../../data_structures/priority_queue'); * with Dijkstra's algorithm * * @param {Object} graph An adjacency list representing the graph - * @param {string} start the starting node + * @param {string} s the starting node * */ function dijkstra(graph, s) { From 7744e07642b413ce6d71c7ffa4f481c189be20b7 Mon Sep 17 00:00:00 2001 From: Felipe Ribeiro Date: Tue, 21 Aug 2018 21:20:25 +0200 Subject: [PATCH 268/280] Disable sonarqube --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c4d4971..3711877 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ node_js: - '9' script: - make - - sonar-scanner after_success: "make coveralls" addons: sonarcloud: From 7825f4bc263bf2b26f9a0387142f0a46c172cee4 Mon Sep 17 00:00:00 2001 From: Prakash Jha Date: Tue, 10 Jul 2018 19:06:43 +0530 Subject: [PATCH 269/280] Added SegmentTree to Data Structures Segment Tree is a very useful data structure which helps perform various operation in logarithmic time. A bottom-up implementation of segment tree is done and it answers queries of sum, min, max over a range. --- src/data_structures/segment_tree.js | 86 +++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/data_structures/segment_tree.js diff --git a/src/data_structures/segment_tree.js b/src/data_structures/segment_tree.js new file mode 100644 index 0000000..24512d4 --- /dev/null +++ b/src/data_structures/segment_tree.js @@ -0,0 +1,86 @@ +/** +* Segment Tree +* +* Segment Tree helps to perform various function over a range efficiently in O(log n) time. +* +* In addition to functions that can be implemented by Fenwick Tree, Segment Tree can even perform functions such as +* minimum or maximum over a range, which cannot be answered by Fenwick Tree. +* +* More complicated functions can be done in logarithmic time by doing lazy modification, however the implementation +* depends on type of function and hence is not implemented here. +* +* Segment Tree is similiar to binary tree. The element value is stored in leaf nodes and value of function from range[l,r] +* is stored in internal nodes. +* +* The root node i.e. index 1 stores the value by performing function over entire range. Similarly other index stores value +* by performing function in range of its subtree. +*/ + +class SegmentTree { + constructor(length) { + this._size = length; + this._elementsSum = new Array(length * 2); + this._elementsMin = new Array(length * 2); + this._elementsMax = new Array(length * 2); + + for (let i = 0; i < this._elementsSum.length; i++) { + this._elementsSum[i] = 0; + this._elementsMin[i] = 0; + this._elementsMax[i] = 0; + } + } + + /** + Updates the value at index with the given value + */ + modify(index, value) { + index = index + this._size; + + this._elementsSum[index] = value; + this._elementsMin[index] = value; + this._elementsMax[index] = value; + for (let i = index; i > 1; i >>= 1) { + this._elementsSum[i >> 1] = (this._elementsSum[i] + this._elementsSum[i ^ 1]); + this._elementsMin[i >> 1] = Math.min(this._elementsMin[i], this._elementsMin[i ^ 1]); + this._elementsMax[i >> 1] = Math.max(this._elementsMax[i], this._elementsMax[i ^ 1]); + } + } + + /** + Return the sum of all elements in the range [from, to] + */ + getSum(from, to) { + let ans = 0; + for (from += this._size, to += this._size + 1; from < to; from >>= 1, to >>= 1) { + if (from % 2 == 1) ans += this._elementsSum[from++]; + if (to % 2 == 1) ans += this._elementsSum[--to]; + } + return ans; + } + + /** + Return the minimum of all elements in the range [from, to] + */ + getMin(from, to) { + let ans = Number.MAX_SAFE_INTEGER; + for (from += this._size, to += this._size + 1; from < to; from >>= 1, to >>= 1) { + if (from % 2 == 1) ans = Math.min(ans, this._elementsMin[from++]); + if (to % 2 == 1) ans = Math.min(ans, this._elementsMin[--to]); + } + return ans; + } + + /** + Return the maximum of all elements in the range [from, to] + */ + getMax(from, to) { + let ans = Number.MIN_SAFE_INTEGER; + for (from += this._size, to += this._size + 1; from < to; from >>= 1, to >>= 1) { + if (from % 2 == 1) ans = Math.max(ans, this._elementsMax[from++]); + if (to % 2 == 1) ans = Math.max(ans, this._elementsMin[--to]); + } + return ans; + } +} + +module.exports = SegmentTree; \ No newline at end of file From ec190a8bba4674b24a1a4870f02761f98bab31fc Mon Sep 17 00:00:00 2001 From: Prakash Jha Date: Mon, 16 Jul 2018 13:21:44 +0530 Subject: [PATCH 270/280] Segment Tree Separate classes for each min,max and sum function. --- src/data_structures/segment_tree.js | 173 ++++++++++++++-------------- 1 file changed, 87 insertions(+), 86 deletions(-) diff --git a/src/data_structures/segment_tree.js b/src/data_structures/segment_tree.js index 24512d4..cd4a488 100644 --- a/src/data_structures/segment_tree.js +++ b/src/data_structures/segment_tree.js @@ -1,86 +1,87 @@ -/** -* Segment Tree -* -* Segment Tree helps to perform various function over a range efficiently in O(log n) time. -* -* In addition to functions that can be implemented by Fenwick Tree, Segment Tree can even perform functions such as -* minimum or maximum over a range, which cannot be answered by Fenwick Tree. -* -* More complicated functions can be done in logarithmic time by doing lazy modification, however the implementation -* depends on type of function and hence is not implemented here. -* -* Segment Tree is similiar to binary tree. The element value is stored in leaf nodes and value of function from range[l,r] -* is stored in internal nodes. -* -* The root node i.e. index 1 stores the value by performing function over entire range. Similarly other index stores value -* by performing function in range of its subtree. -*/ - -class SegmentTree { - constructor(length) { - this._size = length; - this._elementsSum = new Array(length * 2); - this._elementsMin = new Array(length * 2); - this._elementsMax = new Array(length * 2); - - for (let i = 0; i < this._elementsSum.length; i++) { - this._elementsSum[i] = 0; - this._elementsMin[i] = 0; - this._elementsMax[i] = 0; - } - } - - /** - Updates the value at index with the given value - */ - modify(index, value) { - index = index + this._size; - - this._elementsSum[index] = value; - this._elementsMin[index] = value; - this._elementsMax[index] = value; - for (let i = index; i > 1; i >>= 1) { - this._elementsSum[i >> 1] = (this._elementsSum[i] + this._elementsSum[i ^ 1]); - this._elementsMin[i >> 1] = Math.min(this._elementsMin[i], this._elementsMin[i ^ 1]); - this._elementsMax[i >> 1] = Math.max(this._elementsMax[i], this._elementsMax[i ^ 1]); - } - } - - /** - Return the sum of all elements in the range [from, to] - */ - getSum(from, to) { - let ans = 0; - for (from += this._size, to += this._size + 1; from < to; from >>= 1, to >>= 1) { - if (from % 2 == 1) ans += this._elementsSum[from++]; - if (to % 2 == 1) ans += this._elementsSum[--to]; - } - return ans; - } - - /** - Return the minimum of all elements in the range [from, to] - */ - getMin(from, to) { - let ans = Number.MAX_SAFE_INTEGER; - for (from += this._size, to += this._size + 1; from < to; from >>= 1, to >>= 1) { - if (from % 2 == 1) ans = Math.min(ans, this._elementsMin[from++]); - if (to % 2 == 1) ans = Math.min(ans, this._elementsMin[--to]); - } - return ans; - } - - /** - Return the maximum of all elements in the range [from, to] - */ - getMax(from, to) { - let ans = Number.MIN_SAFE_INTEGER; - for (from += this._size, to += this._size + 1; from < to; from >>= 1, to >>= 1) { - if (from % 2 == 1) ans = Math.max(ans, this._elementsMax[from++]); - if (to % 2 == 1) ans = Math.max(ans, this._elementsMin[--to]); - } - return ans; - } -} - -module.exports = SegmentTree; \ No newline at end of file +/** +* Segment Tree +* +* Segment Tree helps to perform various function over a range efficiently +* in O(log n) time. +* +* In addition to functions that can be implemented by Fenwick Tree, +* Segment Tree can even perform functions such as minimum or maximum +* over a range, which cannot be answered by Fenwick Tree. +* +* More complicated functions can be done in logarithmic time by doing +* lazy modification, however the implementation depends on type of function +* and hence is not implemented here. +* +* Segment Tree is similiar to binary tree. The element value is stored in +* leaf nodes and value of function from range[l,r] is stored in internal nodes. +* +* The root node i.e. index 1 stores the value by performing function over +* entire range. Similarly other index stores value by performing function +* in range of its subtree. +* / + +class SumSegmentTree { + // Creates an empty segment tree with capacity = length + constructor(length) { + this._baseValue = 0; + this._size = length; + this._tree = new Array(length*2); + for (let i = 0; i < this._tree.length; i++) { + this._tree[i] = 0; + } + } + + // Commutative binary function to be performed over values + func(value1, value2) { + return (value1 + value2); + } + + // Changes the element at given index to be equal to given value + modify(index, value) { + let idx = index + this._size; + this._tree[idx] = value; + for (let i = idx; i > 1; i >>= 1) { + this._tree[ i >> 1 ] = this.func(this._tree[i], this._tree[i^1]); + } + } + + // Returns the value by performing the binary function in range = [from,to] + get(from, to) { + let ans = this._baseValue; + let l = from + this._size; + let r = to + this._size + 1; + for (; l < r; l >>= 1, r >>= 1) { + if (l&1) ans = this.func(ans, this._tree[l++]); + if (r&1 ) ans = this.func(ans, this._tree[--r]); + } + return ans; + } +} + +class MinSegmentTree extends SumSegmentTree { + constructor(length) { + super(length); + this._baseValue = Number.MAX_SAFE_INTEGER; + } + + func(value1, value2) { + return Math.min(value1, value2); + } +} + +class MaxSegmentTree extends SumSegmentTree { + constructor(length) { + super(length); + this._baseValue = Number.MIN_SAFE_INTEGER; + } + + func(value1, value2) { + return Math.max(value1, value2); + } +} + +module.exports = { + SumSegmentTree, + MinSegmentTree, + MaxSegmentTree +}; From 233edb8f7d0ee54c6564e9a8dcc89c49a3690d72 Mon Sep 17 00:00:00 2001 From: Prakash Jha Date: Wed, 18 Jul 2018 19:50:27 +0530 Subject: [PATCH 271/280] Added test file for Segment Tree --- src/test/data_structures/segment_tree.js | 147 +++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/test/data_structures/segment_tree.js diff --git a/src/test/data_structures/segment_tree.js b/src/test/data_structures/segment_tree.js new file mode 100644 index 0000000..c9491f9 --- /dev/null +++ b/src/test/data_structures/segment_tree.js @@ -0,0 +1,147 @@ +const segmentTree = require('../..').DataStructures.SegmentTree; +const assert = require('assert'); + +describe('SumSegmentTree', () => { + it('allows modification of value at any index', () => { + const tree = new segmentTree.SumSegmentTree(10); + tree.modify(0, 5); + tree.modify(1, 12); + tree.modify(2, 7); + tree.modify(3, -100); + tree.modify(4, 3); + tree.modify(5, 9); + tree.modify(6, 100); + tree.modify(7, 0); + tree.modify(8, -25); + tree.modify(9, 40); + + assert.equal(tree.get(0, 0), 5); + assert.equal(tree.get(5, 5), 9); + assert.equal(tree.get(9, 9), 40); + assert.equal(tree.get(4, 4), 3); + assert.equal(tree.get(3, 3), -100); + assert.equal(tree.get(1, 1), 12); + assert.equal(tree.get(7, 7), 0); + assert.equal(tree.get(8, 8), -25); + }); + + it('allows range queries', () => { + const tree = new segmentTree.SumSegmentTree(10); + tree.modify(0, 5); + tree.modify(1, 12); + tree.modify(2, 7); + tree.modify(3, -100); + tree.modify(4, 3); + tree.modify(5, 9); + tree.modify(6, 100); + tree.modify(7, 0); + tree.modify(8, -25); + tree.modify(9, 40); + + assert.equal(tree.get(0, 5), 5 + 12 + 7 - 100 + 3 + 9); + assert.equal(tree.get(5, 5), 9); + assert.equal(tree.get(7, 9), 0 - 25 + 40); + assert.equal(tree.get(4, 6), 3 + 9 + 100); + assert.equal(tree.get(1, 2), 12 + 7); + assert.equal(tree.get(5, 8), 9 + 100 + 0 - 25); + assert.equal(tree.get(0, 9), 5 + 12 + 7 - 100 + 3 + 9 + 100 + 0 - 25 + 40); + assert.equal(tree.get(8, 8), -25); + }); +}); + +describe('MinSegmentTree', () => { + it('allows modification of value at any index', () => { + const tree = new segmentTree.MinSegmentTree(10); + tree.modify(0, 5); + tree.modify(1, 12); + tree.modify(2, 7); + tree.modify(3, -100); + tree.modify(4, 3); + tree.modify(5, 9); + tree.modify(6, 100); + tree.modify(7, 0); + tree.modify(8, -25); + tree.modify(9, 40); + + assert.equal(tree.get(0, 0), 5); + assert.equal(tree.get(5, 5), 9); + assert.equal(tree.get(9, 9), 40); + assert.equal(tree.get(4, 4), 3); + assert.equal(tree.get(3, 3), -100); + assert.equal(tree.get(1, 1), 12); + assert.equal(tree.get(7, 7), 0); + assert.equal(tree.get(8, 8), -25); + }); + + it('allows range queries', () => { + const tree = new segmentTree.MinSegmentTree(10); + tree.modify(0, 5); + tree.modify(1, 12); + tree.modify(2, 7); + tree.modify(3, -100); + tree.modify(4, 3); + tree.modify(5, 9); + tree.modify(6, 100); + tree.modify(7, 0); + tree.modify(8, -25); + tree.modify(9, 40); + + assert.equal(tree.get(0, 5), -100); + assert.equal(tree.get(5, 5), 9); + assert.equal(tree.get(7, 9), -25); + assert.equal(tree.get(4, 6), 3); + assert.equal(tree.get(1, 2), 7); + assert.equal(tree.get(5, 8), -25); + assert.equal(tree.get(0, 9), -100); + assert.equal(tree.get(6, 6), 100); + }); +}); + +describe('MaxSegmentTree', () => { + it('allows modification of value at any index', () => { + const tree = new segmentTree.MaxSegmentTree(10); + tree.modify(0, 5); + tree.modify(1, 12); + tree.modify(2, 7); + tree.modify(3, -100); + tree.modify(4, 3); + tree.modify(5, 9); + tree.modify(6, 100); + tree.modify(7, 0); + tree.modify(8, -25); + tree.modify(9, 40); + + assert.equal(tree.get(0, 0), 5); + assert.equal(tree.get(5, 5), 9); + assert.equal(tree.get(9, 9), 40); + assert.equal(tree.get(4, 4), 3); + assert.equal(tree.get(3, 3), -100); + assert.equal(tree.get(1, 1), 12); + assert.equal(tree.get(7, 7), 0); + assert.equal(tree.get(8, 8), -25); + }); + + it('allows range queries', () => { + const tree = new segmentTree.MaxSegmentTree(10); + tree.modify(0, 5); + tree.modify(1, 12); + tree.modify(2, 7); + tree.modify(3, -100); + tree.modify(4, 3); + tree.modify(5, 9); + tree.modify(6, 100); + tree.modify(7, 0); + tree.modify(8, -25); + tree.modify(9, 40); + + assert.equal(tree.get(0, 5), 12); + assert.equal(tree.get(5, 5), 9); + assert.equal(tree.get(7, 9), 40); + assert.equal(tree.get(4, 6), 100); + assert.equal(tree.get(1, 2), 12); + assert.equal(tree.get(5, 8), 100); + assert.equal(tree.get(0, 9), 100); + assert.equal(tree.get(3, 3), -100); + }); +}); + From 463a85c51a943a4cc5b593654447afc60f412546 Mon Sep 17 00:00:00 2001 From: Prakash Jha Date: Wed, 18 Jul 2018 19:51:48 +0530 Subject: [PATCH 272/280] Added SegmentTree --- src/data_structures.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/data_structures.js b/src/data_structures.js index 8748d53..6d543ce 100644 --- a/src/data_structures.js +++ b/src/data_structures.js @@ -12,5 +12,6 @@ module.exports = { Stack: require('./data_structures/stack'), Set: require('./data_structures/set'), DisjointSetForest: require('./data_structures/disjoint_set_forest'), - FenwickTree: require('./data_structures/fenwick_tree') + FenwickTree: require('./data_structures/fenwick_tree'), + SegmentTree: require('./data_structures/segment_tree') }; From b052270cb574afd18c2f6a6f37c61bec63113751 Mon Sep 17 00:00:00 2001 From: Prakash Jha Date: Wed, 18 Jul 2018 19:55:19 +0530 Subject: [PATCH 273/280] fixed comment --- src/data_structures/segment_tree.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/data_structures/segment_tree.js b/src/data_structures/segment_tree.js index cd4a488..c5e075b 100644 --- a/src/data_structures/segment_tree.js +++ b/src/data_structures/segment_tree.js @@ -4,21 +4,21 @@ * Segment Tree helps to perform various function over a range efficiently * in O(log n) time. * -* In addition to functions that can be implemented by Fenwick Tree, -* Segment Tree can even perform functions such as minimum or maximum +* In addition to functions that can be implemented by Fenwick Tree, +* Segment Tree can even perform functions such as minimum or maximum * over a range, which cannot be answered by Fenwick Tree. * -* More complicated functions can be done in logarithmic time by doing +* More complicated functions can be done in logarithmic time by doing * lazy modification, however the implementation depends on type of function * and hence is not implemented here. * * Segment Tree is similiar to binary tree. The element value is stored in -* leaf nodes and value of function from range[l,r] is stored in internal nodes. +* leaf nodes and value of function from range[l, r] is stored in internal nodes. * * The root node i.e. index 1 stores the value by performing function over -* entire range. Similarly other index stores value by performing function +* entire range. Similarly other index stores value by performing function * in range of its subtree. -* / +*/ class SumSegmentTree { // Creates an empty segment tree with capacity = length @@ -30,22 +30,22 @@ class SumSegmentTree { this._tree[i] = 0; } } - + // Commutative binary function to be performed over values func(value1, value2) { return (value1 + value2); } - + // Changes the element at given index to be equal to given value modify(index, value) { let idx = index + this._size; this._tree[idx] = value; for (let i = idx; i > 1; i >>= 1) { - this._tree[ i >> 1 ] = this.func(this._tree[i], this._tree[i^1]); + this._tree[i >> 1] = this.func(this._tree[i], this._tree[i ^ 1]); } } - - // Returns the value by performing the binary function in range = [from,to] + + // Returns the value by performing the binary function in range = [from, to] get(from, to) { let ans = this._baseValue; let l = from + this._size; @@ -85,3 +85,4 @@ module.exports = { MinSegmentTree, MaxSegmentTree }; + From c4db9cb7ca47dbc43c097a5bba8dbdaa8d63e7da Mon Sep 17 00:00:00 2001 From: forgotter Date: Wed, 15 Aug 2018 13:15:28 +0530 Subject: [PATCH 274/280] Combined Min, Max and Sum and code refactor. --- src/data_structures/segment_tree.js | 150 ++++++++++++----------- src/test/data_structures/segment_tree.js | 146 +++++++++------------- 2 files changed, 137 insertions(+), 159 deletions(-) diff --git a/src/data_structures/segment_tree.js b/src/data_structures/segment_tree.js index c5e075b..014f324 100644 --- a/src/data_structures/segment_tree.js +++ b/src/data_structures/segment_tree.js @@ -1,88 +1,100 @@ /** -* Segment Tree -* -* Segment Tree helps to perform various function over a range efficiently -* in O(log n) time. -* -* In addition to functions that can be implemented by Fenwick Tree, -* Segment Tree can even perform functions such as minimum or maximum -* over a range, which cannot be answered by Fenwick Tree. -* -* More complicated functions can be done in logarithmic time by doing -* lazy modification, however the implementation depends on type of function -* and hence is not implemented here. -* -* Segment Tree is similiar to binary tree. The element value is stored in -* leaf nodes and value of function from range[l, r] is stored in internal nodes. -* -* The root node i.e. index 1 stores the value by performing function over -* entire range. Similarly other index stores value by performing function -* in range of its subtree. +Segment Tree + +Segment Tree helps to perform various function over a range efficiently +in O(log n) time. + +In addition to functions that can be implemented by Fenwick Tree, +Segment Tree can even perform functions such as minimum or maximum +over a range, which cannot be answered by Fenwick Tree. + +More complicated functions can be done in logarithmic time by doing +lazy modification, however the implementation depends on type of function +and hence is not implemented here. + +Segment Tree is similiar to binary tree. The element value is stored in +leaf nodes and value of function from range[l,r] is stored in internal nodes. + +The root node i.e. index 1 stores the value by performing function over +entire range. Similarly other index stores value by performing function +in range of its subtree. */ -class SumSegmentTree { - // Creates an empty segment tree with capacity = length +class SegmentTree { constructor(length) { - this._baseValue = 0; - this._size = length; - this._tree = new Array(length*2); - for (let i = 0; i < this._tree.length; i++) { - this._tree[i] = 0; - } - } + this._size = length; + this._elementsSum = new Array(length * 2); + this._elementsMin = new Array(length * 2); + this._elementsMax = new Array(length * 2); - // Commutative binary function to be performed over values - func(value1, value2) { - return (value1 + value2); + for (let i = 0; i < this._size; i++) { + this._elementsSum[i] = 0; + this._elementsMin[i] = 0; + this._elementsMax[i] = 0; + } } - // Changes the element at given index to be equal to given value - modify(index, value) { - let idx = index + this._size; - this._tree[idx] = value; - for (let i = idx; i > 1; i >>= 1) { - this._tree[i >> 1] = this.func(this._tree[i], this._tree[i ^ 1]); - } - } + /** + Updates the value at index with the given value + */ + modify(position, value) { + let index = position + this._size; + + this._elementsSum[index] = value; + this._elementsMin[index] = value; + this._elementsMax[index] = value; - // Returns the value by performing the binary function in range = [from, to] - get(from, to) { - let ans = this._baseValue; - let l = from + this._size; - let r = to + this._size + 1; - for (; l < r; l >>= 1, r >>= 1) { - if (l&1) ans = this.func(ans, this._tree[l++]); - if (r&1 ) ans = this.func(ans, this._tree[--r]); - } - return ans; + for (let i = index; i > 1; i >>= 1) { + this._elementsSum[i >> 1] = + (this._elementsSum[i] + this._elementsSum[i ^ 1]); + + this._elementsMin[i >> 1] = + Math.min(this._elementsMin[i], this._elementsMin[i ^ 1]); + + this._elementsMax[i >> 1] = + Math.max(this._elementsMax[i], this._elementsMax[i ^ 1]); + } } -} -class MinSegmentTree extends SumSegmentTree { - constructor(length) { - super(length); - this._baseValue = Number.MAX_SAFE_INTEGER; + /* + code is taken from suggestion by @juanplopes. + + calculate performs the binary operation (addition, maximum, minimum) over + the index containing the query range [from,to] and stores the value in ans + */ + calculate(from, to, where, initialValue, binaryFunction) { + let ans = initialValue; + let startIdx = from + this._size; + let endIdx = to + this._size + 1; + for (; startIdx < endIdx; startIdx >>= 1, endIdx >>= 1) { + if (startIdx & 1) ans = binaryFunction(ans, where[startIdx++]); + if (endIdx & 1) ans = binaryFunction(ans, where[--endIdx]); + } + return ans; } - func(value1, value2) { - return Math.min(value1, value2); + /** + Return the sum of all elements in the range [from, to] + */ + getSum(from, to) { + return this.calculate(from, to, this._elementsSum, 0, (a, b) => a + b); } -} -class MaxSegmentTree extends SumSegmentTree { - constructor(length) { - super(length); - this._baseValue = Number.MIN_SAFE_INTEGER; + /** + Return the minimum of all elements in the range [from, to] + */ + getMin(from, to) { + return this.calculate(from, to, this._elementsMin, + Number.MAX_SAFE_INTEGER, Math.min); } - func(value1, value2) { - return Math.max(value1, value2); + /** + Return the maximum of all elements in the range [from, to] + */ + getMax(from, to) { + return this.calculate(from, to, this._elementsMax, + Number.MIN_SAFE_INTEGER, Math.max); } } -module.exports = { - SumSegmentTree, - MinSegmentTree, - MaxSegmentTree -}; - +module.exports = SegmentTree; \ No newline at end of file diff --git a/src/test/data_structures/segment_tree.js b/src/test/data_structures/segment_tree.js index c9491f9..79a200c 100644 --- a/src/test/data_structures/segment_tree.js +++ b/src/test/data_structures/segment_tree.js @@ -1,57 +1,10 @@ const segmentTree = require('../..').DataStructures.SegmentTree; const assert = require('assert'); -describe('SumSegmentTree', () => { - it('allows modification of value at any index', () => { - const tree = new segmentTree.SumSegmentTree(10); - tree.modify(0, 5); - tree.modify(1, 12); - tree.modify(2, 7); - tree.modify(3, -100); - tree.modify(4, 3); - tree.modify(5, 9); - tree.modify(6, 100); - tree.modify(7, 0); - tree.modify(8, -25); - tree.modify(9, 40); - - assert.equal(tree.get(0, 0), 5); - assert.equal(tree.get(5, 5), 9); - assert.equal(tree.get(9, 9), 40); - assert.equal(tree.get(4, 4), 3); - assert.equal(tree.get(3, 3), -100); - assert.equal(tree.get(1, 1), 12); - assert.equal(tree.get(7, 7), 0); - assert.equal(tree.get(8, 8), -25); - }); - - it('allows range queries', () => { - const tree = new segmentTree.SumSegmentTree(10); - tree.modify(0, 5); - tree.modify(1, 12); - tree.modify(2, 7); - tree.modify(3, -100); - tree.modify(4, 3); - tree.modify(5, 9); - tree.modify(6, 100); - tree.modify(7, 0); - tree.modify(8, -25); - tree.modify(9, 40); - - assert.equal(tree.get(0, 5), 5 + 12 + 7 - 100 + 3 + 9); - assert.equal(tree.get(5, 5), 9); - assert.equal(tree.get(7, 9), 0 - 25 + 40); - assert.equal(tree.get(4, 6), 3 + 9 + 100); - assert.equal(tree.get(1, 2), 12 + 7); - assert.equal(tree.get(5, 8), 9 + 100 + 0 - 25); - assert.equal(tree.get(0, 9), 5 + 12 + 7 - 100 + 3 + 9 + 100 + 0 - 25 + 40); - assert.equal(tree.get(8, 8), -25); - }); -}); +describe('SegmentTree', () => { -describe('MinSegmentTree', () => { it('allows modification of value at any index', () => { - const tree = new segmentTree.MinSegmentTree(10); + const tree = new segmentTree(10); tree.modify(0, 5); tree.modify(1, 12); tree.modify(2, 7); @@ -63,18 +16,34 @@ describe('MinSegmentTree', () => { tree.modify(8, -25); tree.modify(9, 40); - assert.equal(tree.get(0, 0), 5); - assert.equal(tree.get(5, 5), 9); - assert.equal(tree.get(9, 9), 40); - assert.equal(tree.get(4, 4), 3); - assert.equal(tree.get(3, 3), -100); - assert.equal(tree.get(1, 1), 12); - assert.equal(tree.get(7, 7), 0); - assert.equal(tree.get(8, 8), -25); + assert.equal(tree.getSum(0, 0), 5); + assert.equal(tree.getSum(5, 5), 9); + assert.equal(tree.getSum(9, 9), 40); + assert.equal(tree.getSum(4, 4), 3); + assert.equal(tree.getSum(3, 3), -100); + assert.equal(tree.getSum(1, 1), 12); + assert.equal(tree.getSum(7, 7), 0); + assert.equal(tree.getSum(8, 8), -25); + assert.equal(tree.getMin(0, 0), 5); + assert.equal(tree.getMin(5, 5), 9); + assert.equal(tree.getMin(9, 9), 40); + assert.equal(tree.getMin(4, 4), 3); + assert.equal(tree.getMin(3, 3), -100); + assert.equal(tree.getMin(1, 1), 12); + assert.equal(tree.getMin(7, 7), 0); + assert.equal(tree.getMin(8, 8), -25); + assert.equal(tree.getMax(0, 0), 5); + assert.equal(tree.getMax(5, 5), 9); + assert.equal(tree.getMax(9, 9), 40); + assert.equal(tree.getMax(4, 4), 3); + assert.equal(tree.getMax(3, 3), -100); + assert.equal(tree.getMax(1, 1), 12); + assert.equal(tree.getMax(7, 7), 0); + assert.equal(tree.getMax(8, 8), -25); }); - it('allows range queries', () => { - const tree = new segmentTree.MinSegmentTree(10); + it('allows range sum queries', () => { + const tree = new segmentTree(10); tree.modify(0, 5); tree.modify(1, 12); tree.modify(2, 7); @@ -86,20 +55,18 @@ describe('MinSegmentTree', () => { tree.modify(8, -25); tree.modify(9, 40); - assert.equal(tree.get(0, 5), -100); - assert.equal(tree.get(5, 5), 9); - assert.equal(tree.get(7, 9), -25); - assert.equal(tree.get(4, 6), 3); - assert.equal(tree.get(1, 2), 7); - assert.equal(tree.get(5, 8), -25); - assert.equal(tree.get(0, 9), -100); - assert.equal(tree.get(6, 6), 100); + assert.equal(tree.getSum(0, 5), 5 + 12 + 7 - 100 + 3 + 9); + assert.equal(tree.getSum(5, 5), 9); + assert.equal(tree.getSum(7, 9), 0 - 25 + 40); + assert.equal(tree.getSum(4, 6), 3 + 9 + 100); + assert.equal(tree.getSum(1, 2), 12 + 7); + assert.equal(tree.getSum(5, 8), 9 + 100 + 0 - 25); + assert.equal(tree.getSum(0, 9), 5 + 12 + 7 - 100 + 3 + 9 + 100 + 0 - 25 + 40); + assert.equal(tree.getSum(8, 8), -25); }); -}); -describe('MaxSegmentTree', () => { - it('allows modification of value at any index', () => { - const tree = new segmentTree.MaxSegmentTree(10); + it('allows range minimum queries', () => { + const tree = new segmentTree(10); tree.modify(0, 5); tree.modify(1, 12); tree.modify(2, 7); @@ -111,18 +78,18 @@ describe('MaxSegmentTree', () => { tree.modify(8, -25); tree.modify(9, 40); - assert.equal(tree.get(0, 0), 5); - assert.equal(tree.get(5, 5), 9); - assert.equal(tree.get(9, 9), 40); - assert.equal(tree.get(4, 4), 3); - assert.equal(tree.get(3, 3), -100); - assert.equal(tree.get(1, 1), 12); - assert.equal(tree.get(7, 7), 0); - assert.equal(tree.get(8, 8), -25); + assert.equal(tree.getMin(0, 5), -100); + assert.equal(tree.getMin(5, 5), 9); + assert.equal(tree.getMin(7, 9), -25); + assert.equal(tree.getMin(4, 6), 3); + assert.equal(tree.getMin(1, 2), 7); + assert.equal(tree.getMin(5, 8), -25); + assert.equal(tree.getMin(0, 9), -100); + assert.equal(tree.getMin(6, 6), 100); }); - it('allows range queries', () => { - const tree = new segmentTree.MaxSegmentTree(10); + it('allows range maximum queries', () => { + const tree = new segmentTree(10); tree.modify(0, 5); tree.modify(1, 12); tree.modify(2, 7); @@ -134,14 +101,13 @@ describe('MaxSegmentTree', () => { tree.modify(8, -25); tree.modify(9, 40); - assert.equal(tree.get(0, 5), 12); - assert.equal(tree.get(5, 5), 9); - assert.equal(tree.get(7, 9), 40); - assert.equal(tree.get(4, 6), 100); - assert.equal(tree.get(1, 2), 12); - assert.equal(tree.get(5, 8), 100); - assert.equal(tree.get(0, 9), 100); - assert.equal(tree.get(3, 3), -100); + assert.equal(tree.getMax(0, 5), 12); + assert.equal(tree.getMax(5, 5), 9); + assert.equal(tree.getMax(7, 9), 40); + assert.equal(tree.getMax(4, 6), 100); + assert.equal(tree.getMax(1, 2), 12); + assert.equal(tree.getMax(5, 8), 100); + assert.equal(tree.getMax(0, 9), 100); + assert.equal(tree.getMax(3, 3), -100); }); }); - From 6a94a14d3f334b3d22303ce6c5bceb2e3016143c Mon Sep 17 00:00:00 2001 From: forgotter Date: Wed, 15 Aug 2018 13:46:54 +0530 Subject: [PATCH 275/280] refactored code --- src/data_structures/segment_tree.js | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/data_structures/segment_tree.js b/src/data_structures/segment_tree.js index 014f324..7c4ffff 100644 --- a/src/data_structures/segment_tree.js +++ b/src/data_structures/segment_tree.js @@ -34,6 +34,13 @@ class SegmentTree { } } + /* + combines two values, i.e. performs min, max and sum operation as required + */ + combine(val1, val2, combineFn) { + return combineFn(val1, val2); + } + /** Updates the value at index with the given value */ @@ -45,14 +52,17 @@ class SegmentTree { this._elementsMax[index] = value; for (let i = index; i > 1; i >>= 1) { - this._elementsSum[i >> 1] = - (this._elementsSum[i] + this._elementsSum[i ^ 1]); + this._elementsSum[i >> 1] = this.combine( + this._elementsSum[i], this._elementsSum[i ^ 1], (a, b) => a + b + ); - this._elementsMin[i >> 1] = - Math.min(this._elementsMin[i], this._elementsMin[i ^ 1]); + this._elementsMin[i >> 1] = this.combine( + this._elementsMin[i], this._elementsMin[i ^ 1], Math.min + ); - this._elementsMax[i >> 1] = - Math.max(this._elementsMax[i], this._elementsMax[i ^ 1]); + this._elementsMax[i >> 1] = this.combine( + this._elementsMax[i], this._elementsMax[i ^ 1], Math.max + ); } } From cc8c0a13197d0889e1838824c4679f31bfd889c6 Mon Sep 17 00:00:00 2001 From: forgotter Date: Wed, 15 Aug 2018 14:07:06 +0530 Subject: [PATCH 276/280] in-place combination of values, removed extra function --- src/data_structures/segment_tree.js | 21 +++++++-------------- src/test/data_structures/segment_tree.js | 15 ++++++++------- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/data_structures/segment_tree.js b/src/data_structures/segment_tree.js index 7c4ffff..3d2aa91 100644 --- a/src/data_structures/segment_tree.js +++ b/src/data_structures/segment_tree.js @@ -34,13 +34,6 @@ class SegmentTree { } } - /* - combines two values, i.e. performs min, max and sum operation as required - */ - combine(val1, val2, combineFn) { - return combineFn(val1, val2); - } - /** Updates the value at index with the given value */ @@ -52,16 +45,16 @@ class SegmentTree { this._elementsMax[index] = value; for (let i = index; i > 1; i >>= 1) { - this._elementsSum[i >> 1] = this.combine( - this._elementsSum[i], this._elementsSum[i ^ 1], (a, b) => a + b + this._elementsSum[i >> 1] = ( + this._elementsSum[i] + this._elementsSum[i ^ 1] ); - this._elementsMin[i >> 1] = this.combine( - this._elementsMin[i], this._elementsMin[i ^ 1], Math.min + this._elementsMin[i >> 1] = Math.min( + this._elementsMin[i], this._elementsMin[i ^ 1] ); - this._elementsMax[i >> 1] = this.combine( - this._elementsMax[i], this._elementsMax[i ^ 1], Math.max + this._elementsMax[i >> 1] = Math.max( + this._elementsMax[i], this._elementsMax[i ^ 1] ); } } @@ -107,4 +100,4 @@ class SegmentTree { } } -module.exports = SegmentTree; \ No newline at end of file +module.exports = SegmentTree; diff --git a/src/test/data_structures/segment_tree.js b/src/test/data_structures/segment_tree.js index 79a200c..54dc73c 100644 --- a/src/test/data_structures/segment_tree.js +++ b/src/test/data_structures/segment_tree.js @@ -1,10 +1,9 @@ -const segmentTree = require('../..').DataStructures.SegmentTree; +const SegmentTree = require('../..').DataStructures.SegmentTree; const assert = require('assert'); describe('SegmentTree', () => { - it('allows modification of value at any index', () => { - const tree = new segmentTree(10); + const tree = new SegmentTree(10); tree.modify(0, 5); tree.modify(1, 12); tree.modify(2, 7); @@ -43,7 +42,7 @@ describe('SegmentTree', () => { }); it('allows range sum queries', () => { - const tree = new segmentTree(10); + const tree = new SegmentTree(10); tree.modify(0, 5); tree.modify(1, 12); tree.modify(2, 7); @@ -61,12 +60,14 @@ describe('SegmentTree', () => { assert.equal(tree.getSum(4, 6), 3 + 9 + 100); assert.equal(tree.getSum(1, 2), 12 + 7); assert.equal(tree.getSum(5, 8), 9 + 100 + 0 - 25); - assert.equal(tree.getSum(0, 9), 5 + 12 + 7 - 100 + 3 + 9 + 100 + 0 - 25 + 40); + assert.equal( + tree.getSum(0, 9), 5 + 12 + 7 - 100 + 3 + 9 + 100 + 0 - 25 + 40 + ); assert.equal(tree.getSum(8, 8), -25); }); it('allows range minimum queries', () => { - const tree = new segmentTree(10); + const tree = new SegmentTree(10); tree.modify(0, 5); tree.modify(1, 12); tree.modify(2, 7); @@ -89,7 +90,7 @@ describe('SegmentTree', () => { }); it('allows range maximum queries', () => { - const tree = new segmentTree(10); + const tree = new SegmentTree(10); tree.modify(0, 5); tree.modify(1, 12); tree.modify(2, 7); From 083196ba3e92dd5d538fd69f757070933ddce8e7 Mon Sep 17 00:00:00 2001 From: "phuclam.nguyen" Date: Fri, 20 Jul 2018 15:51:50 +0800 Subject: [PATCH 277/280] Add lowerBound implementation and unit tests --- src/algorithms/search/binarysearch.js | 30 ++++++++++++++++++- src/search.js | 3 +- src/test/algorithms/searching/binarysearch.js | 23 ++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/algorithms/search/binarysearch.js b/src/algorithms/search/binarysearch.js index 46c9742..d333f4a 100644 --- a/src/algorithms/search/binarysearch.js +++ b/src/algorithms/search/binarysearch.js @@ -22,4 +22,32 @@ const binarySearch = (sortedArray, element) => { return -1; }; -module.exports = binarySearch; +/** + * lowerBound returns index of the first element greater than the search key + * in logarithmic time (O(log n)) + * + * @param Array + * @param Number\String + * + * @return Number + */ +const lowerBound = (sortedArray, element) => { + let lo = 0; + let hi = sortedArray.length - 1; + + while (lo <= hi) { + const mid = ((hi - lo) >> 1) + lo; + if (sortedArray[mid] > element) { + hi = mid - 1; + } else { + lo = mid + 1; + } + } + + return lo; +}; + +module.exports = { + binarySearch, + lowerBound +}; diff --git a/src/search.js b/src/search.js index 11271b9..3d3de02 100644 --- a/src/search.js +++ b/src/search.js @@ -1,7 +1,8 @@ // Search algorithms module.exports = { bfs: require('./algorithms/search/bfs'), - binarySearch: require('./algorithms/search/binarysearch'), + binarySearch: require('./algorithms/search/binarysearch').binarySearch, + lowerBound: require('./algorithms/search/binarysearch').lowerBound, ternarySearch: require('./algorithms/search/ternary_search'), dfs: require('./algorithms/search/dfs') }; diff --git a/src/test/algorithms/searching/binarysearch.js b/src/test/algorithms/searching/binarysearch.js index 872db13..55cea49 100644 --- a/src/test/algorithms/searching/binarysearch.js +++ b/src/test/algorithms/searching/binarysearch.js @@ -1,4 +1,5 @@ const binarySearch = require('../../..').Search.binarySearch; +const lowerBound = require('../../..').Search.lowerBound; const assert = require('assert'); describe('Binary Search', () => { @@ -13,3 +14,25 @@ describe('Binary Search', () => { assert.equal(binarySearch([1, 2, 3, 4, 5], 100), -1); }); }); + +describe('Lower Bound', () => { + it('finds the first element greater than search key', () => { + let arr = [1, 2, 3, 4, 5]; + + assert.equal(lowerBound(arr, 0), 0); + assert.equal(lowerBound(arr, 1), 1); + assert.equal(lowerBound(arr, 2), 2); + assert.equal(lowerBound(arr, 3), 3); + assert.equal(lowerBound(arr, 4), 4); + assert.equal(lowerBound(arr, 5), 5); + assert.equal(lowerBound(arr, 6), 5); + }); + + it('ignores duplicate values', () => { + let duplicates = [1, 1, 2, 2, 3, 3]; + + assert.equal(lowerBound(duplicates, 1), 2); + assert.equal(lowerBound(duplicates, 2), 4); + assert.equal(lowerBound(duplicates, 3), 6); + }); +}); From dccdcb882812e3dcdb169b0220c512c123dceded Mon Sep 17 00:00:00 2001 From: "phuclam.nguyen" Date: Fri, 20 Jul 2018 16:03:56 +0800 Subject: [PATCH 278/280] Fix a typo --- src/algorithms/search/binarysearch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/search/binarysearch.js b/src/algorithms/search/binarysearch.js index d333f4a..a76f6d9 100644 --- a/src/algorithms/search/binarysearch.js +++ b/src/algorithms/search/binarysearch.js @@ -27,7 +27,7 @@ const binarySearch = (sortedArray, element) => { * in logarithmic time (O(log n)) * * @param Array - * @param Number\String + * @param Number|String * * @return Number */ From 2084c96e829923dd14886effa694b08fb0036c82 Mon Sep 17 00:00:00 2001 From: forgotter Date: Wed, 22 Aug 2018 21:54:21 +0530 Subject: [PATCH 279/280] fixed typo in treap unit test --- src/test/data_structures/treap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/data_structures/treap.js b/src/test/data_structures/treap.js index 8c3c2eb..9357776 100644 --- a/src/test/data_structures/treap.js +++ b/src/test/data_structures/treap.js @@ -99,7 +99,7 @@ describe('Treap', () => { assert.equal(treap.maximum(), 1); }); - it('handles dumplicated elements', () => { + it('handles duplicated elements', () => { treap.insert(1); // [1, 1] assert.equal(treap.size(), 2); From 94b4bb6050b5671f3405af0189369452fda6b4df Mon Sep 17 00:00:00 2001 From: Aaron Goshine Date: Tue, 19 Feb 2019 08:35:22 +0000 Subject: [PATCH 280/280] Updated README updated the readme reflect the current state of the data structures --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 711d5ca..c4921ac 100644 --- a/README.md +++ b/README.md @@ -28,20 +28,21 @@ require('algorithms/data_structures'); // or require('algorithms').DataStructures; ``` - +* AVLTree * BST * DisjointSetForest * FenwickTree * Graph * HashTable * Heap - * MaxHeap - * MinHeap + - MaxHeap + - MinHeap * LinkedList * PriorityQueue * Queue * Set (HashSet) * Stack +* Treap #### Geometry algorithms