From 5ce9398114e4a980f159f0e897f4cc0523d2d3a7 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Wed, 7 Oct 2020 15:04:06 +0530 Subject: [PATCH 01/40] Bracket Balance --- src/BloomFilter.js | 1 + src/bracketBalance.js | 30 ++++++++++++++++++++++++++++++ src/index.js | 6 ++++-- test/search/test_kmp.js | 1 - test/search/test_rabin_karp.js | 1 - test/test_bracketBalance.js | 26 ++++++++++++++++++++++++++ test/test_dice_coeff.js | 1 - 7 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 src/BloomFilter.js create mode 100644 src/bracketBalance.js create mode 100644 test/test_bracketBalance.js diff --git a/src/BloomFilter.js b/src/BloomFilter.js new file mode 100644 index 0000000..9a390c3 --- /dev/null +++ b/src/BloomFilter.js @@ -0,0 +1 @@ +"use strict"; \ No newline at end of file diff --git a/src/bracketBalance.js b/src/bracketBalance.js new file mode 100644 index 0000000..00b0037 --- /dev/null +++ b/src/bracketBalance.js @@ -0,0 +1,30 @@ +/** + * + * @param {String} searchSpace text where balancing needs to be checked + * @returns {boolean} states whether text is balanced or not + */ +function isBalanced(searchSpace){ + if(searchSpace.length == 0) return false; + + bracketStack = [] + for(let i=0; i { + const searchSpace1 = "[[[]]]]",searchSpace2 = "I am (an) as{s}guardian",searchSpace3 = "the [code] {speaker} of nativity {nirvana] is (here",searchSpace4 = "( what if i get (comfortable" + + it("Returns false due to extra closing bracket", () => { + assert.strictEqual(bracketBalance(searchSpace1),false); + }); + + it("Returns true due to balance", () => { + assert.strictEqual(bracketBalance(searchSpace2),true); + }); + + it("Returns false due to misbalance", () => { + assert.strictEqual(bracketBalance(searchSpace3),false); + }); + + it("Returns false due to all opening brackets", () => { + assert.strictEqual(bracketBalance(searchSpace4),false); + }); + + it("Returns false due to no search space", () => { + assert.strictEqual(bracketBalance(""),false); + }); +}); \ No newline at end of file diff --git a/test/test_dice_coeff.js b/test/test_dice_coeff.js index 960a647..22d6135 100644 --- a/test/test_dice_coeff.js +++ b/test/test_dice_coeff.js @@ -1,4 +1,3 @@ -/* eslint-env mocha */ const diceCoeff = require('../src').diceCoeff const assert = require('assert'); From 050f089fce961e42384ac7a4ff2fb1590c5a83bc Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Wed, 7 Oct 2020 15:08:17 +0530 Subject: [PATCH 02/40] README update --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5ba716d..cc72a43 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ List of supported Data Structures and Algorithms are : - [Dice Coefficient](https://github.com/thsubaku9/string-dsa/blob/main/src/dice_coeff.js) - [Knuth Morris Pratt](https://github.com/thsubaku9/string-dsa/blob/main/src/search/kmp.js) - [Rabin Karp](https://github.com/thsubaku9/string-dsa/blob/main/src/search/rabin_karp.js) +- [Bracket Balance](https://github.com/thsubaku9/string-dsa/blob/main/src/bracketBalance.js) ## Utilization From 1801f4bdea7dd42ff6f09bb40be84a02ad6a025f Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Wed, 7 Oct 2020 15:09:58 +0530 Subject: [PATCH 03/40] README update --- README.md | 2 +- src/BloomFilter.js | 2 +- src/bracketBalance.js | 4 ++-- src/index.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index cc72a43..77645d7 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,10 @@ $ npm install string-dsa List of supported Data Structures and Algorithms are : +- [Bracket Balance](https://github.com/thsubaku9/string-dsa/blob/main/src/bracketBalance.js) - [Dice Coefficient](https://github.com/thsubaku9/string-dsa/blob/main/src/dice_coeff.js) - [Knuth Morris Pratt](https://github.com/thsubaku9/string-dsa/blob/main/src/search/kmp.js) - [Rabin Karp](https://github.com/thsubaku9/string-dsa/blob/main/src/search/rabin_karp.js) -- [Bracket Balance](https://github.com/thsubaku9/string-dsa/blob/main/src/bracketBalance.js) ## Utilization diff --git a/src/BloomFilter.js b/src/BloomFilter.js index 9a390c3..3918c74 100644 --- a/src/BloomFilter.js +++ b/src/BloomFilter.js @@ -1 +1 @@ -"use strict"; \ No newline at end of file +"use strict"; diff --git a/src/bracketBalance.js b/src/bracketBalance.js index 00b0037..6f1f712 100644 --- a/src/bracketBalance.js +++ b/src/bracketBalance.js @@ -5,7 +5,7 @@ */ function isBalanced(searchSpace){ if(searchSpace.length == 0) return false; - + bracketStack = [] for(let i=0; i Date: Wed, 7 Oct 2020 15:11:29 +0530 Subject: [PATCH 04/40] README update --- test/test_bracketBalance.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_bracketBalance.js b/test/test_bracketBalance.js index fc58c7a..468252e 100644 --- a/test/test_bracketBalance.js +++ b/test/test_bracketBalance.js @@ -23,4 +23,4 @@ describe("Bracket Balanced",() => { it("Returns false due to no search space", () => { assert.strictEqual(bracketBalance(""),false); }); -}); \ No newline at end of file +}); From 0b0d1825e775942992047a5581a6bcaa4d11cdb2 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Thu, 8 Oct 2020 16:05:42 +0530 Subject: [PATCH 05/40] Bloom Filter Update! --- README.md | 3 +- package.json | 4 +- src/BloomFilter.js | 107 +++++++++++++++++++++++++++++++++++++++ src/dice_coeff.js | 2 +- src/index.js | 13 +++-- test/test_BloomFilter.js | 25 +++++++++ test/test_dice_coeff.js | 2 +- 7 files changed, 146 insertions(+), 10 deletions(-) create mode 100644 test/test_BloomFilter.js diff --git a/README.md b/README.md index 77645d7..f1e3f53 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ $ npm install string-dsa List of supported Data Structures and Algorithms are : +- [Bloom Filter](https://github.com/thsubaku9/string-dsa/blob/main/src/BloomFilter.js) - [Bracket Balance](https://github.com/thsubaku9/string-dsa/blob/main/src/bracketBalance.js) - [Dice Coefficient](https://github.com/thsubaku9/string-dsa/blob/main/src/dice_coeff.js) - [Knuth Morris Pratt](https://github.com/thsubaku9/string-dsa/blob/main/src/search/kmp.js) @@ -37,7 +38,7 @@ $ npm install Testing: ```sh -$ npm run test +$ npm test ``` Coverage: diff --git a/package.json b/package.json index f9531b0..8ee11c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "0.1.1", + "version": "0.2.0", "description": "String Data Structures and Algorithm Library in JavaScript", "main": "src/index.js", "files": [ @@ -17,7 +17,7 @@ "type": "git", "url": "git+https://github.com/thsubaku9/string-dsa.git" }, - "keywords": [], + "keywords": ["String Algorithms","String Data Structures"], "author": "Kaustubh J ", "license": "ISC", "bugs": { diff --git a/src/BloomFilter.js b/src/BloomFilter.js index 3918c74..0c6a9db 100644 --- a/src/BloomFilter.js +++ b/src/BloomFilter.js @@ -1 +1,108 @@ "use strict"; + +/**Class implementation of Bloom Filter */ +class BF{ + /** + * + * @param {Number} buckets The number of buckets for the hash function + * @param {Number} splits The number of splits you wish to have + * @param {Function[]} customHashFn custom hashing function + * + * @returns {BF} the demanded Bloom Filter + */ + constructor(buckets, splits,customHashFn = null){ + this._bucketSize = buckets; + this._splitSize = splits; + this.bucket = new Array(); + this._useInternalHashFn = true; + this._customHashFn = undefined; + this._insertionCount = 0; + + for (let x = 0; x < this._splitSize; x++){ + let internalArray = new Array(this._bucketSize); + for (let y = 0; y< this._bucketSize; y++) internalArray[y] = false; + this.bucket.push(internalArray); + } + + if (customHashFn != null && customHashFn.length == splits){ + this._useInternalHashFn = false; + this._customHashFn = customHashFn; + } else { + this._customHashFn = []; + for(let i=1; i { + return (x) => { + let hash_value = 0; + for (let j=0;j { + + const myBloomFilter = new BloomFilter(100,5); + const t1="Genshin Impact", t2="Dead Cells", t3="Katana Zero", t4="Paladins"; + + it("Insert a few values",() =>{ + assert.doesNotThrow(() => { + myBloomFilter.insert(t1); + myBloomFilter.insert(t2); + }); + }); + + it("check for existence of an inserted value", () => { + assert.strictEqual(myBloomFilter.exists(t1),1); + assert.strictEqual(myBloomFilter.exists(t2),1); + }); + + it("Uninserted value should not exist (AKA True Negative)", () => { + assert.strictEqual(myBloomFilter.exists(t3),0); + assert.strictEqual(myBloomFilter.exists(t4),0); + }); +}); diff --git a/test/test_dice_coeff.js b/test/test_dice_coeff.js index 22d6135..9280515 100644 --- a/test/test_dice_coeff.js +++ b/test/test_dice_coeff.js @@ -10,7 +10,7 @@ describe('Dice Coefficient', () => { it('should return 1 for the same string', () => { const result = diceCoeff(stringOne, stringOne, n); - assert.strictEqual(result,1); + assert.strictEqual(result,1); }); it('should return -1 if either of the strings is empty', () => { From c1f956db14e67f19ba1dc0c47ebd2f3773c0cbde Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Thu, 8 Oct 2020 16:14:58 +0530 Subject: [PATCH 06/40] readme changes --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f1e3f53..8a779b3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# string-dsa +# string-dsa [![Build Status](https://travis-ci.com/thsubaku9/string-dsa.svg?branch=main)](https://travis-ci.com/thsubaku9/string-dsa) > String oriented Data Structures and Algorithms library for JavaScript ## Installation From 8549287c968a9bbbece20c733d025d87b18a25eb Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Thu, 8 Oct 2020 16:26:38 +0530 Subject: [PATCH 07/40] spacing --- src/dice_coeff.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dice_coeff.js b/src/dice_coeff.js index c8b186e..b12a38b 100644 --- a/src/dice_coeff.js +++ b/src/dice_coeff.js @@ -58,4 +58,4 @@ function computeDice(st1, st2, n) { //score = 2*sharedValueCount/ (st1ValueCount + st2ValueCount) } -module.exports = computeDice; \ No newline at end of file +module.exports = computeDice; From 2ada1ad0b0029636ca20520666c7dc9ebbb1fe04 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Sat, 10 Oct 2020 16:23:30 +0530 Subject: [PATCH 08/40] Custom string sort supported --- README.md | 2 +- src/stringSort.js | 79 +++++++++++++++++++++++++++++++++++++++++++++++ test/test_sort.js | 38 +++++++++++++++++++++++ 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/stringSort.js create mode 100644 test/test_sort.js diff --git a/README.md b/README.md index 8a779b3..250eeae 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ List of supported Data Structures and Algorithms are : - [Dice Coefficient](https://github.com/thsubaku9/string-dsa/blob/main/src/dice_coeff.js) - [Knuth Morris Pratt](https://github.com/thsubaku9/string-dsa/blob/main/src/search/kmp.js) - [Rabin Karp](https://github.com/thsubaku9/string-dsa/blob/main/src/search/rabin_karp.js) - +- [Custom Sort](ttps://github.com/thsubaku9/string-dsa/blob/main/src/search/stringSort.js) ## Utilization To utilize in Node.Js: diff --git a/src/stringSort.js b/src/stringSort.js new file mode 100644 index 0000000..7dac2de --- /dev/null +++ b/src/stringSort.js @@ -0,0 +1,79 @@ +//This is the best performing comparitive sort using n*l*log(n) timing +//TODO: Burst Sort and Cantor Hashing for optimized sorting + +/** + * Returns index wise sorted array for a string array + * + * @param {object[]} stringArray an Array of Objects + * @param {boolean} byIndex set true if you want results returned by index + * @param {Function} compartorFn implement your custom comparatorFn here ! + * @returns {object[]} Array of index/object in sorted fashion + */ +function sort(stringArray, byIndex = false, compartorFn = null){ + if(stringArray.length <1) return []; + + internalComp = compartorFn === null ? (x,y) => { + let i=0; + while(i { + + const unsortedArr = ["its","the","its","the","rick","dance"]; + const reverseComparator = (y,x) =>{ + let i=0; + while(i { + const res = sort(unsortedArr,true); + assert.deepStrictEqual(res,[ 5, 0, 2, 4, 1, 3 ]); + }); + + it(`should return correct sorted order for the array ${unsortedArr}`,() => { + const res = sort(unsortedArr,false); + assert.deepStrictEqual(res,[ 'dance', 'its', 'its', 'rick', 'the', 'the' ]); + }) + + it(`should return correct descending sort for the array ${unsortedArr}`,() => { + const res = sort(unsortedArr,false,reverseComparator); + assert.deepStrictEqual(res,[ 'the', 'the', 'rick', 'its', 'its', 'dance' ]); + }) + + it(`should return [] for empty array`,() => { + const res = sort([],false); + assert.deepStrictEqual(res,[]); + }) +}); From 5453837c726773f3736acc93565dcf998e48c346 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Sat, 10 Oct 2020 16:24:12 +0530 Subject: [PATCH 09/40] Custom string sort supported --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 250eeae..666554b 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,10 @@ List of supported Data Structures and Algorithms are : - [Bloom Filter](https://github.com/thsubaku9/string-dsa/blob/main/src/BloomFilter.js) - [Bracket Balance](https://github.com/thsubaku9/string-dsa/blob/main/src/bracketBalance.js) +- [Custom Sort](ttps://github.com/thsubaku9/string-dsa/blob/main/src/search/stringSort.js) - [Dice Coefficient](https://github.com/thsubaku9/string-dsa/blob/main/src/dice_coeff.js) - [Knuth Morris Pratt](https://github.com/thsubaku9/string-dsa/blob/main/src/search/kmp.js) - [Rabin Karp](https://github.com/thsubaku9/string-dsa/blob/main/src/search/rabin_karp.js) -- [Custom Sort](ttps://github.com/thsubaku9/string-dsa/blob/main/src/search/stringSort.js) ## Utilization To utilize in Node.Js: From b082d22671cbd99eac1314c2c243efcaf9de8094 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Sat, 10 Oct 2020 16:28:16 +0530 Subject: [PATCH 10/40] Custom string sort supported --- package.json | 4 ++-- src/index.js | 4 +++- test/test_sort.js | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 8ee11c1..24f7eb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "0.2.0", + "version": "0.2.1", "description": "String Data Structures and Algorithm Library in JavaScript", "main": "src/index.js", "files": [ @@ -17,7 +17,7 @@ "type": "git", "url": "git+https://github.com/thsubaku9/string-dsa.git" }, - "keywords": ["String Algorithms","String Data Structures"], + "keywords": ["String Algorithms","String Data Structures","Bloom Filter","Custom Sort"], "author": "Kaustubh J ", "license": "ISC", "bugs": { diff --git a/src/index.js b/src/index.js index ba2ac8e..e192cfd 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,6 @@ const bracketBalance = require('./bracketBalance'); const BloomFilter = require('./BloomFilter'); +const customSort = require('./stringSort'); const diceCoeff = require('./dice_coeff'); const kmp = require('./search').kmp; const rabinKarp = require('./search').rabinKarp; @@ -7,7 +8,8 @@ const rabinKarp = require('./search').rabinKarp; module.exports = { BloomFilter, - bracketBalance, + bracketBalance, + customSort, diceCoeff, kmp, rabinKarp diff --git a/test/test_sort.js b/test/test_sort.js index 14432a5..9bd6736 100644 --- a/test/test_sort.js +++ b/test/test_sort.js @@ -1,4 +1,4 @@ -const sort = require('../src').sort; +const sort = require('../src').customSort; const assert = require('assert'); describe("",() => { From 5eccfad7fbd1d66222f3b7984425afccbd23b04b Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Sat, 10 Oct 2020 16:30:12 +0530 Subject: [PATCH 11/40] Custom string sort supported --- test/test_sort.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_sort.js b/test/test_sort.js index 9bd6736..e1b441d 100644 --- a/test/test_sort.js +++ b/test/test_sort.js @@ -1,7 +1,7 @@ const sort = require('../src').customSort; const assert = require('assert'); -describe("",() => { +describe("Custom String Sorting",() => { const unsortedArr = ["its","the","its","the","rick","dance"]; const reverseComparator = (y,x) =>{ From 10f4b66b9775326b3c48fc8b91e6e333c49041fd Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Fri, 16 Oct 2020 12:16:56 +0530 Subject: [PATCH 12/40] sorted implemented --- src/BloomFilter.js | 2 +- src/stringSort.js | 36 ++++++++++++++++++++++++++++++++++-- test/test_sort.js | 13 ++++++++++++- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/BloomFilter.js b/src/BloomFilter.js index 0c6a9db..f951f73 100644 --- a/src/BloomFilter.js +++ b/src/BloomFilter.js @@ -99,7 +99,7 @@ class BF{ let fpr = 1; for( internal_iter= 0; internal_iter { + const internalComp = compartorFn === null ? (x,y) => { let i=0; while(i { + let i=0; + while(i0) return false; + } + return true; +} + +module.exports = { + sort: sort, + sorted: sorted +}; diff --git a/test/test_sort.js b/test/test_sort.js index e1b441d..87d0a23 100644 --- a/test/test_sort.js +++ b/test/test_sort.js @@ -1,4 +1,5 @@ -const sort = require('../src').customSort; +const sort = require('../src').customSort.sort; +const sorted = require('../src').customSort.sorted; const assert = require('assert'); describe("Custom String Sorting",() => { @@ -35,4 +36,14 @@ describe("Custom String Sorting",() => { const res = sort([],false); assert.deepStrictEqual(res,[]); }) + + it(`should return false for unsorted array`, () =>{ + const res = sorted(unsortedArr); + assert.deepStrictEqual(res,false); + }); + + it(`should return true for sorted array`, () =>{ + const res = sorted(sort(unsortedArr,false)); + assert.deepStrictEqual(res,true); + }); }); From a6c301bad71e796834c42017870855b0c8349d18 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Sat, 17 Oct 2020 14:12:46 +0530 Subject: [PATCH 13/40] webpack config --- .travis.yml | 7 +- package-lock.json | 368 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 15 +- src/stringSort.js | 2 +- webpack.config.js | 23 +++ 5 files changed, 409 insertions(+), 6 deletions(-) create mode 100644 webpack.config.js diff --git a/.travis.yml b/.travis.yml index c45caec..996bbe1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ +sudo: false + language: node_js node_js: @@ -7,4 +9,7 @@ install: - npm install script: - - npm test \ No newline at end of file + - npm test + +notifications: + email: false \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0f5134c..580cb77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "0.1.1", + "version": "0.2.3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -353,6 +353,12 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", + "dev": true + }, "@webassemblyjs/ast": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", @@ -678,6 +684,15 @@ "is-string": "^1.0.4" } }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, "asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -725,6 +740,12 @@ } } }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -738,12 +759,56 @@ "dev": true, "optional": true }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", + "dev": true + }, + "babel-loader": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", + "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", + "dev": true, + "requires": { + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.4.0", + "mkdirp": "^0.5.3", + "pify": "^4.0.1", + "schema-utils": "^2.6.5" + }, + "dependencies": { + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + } + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -811,6 +876,15 @@ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", "dev": true }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -1072,6 +1146,12 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, "chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -1216,6 +1296,15 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -1307,6 +1396,19 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "coveralls": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.0.tgz", + "integrity": "sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ==", + "dev": true, + "requires": { + "js-yaml": "^3.13.1", + "lcov-parse": "^1.0.0", + "log-driver": "^1.2.7", + "minimist": "^1.2.5", + "request": "^2.88.2" + } + }, "create-ecdh": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", @@ -1401,6 +1503,15 @@ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -1480,6 +1591,12 @@ } } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, "des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -1539,6 +1656,16 @@ "stream-shift": "^1.0.0" } }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "elliptic": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", @@ -1843,6 +1970,12 @@ "homedir-polyfill": "^1.0.1" } }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", @@ -1929,6 +2062,12 @@ } } }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2058,6 +2197,23 @@ } } }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -2137,6 +2293,15 @@ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -2233,6 +2398,22 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -2386,6 +2567,17 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -2691,6 +2883,12 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, "istanbul-lib-coverage": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", @@ -2888,6 +3086,12 @@ "esprima": "^4.0.0" } }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -2900,12 +3104,24 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, "json5": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", @@ -2915,12 +3131,30 @@ "minimist": "^1.2.0" } }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, + "lcov-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", + "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", + "dev": true + }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -2959,6 +3193,12 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "dev": true + }, "log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -3152,6 +3392,21 @@ } } }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -3260,6 +3515,12 @@ "yargs-unparser": "1.6.1" } }, + "mocha-lcov-reporter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mocha-lcov-reporter/-/mocha-lcov-reporter-1.3.0.tgz", + "integrity": "sha1-Rpve9PivyaEWBW8HnfYYLQr7A4Q=", + "dev": true + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -3578,6 +3839,12 @@ } } }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3813,6 +4080,12 @@ "sha.js": "^2.4.8" } }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", @@ -3931,6 +4204,12 @@ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, "public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", @@ -3992,6 +4271,12 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -4099,6 +4384,34 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4543,6 +4856,23 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, "ssri": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", @@ -4826,6 +5156,16 @@ "is-number": "^7.0.0" } }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, "tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", @@ -4838,6 +5178,21 @@ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -5016,6 +5371,17 @@ "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", "dev": true }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", diff --git a/package.json b/package.json index cd90a46..2ec555e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "0.2.2", + "version": "0.2.3", "description": "String Data Structures and Algorithm Library in JavaScript", "main": "src/index.js", "files": [ @@ -8,16 +8,22 @@ "src" ], "scripts": { - "coverage":"nyc mocha --recursive", + "coverage": "nyc mocha --recursive", "dev": "webpack -d", "test": "mocha --recursive", + "test:coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls", "prod": "webpack -p" }, "repository": { "type": "git", "url": "git+https://github.com/thsubaku9/string-dsa.git" }, - "keywords": ["String Algorithms","String Data Structures","Bloom Filter","Custom Sort"], + "keywords": [ + "String Algorithms", + "String Data Structures", + "Bloom Filter", + "Custom Sort" + ], "author": "Kaustubh J ", "license": "ISC", "bugs": { @@ -25,7 +31,10 @@ }, "homepage": "https://github.com/thsubaku9/string-dsa#readme", "devDependencies": { + "babel-loader": "^8.1.0", + "coveralls": "^3.1.0", "mocha": "^8.1.3", + "mocha-lcov-reporter": "^1.3.0", "nyc": "^15.1.0", "webpack": "^4.44.2", "webpack-cli": "^3.3.12" diff --git a/src/stringSort.js b/src/stringSort.js index 044071e..1df774b 100644 --- a/src/stringSort.js +++ b/src/stringSort.js @@ -70,7 +70,7 @@ function internalSort(indexArray,stringArray,internalComp){ grandMerge.push(sortedRight[0]); sortedRight = sortedRight.slice(1); } - delete leftAr; delete rightAr; + //delete leftAr; delete rightAr; return grandMerge; } diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..361ba8e --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,23 @@ +const path = require('path'); + +module.exports = { + entry : {'string-dsa': './src/index.js'}, + output : { + path: path.resolve(__dirname, 'dist'), + filename: "[name].js", + library: 'stringdsa', + libraryTarget: 'umd' + }, + module : { + rules: [{ + test : /\.js$/, + exclude : /(node_modules)/, + loader: "babel-loader" + }] + }, + devServer : { + contentBase : path.resolve(__dirname, 'dist'), + compress : true, + port : 3000 + } +}; From 11084bddfd973f688d5fd6179f31bcfb0939682d Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Mon, 19 Oct 2020 13:34:43 +0530 Subject: [PATCH 14/40] Edit Distance and 0.3.0 changes --- .travis.yml | 1 + README.md | 3 ++- package.json | 5 +++-- src/edit_distance.js | 37 +++++++++++++++++++++++++++++++++++++ src/index.js | 2 ++ src/stringSort.js | 2 +- test/test_edit_distance.js | 26 ++++++++++++++++++++++++++ 7 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 src/edit_distance.js create mode 100644 test/test_edit_distance.js diff --git a/.travis.yml b/.travis.yml index 996bbe1..0528add 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ install: script: - npm test + - npm run test:coveralls notifications: email: false \ No newline at end of file diff --git a/README.md b/README.md index be5f46c..a9fb686 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# string-dsa [![Build Status](https://travis-ci.com/thsubaku9/string-dsa.svg?branch=main)](https://travis-ci.com/thsubaku9/string-dsa) +# string-dsa [![Build Status](https://travis-ci.com/thsubaku9/string-dsa.svg?branch=main)](https://travis-ci.com/thsubaku9/string-dsa) [![Coverage Status](https://coveralls.io/repos/github/thsubaku9/string-dsa/badge.svg?branch=main)](https://coveralls.io/github/thsubaku9/string-dsa?branch=main) > String oriented Data Structures and Algorithms library for JavaScript ## Installation @@ -15,6 +15,7 @@ List of supported Data Structures and Algorithms are : - [Bracket Balance](https://github.com/thsubaku9/string-dsa/blob/main/src/bracketBalance.js) - [Custom Sort](https://github.com/thsubaku9/string-dsa/blob/main/src/stringSort.js) - [Dice Coefficient](https://github.com/thsubaku9/string-dsa/blob/main/src/dice_coeff.js) +- [Edit/Levenshtein Distance](https://github.com/thsubaku9/string-dsa/blob/main/src/edit_distance.js) - [Knuth Morris Pratt](https://github.com/thsubaku9/string-dsa/blob/main/src/search/kmp.js) - [Rabin Karp](https://github.com/thsubaku9/string-dsa/blob/main/src/search/rabin_karp.js) ## Utilization diff --git a/package.json b/package.json index 2ec555e..f446672 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "0.2.3", + "version": "0.3.0", "description": "String Data Structures and Algorithm Library in JavaScript", "main": "src/index.js", "files": [ @@ -22,7 +22,8 @@ "String Algorithms", "String Data Structures", "Bloom Filter", - "Custom Sort" + "Custom Sort", + "Levenshtein Distance" ], "author": "Kaustubh J ", "license": "ISC", diff --git a/src/edit_distance.js b/src/edit_distance.js new file mode 100644 index 0000000..1450808 --- /dev/null +++ b/src/edit_distance.js @@ -0,0 +1,37 @@ +function min(a,b){ + return a < b ? a : b; +} +/** Finds the Edit distance between two strings + * + * @param {String} string1 the first string + * @param {String} string2 the second string + * + * @returns {Number} states the edit distance between two strings + */ +function editDistance(string1, string2) { + editDistanceMatrix = new Array(); + + for(let i = 0; i< string1.length + 1; i++) { + editDistanceMatrix.push(new Array(string2.length + 1)); + } + + for(let i = 0; i< string2.length + 1; i++){ + editDistanceMatrix[0][i] = i; + } + + for(let i = 0; i< string1.length + 1; i++){ + editDistanceMatrix[i][0] = i; + } + + for(let i = 1; i { + const st1 = "bike", st2 = "bichael", st3 = "chef", st4 = "chefery" + it(`should return ${st3.length} for comparision between "" and ${st3}`, () => { + const res = editDistance("",st3); + assert.strictEqual(res,st3.length); + }) + + it(`should return 3 for comparision between ${st3} and ${st4}`, () => { + const res = editDistance(st3,st4); + assert.strictEqual(res,3); + }) + + it(`should return 4 for comparision between ${st1} and ${st3}`, () => { + const res = editDistance(st1,st3); + assert.strictEqual(res,4); + }) + + it(`should return 4 for comparision between ${st1} and ${st2}`, () => { + const res = editDistance(st1,st2); + assert.strictEqual(res,4); + }) +}) \ No newline at end of file From c8be77fe58f64399d5144aa2a6f3f9891227d192 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Thu, 29 Oct 2020 17:16:37 +0530 Subject: [PATCH 15/40] temp --- README.md | 1 + package.json | 5 +- src/Trie.js | 114 ++++++++++++++++++++++++++++++++++++++++++++++ test/test_Trie.js | 11 +++++ 4 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 src/Trie.js create mode 100644 test/test_Trie.js diff --git a/README.md b/README.md index a9fb686..d68e3c9 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ List of supported Data Structures and Algorithms are : - [Edit/Levenshtein Distance](https://github.com/thsubaku9/string-dsa/blob/main/src/edit_distance.js) - [Knuth Morris Pratt](https://github.com/thsubaku9/string-dsa/blob/main/src/search/kmp.js) - [Rabin Karp](https://github.com/thsubaku9/string-dsa/blob/main/src/search/rabin_karp.js) +- [Trie](https://github.com/thsubaku9/string-dsa/blob/main/src/Trie.js) ## Utilization To utilize in Node.Js: diff --git a/package.json b/package.json index 3988c89..6cb7490 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "0.3.1", + "version": "1.0.0", "description": "String Data Structures and Algorithm Library in JavaScript", "main": "src/index.js", "files": [ @@ -23,7 +23,8 @@ "String Data Structures", "Bloom Filter", "Custom Sort", - "Levenshtein Distance" + "Levenshtein Distance", + "Trie" ], "author": "Kaustubh J ", "license": "ISC", diff --git a/src/Trie.js b/src/Trie.js new file mode 100644 index 0000000..d0d6759 --- /dev/null +++ b/src/Trie.js @@ -0,0 +1,114 @@ +"use strict"; + +/**Class implementation of Trie */ +class Trie{ + /** + * Instantiate your Trie class + */ + constructor(){ + this._rootNode = new Object(); + this._rootNode["$"] = false; + } + + /** + * + * @param {String} searchTerm search term to be inserted into the trie + */ + insertSingle(searchTerm){ + //use the root node, if current element isn't there add it; go down the node and iterate over the word + let currNode = this._rootNode; + for (let j=0; j canRemove: ${canRemove} and string value: ${searchTerm[currentIter]}`); + if(canRemove){ + currentNode[searchTerm[currentIter]] = undefined; + return this._hasChildren(currentNode) == 0; + } + } + } else if(currentIter == searchTerm.length) { + console.log("END") + currentNode["$"] = false + if( this._hasChildren(currentNode) == 0) { + return true; + } + } + return false; + } + + /** + * + * @param {Array} searchList pass a List of search terms to be removed from the Trie + */ + removeList(searchList){ + for( let i=0; i{ + + it("",() => { + + }); + + +}) \ No newline at end of file From ac3a4134755073bd623337163bf509cfe1065cb2 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Thu, 29 Oct 2020 23:23:53 +0530 Subject: [PATCH 16/40] Trie almost done --- src/Trie.js | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Trie.js b/src/Trie.js index d0d6759..dfa1b30 100644 --- a/src/Trie.js +++ b/src/Trie.js @@ -51,7 +51,8 @@ class Trie{ _hasChildren(currentNode){ let thisNodeChildren = 0; for (let x in currentNode){ - if(x != undefined && x !="$") thisNodeChildren +=1; + if (x == "$") thisNodeChildren += currentNode[x]; + else if(currentNode[x] != undefined) thisNodeChildren +=1; } return thisNodeChildren; @@ -61,15 +62,13 @@ class Trie{ //recursively dive deep; at reaching depth check if any more elements branch out from this node, if they do return false, else delete the node and return true. recursive step out if(currentIter canRemove: ${canRemove} and string value: ${searchTerm[currentIter]}`); - if(canRemove){ - currentNode[searchTerm[currentIter]] = undefined; + let canRemove = this._removeSingle(searchTerm,currentNode[searchTerm[currentIter]],currentIter +1) + if(canRemove){ + currentNode[searchTerm[currentIter]] = undefined; return this._hasChildren(currentNode) == 0; } } - } else if(currentIter == searchTerm.length) { - console.log("END") + } else if(currentIter == searchTerm.length) { currentNode["$"] = false if( this._hasChildren(currentNode) == 0) { return true; @@ -88,10 +87,20 @@ class Trie{ } } + /** + * + * @param {String} searchSpace the text to be searched over + * + * @returns {Object[]} where each index gives a start position and end position of the term + */ find(searchSpace){ //iterate over all elements and match according to the trie created + for(let i=0;i Date: Fri, 30 Oct 2020 00:15:43 +0530 Subject: [PATCH 17/40] README enhancement --- README.md | 13 ++++++++++++- src/index.js | 4 +++- test/test_Trie.js | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d68e3c9..7bda61b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# string-dsa [![Build Status](https://travis-ci.com/thsubaku9/string-dsa.svg?branch=main)](https://travis-ci.com/thsubaku9/string-dsa) [![Coverage Status](https://coveralls.io/repos/github/thsubaku9/string-dsa/badge.svg?branch=main)](https://coveralls.io/github/thsubaku9/string-dsa?branch=main) +# string-dsa [![Build Status](https://travis-ci.com/thsubaku9/string-dsa.svg?branch=main)](https://travis-ci.com/thsubaku9/string-dsa) [![Coverage Status](https://coveralls.io/repos/github/thsubaku9/string-dsa/badge.svg?branch=main)](https://coveralls.io/github/thsubaku9/string-dsa?branch=main) ![npm](https://img.shields.io/npm/dt/string-dsa?color=cyan&label=Downloads) ![npm](https://img.shields.io/badge/Niche-Yep%20!-ff69b4) > String oriented Data Structures and Algorithms library for JavaScript ## Installation @@ -27,6 +27,17 @@ To utilize in Node.Js: const stringDSA = require('string-dsa'); ``` +To utilize in Frontend: + +```sh +#follow cloning steps +$ npm run prod +$ cp ./dist/string-dsa.js /YOUR/DIRECTORY/FILENAME.js +``` + +```html + +``` ## Development Steps Cloning: diff --git a/src/index.js b/src/index.js index 3386a8e..b8072ce 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,7 @@ const diceCoeff = require('./dice_coeff'); const editDist = require('./edit_distance'); const kmp = require('./search').kmp; const rabinKarp = require('./search').rabinKarp; +const Trie = require('./Trie'); module.exports = { @@ -14,5 +15,6 @@ module.exports = { diceCoeff, editDist, kmp, - rabinKarp + rabinKarp, + Trie }; diff --git a/test/test_Trie.js b/test/test_Trie.js index ce5d9ff..d47ae7a 100644 --- a/test/test_Trie.js +++ b/test/test_Trie.js @@ -1,5 +1,5 @@ const assert = require('assert'); - +const Trie = require('../src').Trie; describe("Trie based tests",() =>{ From 55fd0124c0e2860d6a93bcb6bde4cc2ddf0cfe12 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Fri, 30 Oct 2020 14:46:37 +0530 Subject: [PATCH 18/40] Trie done --- README.md | 6 +++--- src/Trie.js | 21 +++++++++++++++++++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7bda61b..6ecc9b8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# string-dsa [![Build Status](https://travis-ci.com/thsubaku9/string-dsa.svg?branch=main)](https://travis-ci.com/thsubaku9/string-dsa) [![Coverage Status](https://coveralls.io/repos/github/thsubaku9/string-dsa/badge.svg?branch=main)](https://coveralls.io/github/thsubaku9/string-dsa?branch=main) ![npm](https://img.shields.io/npm/dt/string-dsa?color=cyan&label=Downloads) ![npm](https://img.shields.io/badge/Niche-Yep%20!-ff69b4) +# string-dsa [![Build Status](https://travis-ci.com/thsubaku9/string-dsa.svg?branch=main)](https://travis-ci.com/thsubaku9/string-dsa) [![Coverage Status](https://coveralls.io/repos/github/thsubaku9/string-dsa/badge.svg?branch=main)](https://coveralls.io/github/thsubaku9/string-dsa?branch=main) ![npm](https://img.shields.io/npm/dt/string-dsa?color=fddb3a) ![npm](https://img.shields.io/badge/Niche-Yep%20!-ff69b4) > String oriented Data Structures and Algorithms library for JavaScript ## Installation @@ -27,10 +27,10 @@ To utilize in Node.Js: const stringDSA = require('string-dsa'); ``` -To utilize in Frontend: +To utilize in Vanilla Js: ```sh -#follow cloning steps +# follow cloning steps $ npm run prod $ cp ./dist/string-dsa.js /YOUR/DIRECTORY/FILENAME.js ``` diff --git a/src/Trie.js b/src/Trie.js index dfa1b30..17e17e0 100644 --- a/src/Trie.js +++ b/src/Trie.js @@ -91,16 +91,33 @@ class Trie{ * * @param {String} searchSpace the text to be searched over * - * @returns {Object[]} where each index gives a start position and end position of the term + * @returns {Array[]} where each index gives a start position and end position of the term */ find(searchSpace){ //iterate over all elements and match according to the trie created + let returnArray = []; for(let i=0;i Date: Fri, 30 Oct 2020 16:00:24 +0530 Subject: [PATCH 19/40] tried and tested --- README.md | 2 +- package-lock.json | 2 +- package.json | 4 ++-- src/Trie.js | 4 ++-- test/test_Trie.js | 20 ++++++++++++++++++-- 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 6ecc9b8..3e4d36c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# string-dsa [![Build Status](https://travis-ci.com/thsubaku9/string-dsa.svg?branch=main)](https://travis-ci.com/thsubaku9/string-dsa) [![Coverage Status](https://coveralls.io/repos/github/thsubaku9/string-dsa/badge.svg?branch=main)](https://coveralls.io/github/thsubaku9/string-dsa?branch=main) ![npm](https://img.shields.io/npm/dt/string-dsa?color=fddb3a) ![npm](https://img.shields.io/badge/Niche-Yep%20!-ff69b4) +# string-dsa [![Build Status](https://travis-ci.com/thsubaku9/string-dsa.svg?branch=main)](https://travis-ci.com/thsubaku9/string-dsa) [![Coverage Status](https://coveralls.io/repos/github/thsubaku9/string-dsa/badge.svg?branch=main)](https://coveralls.io/github/thsubaku9/string-dsa?branch=main) ![npm](https://img.shields.io/npm/dt/string-dsa?color=fddb3a) ![npm](https://img.shields.io/badge/Niche-Yep!-ff69b4) > String oriented Data Structures and Algorithms library for JavaScript ## Installation diff --git a/package-lock.json b/package-lock.json index 580cb77..98d39aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "0.2.3", + "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 6cb7490..b5df213 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,14 @@ { "name": "string-dsa", "version": "1.0.0", - "description": "String Data Structures and Algorithm Library in JavaScript", + "description": "String Data Structures and Algorithms Library in JavaScript", "main": "src/index.js", "files": [ "dist", "src" ], "scripts": { - "coverage": "nyc mocha --recursive", + "coverage": "nyc mocha --recursive", "dev": "webpack -d", "test": "mocha --recursive", "test:coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls", diff --git a/src/Trie.js b/src/Trie.js index 17e17e0..bb46044 100644 --- a/src/Trie.js +++ b/src/Trie.js @@ -119,7 +119,7 @@ class Trie{ /** - * @returns {Array} returns the Array of all inserted elements + * @returns {String[]} returns the array of all inserted elements */ listAllElements(){ let elementList = [] @@ -132,7 +132,7 @@ class Trie{ elementList.push(stringSeq); } for (let x in node){ - if(x != "$") this._listFromNode(node[x],elementList,stringSeq + x); + if(x != "$" && (node[x] != undefined)) this._listFromNode(node[x],elementList,stringSeq + x); } } } diff --git a/test/test_Trie.js b/test/test_Trie.js index d47ae7a..76d65ba 100644 --- a/test/test_Trie.js +++ b/test/test_Trie.js @@ -3,9 +3,25 @@ const Trie = require('../src').Trie; describe("Trie based tests",() =>{ - it("",() => { + const myT = new Trie(); + const st1 = "can" + const st2 = "candy" + const st3 = "ban" + const searchSpace = "can the real candy ban?" + const resultPos = [ [ 0, 2 ], [ 13, 15 ], [ 13, 17 ], [ 19, 21 ] ] + it("should insert a bunch of keys",() => { + myT.insertList([st1,st2,st3]) + assert.deepStrictEqual(myT.listAllElements(),[st1,st2,st3]) + }); + it("should find correct locations of searchSpace",() => { + const res = myT.find(searchSpace) + assert.deepStrictEqual(res,resultPos) }); - + it("remove given keys", () => { + myT.removeList([st2,st3]) + assert.deepStrictEqual(myT.listAllElements(),[st1]); + myT.insertList([st2,st3]) + }) }) \ No newline at end of file From 6cac38f78d1648693a3f20abaf8bbfc8546e51e9 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Wed, 4 Nov 2020 13:20:24 +0530 Subject: [PATCH 20/40] Trie enhancements --- package.json | 2 +- src/Trie.js | 34 +++++++++++++++++++++++++++++++++- test/test_Trie.js | 9 ++++++++- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index b5df213..9a502cd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.0.0", + "version": "1.0.1", "description": "String Data Structures and Algorithms Library in JavaScript", "main": "src/index.js", "files": [ diff --git a/src/Trie.js b/src/Trie.js index bb46044..cf538da 100644 --- a/src/Trie.js +++ b/src/Trie.js @@ -135,6 +135,38 @@ class Trie{ if(x != "$" && (node[x] != undefined)) this._listFromNode(node[x],elementList,stringSeq + x); } } + + /** + * + * @param {String} searchTerm + * + * @return {Boolean} States whether the given search term exists or not + */ + contains(searchTerm){ + let currentNode = this._rootNode; + for(let k=0; k{ const st1 = "can" const st2 = "candy" const st3 = "ban" + const na1 = "batman" const searchSpace = "can the real candy ban?" const resultPos = [ [ 0, 2 ], [ 13, 15 ], [ 13, 17 ], [ 19, 21 ] ] + const existResult = [true,true,true,false]; it("should insert a bunch of keys",() => { myT.insertList([st1,st2,st3]) assert.deepStrictEqual(myT.listAllElements(),[st1,st2,st3]) @@ -24,4 +26,9 @@ describe("Trie based tests",() =>{ assert.deepStrictEqual(myT.listAllElements(),[st1]); myT.insertList([st2,st3]) }) -}) \ No newline at end of file + + it("should check whether the given keys exist or not",() => { + const res = myT.containsList([st1,st2,st3,na1]) + assert.deepStrictEqual(res,existResult) + }) +}) From ca54462fadb2411dd4d301c1d6900b4d1190c805 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Sun, 8 Nov 2020 22:36:11 +0530 Subject: [PATCH 21/40] LCS supported --- package-lock.json | 518 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 3 +- src/index.js | 4 +- src/lcs.js | 46 ++++ test/test_lcs.js | 39 ++++ 5 files changed, 607 insertions(+), 3 deletions(-) create mode 100644 src/lcs.js create mode 100644 test/test_lcs.js diff --git a/package-lock.json b/package-lock.json index 98d39aa..ae713da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.0.0", + "version": "1.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -283,6 +283,41 @@ "to-fast-properties": "^2.0.0" } }, + "@eslint/eslintrc": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.1.tgz", + "integrity": "sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -552,6 +587,12 @@ "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", "dev": true }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, "aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -752,6 +793,12 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async-each": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", @@ -1140,6 +1187,12 @@ } } }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -1533,6 +1586,12 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, "default-require-extensions": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", @@ -1638,6 +1697,15 @@ } } }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", @@ -1733,6 +1801,15 @@ } } }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -1856,6 +1933,131 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, + "eslint": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.13.0.tgz", + "integrity": "sha512-uCORMuOO8tUzJmsdRtrvcGq5qposf7Rw0LwkTJkoDbOycVQtQjmnhZSuLQnozLE4TmAzlMVV45eCHmQ1OpDKUQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@eslint/eslintrc": "^0.2.1", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.0", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, "eslint-scope": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", @@ -1866,12 +2068,77 @@ "estraverse": "^4.1.1" } }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true + }, + "espree": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", + "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, "esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -1895,6 +2162,12 @@ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "events": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", @@ -2080,12 +2353,27 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, "figgy-pudding": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", "dev": true }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -2137,6 +2425,34 @@ "is-buffer": "~2.0.3" } }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, "flush-write-stream": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", @@ -2269,6 +2585,12 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "gensync": { "version": "1.0.0-beta.1", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", @@ -2596,6 +2918,30 @@ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", + "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } + }, "import-local": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", @@ -3116,6 +3462,12 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -3155,6 +3507,16 @@ "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", "dev": true }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -3560,6 +3922,12 @@ "to-regex": "^3.0.1" } }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -3937,6 +4305,20 @@ "wrappy": "1" } }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -4005,6 +4387,15 @@ "readable-stream": "^2.1.5" } }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "parse-asn1": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", @@ -4158,6 +4549,12 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -4179,6 +4576,12 @@ "fromentries": "^1.2.0" } }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, "promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", @@ -4356,6 +4759,12 @@ "safe-regex": "^1.1.0" } }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, "release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -4624,6 +5033,43 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + } + } + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -5017,6 +5463,46 @@ "has-flag": "^4.0.0" } }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "tapable": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", @@ -5078,6 +5564,12 @@ "minimatch": "^3.0.4" } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -5193,6 +5685,15 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -5752,6 +6253,12 @@ "string-width": "^1.0.2 || 2" } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "worker-farm": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", @@ -5836,6 +6343,15 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, "write-file-atomic": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", diff --git a/package.json b/package.json index 9a502cd..a1598bd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.0.1", + "version": "1.2.0", "description": "String Data Structures and Algorithms Library in JavaScript", "main": "src/index.js", "files": [ @@ -35,6 +35,7 @@ "devDependencies": { "babel-loader": "^8.1.0", "coveralls": "^3.1.0", + "eslint": "^7.13.0", "mocha": "^8.1.3", "mocha-lcov-reporter": "^1.3.0", "nyc": "^15.1.0", diff --git a/src/index.js b/src/index.js index b8072ce..783007c 100644 --- a/src/index.js +++ b/src/index.js @@ -4,6 +4,7 @@ const customSort = require('./stringSort'); const diceCoeff = require('./dice_coeff'); const editDist = require('./edit_distance'); const kmp = require('./search').kmp; +const lcs = require('./lcs') const rabinKarp = require('./search').rabinKarp; const Trie = require('./Trie'); @@ -14,7 +15,8 @@ module.exports = { customSort, diceCoeff, editDist, - kmp, + kmp, + lcs, rabinKarp, Trie }; diff --git a/src/lcs.js b/src/lcs.js new file mode 100644 index 0000000..34c1f69 --- /dev/null +++ b/src/lcs.js @@ -0,0 +1,46 @@ +function max(a,b){ + return a >b ? a : b; +} + +/** + * + * @param {String} string1 the first string to be used in LCS search + * @param {String} string2 the second string to be used in LCS search + * + * @return {Number} the largest common substring size + */ +function lcs(string1,string2) { + if(!(string1.length & string1.length)){ + return 0; + } + let matchMatrix = Array(); + for (let i=0; i<=string1.length; i++){ + let emptyArray = Array(); + for (let j=0; j<=string2.length ;j++){ + emptyArray.push(0); + } + + matchMatrix.push(emptyArray) + } + + for(let i1 = 0; i1<=string1.length; i1++){ + matchMatrix[i1][0] = 0 + } + + for (let i2 =0; i2<=string2.length; i2++){ + matchMatrix[0][i2] = 0 + } + + for(let i1=1; i1<=string1.length; i1++){ + for(let i2=1; i2<=string2.length; i2++){ + if( string1[i1 - 1] == string2[i2 - 1] ) { + matchMatrix[i1][i2] = matchMatrix[i1 -1][i2 -1] + 1 + } else { + matchMatrix[i1][i2] = max(max(matchMatrix[i1 -1][i2 -1],matchMatrix[i1 -1][i2]),max(matchMatrix[i1 -1][i2 -1],matchMatrix[i1][i2 -1])) + } + } + } + return matchMatrix[string1.length][string2.length]; +} + +module.exports = lcs; \ No newline at end of file diff --git a/test/test_lcs.js b/test/test_lcs.js new file mode 100644 index 0000000..5f41b4c --- /dev/null +++ b/test/test_lcs.js @@ -0,0 +1,39 @@ +const lcs = require('../src').lcs +const assert = require('assert') + +describe("Tests related to Largest Common SubSequence",() => { + + const st1 = "bananas" + const st2 = "panama" + const st3 = "ppp" + const st4 = "ananas" + it(`should return 0 for lcs of ${""} and ${""} -> Handles empty string case`, () => { + const res = lcs("","") + assert.strictEqual(res,0); + }) + + it(`should return ${st1.length} for lcs of ${st1} and ${st1} -> Handles complete overlap case`, () => { + const res = lcs(st1,st1) + assert.strictEqual(res,st1.length) + }) + + it(`should return 4 for lcs of ${st1} and ${st2} -> handles partial overlap case`, () => { + const res = lcs(st1,st2) + assert.strictEqual(res,4) + }) + + it(`should return 0 for lcs of ${st1} and ${st3} -> handles no overlap case`, () => { + const res = lcs(st1,st3) + assert.strictEqual(res,0) + }) + + it(`should return 6 for lcs of ${st1} and ${st4} -> handles partial overlap case`, () => { + const res = lcs(st1,st4) + assert.strictEqual(res,6) + }) + + it(`should return 1 for lcs of ${st2} and ${st3} -> handles repetative letter case`, () => { + const res = lcs(st2,st3) + assert.strictEqual(res,1) + }) +}) \ No newline at end of file From d6f55e7b4942ce312e1cb839532df32c26dde0e5 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Tue, 10 Nov 2020 11:39:59 +0530 Subject: [PATCH 22/40] few minor fixes, started linting work --- .eslintrc.json | 21 ++ .travis.yml | 2 + README.md | 1 + package-lock.json | 501 ++++++++++++++++++++++++++++++++++++++- package.json | 9 +- src/search/index.js | 8 +- src/search/kmp.js | 76 +++--- src/search/rabin_karp.js | 114 ++++----- test/test_BloomFilter.js | 7 +- 9 files changed, 634 insertions(+), 105 deletions(-) create mode 100644 .eslintrc.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..1b2f056 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,21 @@ +{ + "env": { + "browser": true, + "commonjs": true, + "es2021": true, + "node": true + }, + "extends": [ + "airbnb-base" + ], + "parserOptions": { + "ecmaVersion": 12 + }, + "rules": { + "camelcase": ["off"], + "eqeqeq": ["off"], + "linebreak-style": ["error", "windows"], + "max-len": ["warn"], + "no-plusplus":["off"] + } +} diff --git a/.travis.yml b/.travis.yml index 6dd5e0b..ce0dbde 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,9 @@ install: - npm install script: + #- npm run lint - npm test + - npm run prod - npm run test:coveralls diff --git a/README.md b/README.md index 3e4d36c..99aa957 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ List of supported Data Structures and Algorithms are : - [Dice Coefficient](https://github.com/thsubaku9/string-dsa/blob/main/src/dice_coeff.js) - [Edit/Levenshtein Distance](https://github.com/thsubaku9/string-dsa/blob/main/src/edit_distance.js) - [Knuth Morris Pratt](https://github.com/thsubaku9/string-dsa/blob/main/src/search/kmp.js) +- [Longest Common Substring](https://github.com/thsubaku9/string-dsa/blob/main/src/lcs.js) - [Rabin Karp](https://github.com/thsubaku9/string-dsa/blob/main/src/search/rabin_karp.js) - [Trie](https://github.com/thsubaku9/string-dsa/blob/main/src/Trie.js) ## Utilization diff --git a/package-lock.json b/package-lock.json index ae713da..ea8e698 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.2.0", + "version": "1.2.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -394,6 +394,12 @@ "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", "dev": true }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, "@webassemblyjs/ast": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", @@ -707,12 +713,33 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + } + }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, "array.prototype.map": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz", @@ -1187,6 +1214,16 @@ } } }, + "call-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", + "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.0" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1394,6 +1431,12 @@ "typedarray": "^0.0.6" } }, + "confusing-browser-globals": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", + "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", + "dev": true + }, "console-browserify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", @@ -1406,6 +1449,12 @@ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", "dev": true }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, "convert-source-map": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", @@ -1819,6 +1868,15 @@ "prr": "~1.0.1" } }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, "es-abstract": { "version": "1.17.7", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", @@ -2058,6 +2116,203 @@ } } }, + "eslint-config-airbnb-base": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz", + "integrity": "sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.2" + }, + "dependencies": { + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + } + } + }, + "eslint-config-google": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", + "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + } + } + }, + "eslint-plugin-import": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "eslint-scope": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", @@ -2603,6 +2858,17 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-intrinsic": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", + "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, "get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -2883,6 +3149,12 @@ "parse-passwd": "^1.0.0" } }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, "html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -3030,6 +3302,12 @@ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", "dev": true }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3517,6 +3795,32 @@ "type-check": "~0.4.0" } }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -3988,6 +4292,18 @@ "process-on-spawn": "^1.0.0" } }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -4287,6 +4603,17 @@ "object-keys": "^1.0.11" } }, + "object.entries": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", + "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "has": "^1.0.3" + } + }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -4296,6 +4623,18 @@ "isobject": "^3.0.1" } }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4409,6 +4748,15 @@ "safe-buffer": "^5.1.1" } }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -4458,6 +4806,23 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "pbkdf2": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", @@ -4711,6 +5076,78 @@ "safe-buffer": "^5.1.0" } }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -5287,6 +5724,38 @@ } } }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", + "dev": true + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -5658,6 +6127,26 @@ "punycode": "^2.1.1" } }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, "tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", @@ -5872,6 +6361,16 @@ "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", "dev": true }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", diff --git a/package.json b/package.json index a1598bd..0c8f95d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.2.0", + "version": "1.2.1", "description": "String Data Structures and Algorithms Library in JavaScript", "main": "src/index.js", "files": [ @@ -8,10 +8,11 @@ "src" ], "scripts": { - "coverage": "nyc mocha --recursive", + "coverage": "nyc npm test", "dev": "webpack -d", + "lint": "eslint ./src ./test", "test": "mocha --recursive", - "test:coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls", + "test:coveralls": "npm run coverage && nyc report --reporter=text-lcov | coveralls", "prod": "webpack -p" }, "repository": { @@ -36,6 +37,8 @@ "babel-loader": "^8.1.0", "coveralls": "^3.1.0", "eslint": "^7.13.0", + "eslint-config-airbnb-base": "^14.2.1", + "eslint-plugin-import": "^2.22.1", "mocha": "^8.1.3", "mocha-lcov-reporter": "^1.3.0", "nyc": "^15.1.0", diff --git a/src/search/index.js b/src/search/index.js index 4ee7f4d..142bd05 100644 --- a/src/search/index.js +++ b/src/search/index.js @@ -1,7 +1,7 @@ -const kmp = require('./kmp') -const rabinKarp = require('./rabin_karp') +const kmp = require('./kmp'); +const rabinKarp = require('./rabin_karp'); module.exports = { kmp, - rabinKarp -}; \ No newline at end of file + rabinKarp, +}; diff --git a/src/search/kmp.js b/src/search/kmp.js index b1f903a..9062b57 100644 --- a/src/search/kmp.js +++ b/src/search/kmp.js @@ -1,28 +1,27 @@ -function kmp(searchTerm,searchSpace,uniqueToken = '\b'){ - //borderSize will be used to match up with searchTerm + $ + searchSpace - var borderSize = [] - var textArray = searchTerm + uniqueToken + searchSpace - borderSize.push(0); - - let border = 0; - for (i=1; i 0) && (textArray[i] != textArray[border])) { - border = borderSize[border - 1] - } +function kmp(searchTerm, searchSpace, uniqueToken = '\b') { + // borderSize will be used to match up with searchTerm + $ + searchSpace + const borderSize = []; + const textArray = searchTerm + uniqueToken + searchSpace; + borderSize.push(0); - if(textArray[i] == textArray[border]){ - border += 1 - borderSize.push(border) - } else { - border = 0 - borderSize.push(border) - } + let border = 0; + for (let i = 1; i < searchTerm.length + searchSpace.length + 1; i++) { + while ((border > 0) && (textArray[i] !== textArray[border])) { + border = borderSize[border - 1]; } - //returns the end positions - return borderSize -} + if (textArray[i] === textArray[border]) { + border += 1; + borderSize.push(border); + } else { + border = 0; + borderSize.push(border); + } + } + // returns the end positions + return borderSize; +} /** * Returns an Array of starting indexes where searchTerm was found. Returns [-1] if no element @@ -31,24 +30,23 @@ function kmp(searchTerm,searchSpace,uniqueToken = '\b'){ * @param {String} uniqueToken unique never occuring token for border cover * @return {Number[]} Array containing index location of matches */ -function run_kmp(searchTerm,searchSpace,uniqueToken = '\b'){ - if (searchTerm.length<1 || searchSpace.length<1){ - return [-1] - } else { - let startIndex = [] - correctPositions = kmp(searchTerm,searchSpace,uniqueToken = '\b') - for (i =0; i0){ - if (internal_exponent%2==0){ - internal_base *= internal_base - internal_exponent = parseInt(internal_exponent/2) - } else { - final_output *= internal_base - internal_exponent -= 1 - } +function pow(base, exponent) { + let final_output = 1; let internal_base = base; let + internal_exponent = exponent; + while (internal_exponent > 0) { + if (internal_exponent % 2 == 0) { + internal_base *= internal_base; + internal_exponent = parseInt(internal_exponent / 2, 10); + } else { + final_output *= internal_base; + internal_exponent -= 1; } - return final_output + } + return final_output; } -function linearCompare(searchTerm, searchSpace, startPoint, endPoint){ - if(endPoint-startPoint + 1 != searchTerm.length ){ - return false - } +function linearCompare(searchTerm, searchSpace, startPoint, endPoint) { + if (endPoint - startPoint + 1 != searchTerm.length) { + return false; + } - let j; - for (j = startPoint; j < endPoint+1; j++){ - if(searchTerm[j-startPoint] != searchSpace[j]){ - return false; - } - } - return true; + let j; + for (j = startPoint; j < endPoint + 1; j++) { + if (searchTerm[j - startPoint] != searchSpace[j]) { + return false; + } + } + return true; } /** @@ -34,47 +35,46 @@ function linearCompare(searchTerm, searchSpace, startPoint, endPoint){ * @param {Number} bucket Size of your bucket (more is better) * @return {Number[]} Array containing index location of matches */ -function rabin_karp(searchTerm, searchSpace, polynomial = 7, bucket = 3000){ - if (searchTerm.length<1 || searchSpace.length<1){ - return [-1] - } - - let hash_val = 0 - for(i=0; i= searchTerm.length){ - super_hash -= (nth_polynomial_chain * searchSpace.charCodeAt(currentTermIndex)) - currentTermIndex +=1 - } - current_hash = super_hash % bucket + let super_hash = 0; let current_hash = 0; + let currentTermIndex = 0; + const nth_polynomial_chain = pow(polynomial, searchTerm.length); - //console.log(currentTermIndex + " to " +j + " :" + current_hash+ "\n") - if (current_hash == hash_val){ - if(linearCompare(searchTerm,searchSpace,currentTermIndex,j)){ - startIndex.push(currentTermIndex); - } - } + for (let j = 0; j < searchSpace.length; j++) { + super_hash *= polynomial; + super_hash += searchSpace.charCodeAt(j); + + if (j >= searchTerm.length) { + super_hash -= (nth_polynomial_chain * searchSpace.charCodeAt(currentTermIndex)); + currentTermIndex += 1; } + current_hash = super_hash % bucket; - if (startIndex.length<1){ - return [-1] - } else { - return startIndex + // console.log(currentTermIndex + " to " +j + " :" + current_hash+ "\n") + if (current_hash == hash_val) { + if (linearCompare(searchTerm, searchSpace, currentTermIndex, j)) { + startIndex.push(currentTermIndex); + } } + } + + if (startIndex.length < 1) { + return [-1]; + } + return startIndex; } -module.exports = rabin_karp +module.exports = rabin_karp; diff --git a/test/test_BloomFilter.js b/test/test_BloomFilter.js index d9def90..1db9e3e 100644 --- a/test/test_BloomFilter.js +++ b/test/test_BloomFilter.js @@ -3,7 +3,7 @@ const BloomFilter = require('../src').BloomFilter; describe("Bloom Filter", () => { - const myBloomFilter = new BloomFilter(100,5); + const myBloomFilter = new BloomFilter(100,25); const t1="Genshin Impact", t2="Dead Cells", t3="Katana Zero", t4="Paladins"; it("Insert a few values",() =>{ @@ -22,4 +22,9 @@ describe("Bloom Filter", () => { assert.strictEqual(myBloomFilter.exists(t3),0); assert.strictEqual(myBloomFilter.exists(t4),0); }); + + it("Should have a low FPR rate (less that 10% clash)",() =>{ + assert.notStrictEqual(myBloomFilter.FalsePositiveRate > 0.1,true) + }); + }); From 48eff458b818b3b7aa9a17dcdc6b2c45d6684d99 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Tue, 10 Nov 2020 22:51:14 +0530 Subject: [PATCH 23/40] linting ongoing --- .eslintrc.json | 13 ++- .travis.yml | 2 +- src/BloomFilter.js | 165 ++++++++++++++++++-------------------- src/bracketBalance.js | 42 +++++----- src/dice_coeff.js | 63 +++++++-------- src/search/AhoCorasick.js | 0 src/suffix/index.js | 0 7 files changed, 143 insertions(+), 142 deletions(-) create mode 100644 src/search/AhoCorasick.js create mode 100644 src/suffix/index.js diff --git a/.eslintrc.json b/.eslintrc.json index 1b2f056..a6a2ed3 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -13,9 +13,20 @@ }, "rules": { "camelcase": ["off"], + "class-methods-use-this": ["error"], + "comma-dangle": ["error"], "eqeqeq": ["off"], "linebreak-style": ["error", "windows"], "max-len": ["warn"], - "no-plusplus":["off"] + "no-array-constructor": ["warn"], + "no-bitwise": ["off"], + "no-console": ["error"], // eslint-disable-line no-console if you wish to deliberately use console + "no-continue": ["off"], + "no-param-reassign": ["off"], + "no-plusplus": ["off"], + "no-restricted-syntax": ["warn"], + "no-shadow": ["off"], + "no-underscore-dangle": ["off"] + } } diff --git a/.travis.yml b/.travis.yml index ce0dbde..8942b80 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ install: - npm install script: - #- npm run lint + - npm run lint - npm test - npm run prod - npm run test:coveralls diff --git a/src/BloomFilter.js b/src/BloomFilter.js index f951f73..aa6d008 100644 --- a/src/BloomFilter.js +++ b/src/BloomFilter.js @@ -1,108 +1,101 @@ -"use strict"; - -/**Class implementation of Bloom Filter */ -class BF{ - /** - * +/** Class implementation of Bloom Filter */ +class BF { + /** + * * @param {Number} buckets The number of buckets for the hash function * @param {Number} splits The number of splits you wish to have * @param {Function[]} customHashFn custom hashing function - * + * * @returns {BF} the demanded Bloom Filter */ - constructor(buckets, splits,customHashFn = null){ - this._bucketSize = buckets; - this._splitSize = splits; - this.bucket = new Array(); - this._useInternalHashFn = true; - this._customHashFn = undefined; - this._insertionCount = 0; - - for (let x = 0; x < this._splitSize; x++){ - let internalArray = new Array(this._bucketSize); - for (let y = 0; y< this._bucketSize; y++) internalArray[y] = false; - this.bucket.push(internalArray); - } + constructor(buckets, splits, customHashFn = null) { + this._bucketSize = buckets; + this._splitSize = splits; + this.bucket = new Array(); + this._useInternalHashFn = true; + this._customHashFn = undefined; + this._insertionCount = 0; - if (customHashFn != null && customHashFn.length == splits){ - this._useInternalHashFn = false; - this._customHashFn = customHashFn; - } else { - this._customHashFn = []; - for(let i=1; i { - return (x) => { - let hash_value = 0; - for (let j=0;j (x) => { + let hash_value = 0; + for (let j = 0; j < x.length; j++) { + hash_value *= i; + hash_value += x.charCodeAt(j); + hash_value %= this._bucketSize; + } + return hash_value; + })(i)); + } } + } - /** - * - * @param {Object} elem Object that you wish to insert into the Bloom Filter (Should possess toString Property !!) - */ - insert(elem){ - try { - let elem_string = elem.toString(); + get bucketSize() { + return this._bucketSize; + } + + get splitSize() { + return this._splitSize; + } - for (let i=0; i count - let startpos; let currentGram = ""; - for (startpos = 0; startpos < str.length; startpos += 1) { - currentGram += str[startpos] + const gramSplit = new Map(); // gram <-> count + let currentGram = ''; + for (let startpos = 0; startpos < str.length; startpos += 1) { + currentGram += str[startpos]; if (startpos >= n - 1) { if (gramSplit.has(currentGram)) { - gramSplit.set(currentGram,gramSplit.get(currentGram) + 1) + gramSplit.set(currentGram, gramSplit.get(currentGram) + 1); } else { - gramSplit.set(currentGram,1) + gramSplit.set(currentGram, 1); } - currentGram = currentGram.substr(1) + currentGram = currentGram.substr(1); } - } - return gramSplit -}; + } + return gramSplit; +} function min(a, b) { return a > b ? b : a; -}; +} /** * Returns the computed Dice Coefficient for the given n-gram of the two strings @@ -28,34 +28,33 @@ function min(a, b) { * @return {Number} a number between 0 and 1 */ function computeDice(st1, st2, n) { - if (st1.length < 1 || st2.length < 1 || n > min(st1.length, st2.length)) return -1; - mapSt1 = nGram(st1, n) - mapSt2 = nGram(st2, n) - + const mapSt1 = nGram(st1, n); + const mapSt2 = nGram(st2, n); + let sharedValueCount = 0; - - for (let x of mapSt1.keys()){ - if(mapSt2.has(x)){ - sharedValueCount += min(mapSt1.get(x), mapSt2.get(x)); + + for (const x of mapSt1.keys()) { + if (mapSt2.has(x)) { + sharedValueCount += min(mapSt1.get(x), mapSt2.get(x)); } } - - let st1ValueCount = 0,st2ValueCount = 0; - - for (let x of mapSt1.keys()){ - st1ValueCount += mapSt1.get(x) + + let st1ValueCount = 0; let st2ValueCount = 0; + + for (const x of mapSt1.keys()) { + st1ValueCount += mapSt1.get(x); } - - for (let x of mapSt2.keys()){ - st2ValueCount += mapSt2.get(x) + + for (const x of mapSt2.keys()) { + st2ValueCount += mapSt2.get(x); } - - let score = (2 * sharedValueCount) / (st1ValueCount + st2ValueCount) - - return score - //score = 2*sharedValueCount/ (st1ValueCount + st2ValueCount) + + const score = (2 * sharedValueCount) / (st1ValueCount + st2ValueCount); + + return score; + // score = 2*sharedValueCount/ (st1ValueCount + st2ValueCount) } module.exports = computeDice; diff --git a/src/search/AhoCorasick.js b/src/search/AhoCorasick.js new file mode 100644 index 0000000..e69de29 diff --git a/src/suffix/index.js b/src/suffix/index.js new file mode 100644 index 0000000..e69de29 From 493c473cfa2e558d20c38eaab56f27ecc3d98e3e Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Fri, 13 Nov 2020 21:11:34 +0530 Subject: [PATCH 24/40] Minor updates --- .eslintrc.json | 7 +- package.json | 9 +- src/BloomFilter.js | 2 + src/Trie.js | 248 ++++++++++++++++----------------- src/dice_coeff.js | 1 - src/edit_distance.js | 46 +++--- src/index.js | 9 +- src/lcs.js | 62 ++++----- src/search/AhoCorasick.js | 18 +++ src/stringSort.js | 164 +++++++++++----------- test/search/test_kmp.js | 52 ++++--- test/search/test_rabin_karp.js | 52 ++++--- test/test_BloomFilter.js | 41 +++--- test/test_Trie.js | 58 ++++---- test/test_bracketBalance.js | 36 ++--- test/test_dice_coeff.js | 21 ++- test/test_edit_distance.js | 44 +++--- test/test_lcs.js | 65 +++++---- test/test_sort.js | 93 ++++++------- 19 files changed, 511 insertions(+), 517 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index a6a2ed3..77ebe49 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -13,7 +13,7 @@ }, "rules": { "camelcase": ["off"], - "class-methods-use-this": ["error"], + "class-methods-use-this": ["warn"], "comma-dangle": ["error"], "eqeqeq": ["off"], "linebreak-style": ["error", "windows"], @@ -22,11 +22,14 @@ "no-bitwise": ["off"], "no-console": ["error"], // eslint-disable-line no-console if you wish to deliberately use console "no-continue": ["off"], + "no-new-object": ["off"], "no-param-reassign": ["off"], "no-plusplus": ["off"], "no-restricted-syntax": ["warn"], "no-shadow": ["off"], - "no-underscore-dangle": ["off"] + "no-underscore-dangle": ["off"], + "quotes" :["off"], + "strict": ["off"] } } diff --git a/package.json b/package.json index 0c8f95d..926e5dc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.2.1", + "version": "1.2.2", "description": "String Data Structures and Algorithms Library in JavaScript", "main": "src/index.js", "files": [ @@ -8,12 +8,11 @@ "src" ], "scripts": { - "coverage": "nyc npm test", - "dev": "webpack -d", - "lint": "eslint ./src ./test", + "coverage": "nyc npm test", + "lint": "eslint ./src", "test": "mocha --recursive", "test:coveralls": "npm run coverage && nyc report --reporter=text-lcov | coveralls", - "prod": "webpack -p" + "prod": "webpack -d" }, "repository": { "type": "git", diff --git a/src/BloomFilter.js b/src/BloomFilter.js index aa6d008..00f8a9d 100644 --- a/src/BloomFilter.js +++ b/src/BloomFilter.js @@ -1,3 +1,5 @@ +"use strict"; + /** Class implementation of Bloom Filter */ class BF { /** diff --git a/src/Trie.js b/src/Trie.js index 323caf3..db5f9a9 100644 --- a/src/Trie.js +++ b/src/Trie.js @@ -1,173 +1,169 @@ "use strict"; -/**Class implementation of Trie */ -class Trie{ - /** +/** Class implementation of Trie */ +class Trie { + /** * Instantiate your Trie class */ - constructor(){ - this._rootNode = new Object(); - this._rootNode["$"] = false; - } + constructor() { + this._rootNode = new Object(); + this._rootNode.$ = false; + } - /** - * + /** + * * @param {String} searchTerm search term to be inserted into the trie */ - insertSingle(searchTerm){ - //use the root node, if current element isn't there add it; go down the node and iterate over the word - let currNode = this._rootNode; - for (let j=0; jb ? a : b; +function max(a, b) { + return a > b ? a : b; } /** - * + * * @param {String} string1 the first string to be used in LCS search * @param {String} string2 the second string to be used in LCS search - * + * * @return {Number} the largest common substring size */ -function lcs(string1,string2) { - if(!(string1.length & string1.length)){ - return 0; +function lcs(string1, string2) { + if (!(string1.length & string1.length)) { + return 0; + } + const matchMatrix = Array(); + for (let i = 0; i <= string1.length; i++) { + const emptyArray = Array(); + for (let j = 0; j <= string2.length; j++) { + emptyArray.push(0); } - let matchMatrix = Array(); - for (let i=0; i<=string1.length; i++){ - let emptyArray = Array(); - for (let j=0; j<=string2.length ;j++){ - emptyArray.push(0); - } - matchMatrix.push(emptyArray) - } + matchMatrix.push(emptyArray); + } - for(let i1 = 0; i1<=string1.length; i1++){ - matchMatrix[i1][0] = 0 - } + for (let i1 = 0; i1 <= string1.length; i1++) { + matchMatrix[i1][0] = 0; + } - for (let i2 =0; i2<=string2.length; i2++){ - matchMatrix[0][i2] = 0 - } + for (let i2 = 0; i2 <= string2.length; i2++) { + matchMatrix[0][i2] = 0; + } - for(let i1=1; i1<=string1.length; i1++){ - for(let i2=1; i2<=string2.length; i2++){ - if( string1[i1 - 1] == string2[i2 - 1] ) { - matchMatrix[i1][i2] = matchMatrix[i1 -1][i2 -1] + 1 - } else { - matchMatrix[i1][i2] = max(max(matchMatrix[i1 -1][i2 -1],matchMatrix[i1 -1][i2]),max(matchMatrix[i1 -1][i2 -1],matchMatrix[i1][i2 -1])) - } - } + for (let i1 = 1; i1 <= string1.length; i1++) { + for (let i2 = 1; i2 <= string2.length; i2++) { + if (string1[i1 - 1] == string2[i2 - 1]) { + matchMatrix[i1][i2] = matchMatrix[i1 - 1][i2 - 1] + 1; + } else { + matchMatrix[i1][i2] = max(max(matchMatrix[i1 - 1][i2 - 1], matchMatrix[i1 - 1][i2]), max(matchMatrix[i1 - 1][i2 - 1], matchMatrix[i1][i2 - 1])); + } } - return matchMatrix[string1.length][string2.length]; + } + return matchMatrix[string1.length][string2.length]; } -module.exports = lcs; \ No newline at end of file +module.exports = lcs; diff --git a/src/search/AhoCorasick.js b/src/search/AhoCorasick.js index e69de29..c8abe68 100644 --- a/src/search/AhoCorasick.js +++ b/src/search/AhoCorasick.js @@ -0,0 +1,18 @@ +"use strict"; + +class AC{ + /** + * + * @param {String[]} keywordList the list of keywords that you wish to use for searching + * @param {Number} maxStates the number of states that are allowed (maxStates >= total number of letters in keywordlist). Set as -1 to allow the algorithm to figure out by itself + */ + constructor(keywordList,maxStates = -1){ + this.totalStates = maxStates > 0 ? maxStates : keywordList.reduce((letterCount,str) => {return letterCount + str.length},0) + } + + find(searchSpace){ + + } +} + +//module.exports = AC; \ No newline at end of file diff --git a/src/stringSort.js b/src/stringSort.js index fa14fff..67065ba 100644 --- a/src/stringSort.js +++ b/src/stringSort.js @@ -1,111 +1,103 @@ -//This is the best performing comparitive sort using n*l*log(n) timing -//TODO: Burst Sort and Cantor Hashing for optimized sorting +function internalSort(indexArray, stringArray, internalComp) { + if (indexArray.length == 1) { + return indexArray; + } + const midpt = parseInt(indexArray.length / 2, 10); + const grandMerge = []; + const leftAr = indexArray.slice(0, midpt); + const rightAr = indexArray.slice(midpt, indexArray.length); + + let sortedLeft = internalSort(leftAr, stringArray, internalComp); + let sortedRight = internalSort(rightAr, stringArray, internalComp); + + while (sortedLeft.length && sortedRight.length) { + if (internalComp(stringArray[sortedLeft[0]], stringArray[sortedRight[0]]) <= 0) { + grandMerge.push(sortedLeft[0]); + sortedLeft = sortedLeft.slice(1); + } else { + grandMerge.push(sortedRight[0]); + sortedRight = sortedRight.slice(1); + } + } + + while (sortedLeft.length) { + grandMerge.push(sortedLeft[0]); + sortedLeft = sortedLeft.slice(1); + } + + while (sortedRight.length) { + grandMerge.push(sortedRight[0]); + sortedRight = sortedRight.slice(1); + } + // delete leftAr; delete rightAr; + + return grandMerge; +} /** * Returns index wise sorted array for a string array - * + * * @param {object[]} stringArray an Array of Objects * @param {boolean} byIndex set true if you want results returned by index * @param {Function} compartorFn implement your custom comparatorFn here ! * @returns {object[]} Array of index/object in sorted fashion */ -function sort(stringArray, byIndex = false, compartorFn = null){ - if(stringArray.length <1) return []; - - const internalComp = compartorFn === null ? (x,y) => { - let i=0; - while(i { + let i = 0; + while (i < x.length && i < y.length) { + if (x.charCodeAt(i) != y.charCodeAt(i)) { + return (x.charCodeAt(i) - y.charCodeAt(i)); + } + i++; } -} - -function internalSort(indexArray,stringArray,internalComp){ - if(indexArray.length == 1) { - return indexArray; - } else { - let midpt = parseInt(indexArray.length/2); - let grandMerge = [] - let leftAr = indexArray.slice(0,midpt) - let rightAr = indexArray.slice(midpt,indexArray.length) - - let sortedLeft = internalSort(leftAr,stringArray,internalComp); - let sortedRight = internalSort(rightAr,stringArray,internalComp); - - while(sortedLeft.length && sortedRight.length){ - if(internalComp(stringArray[sortedLeft[0]],stringArray[sortedRight[0]]) <= 0) { - grandMerge.push(sortedLeft[0]); - sortedLeft = sortedLeft.slice(1); - } else { - grandMerge.push(sortedRight[0]); - sortedRight = sortedRight.slice(1); - } - } + return (x.length - y.length); + } : compartorFn; + const indexArray = Array(stringArray.length); + for (let i = 0; i < stringArray.length; i++) indexArray[i] = i; - while(sortedLeft.length){ - grandMerge.push(sortedLeft[0]); - sortedLeft = sortedLeft.slice(1); - } + const result = internalSort(indexArray, stringArray, internalComp); - while(sortedRight.length){ - grandMerge.push(sortedRight[0]); - sortedRight = sortedRight.slice(1); - } - //delete leftAr; delete rightAr; - - return grandMerge; - } + if (byIndex) { + return result; + } + const valueResult = []; + for (let i = 0; i < result.length; i++) { + valueResult.push(stringArray[result[i]]); + } + return valueResult; } /** - * + * * @param {object[]} array an Array of Objects * @param {Function} compartorFn comparator function - * + * * @returns {boolean} states whether the array is sorted or not */ -function sorted(array, compartorFn = null){ - if (array.length <2 ) return true; +function sorted(array, compartorFn = null) { + if (array.length < 2) return true; - const internalComp = compartorFn === null ? (x,y) => { - let i=0; - while(i0) return false; + const internalComp = compartorFn === null ? (x, y) => { + let i = 0; + while (i < x.length && i < y.length) { + if (x.charCodeAt(i) != y.charCodeAt(i)) { + return (x.charCodeAt(i) - y.charCodeAt(i)); + } + i++; } - return true; + return (x.length - y.length); + } : compartorFn; + + for (let x = 0; x < array.length - 1; x++) { + if (internalComp(array[x], array[x + 1]) > 0) return false; + } + return true; } module.exports = { - sort: sort, - sorted: sorted + sort, + sorted, }; diff --git a/test/search/test_kmp.js b/test/search/test_kmp.js index 6b4e843..9daff37 100644 --- a/test/search/test_kmp.js +++ b/test/search/test_kmp.js @@ -1,36 +1,32 @@ -const kmp = require("../../src").kmp; const assert = require('assert'); - +const { kmp } = require("../../src"); describe('Knuth Morris Pratt', () => { - - const searchTerm1 = "cancan", searchTerm2 = "mixolydian", searchTerm3 = "pina"; - const searchSpace1 = "cancancan like a tin cancan?", searchSpace2 = "what even do you mean", searchSpace3 = "pina colada and what ?"; + const searchTerm1 = "cancan"; const searchTerm2 = "mixolydian"; const + searchTerm3 = "pina"; + const searchSpace1 = "cancancan like a tin cancan?"; const searchSpace2 = "what even do you mean"; const + searchSpace3 = "pina colada and what ?"; + + it(`should return index of "${searchTerm1}" in three positions for "${searchSpace1}"`, () => { + const result = kmp(searchTerm1, searchSpace1); + assert.deepStrictEqual(result, [0, 3, 21]); + }); - it(`should return index of "${searchTerm1}" in three positions for "${searchSpace1}"`, () => { - - const result = kmp(searchTerm1,searchSpace1) - assert.deepStrictEqual(result, [0,3,21]); - }); - - it(`should return [-1] for "${searchTerm2}" in "${searchSpace2}"`, () => { - - const result = kmp(searchTerm2,searchSpace2) - assert.deepStrictEqual(result, [-1]); - }); - - it(`should return one index for "${searchTerm3}" in "${searchSpace3}" `, () => { - - const result = kmp(searchTerm3,searchSpace3) - assert.deepStrictEqual(result, [0]); - }); + it(`should return [-1] for "${searchTerm2}" in "${searchSpace2}"`, () => { + const result = kmp(searchTerm2, searchSpace2); + assert.deepStrictEqual(result, [-1]); + }); - it('should return [-1] if either the searchTerm or searchSpace is empty', () => { + it(`should return one index for "${searchTerm3}" in "${searchSpace3}" `, () => { + const result = kmp(searchTerm3, searchSpace3); + assert.deepStrictEqual(result, [0]); + }); - const resultOne = kmp("",searchSpace1); - assert.deepStrictEqual(resultOne, [-1]); + it('should return [-1] if either the searchTerm or searchSpace is empty', () => { + const resultOne = kmp("", searchSpace1); + assert.deepStrictEqual(resultOne, [-1]); - const resultTwo = kmp(searchTerm1,""); - assert.deepStrictEqual(resultTwo, [-1]); - }); + const resultTwo = kmp(searchTerm1, ""); + assert.deepStrictEqual(resultTwo, [-1]); + }); }); diff --git a/test/search/test_rabin_karp.js b/test/search/test_rabin_karp.js index ccd6187..29a4920 100644 --- a/test/search/test_rabin_karp.js +++ b/test/search/test_rabin_karp.js @@ -1,36 +1,32 @@ -const rabin_karp = require("../../src").rabinKarp const assert = require('assert'); - +const rabin_karp = require("../../src").rabinKarp; describe('Rabin Karp', () => { - - const searchTerm1 = "cancan", searchTerm2 = "mixolydian", searchTerm3 = "pina"; - const searchSpace1 = "cancancan like a tin cancan?", searchSpace2 = "what even do you mean", searchSpace3 = "pina colada and what ?"; + const searchTerm1 = "cancan"; const searchTerm2 = "mixolydian"; const + searchTerm3 = "pina"; + const searchSpace1 = "cancancan like a tin cancan?"; const searchSpace2 = "what even do you mean"; const + searchSpace3 = "pina colada and what ?"; + + it(`should return index of ${searchTerm1} in three positions for ${searchSpace1}`, () => { + const result = rabin_karp(searchTerm1, searchSpace1); + assert.deepStrictEqual(result, [0, 3, 21]); + }); - it(`should return index of \"${searchTerm1}\" in three positions for \"${searchSpace1}\"`, () => { - - const result = rabin_karp(searchTerm1,searchSpace1) - assert.deepStrictEqual(result, [0,3,21]); - }); - - it(`should return [-1] for \"${searchTerm2}\" in \"${searchSpace2}\"`, () => { - - const result = rabin_karp(searchTerm2,searchSpace2) - assert.deepStrictEqual(result, [-1]); - }); - - it(`should return one index for \"${searchTerm3}\" in \"${searchSpace3}\" `, () => { - - const result = rabin_karp(searchTerm3,searchSpace3) - assert.deepStrictEqual(result, [0]); - }); + it(`should return [-1] for ${searchTerm2} in ${searchSpace2}`, () => { + const result = rabin_karp(searchTerm2, searchSpace2); + assert.deepStrictEqual(result, [-1]); + }); - it('should return [-1] if either the searchTerm or searchSpace is empty', () => { + it(`should return one index for ${searchTerm3} in ${searchSpace3} `, () => { + const result = rabin_karp(searchTerm3, searchSpace3); + assert.deepStrictEqual(result, [0]); + }); - const resultOne = rabin_karp("",searchSpace1); - assert.deepStrictEqual(resultOne, [-1]); + it('should return [-1] if either the searchTerm or searchSpace is empty', () => { + const resultOne = rabin_karp("", searchSpace1); + assert.deepStrictEqual(resultOne, [-1]); - const resultTwo = rabin_karp(searchTerm1,""); - assert.deepStrictEqual(resultTwo, [-1]); - }); + const resultTwo = rabin_karp(searchTerm1, ""); + assert.deepStrictEqual(resultTwo, [-1]); + }); }); diff --git a/test/test_BloomFilter.js b/test/test_BloomFilter.js index 1db9e3e..a425e42 100644 --- a/test/test_BloomFilter.js +++ b/test/test_BloomFilter.js @@ -1,30 +1,29 @@ const assert = require('assert'); -const BloomFilter = require('../src').BloomFilter; +const { BloomFilter } = require('../src'); describe("Bloom Filter", () => { + const myBloomFilter = new BloomFilter(100, 25); + const t1 = "Genshin Impact"; const t2 = "Dead Cells"; const t3 = "Katana Zero"; const + t4 = "Paladins"; - const myBloomFilter = new BloomFilter(100,25); - const t1="Genshin Impact", t2="Dead Cells", t3="Katana Zero", t4="Paladins"; - - it("Insert a few values",() =>{ - assert.doesNotThrow(() => { - myBloomFilter.insert(t1); - myBloomFilter.insert(t2); - }); + it("Insert a few values", () => { + assert.doesNotThrow(() => { + myBloomFilter.insert(t1); + myBloomFilter.insert(t2); }); + }); - it("check for existence of an inserted value", () => { - assert.strictEqual(myBloomFilter.exists(t1),1); - assert.strictEqual(myBloomFilter.exists(t2),1); - }); + it("check for existence of an inserted value", () => { + assert.strictEqual(myBloomFilter.exists(t1), 1); + assert.strictEqual(myBloomFilter.exists(t2), 1); + }); - it("Uninserted value should not exist (AKA True Negative)", () => { - assert.strictEqual(myBloomFilter.exists(t3),0); - assert.strictEqual(myBloomFilter.exists(t4),0); - }); + it("Uninserted value should not exist (AKA True Negative)", () => { + assert.strictEqual(myBloomFilter.exists(t3), 0); + assert.strictEqual(myBloomFilter.exists(t4), 0); + }); - it("Should have a low FPR rate (less that 10% clash)",() =>{ - assert.notStrictEqual(myBloomFilter.FalsePositiveRate > 0.1,true) - }); - + it("Should have a low FPR rate (less that 10% clash)", () => { + assert.notStrictEqual(myBloomFilter.FalsePositiveRate > 0.1, true); + }); }); diff --git a/test/test_Trie.js b/test/test_Trie.js index 29c04b7..9f6cf60 100644 --- a/test/test_Trie.js +++ b/test/test_Trie.js @@ -1,35 +1,33 @@ const assert = require('assert'); -const Trie = require('../src').Trie; +const { Trie } = require('../src'); -describe("Trie based tests",() =>{ +describe("Trie based tests", () => { + const myT = new Trie(); + const st1 = "can"; + const st2 = "candy"; + const st3 = "ban"; + const na1 = "batman"; + const searchSpace = "can the real candy ban?"; + const resultPos = [[0, 2], [13, 15], [13, 17], [19, 21]]; + const existResult = [true, true, true, false]; + it("should insert a bunch of keys", () => { + myT.insertList([st1, st2, st3]); + assert.deepStrictEqual(myT.listAllElements(), [st1, st2, st3]); + }); - const myT = new Trie(); - const st1 = "can" - const st2 = "candy" - const st3 = "ban" - const na1 = "batman" - const searchSpace = "can the real candy ban?" - const resultPos = [ [ 0, 2 ], [ 13, 15 ], [ 13, 17 ], [ 19, 21 ] ] - const existResult = [true,true,true,false]; - it("should insert a bunch of keys",() => { - myT.insertList([st1,st2,st3]) - assert.deepStrictEqual(myT.listAllElements(),[st1,st2,st3]) - }); + it("should find correct locations of searchSpace", () => { + const res = myT.find(searchSpace); + assert.deepStrictEqual(res, resultPos); + }); - it("should find correct locations of searchSpace",() => { - const res = myT.find(searchSpace) - assert.deepStrictEqual(res,resultPos) - }); - - it("remove given keys", () => { - myT.removeList([st2,st3]) - assert.deepStrictEqual(myT.listAllElements(),[st1]); - myT.insertList([st2,st3]) - }) - - it("should check whether the given keys exist or not",() => { - const res = myT.containsList([st1,st2,st3,na1]) - assert.deepStrictEqual(res,existResult) - }) -}) + it("remove given keys", () => { + myT.removeList([st2, st3]); + assert.deepStrictEqual(myT.listAllElements(), [st1]); + myT.insertList([st2, st3]); + }); + it("should check whether the given keys exist or not", () => { + const res = myT.containsList([st1, st2, st3, na1]); + assert.deepStrictEqual(res, existResult); + }); +}); diff --git a/test/test_bracketBalance.js b/test/test_bracketBalance.js index 468252e..ad1c019 100644 --- a/test/test_bracketBalance.js +++ b/test/test_bracketBalance.js @@ -1,26 +1,26 @@ -const bracketBalance = require('../src').bracketBalance; const assert = require('assert'); +const { bracketBalance } = require('../src'); -describe("Bracket Balanced",() => { - const searchSpace1 = "[[[]]]]",searchSpace2 = "I am (an) as{s}guardian",searchSpace3 = "the [code] {speaker} of nativity {nirvana] is (here",searchSpace4 = "( what if i get (comfortable" +describe("Bracket Balanced", () => { + const searchSpace1 = "[[[]]]]"; const searchSpace2 = "I am (an) as{s}guardian"; const searchSpace3 = "the [code] {speaker} of nativity {nirvana] is (here"; const searchSpace4 = "( what if i get (comfortable"; - it("Returns false due to extra closing bracket", () => { - assert.strictEqual(bracketBalance(searchSpace1),false); - }); + it("Returns false due to extra closing bracket", () => { + assert.strictEqual(bracketBalance(searchSpace1), false); + }); - it("Returns true due to balance", () => { - assert.strictEqual(bracketBalance(searchSpace2),true); - }); + it("Returns true due to balance", () => { + assert.strictEqual(bracketBalance(searchSpace2), true); + }); - it("Returns false due to misbalance", () => { - assert.strictEqual(bracketBalance(searchSpace3),false); - }); + it("Returns false due to misbalance", () => { + assert.strictEqual(bracketBalance(searchSpace3), false); + }); - it("Returns false due to all opening brackets", () => { - assert.strictEqual(bracketBalance(searchSpace4),false); - }); + it("Returns false due to all opening brackets", () => { + assert.strictEqual(bracketBalance(searchSpace4), false); + }); - it("Returns false due to no search space", () => { - assert.strictEqual(bracketBalance(""),false); - }); + it("Returns false due to no search space", () => { + assert.strictEqual(bracketBalance(""), false); + }); }); diff --git a/test/test_dice_coeff.js b/test/test_dice_coeff.js index 9280515..8c4ea08 100644 --- a/test/test_dice_coeff.js +++ b/test/test_dice_coeff.js @@ -1,38 +1,37 @@ -const diceCoeff = require('../src').diceCoeff const assert = require('assert'); +const { diceCoeff } = require('../src'); describe('Dice Coefficient', () => { const stringOne = 'batman'; const stringTwo = 'cowgirl'; - const stringThree = 'batmen'; + const stringThree = 'batmen'; const n = 2; const over = 100; it('should return 1 for the same string', () => { const result = diceCoeff(stringOne, stringOne, n); - assert.strictEqual(result,1); + assert.strictEqual(result, 1); }); - it('should return -1 if either of the strings is empty', () => { + it('should return -1 if either of the strings is empty', () => { const resultOne = diceCoeff('', stringTwo, n); - assert.strictEqual(resultOne,-1); + assert.strictEqual(resultOne, -1); const resultTwo = diceCoeff(stringOne, '', n); - assert.strictEqual(resultTwo,-1); + assert.strictEqual(resultTwo, -1); }); - it('should return -1 if the n value is more than the minimum length of either of the two strings', () => { + it('should return -1 if the n value is more than the minimum length of either of the two strings', () => { const result = diceCoeff(stringOne, stringTwo, over); assert.strictEqual(result, -1); }); - - it(`should return 0 for ${stringOne} and ${stringTwo} with n = ${n}`, () => { + it(`should return 0 for ${stringOne} and ${stringTwo} with n = ${n}`, () => { const result = diceCoeff(stringOne, stringTwo, n); assert.strictEqual(result, 0); }); - it(`should return 0.6 for ${stringOne} and ${stringThree} with n = ${n}`, () => { + it(`should return 0.6 for ${stringOne} and ${stringThree} with n = ${n}`, () => { const result = diceCoeff(stringOne, stringThree, n); - assert.strictEqual(result, 0.6) + assert.strictEqual(result, 0.6); }); }); diff --git a/test/test_edit_distance.js b/test/test_edit_distance.js index 4ca1187..8d5c962 100644 --- a/test/test_edit_distance.js +++ b/test/test_edit_distance.js @@ -1,26 +1,26 @@ -const editDist = require('../src').editDist; const assert = require('assert'); const editDistance = require('../src').editDist; -describe("Edit Distance Test", ()=> { - const st1 = "bike", st2 = "bichael", st3 = "chef", st4 = "chefery" - it(`should return ${st3.length} for comparision between "" and ${st3}`, () => { - const res = editDistance("",st3); - assert.strictEqual(res,st3.length); - }) +describe("Edit Distance Test", () => { + const st1 = "bike"; const st2 = "bichael"; const st3 = "chef"; const + st4 = "chefery"; + it(`should return ${st3.length} for comparision between "" and ${st3}`, () => { + const res = editDistance("", st3); + assert.strictEqual(res, st3.length); + }); - it(`should return 3 for comparision between ${st3} and ${st4}`, () => { - const res = editDistance(st3,st4); - assert.strictEqual(res,3); - }) - - it(`should return 4 for comparision between ${st1} and ${st3}`, () => { - const res = editDistance(st1,st3); - assert.strictEqual(res,4); - }) - - it(`should return 4 for comparision between ${st1} and ${st2}`, () => { - const res = editDistance(st1,st2); - assert.strictEqual(res,4); - }) -}) \ No newline at end of file + it(`should return 3 for comparision between ${st3} and ${st4}`, () => { + const res = editDistance(st3, st4); + assert.strictEqual(res, 3); + }); + + it(`should return 4 for comparision between ${st1} and ${st3}`, () => { + const res = editDistance(st1, st3); + assert.strictEqual(res, 4); + }); + + it(`should return 4 for comparision between ${st1} and ${st2}`, () => { + const res = editDistance(st1, st2); + assert.strictEqual(res, 4); + }); +}); diff --git a/test/test_lcs.js b/test/test_lcs.js index 5f41b4c..e257782 100644 --- a/test/test_lcs.js +++ b/test/test_lcs.js @@ -1,39 +1,38 @@ -const lcs = require('../src').lcs -const assert = require('assert') +const assert = require('assert'); +const { lcs } = require('../src'); -describe("Tests related to Largest Common SubSequence",() => { +describe("Tests related to Largest Common SubSequence", () => { + const st1 = "bananas"; + const st2 = "panama"; + const st3 = "ppp"; + const st4 = "ananas"; + it(`should return 0 for lcs of ${""} and ${""} -> Handles empty string case`, () => { + const res = lcs("", ""); + assert.strictEqual(res, 0); + }); - const st1 = "bananas" - const st2 = "panama" - const st3 = "ppp" - const st4 = "ananas" - it(`should return 0 for lcs of ${""} and ${""} -> Handles empty string case`, () => { - const res = lcs("","") - assert.strictEqual(res,0); - }) + it(`should return ${st1.length} for lcs of ${st1} and ${st1} -> Handles complete overlap case`, () => { + const res = lcs(st1, st1); + assert.strictEqual(res, st1.length); + }); - it(`should return ${st1.length} for lcs of ${st1} and ${st1} -> Handles complete overlap case`, () => { - const res = lcs(st1,st1) - assert.strictEqual(res,st1.length) - }) - - it(`should return 4 for lcs of ${st1} and ${st2} -> handles partial overlap case`, () => { - const res = lcs(st1,st2) - assert.strictEqual(res,4) - }) + it(`should return 4 for lcs of ${st1} and ${st2} -> handles partial overlap case`, () => { + const res = lcs(st1, st2); + assert.strictEqual(res, 4); + }); - it(`should return 0 for lcs of ${st1} and ${st3} -> handles no overlap case`, () => { - const res = lcs(st1,st3) - assert.strictEqual(res,0) - }) + it(`should return 0 for lcs of ${st1} and ${st3} -> handles no overlap case`, () => { + const res = lcs(st1, st3); + assert.strictEqual(res, 0); + }); - it(`should return 6 for lcs of ${st1} and ${st4} -> handles partial overlap case`, () => { - const res = lcs(st1,st4) - assert.strictEqual(res,6) - }) + it(`should return 6 for lcs of ${st1} and ${st4} -> handles partial overlap case`, () => { + const res = lcs(st1, st4); + assert.strictEqual(res, 6); + }); - it(`should return 1 for lcs of ${st2} and ${st3} -> handles repetative letter case`, () => { - const res = lcs(st2,st3) - assert.strictEqual(res,1) - }) -}) \ No newline at end of file + it(`should return 1 for lcs of ${st2} and ${st3} -> handles repetative letter case`, () => { + const res = lcs(st2, st3); + assert.strictEqual(res, 1); + }); +}); diff --git a/test/test_sort.js b/test/test_sort.js index 87d0a23..e75f7ff 100644 --- a/test/test_sort.js +++ b/test/test_sort.js @@ -1,49 +1,48 @@ -const sort = require('../src').customSort.sort; -const sorted = require('../src').customSort.sorted; const assert = require('assert'); - -describe("Custom String Sorting",() => { - - const unsortedArr = ["its","the","its","the","rick","dance"]; - const reverseComparator = (y,x) =>{ - let i=0; - while(i { - const res = sort(unsortedArr,true); - assert.deepStrictEqual(res,[ 5, 0, 2, 4, 1, 3 ]); - }); - - it(`should return correct sorted order for the array ${unsortedArr}`,() => { - const res = sort(unsortedArr,false); - assert.deepStrictEqual(res,[ 'dance', 'its', 'its', 'rick', 'the', 'the' ]); - }) - - it(`should return correct descending sort for the array ${unsortedArr}`,() => { - const res = sort(unsortedArr,false,reverseComparator); - assert.deepStrictEqual(res,[ 'the', 'the', 'rick', 'its', 'its', 'dance' ]); - }) - - it(`should return [] for empty array`,() => { - const res = sort([],false); - assert.deepStrictEqual(res,[]); - }) - - it(`should return false for unsorted array`, () =>{ - const res = sorted(unsortedArr); - assert.deepStrictEqual(res,false); - }); - - it(`should return true for sorted array`, () =>{ - const res = sorted(sort(unsortedArr,false)); - assert.deepStrictEqual(res,true); - }); +const { sort } = require('../src').customSort; +const { sorted } = require('../src').customSort; + + +describe("Custom String Sorting", () => { + const unsortedArr = ["its", "the", "its", "the", "rick", "dance"]; + const reverseComparator = (y, x) => { + let i = 0; + while (i < x.length && i < y.length) { + if (x.charCodeAt(i) != y.charCodeAt(i)) { + return (x.charCodeAt(i) - y.charCodeAt(i)); + } + i++; + } + return (x.length - y.length); + }; + + it(`should return correct indices for the array ${unsortedArr}`, () => { + const res = sort(unsortedArr, true); + assert.deepStrictEqual(res, [5, 0, 2, 4, 1, 3]); + }); + + it(`should return correct sorted order for the array ${unsortedArr}`, () => { + const res = sort(unsortedArr, false); + assert.deepStrictEqual(res, ['dance', 'its', 'its', 'rick', 'the', 'the']); + }); + + it(`should return correct descending sort for the array ${unsortedArr}`, () => { + const res = sort(unsortedArr, false, reverseComparator); + assert.deepStrictEqual(res, ['the', 'the', 'rick', 'its', 'its', 'dance']); + }); + + it(`should return [] for empty array`, () => { + const res = sort([], false); + assert.deepStrictEqual(res, []); + }); + + it(`should return false for unsorted array`, () => { + const res = sorted(unsortedArr); + assert.deepStrictEqual(res, false); + }); + + it(`should return true for sorted array`, () => { + const res = sorted(sort(unsortedArr, false)); + assert.deepStrictEqual(res, true); + }); }); From 0590e93b4a92a069399447d0de8ce57458e07b46 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Fri, 13 Nov 2020 21:25:08 +0530 Subject: [PATCH 25/40] merge modification --- .travis.yml | 2 +- src/search/AhoCorasick.js | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8942b80..65e5756 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ sudo: false language: node_js node_js: - - 10.5 + - 10.15.0 install: - npm install diff --git a/src/search/AhoCorasick.js b/src/search/AhoCorasick.js index c8abe68..e229947 100644 --- a/src/search/AhoCorasick.js +++ b/src/search/AhoCorasick.js @@ -1,18 +1,18 @@ "use strict"; -class AC{ - /** - * +class AC { + /** + * * @param {String[]} keywordList the list of keywords that you wish to use for searching * @param {Number} maxStates the number of states that are allowed (maxStates >= total number of letters in keywordlist). Set as -1 to allow the algorithm to figure out by itself */ - constructor(keywordList,maxStates = -1){ - this.totalStates = maxStates > 0 ? maxStates : keywordList.reduce((letterCount,str) => {return letterCount + str.length},0) - } - - find(searchSpace){ + constructor(keywordList, maxStates = -1) { + this.totalStates = maxStates > 0 ? maxStates : keywordList.reduce((letterCount, str) => letterCount + str.length, 0); + } - } + find(searchSpace) { + return searchSpace; + } } -//module.exports = AC; \ No newline at end of file +module.exports = AC; From 9cb55089accf5b5e3e6840b8f3c376cfcbb01ab4 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Fri, 13 Nov 2020 21:31:33 +0530 Subject: [PATCH 26/40] LF update --- .eslintrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index 7aef11b..e30efff 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -16,7 +16,7 @@ "class-methods-use-this": ["warn"], "comma-dangle": ["error"], "eqeqeq": ["off"], - "linebreak-style": ["error", "windows"], + "linebreak-style": ["warn", "linux"], "max-len": ["warn"], "no-array-constructor": ["warn"], "no-bitwise": ["off"], From 65d609ec34acaacdaef439052fae365cd2ffceaa Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Fri, 13 Nov 2020 21:34:12 +0530 Subject: [PATCH 27/40] LF update --- .eslintrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index e30efff..5d76fd8 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -16,7 +16,7 @@ "class-methods-use-this": ["warn"], "comma-dangle": ["error"], "eqeqeq": ["off"], - "linebreak-style": ["warn", "linux"], + "linebreak-style": ["off"], "max-len": ["warn"], "no-array-constructor": ["warn"], "no-bitwise": ["off"], From 6d416a32c2c855edc50c3a76f4b715566bd7a49c Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Wed, 18 Nov 2020 18:32:38 +0530 Subject: [PATCH 28/40] Aho Corasick main files --- README.md | 1 + package.json | 3 +- src/index.js | 4 +- src/search/AhoCorasick.js | 112 +++++++++++++++++++++++++++++++- src/search/index.js | 3 +- test/search/test_AhoCorasick.js | 27 ++++++++ 6 files changed, 144 insertions(+), 6 deletions(-) create mode 100644 test/search/test_AhoCorasick.js diff --git a/README.md b/README.md index 99aa957..e0528bf 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ $ npm install string-dsa List of supported Data Structures and Algorithms are : +- [Aho Corasick](https://github.com/thsubaku9/string-dsa/blob/main/src/AhoCorasick.js) - [Bloom Filter](https://github.com/thsubaku9/string-dsa/blob/main/src/BloomFilter.js) - [Bracket Balance](https://github.com/thsubaku9/string-dsa/blob/main/src/bracketBalance.js) - [Custom Sort](https://github.com/thsubaku9/string-dsa/blob/main/src/stringSort.js) diff --git a/package.json b/package.json index 926e5dc..c01f279 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.2.2", + "version": "1.3.0", "description": "String Data Structures and Algorithms Library in JavaScript", "main": "src/index.js", "files": [ @@ -21,6 +21,7 @@ "keywords": [ "String Algorithms", "String Data Structures", + "Aho Corasick", "Bloom Filter", "Custom Sort", "Levenshtein Distance", diff --git a/src/index.js b/src/index.js index 24e4def..e03bb5f 100644 --- a/src/index.js +++ b/src/index.js @@ -3,12 +3,12 @@ const BloomFilter = require('./BloomFilter'); const customSort = require('./stringSort'); const diceCoeff = require('./dice_coeff'); const editDist = require('./edit_distance'); -const { kmp } = require('./search'); +const { AhoCorasick,kmp,rabinKarp } = require('./search'); const lcs = require('./lcs'); -const { rabinKarp } = require('./search'); const Trie = require('./Trie'); module.exports = { + AhoCorasick, BloomFilter, bracketBalance, customSort, diff --git a/src/search/AhoCorasick.js b/src/search/AhoCorasick.js index e229947..508b710 100644 --- a/src/search/AhoCorasick.js +++ b/src/search/AhoCorasick.js @@ -1,5 +1,6 @@ "use strict"; +//AC is being implemented as a transition: map> for lesser restrictions and failure: array[state] and output: array[state] class AC { /** * @@ -7,11 +8,118 @@ class AC { * @param {Number} maxStates the number of states that are allowed (maxStates >= total number of letters in keywordlist). Set as -1 to allow the algorithm to figure out by itself */ constructor(keywordList, maxStates = -1) { - this.totalStates = maxStates > 0 ? maxStates : keywordList.reduce((letterCount, str) => letterCount + str.length, 0); + this.totalStates = maxStates > 0 ? maxStates : (keywordList.reduce((letterCount, str) => letterCount + str.length, 0) + 1); + this.keyWords = new Array(...keywordList); + this.states = 0; + //this.stateTransitions = new Map>(); -- for typescript + this.stateTransitions = new Map(); + + this.stateTransitions.set(0,new Map()); + + this.failureTransition = new Array(this.totalStates); + + this.stateOutput = new Array(this.totalStates); + + for(let i=0; i 0; myOutputs >>= 1, index++){ + if(myOutputs & 0x01 ){ + let locationPair = [] + locationPair.push(i - (this.keyWords[index].length - 1)) + locationPair.push(i) + resultLocation.push(locationPair); + } + } + } + } + + return resultLocation; } } diff --git a/src/search/index.js b/src/search/index.js index 142bd05..b2cd393 100644 --- a/src/search/index.js +++ b/src/search/index.js @@ -1,7 +1,8 @@ const kmp = require('./kmp'); const rabinKarp = require('./rabin_karp'); - +const AhoCorasick = require('./AhoCorasick') module.exports = { + AhoCorasick, kmp, rabinKarp, }; diff --git a/test/search/test_AhoCorasick.js b/test/search/test_AhoCorasick.js new file mode 100644 index 0000000..42e1d95 --- /dev/null +++ b/test/search/test_AhoCorasick.js @@ -0,0 +1,27 @@ +const assert = require("assert"); +const AhoCorasick = require("../../src").AhoCorasick; + +describe("Aho Corasick tests", () => { + const keywordList = ["lemon","lemonade","monday","zebras"] + const searchSpace = "lemon and lemonday is nice for zebzebras" + const hitLocation = [] + var mySearcher = undefined; + it("Insert the necessary keywords", () => { + mySearcher = new AhoCorasick(keywordList); + + assert.deepStrictEqual(mySearcher.keyWords ,keywordList); + }) + + it("Should state the maximum number of required states",() => { + assert.strictEqual(mySearcher.totalStates,keywordList.reduce((prevVal,currentVal) => prevVal + currentVal.length, 1)) + }) + + it("Should state the actual number of used states",() =>{ + assert.strictEqual(mySearcher.totalStates >= mySearcher.states,true) + }) + + it("Find the matching keywords in given text", () => { + assert.deepStrictEqual(mySearcher.find(searchSpace),hitLocation); + }) + +}) \ No newline at end of file From 3c41b783ec9701992770f81b06ec62d45cd156d4 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Wed, 18 Nov 2020 22:59:09 +0530 Subject: [PATCH 29/40] Aho Corasick Polishing --- .eslintrc.json | 1 + src/search/AhoCorasick.js | 116 ++++++++++++++++---------------- test/search/test_AhoCorasick.js | 39 ++++++----- 3 files changed, 79 insertions(+), 77 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 5d76fd8..c8004ba 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -28,6 +28,7 @@ "no-restricted-syntax": ["warn"], "no-shadow": ["off"], "no-underscore-dangle": ["off"], + "prefer-const": ["off"], "quotes" :["off"], "strict": ["off"] } diff --git a/src/search/AhoCorasick.js b/src/search/AhoCorasick.js index 508b710..390fc14 100644 --- a/src/search/AhoCorasick.js +++ b/src/search/AhoCorasick.js @@ -1,6 +1,6 @@ "use strict"; -//AC is being implemented as a transition: map> for lesser restrictions and failure: array[state] and output: array[state] +// AC is being implemented as a transition: map> for lesser restrictions and failure: array[state] and output: array[state] class AC { /** * @@ -11,108 +11,110 @@ class AC { this.totalStates = maxStates > 0 ? maxStates : (keywordList.reduce((letterCount, str) => letterCount + str.length, 0) + 1); this.keyWords = new Array(...keywordList); this.states = 0; - //this.stateTransitions = new Map>(); -- for typescript + // this.stateTransitions = new Map>(); -- for typescript this.stateTransitions = new Map(); - this.stateTransitions.set(0,new Map()); + this.stateTransitions.set(0, new Map()); this.failureTransition = new Array(this.totalStates); this.stateOutput = new Array(this.totalStates); - for(let i=0; i 0; myOutputs >>= 1, index++){ - if(myOutputs & 0x01 ){ - let locationPair = [] - locationPair.push(i - (this.keyWords[index].length - 1)) - locationPair.push(i) + for (let myOutputs = this.stateOutput[currentState], index = 0; myOutputs > 0; myOutputs >>= 1, index++) { + if (myOutputs & 0x01) { + let locationPair = []; + locationPair.push(i - (this.keyWords[index].length - 1)); + locationPair.push(i); resultLocation.push(locationPair); } } diff --git a/test/search/test_AhoCorasick.js b/test/search/test_AhoCorasick.js index 42e1d95..d69ba5d 100644 --- a/test/search/test_AhoCorasick.js +++ b/test/search/test_AhoCorasick.js @@ -1,27 +1,26 @@ const assert = require("assert"); -const AhoCorasick = require("../../src").AhoCorasick; +const { AhoCorasick } = require("../../src"); describe("Aho Corasick tests", () => { - const keywordList = ["lemon","lemonade","monday","zebras"] - const searchSpace = "lemon and lemonday is nice for zebzebras" - const hitLocation = [] - var mySearcher = undefined; - it("Insert the necessary keywords", () => { - mySearcher = new AhoCorasick(keywordList); + const keywordList = ["lemon", "lemonade", "monday", "zebras"]; + const searchSpace = "lemon and lemonday is nice for zebzebras"; + const hitLocation = [[0, 4], [10, 14], [12, 17], [34, 39]]; + let mySearcher; + it("Insert the necessary keywords", () => { + mySearcher = new AhoCorasick(keywordList); - assert.deepStrictEqual(mySearcher.keyWords ,keywordList); - }) + assert.deepStrictEqual(mySearcher.keyWords, keywordList); + }); - it("Should state the maximum number of required states",() => { - assert.strictEqual(mySearcher.totalStates,keywordList.reduce((prevVal,currentVal) => prevVal + currentVal.length, 1)) - }) + it("Should state the maximum number of required states", () => { + assert.strictEqual(mySearcher.totalStates, keywordList.reduce((prevVal, currentVal) => prevVal + currentVal.length, 1)); + }); - it("Should state the actual number of used states",() =>{ - assert.strictEqual(mySearcher.totalStates >= mySearcher.states,true) - }) + it("Should state the actual number of used states", () => { + assert.strictEqual(mySearcher.totalStates >= mySearcher.states, true); + }); - it("Find the matching keywords in given text", () => { - assert.deepStrictEqual(mySearcher.find(searchSpace),hitLocation); - }) - -}) \ No newline at end of file + it("Find the matching keywords in given text", () => { + assert.deepStrictEqual(mySearcher.find(searchSpace), hitLocation); + }); +}); From e28e34fdfc3f7b17d352bc376d20a991f13b79cc Mon Sep 17 00:00:00 2001 From: Kaustubh J Date: Wed, 18 Nov 2020 23:05:43 +0530 Subject: [PATCH 30/40] Update index.js --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index e03bb5f..2637afd 100644 --- a/src/index.js +++ b/src/index.js @@ -3,7 +3,7 @@ const BloomFilter = require('./BloomFilter'); const customSort = require('./stringSort'); const diceCoeff = require('./dice_coeff'); const editDist = require('./edit_distance'); -const { AhoCorasick,kmp,rabinKarp } = require('./search'); +const { AhoCorasick, kmp, rabinKarp } = require('./search'); const lcs = require('./lcs'); const Trie = require('./Trie'); From f220a70d390cb813f8b513be581025ae3d1079ff Mon Sep 17 00:00:00 2001 From: Kaustubh J Date: Wed, 18 Nov 2020 23:07:06 +0530 Subject: [PATCH 31/40] Update index.js --- src/search/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/search/index.js b/src/search/index.js index b2cd393..b658b0f 100644 --- a/src/search/index.js +++ b/src/search/index.js @@ -1,6 +1,7 @@ const kmp = require('./kmp'); const rabinKarp = require('./rabin_karp'); -const AhoCorasick = require('./AhoCorasick') +const AhoCorasick = require('./AhoCorasick'); + module.exports = { AhoCorasick, kmp, From 553142da50c6c77cce62916e0960a88d9ed230b6 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Wed, 18 Nov 2020 23:24:01 +0530 Subject: [PATCH 32/40] darn mini annotation bugs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c01f279..8b65667 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.3.0", + "version": "1.3.1", "description": "String Data Structures and Algorithms Library in JavaScript", "main": "src/index.js", "files": [ From 2811d95d871ddf0ca74e39883bbeba3629ec6eb0 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Fri, 20 Nov 2020 15:16:23 +0530 Subject: [PATCH 33/40] AhoCorasick fix --- package.json | 2 +- src/search/AhoCorasick.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8b65667..c18c46b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.3.1", + "version": "1.3.2", "description": "String Data Structures and Algorithms Library in JavaScript", "main": "src/index.js", "files": [ diff --git a/src/search/AhoCorasick.js b/src/search/AhoCorasick.js index 390fc14..df44eb8 100644 --- a/src/search/AhoCorasick.js +++ b/src/search/AhoCorasick.js @@ -46,7 +46,8 @@ class AC { } while (buffer.length) { - let currentState = buffer.pop(); + let currentState = buffer[0]; + buffer = buffer.slice(1); for (let x of this.stateTransitions.get(currentState).keys()) { if (x == undefined) continue; From e5a682738007a2696a12ac6fa2202c730aff45a1 Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Wed, 25 Nov 2020 23:13:02 +0530 Subject: [PATCH 34/40] Burst Sort support --- package.json | 2 +- src/Trie.js | 38 +++++++++++++++ src/edit_distance.js | 2 +- src/lcs.js | 2 +- src/suffix/SuffixMain.js | 100 +++++++++++++++++++++++++++++++++++++++ src/suffix/index.js | 5 ++ test/test_Trie.js | 7 +++ 7 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 src/suffix/SuffixMain.js diff --git a/package.json b/package.json index c18c46b..db5a04c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.3.2", + "version": "1.4.0", "description": "String Data Structures and Algorithms Library in JavaScript", "main": "src/index.js", "files": [ diff --git a/src/Trie.js b/src/Trie.js index db5f9a9..732621e 100644 --- a/src/Trie.js +++ b/src/Trie.js @@ -164,6 +164,44 @@ class Trie { } return res; } + + /** + * @returns {String[]} returns the ordered value of keys using BurstSort + */ + burstSort() { + const arr = []; + this._burstSortInternal(this._rootNode, arr, ""); + return arr; + } + + _burstSortInternal(node, arr, collectorString) { + let c; + if (node.$ === true) arr.push(collectorString); + + // Numerics + for (let i = 0; i < 10; i++) { + c = String(0 + i); + if (node[c] !== undefined) { + this._burstSortInternal(node[c], arr, collectorString + c); + } + } + + // Upper Case + for (let i = 0; i < 26; i++) { + c = String.fromCharCode(i + "A".charCodeAt(0)); + if (node[c] !== undefined) { + this._burstSortInternal(node[c], arr, collectorString + c); + } + } + + // Lower Case + for (let i = 0; i < 26; i++) { + c = String.fromCharCode(i + "a".charCodeAt(0)); + if (node[c] !== undefined) { + this._burstSortInternal(node[c], arr, collectorString + c); + } + } + } } module.exports = Trie; diff --git a/src/edit_distance.js b/src/edit_distance.js index d844d8f..8538268 100644 --- a/src/edit_distance.js +++ b/src/edit_distance.js @@ -28,7 +28,7 @@ function editDistance(string1, string2) { if (string1.charAt(i - 1) === string2.charAt(j - 1)) { editDistanceMatrix[i][j] = editDistanceMatrix[i - 1][j - 1]; } else { - editDistanceMatrix[i][j] = min(min(editDistanceMatrix[i - 1][j - 1], editDistanceMatrix[i][j - 1]), min(editDistanceMatrix[i][j - 1], editDistanceMatrix[i - 1][j])) + 1; + editDistanceMatrix[i][j] = min(editDistanceMatrix[i - 1][j - 1], min(editDistanceMatrix[i][j - 1], editDistanceMatrix[i - 1][j])) + 1; } } } diff --git a/src/lcs.js b/src/lcs.js index 34b682c..efc5837 100644 --- a/src/lcs.js +++ b/src/lcs.js @@ -36,7 +36,7 @@ function lcs(string1, string2) { if (string1[i1 - 1] == string2[i2 - 1]) { matchMatrix[i1][i2] = matchMatrix[i1 - 1][i2 - 1] + 1; } else { - matchMatrix[i1][i2] = max(max(matchMatrix[i1 - 1][i2 - 1], matchMatrix[i1 - 1][i2]), max(matchMatrix[i1 - 1][i2 - 1], matchMatrix[i1][i2 - 1])); + matchMatrix[i1][i2] = max(max(matchMatrix[i1][i2 - 1], matchMatrix[i1 - 1][i2]), matchMatrix[i1 - 1][i2 - 1]); } } } diff --git a/src/suffix/SuffixMain.js b/src/suffix/SuffixMain.js new file mode 100644 index 0000000..e76b2cf --- /dev/null +++ b/src/suffix/SuffixMain.js @@ -0,0 +1,100 @@ +"use strict"; + +// const Suffix = require("./src/suffix").Suffixer +// mySfx = new Suffix("marijuana") + +class Suffixer { + constructor(mainString) { + this.CHAR_LIM = 27; + this.originalString = `${mainString.toLowerCase()}$`; + + this.order = new Array(this.originalString.length); + this.class = new Array(this.originalString.length); + this.lcpArray = new Array(this.originalString.length); + this.suffixConstructed = false; + } + + charOrder() { + let charCount = new Array(this.CHAR_LIM); + for (let i = 0; i < this.CHAR_LIM; i++) charCount[i] = 0; + + for (let i = 0; i < this.originalString.length; i++) { + if (this.originalString.charAt(i) === "$") { + charCount[0] += 1; + } else { + charCount[this.originalString.charCodeAt(i) - "a".charCodeAt(0) + 1] += 1; + } + } + + for (let i = 1; i < this.CHAR_LIM; i++) { + charCount[i] += charCount[i - 1]; + } + + for (let i = this.originalString.length - 1; i >= 0; i--) { + let c; + if (this.originalString.charAt(i) === "$") { + c = 0; + } else { + c = this.originalString.charCodeAt(i) - "a".charCodeAt(0) + 1; + } + charCount[c] -= 1; + this.order[charCount[c]] = i; + } + } + + charClass() { + let pos = 0; let + classNumber = 0; + this.class[this.order[pos]] = classNumber; + pos++; + while (pos < this.originalString.length) { + if (this.originalString.charAt(this.order[pos - 1]) !== this.originalString.charAt(this.order[pos])) { + classNumber += 1; + } + this.class[this.order[pos]] = classNumber; + pos++; + } + } + + /* + sortDouble(L) { + let newOrder = new Array(this.originalString.length); + + return newOrder; + } + + updateClass(L) { + let newClass = new Array(this.originalString.length); + + return newClass; + } +*/ + + suffixArray() { + if (this.suffixConstructed) return this.order; + + let L = 1; + this.charOrder(); + this.charClass(); + while (L < this.originalString.length) { + // this.order = this.sortDouble(L); + // this.class = this.updateClass(L); + L *= 2; + } + + this.suffixConstructed = true; + return this.order; + } + + /* + lcpArray(){ + if(!this.suffixConstructed) this.suffixArray() + + for (let i=0; i< this.originalString.length; i++) this.lcpArray[i] = 0 + + // Do LCP stuff + } + */ +} + +module.exports = Suffixer; diff --git a/src/suffix/index.js b/src/suffix/index.js index e69de29..bef6606 100644 --- a/src/suffix/index.js +++ b/src/suffix/index.js @@ -0,0 +1,5 @@ +const Suffixer = require("./SuffixMain"); + +module.exports = { + Suffixer, +}; diff --git a/test/test_Trie.js b/test/test_Trie.js index 9f6cf60..28c1288 100644 --- a/test/test_Trie.js +++ b/test/test_Trie.js @@ -10,6 +10,8 @@ describe("Trie based tests", () => { const searchSpace = "can the real candy ban?"; const resultPos = [[0, 2], [13, 15], [13, 17], [19, 21]]; const existResult = [true, true, true, false]; + const orderedKeys = [st3,st1,st2]; + it("should insert a bunch of keys", () => { myT.insertList([st1, st2, st3]); assert.deepStrictEqual(myT.listAllElements(), [st1, st2, st3]); @@ -30,4 +32,9 @@ describe("Trie based tests", () => { const res = myT.containsList([st1, st2, st3, na1]); assert.deepStrictEqual(res, existResult); }); + + it("should perform burstsort properly",() =>{ + const res = myT.burstSort(); + assert.deepStrictEqual(res,orderedKeys); + }); }); From cb35809d29fe880d225caa129a1825bfedd9c15e Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Wed, 25 Nov 2020 23:58:57 +0530 Subject: [PATCH 35/40] Suffix Array --- src/suffix/SuffixMain.js | 57 +++++++++++++++++++++++++++----------- test/suffix/test_Suffix.js | 1 + 2 files changed, 42 insertions(+), 16 deletions(-) create mode 100644 test/suffix/test_Suffix.js diff --git a/src/suffix/SuffixMain.js b/src/suffix/SuffixMain.js index e76b2cf..e5f883a 100644 --- a/src/suffix/SuffixMain.js +++ b/src/suffix/SuffixMain.js @@ -42,33 +42,58 @@ class Suffixer { } } - charClass() { - let pos = 0; let - classNumber = 0; - this.class[this.order[pos]] = classNumber; - pos++; - while (pos < this.originalString.length) { - if (this.originalString.charAt(this.order[pos - 1]) !== this.originalString.charAt(this.order[pos])) { - classNumber += 1; - } - this.class[this.order[pos]] = classNumber; - pos++; - } + charClass() { + this.class[this.order[0]] = 0; + for(let i = 1; i=0; i--){ + let cyclicShiftPosition = (this.order[i] - L + this.originalString.length) % (this.originalString.length) + let cl = this.class[cyclicShiftPosition] + count[cl] -= 1 + newOrder [count[cl]] = cyclicShiftPosition + } + return newOrder; } updateClass(L) { let newClass = new Array(this.originalString.length); + newClass[this.order[0]] = 0 + + for(let i=1; i Date: Thu, 26 Nov 2020 00:22:48 +0530 Subject: [PATCH 36/40] Suffix shift bug --- src/suffix/SuffixMain.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/suffix/SuffixMain.js b/src/suffix/SuffixMain.js index e5f883a..b944680 100644 --- a/src/suffix/SuffixMain.js +++ b/src/suffix/SuffixMain.js @@ -83,7 +83,7 @@ class Suffixer { for(let i=1; i Date: Sat, 28 Nov 2020 00:08:41 +0530 Subject: [PATCH 37/40] lcp and suffix array --- src/index.js | 2 ++ src/suffix/SuffixMain.js | 72 ++++++++++++++++++++++++++++++++------ src/suffix/index.js | 4 +-- test/suffix/test_Suffix.js | 15 +++++++- 4 files changed, 79 insertions(+), 14 deletions(-) diff --git a/src/index.js b/src/index.js index 2637afd..edc90e7 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,7 @@ const diceCoeff = require('./dice_coeff'); const editDist = require('./edit_distance'); const { AhoCorasick, kmp, rabinKarp } = require('./search'); const lcs = require('./lcs'); +const SuffixOps = require('./suffix') const Trie = require('./Trie'); module.exports = { @@ -17,5 +18,6 @@ module.exports = { kmp, lcs, rabinKarp, + SuffixOps, Trie, }; diff --git a/src/suffix/SuffixMain.js b/src/suffix/SuffixMain.js index b944680..e1b8486 100644 --- a/src/suffix/SuffixMain.js +++ b/src/suffix/SuffixMain.js @@ -1,17 +1,18 @@ "use strict"; -// const Suffix = require("./src/suffix").Suffixer +// const Suffix = require("./src/suffix").SuffixOps // mySfx = new Suffix("marijuana") - -class Suffixer { +// mySfx.computeLcpArray() +class SuffixMain { constructor(mainString) { this.CHAR_LIM = 27; this.originalString = `${mainString.toLowerCase()}$`; this.order = new Array(this.originalString.length); this.class = new Array(this.originalString.length); - this.lcpArray = new Array(this.originalString.length); + this.lcpArray = new Array(this.originalString.length - 1); this.suffixConstructed = false; + this.lcpConstructed = false; } charOrder() { @@ -111,15 +112,64 @@ class Suffixer { return this.order; } - /* - lcpArray(){ - if(!this.suffixConstructed) this.suffixArray() + reverseIndexSA(){ + let iSA = new Array(this.order.length) - for (let i=0; i< this.originalString.length; i++) this.lcpArray[i] = 0 + for(let i=0; i 0 ? lcp : 0 + + while ((i + currentLcp { + const st1 = "bananas" + const st2 = "marijuana" + it("Find the suffix array given the string", () =>{ + + }) + + it("Find the lcp array given the string", () =>{ + + }) +}) \ No newline at end of file From 9f657566965b74953070485c8b86ec4e5d36b75f Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Sat, 28 Nov 2020 23:56:24 +0530 Subject: [PATCH 38/40] Suffix and LCP Array --- README.md | 3 + package.json | 3 +- src/index.js | 4 +- src/suffix/SuffixMain.js | 190 ++++++++++++++++++++------------- src/suffix/index.js | 4 +- test/search/test_rabin_karp.js | 12 +-- test/suffix/test_Suffix.js | 30 ++++-- 7 files changed, 148 insertions(+), 98 deletions(-) diff --git a/README.md b/README.md index e0c4256..06d34dc 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,15 @@ List of supported Data Structures and Algorithms are : - [Aho Corasick](https://github.com/thsubaku9/string-dsa/blob/main/src/search/AhoCorasick.js) - [Bloom Filter](https://github.com/thsubaku9/string-dsa/blob/main/src/BloomFilter.js) - [Bracket Balance](https://github.com/thsubaku9/string-dsa/blob/main/src/bracketBalance.js) +- [Burst Sort](https://github.com/thsubaku9/string-dsa/blob/main/src/Trie.js) - [Custom Sort](https://github.com/thsubaku9/string-dsa/blob/main/src/stringSort.js) - [Dice Coefficient](https://github.com/thsubaku9/string-dsa/blob/main/src/dice_coeff.js) - [Edit/Levenshtein Distance](https://github.com/thsubaku9/string-dsa/blob/main/src/edit_distance.js) - [Knuth Morris Pratt](https://github.com/thsubaku9/string-dsa/blob/main/src/search/kmp.js) +- [Longest Common Prefix](https://github.com/thsubaku9/string-dsa/blob/main/src/suffix/SuffixMain.js) - [Longest Common Substring](https://github.com/thsubaku9/string-dsa/blob/main/src/lcs.js) - [Rabin Karp](https://github.com/thsubaku9/string-dsa/blob/main/src/search/rabin_karp.js) +- [Suffix Array](https://github.com/thsubaku9/string-dsa/blob/main/src/suffix/SuffixMain.js) - [Trie](https://github.com/thsubaku9/string-dsa/blob/main/src/Trie.js) ## Utilization diff --git a/package.json b/package.json index db5a04c..2f9b293 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.4.0", + "version": "1.5.0", "description": "String Data Structures and Algorithms Library in JavaScript", "main": "src/index.js", "files": [ @@ -25,6 +25,7 @@ "Bloom Filter", "Custom Sort", "Levenshtein Distance", + "Suffix Array", "Trie" ], "author": "Kaustubh J ", diff --git a/src/index.js b/src/index.js index edc90e7..1ab12f1 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,7 @@ const diceCoeff = require('./dice_coeff'); const editDist = require('./edit_distance'); const { AhoCorasick, kmp, rabinKarp } = require('./search'); const lcs = require('./lcs'); -const SuffixOps = require('./suffix') +const { Suffix } = require('./suffix'); const Trie = require('./Trie'); module.exports = { @@ -18,6 +18,6 @@ module.exports = { kmp, lcs, rabinKarp, - SuffixOps, + Suffix, Trie, }; diff --git a/src/suffix/SuffixMain.js b/src/suffix/SuffixMain.js index e1b8486..36abaec 100644 --- a/src/suffix/SuffixMain.js +++ b/src/suffix/SuffixMain.js @@ -1,8 +1,5 @@ "use strict"; -// const Suffix = require("./src/suffix").SuffixOps -// mySfx = new Suffix("marijuana") -// mySfx.computeLcpArray() class SuffixMain { constructor(mainString) { this.CHAR_LIM = 27; @@ -15,8 +12,14 @@ class SuffixMain { this.lcpConstructed = false; } + /** + * This function should be used to find monomer index based order array + * + * @returns {Array} returns the character order based array for the given string + */ charOrder() { let charCount = new Array(this.CHAR_LIM); + let charOrderArray = new Array(this.originalString.length); for (let i = 0; i < this.CHAR_LIM; i++) charCount[i] = 0; for (let i = 0; i < this.originalString.length; i++) { @@ -39,72 +42,103 @@ class SuffixMain { c = this.originalString.charCodeAt(i) - "a".charCodeAt(0) + 1; } charCount[c] -= 1; - this.order[charCount[c]] = i; + charOrderArray[charCount[c]] = i; } + + return charOrderArray; } - charClass() { - this.class[this.order[0]] = 0; - for(let i = 1; i=0; i--){ - let cyclicShiftPosition = (this.order[i] - L + this.originalString.length) % (this.originalString.length) - let cl = this.class[cyclicShiftPosition] - count[cl] -= 1 - newOrder [count[cl]] = cyclicShiftPosition + for (let i = this.originalString.length - 1; i >= 0; i--) { + let cyclicShiftPosition = (this.order[i] - L + this.originalString.length) % (this.originalString.length); + let cl = this.class[cyclicShiftPosition]; + count[cl] -= 1; + newOrder[count[cl]] = cyclicShiftPosition; } - + return newOrder; } + /** + * This function uodates the 2*L-gram based classification array + * + * @param {*} L the number of positions the start of the gram is located + * + * @returns {Array} the classified 2*L-gram array + */ updateClass(L) { let newClass = new Array(this.originalString.length); - newClass[this.order[0]] = 0 + newClass[this.order[0]] = 0; - for(let i=1; i 0 ? lcp : 0 - - while ((i + currentLcp 0 ? lcp : 0; + + while ((i + currentLcp < this.originalString.length) && (j + currentLcp < this.originalString.length)) { + if (this.originalString.charAt(i + currentLcp) == this.originalString.charAt(j + currentLcp)) { + currentLcp += 1; } else { - break + break; } } - return currentLcp + return currentLcp; } - computeLcpArray(){ - if (this.lcpConstructed) return this.lcpArray + /** + * This function computes the LCP for given suffix array + * + * @returns {Array} LCP array + */ + computeLcpArray() { + if (this.lcpConstructed) return this.lcpArray; + + if (!this.suffixConstructed) this.suffixArray(); + for (let i = 0; i < this.originalString.length - 1; i++) this.lcpArray[i] = 0; - if(!this.suffixConstructed) this.suffixArray() - for (let i=0; i< this.originalString.length-1; i++) this.lcpArray[i] = 0 - let isa = this.reverseIndexSA(); let s_len = this.originalString.length; - let lcp = 0; + let lcp = 0; let suffix = this.order[0]; - //compute the lcp for the initial location - for(let i=0; i< s_len; i++){ - let pos = isa[suffix] - if(pos == s_len -1){ - console.log(`Suffix : ${suffix} | Position: ${pos}`) - lcp = 0 - suffix = (suffix + 1) % s_len + // compute the lcp for the initial location + for (let i = 0; i < s_len; i++) { + let pos = isa[suffix]; + if (pos == s_len - 1) { + lcp = 0; + suffix = (suffix + 1) % s_len; continue; } - let nextSuffix = this.order[pos + 1] - - console.log(`Suffix : ${suffix} | Position: ${pos} | nextSuffix : ${nextSuffix}`) - - lcp = this._computeLcp(suffix,nextSuffix,lcp-1) - this.lcpArray[pos] = lcp - suffix = (suffix + 1) % s_len + let nextSuffix = this.order[pos + 1]; + lcp = this._computeLcp(suffix, nextSuffix, lcp - 1); + this.lcpArray[pos] = lcp; + suffix = (suffix + 1) % s_len; } - this.lcpConstructed = true - return this.lcpArray + this.lcpConstructed = true; + return this.lcpArray; } - } module.exports = SuffixMain; diff --git a/src/suffix/index.js b/src/suffix/index.js index b547f33..880b5d5 100644 --- a/src/suffix/index.js +++ b/src/suffix/index.js @@ -1,5 +1,5 @@ -const SuffixOps = require("./SuffixMain"); +const Suffix = require("./SuffixMain"); module.exports = { - SuffixOps, + Suffix, }; diff --git a/test/search/test_rabin_karp.js b/test/search/test_rabin_karp.js index 29a4920..295f07a 100644 --- a/test/search/test_rabin_karp.js +++ b/test/search/test_rabin_karp.js @@ -1,5 +1,5 @@ const assert = require('assert'); -const rabin_karp = require("../../src").rabinKarp; +const { rabinKarp } = require("../../src"); describe('Rabin Karp', () => { const searchTerm1 = "cancan"; const searchTerm2 = "mixolydian"; const @@ -8,25 +8,25 @@ describe('Rabin Karp', () => { searchSpace3 = "pina colada and what ?"; it(`should return index of ${searchTerm1} in three positions for ${searchSpace1}`, () => { - const result = rabin_karp(searchTerm1, searchSpace1); + const result = rabinKarp(searchTerm1, searchSpace1); assert.deepStrictEqual(result, [0, 3, 21]); }); it(`should return [-1] for ${searchTerm2} in ${searchSpace2}`, () => { - const result = rabin_karp(searchTerm2, searchSpace2); + const result = rabinKarp(searchTerm2, searchSpace2); assert.deepStrictEqual(result, [-1]); }); it(`should return one index for ${searchTerm3} in ${searchSpace3} `, () => { - const result = rabin_karp(searchTerm3, searchSpace3); + const result = rabinKarp(searchTerm3, searchSpace3); assert.deepStrictEqual(result, [0]); }); it('should return [-1] if either the searchTerm or searchSpace is empty', () => { - const resultOne = rabin_karp("", searchSpace1); + const resultOne = rabinKarp("", searchSpace1); assert.deepStrictEqual(resultOne, [-1]); - const resultTwo = rabin_karp(searchTerm1, ""); + const resultTwo = rabinKarp(searchTerm1, ""); assert.deepStrictEqual(resultTwo, [-1]); }); }); diff --git a/test/suffix/test_Suffix.js b/test/suffix/test_Suffix.js index 3b715a3..d7d4dec 100644 --- a/test/suffix/test_Suffix.js +++ b/test/suffix/test_Suffix.js @@ -1,14 +1,22 @@ -const assert = require("assert") -const SuffixMain = require("../../src").SuffixOps +const assert = require("assert"); +const { Suffix } = require("../../src"); describe("Tests related to SUFFIX Opertaions", () => { - const st1 = "bananas" - const st2 = "marijuana" - it("Find the suffix array given the string", () =>{ + const st1 = "marijuana"; + const st2 = "bananas"; + const SA1 = new Suffix(st1); + const SA2 = new Suffix(st2); + const sa_1 = [9, 8, 6, 1, 3, 4, 0, 7, 2, 5]; + const sa_2 = [7, 1, 3, 5, 0, 2, 4, 6]; + const lcp_1 = [0, 1, 1, 0, 0, 0, 0, 0, 0]; + const lcp_2 = [0, 3, 1, 0, 0, 2, 0]; + it("Find the suffix array given the string", () => { + assert.deepStrictEqual(SA1.suffixArray(), sa_1); + assert.deepStrictEqual(SA2.suffixArray(), sa_2); + }); - }) - - it("Find the lcp array given the string", () =>{ - - }) -}) \ No newline at end of file + it("Find the lcp array given the string", () => { + assert.deepStrictEqual(SA1.computeLcpArray(), lcp_1); + assert.deepStrictEqual(SA2.computeLcpArray(), lcp_2); + }); +}); From a8397501fd1702b8b917f1453705b380d2eb771e Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Sun, 29 Nov 2020 20:49:15 +0530 Subject: [PATCH 39/40] minor update --- README.md | 6 +++--- package.json | 2 +- src/index.js | 6 ++++-- src/sort/burstSort.js | 14 ++++++++++++++ src/sort/index.js | 9 +++++++++ src/{ => sort}/stringSort.js | 0 test/test_sort.js | 22 ++++++++++++++-------- 7 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 src/sort/burstSort.js create mode 100644 src/sort/index.js rename src/{ => sort}/stringSort.js (100%) diff --git a/README.md b/README.md index 06d34dc..3d170fd 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,13 @@ List of supported Data Structures and Algorithms are : - [Aho Corasick](https://github.com/thsubaku9/string-dsa/blob/main/src/search/AhoCorasick.js) - [Bloom Filter](https://github.com/thsubaku9/string-dsa/blob/main/src/BloomFilter.js) - [Bracket Balance](https://github.com/thsubaku9/string-dsa/blob/main/src/bracketBalance.js) -- [Burst Sort](https://github.com/thsubaku9/string-dsa/blob/main/src/Trie.js) -- [Custom Sort](https://github.com/thsubaku9/string-dsa/blob/main/src/stringSort.js) +- [Burst Sort](https://github.com/thsubaku9/string-dsa/blob/main/src/sort/burstSort.js) +- [Custom Sort](https://github.com/thsubaku9/string-dsa/blob/main/src/sort/stringSort.js) - [Dice Coefficient](https://github.com/thsubaku9/string-dsa/blob/main/src/dice_coeff.js) - [Edit/Levenshtein Distance](https://github.com/thsubaku9/string-dsa/blob/main/src/edit_distance.js) - [Knuth Morris Pratt](https://github.com/thsubaku9/string-dsa/blob/main/src/search/kmp.js) - [Longest Common Prefix](https://github.com/thsubaku9/string-dsa/blob/main/src/suffix/SuffixMain.js) -- [Longest Common Substring](https://github.com/thsubaku9/string-dsa/blob/main/src/lcs.js) +- [Longest Common SubSequence](https://github.com/thsubaku9/string-dsa/blob/main/src/lcs.js) - [Rabin Karp](https://github.com/thsubaku9/string-dsa/blob/main/src/search/rabin_karp.js) - [Suffix Array](https://github.com/thsubaku9/string-dsa/blob/main/src/suffix/SuffixMain.js) - [Trie](https://github.com/thsubaku9/string-dsa/blob/main/src/Trie.js) diff --git a/package.json b/package.json index 2f9b293..7f796b6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.5.0", + "version": "1.5.1", "description": "String Data Structures and Algorithms Library in JavaScript", "main": "src/index.js", "files": [ diff --git a/src/index.js b/src/index.js index 1ab12f1..fd4ba97 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,10 @@ const bracketBalance = require('./bracketBalance'); const BloomFilter = require('./BloomFilter'); -const customSort = require('./stringSort'); const diceCoeff = require('./dice_coeff'); const editDist = require('./edit_distance'); -const { AhoCorasick, kmp, rabinKarp } = require('./search'); const lcs = require('./lcs'); +const { AhoCorasick, kmp, rabinKarp } = require('./search'); +const { burstSort, customSort, sorted } = require('./sort'); const { Suffix } = require('./suffix'); const Trie = require('./Trie'); @@ -12,6 +12,7 @@ module.exports = { AhoCorasick, BloomFilter, bracketBalance, + burstSort, customSort, diceCoeff, editDist, @@ -19,5 +20,6 @@ module.exports = { lcs, rabinKarp, Suffix, + sorted, Trie, }; diff --git a/src/sort/burstSort.js b/src/sort/burstSort.js new file mode 100644 index 0000000..8b633f2 --- /dev/null +++ b/src/sort/burstSort.js @@ -0,0 +1,14 @@ +const Trie = require("../Trie"); + +/** + * + * @param {String[]} keywords the keywords that you wish to sort + */ +function burstSort(keywords) { + let internalTrie = new Trie(); + internalTrie.insertList(keywords); + let result = internalTrie.burstSort(); + return result; +} + +module.exports = burstSort; diff --git a/src/sort/index.js b/src/sort/index.js new file mode 100644 index 0000000..d9f7359 --- /dev/null +++ b/src/sort/index.js @@ -0,0 +1,9 @@ +const burstSort = require("./burstSort"); +const customSort = require("./stringSort").sort; +const { sorted } = require("./stringSort"); + +module.exports = { + burstSort, + customSort, + sorted, +}; diff --git a/src/stringSort.js b/src/sort/stringSort.js similarity index 100% rename from src/stringSort.js rename to src/sort/stringSort.js diff --git a/test/test_sort.js b/test/test_sort.js index e75f7ff..bbab9fc 100644 --- a/test/test_sort.js +++ b/test/test_sort.js @@ -1,10 +1,9 @@ const assert = require('assert'); -const { sort } = require('../src').customSort; -const { sorted } = require('../src').customSort; - +const { burstSort, customSort, sorted } = require('../src'); describe("Custom String Sorting", () => { const unsortedArr = ["its", "the", "its", "the", "rick", "dance"]; + const burstUnsortedArr = ["can", "batman", "animate", "hippies"]; const reverseComparator = (y, x) => { let i = 0; while (i < x.length && i < y.length) { @@ -17,22 +16,22 @@ describe("Custom String Sorting", () => { }; it(`should return correct indices for the array ${unsortedArr}`, () => { - const res = sort(unsortedArr, true); + const res = customSort(unsortedArr, true); assert.deepStrictEqual(res, [5, 0, 2, 4, 1, 3]); }); it(`should return correct sorted order for the array ${unsortedArr}`, () => { - const res = sort(unsortedArr, false); + const res = customSort(unsortedArr, false); assert.deepStrictEqual(res, ['dance', 'its', 'its', 'rick', 'the', 'the']); }); it(`should return correct descending sort for the array ${unsortedArr}`, () => { - const res = sort(unsortedArr, false, reverseComparator); + const res = customSort(unsortedArr, false, reverseComparator); assert.deepStrictEqual(res, ['the', 'the', 'rick', 'its', 'its', 'dance']); }); it(`should return [] for empty array`, () => { - const res = sort([], false); + const res = customSort([], false); assert.deepStrictEqual(res, []); }); @@ -42,7 +41,14 @@ describe("Custom String Sorting", () => { }); it(`should return true for sorted array`, () => { - const res = sorted(sort(unsortedArr, false)); + const res = sorted(customSort(unsortedArr, false)); assert.deepStrictEqual(res, true); }); + + it("should perform burstsort properly",() =>{ + const res = burstSort(burstUnsortedArr); + const res2 = customSort(burstUnsortedArr,false); + assert.deepStrictEqual(res,res2); + }); + }); From 62f71fdaaf4af41ede8d7643e289d8768dc8056f Mon Sep 17 00:00:00 2001 From: Kukulkan Date: Sun, 29 Nov 2020 23:52:37 +0530 Subject: [PATCH 40/40] BWT --- README.md | 3 ++- package.json | 3 ++- src/index.js | 3 ++- src/suffix/BWT.js | 50 ++++++++++++++++++++++++++++++++++++++++ src/suffix/SuffixMain.js | 2 +- src/suffix/index.js | 2 ++ test/suffix/test_BWT.js | 23 ++++++++++++++++++ 7 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 src/suffix/BWT.js create mode 100644 test/suffix/test_BWT.js diff --git a/README.md b/README.md index 3d170fd..00f9c5b 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ List of supported Data Structures and Algorithms are : - [Aho Corasick](https://github.com/thsubaku9/string-dsa/blob/main/src/search/AhoCorasick.js) - [Bloom Filter](https://github.com/thsubaku9/string-dsa/blob/main/src/BloomFilter.js) - [Bracket Balance](https://github.com/thsubaku9/string-dsa/blob/main/src/bracketBalance.js) +- [Burrows Wheeler Transform](https://github.com/thsubaku9/string-dsa/blob/main/src/suffix/BWT.js) - [Burst Sort](https://github.com/thsubaku9/string-dsa/blob/main/src/sort/burstSort.js) - [Custom Sort](https://github.com/thsubaku9/string-dsa/blob/main/src/sort/stringSort.js) - [Dice Coefficient](https://github.com/thsubaku9/string-dsa/blob/main/src/dice_coeff.js) @@ -68,4 +69,4 @@ $ npm run coverage ## License -[ISC](https://github.com/thsubaku9/string-dsa/blob/main/LICENSE) +[GNU General Public License v3.0](https://github.com/thsubaku9/string-dsa/blob/main/LICENSE) diff --git a/package.json b/package.json index 7f796b6..feefd66 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.5.1", + "version": "2.0.0", "description": "String Data Structures and Algorithms Library in JavaScript", "main": "src/index.js", "files": [ @@ -23,6 +23,7 @@ "String Data Structures", "Aho Corasick", "Bloom Filter", + "Burrows Wheeler Transform", "Custom Sort", "Levenshtein Distance", "Suffix Array", diff --git a/src/index.js b/src/index.js index fd4ba97..321d53e 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,7 @@ const editDist = require('./edit_distance'); const lcs = require('./lcs'); const { AhoCorasick, kmp, rabinKarp } = require('./search'); const { burstSort, customSort, sorted } = require('./sort'); -const { Suffix } = require('./suffix'); +const { BWT, Suffix } = require('./suffix'); const Trie = require('./Trie'); module.exports = { @@ -13,6 +13,7 @@ module.exports = { BloomFilter, bracketBalance, burstSort, + BWT, customSort, diceCoeff, editDist, diff --git a/src/suffix/BWT.js b/src/suffix/BWT.js new file mode 100644 index 0000000..2d3363f --- /dev/null +++ b/src/suffix/BWT.js @@ -0,0 +1,50 @@ +const { sort } = require("../sort/stringSort"); +const Suffix = require("./SuffixMain"); + +/** + * Burrows Wheeler Transformation + * + * @param {String} text the string that you wish to find BWT of + * + * @returns {String} the respective BWT of the string + */ +function transform(text) { + let mySfx = new Suffix(text); + let bwt_t = ""; + + let res = mySfx.suffixArray(); + + for (let i = 0; i < res.length; i++) { + bwt_t += mySfx.originalString[(res[i] + res.length - 1) % res.length]; + } + + return bwt_t; +} + +/** + * inverse Burrows Wheeler Transformation + * + * @param {String} bwt_t the BWT representation of the string + * + * @returns {String} the original string + */ +function inverse_transform(bwt_t) { + let index_sort = sort(bwt_t.split(""), true); + let inverse_index_pos = new Array(bwt_t.length); + for (let i = 0; i < bwt_t.length; i++) inverse_index_pos[index_sort[i]] = i; + + let start_pos = index_sort[0]; let end_pos = 0; + let text = bwt_t[start_pos]; + + while (end_pos != index_sort[0]) { + text = bwt_t[end_pos] + text; + start_pos = end_pos; + end_pos = inverse_index_pos[end_pos]; + } + return text; +} + +module.exports = { + transform, + inverse_transform, +}; diff --git a/src/suffix/SuffixMain.js b/src/suffix/SuffixMain.js index e5921d9..6ced2e0 100644 --- a/src/suffix/SuffixMain.js +++ b/src/suffix/SuffixMain.js @@ -125,7 +125,7 @@ class SuffixMain { } /** - * This function computes the suffixArray of the given string in linear time + * This function computes the suffixArray of the given string * * @returns {Array} indexed based suffix array */ diff --git a/src/suffix/index.js b/src/suffix/index.js index 880b5d5..4b9356e 100644 --- a/src/suffix/index.js +++ b/src/suffix/index.js @@ -1,5 +1,7 @@ const Suffix = require("./SuffixMain"); +const BWT = require("./BWT"); module.exports = { + BWT, Suffix, }; diff --git a/test/suffix/test_BWT.js b/test/suffix/test_BWT.js new file mode 100644 index 0000000..479b041 --- /dev/null +++ b/test/suffix/test_BWT.js @@ -0,0 +1,23 @@ +const assert = require("assert"); +const BWT = require("../../src").BWT +describe("BWT tests", () =>{ + + const st1 = "candy" , st2 = "banana" + const bwt1 = "yc$nad", bwt2 = "annb$aa" + const inv1 = `${st1}$`, inv2 = `${st2}$` + it("should find the correct BWT", () =>{ + const res1 = BWT.transform(st1) + const res2 = BWT.transform(st2) + + assert.deepStrictEqual(res1, bwt1); + assert.deepStrictEqual(res2, bwt2); + }) + + it("should find the correct iBWT", () =>{ + const res1 = BWT.inverse_transform(bwt1) + const res2 = BWT.inverse_transform(bwt2) + + assert.deepStrictEqual(res1,inv1); + assert.deepStrictEqual(res2,inv2); + }) +})